├── CNAME
├── docs
├── CNAME
├── favicon.png
├── plugins
│ ├── cycling_edp.png
│ ├── imagery_edp.png
│ ├── metadata
│ │ ├── amenity-bench-type.jpg
│ │ ├── roof-shape-field.jpg
│ │ ├── modes.md
│ │ ├── imagery.md
│ │ ├── index.md
│ │ ├── presets.md
│ │ └── element_kinds.md
│ ├── publish.md
│ ├── code
│ │ └── index.md
│ ├── index.md
│ └── install.md
├── guide
│ ├── releases
│ │ ├── ed6-drag.avif
│ │ ├── ed7-cache.avif
│ │ ├── ed6-compass.avif
│ │ ├── ed6-confirm.avif
│ │ ├── ed6-profile.png
│ │ ├── ed6-weekdays.png
│ │ ├── ed7-pending.png
│ │ ├── ed7-vector.avif
│ │ ├── ed7-buildings.avif
│ │ ├── ed7-rotation.avif
│ │ ├── ed7-preset-icons.png
│ │ ├── 7.0.md
│ │ └── 6.0.md
│ ├── index.md
│ ├── quick_start.md
│ ├── preface.md
│ └── faq.md
├── develop
│ ├── images
│ │ ├── editor-fields.png
│ │ ├── micromapping-legend.png
│ │ └── weblate-translation-pane.png
│ ├── index.md
│ ├── build.md
│ ├── bugs.md
│ ├── design.md
│ ├── translate.md
│ ├── structure.md
│ ├── presets.md
│ └── cases.md
├── stylesheets
│ └── extra.css
├── privacy_policy.md
├── index.md
└── images
│ ├── appstore-android.svg
│ └── appstore-fdroid.svg
├── .gitignore
├── _config.yml
├── assets
├── images
│ ├── hero-figure.png
│ ├── testflight_button.png
│ ├── icon-rocket.svg
│ ├── icon-target.svg
│ ├── bars.svg
│ ├── logo-icon.svg
│ ├── icon-cogs.svg
│ ├── appstore-android.svg
│ └── appstore-fdroid.svg
├── js
│ └── flipster-custom.js
└── plugins
│ └── jquery-flipster
│ └── dist
│ ├── jquery.flipster.min.css
│ ├── jquery.flipster.min.js
│ └── jquery.flipster.css
├── README.md
├── ru
├── privacy_policy.md
└── faq.md
├── fr
├── privacy_policy.md
└── faq.md
├── .well-known
├── apple-app-site-association
└── assetlinks.json
├── .github
└── workflows
│ └── docs.yml
├── en
├── privacy_policy.md
└── faq.md
├── mkdocs.yml
├── LICENSE
└── index.html
/CNAME:
--------------------------------------------------------------------------------
1 | every-door.app
--------------------------------------------------------------------------------
/docs/CNAME:
--------------------------------------------------------------------------------
1 | every-door.app
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | site/
2 | .venv/
3 | *.swp
4 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | include: [".well-known"]
2 |
--------------------------------------------------------------------------------
/docs/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zverik/everydoor-website/main/docs/favicon.png
--------------------------------------------------------------------------------
/assets/images/hero-figure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zverik/everydoor-website/main/assets/images/hero-figure.png
--------------------------------------------------------------------------------
/docs/plugins/cycling_edp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zverik/everydoor-website/main/docs/plugins/cycling_edp.png
--------------------------------------------------------------------------------
/docs/plugins/imagery_edp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zverik/everydoor-website/main/docs/plugins/imagery_edp.png
--------------------------------------------------------------------------------
/docs/guide/releases/ed6-drag.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zverik/everydoor-website/main/docs/guide/releases/ed6-drag.avif
--------------------------------------------------------------------------------
/docs/guide/releases/ed7-cache.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zverik/everydoor-website/main/docs/guide/releases/ed7-cache.avif
--------------------------------------------------------------------------------
/assets/images/testflight_button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zverik/everydoor-website/main/assets/images/testflight_button.png
--------------------------------------------------------------------------------
/docs/guide/releases/ed6-compass.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zverik/everydoor-website/main/docs/guide/releases/ed6-compass.avif
--------------------------------------------------------------------------------
/docs/guide/releases/ed6-confirm.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zverik/everydoor-website/main/docs/guide/releases/ed6-confirm.avif
--------------------------------------------------------------------------------
/docs/guide/releases/ed6-profile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zverik/everydoor-website/main/docs/guide/releases/ed6-profile.png
--------------------------------------------------------------------------------
/docs/guide/releases/ed6-weekdays.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zverik/everydoor-website/main/docs/guide/releases/ed6-weekdays.png
--------------------------------------------------------------------------------
/docs/guide/releases/ed7-pending.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zverik/everydoor-website/main/docs/guide/releases/ed7-pending.png
--------------------------------------------------------------------------------
/docs/guide/releases/ed7-vector.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zverik/everydoor-website/main/docs/guide/releases/ed7-vector.avif
--------------------------------------------------------------------------------
/docs/develop/images/editor-fields.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zverik/everydoor-website/main/docs/develop/images/editor-fields.png
--------------------------------------------------------------------------------
/docs/guide/releases/ed7-buildings.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zverik/everydoor-website/main/docs/guide/releases/ed7-buildings.avif
--------------------------------------------------------------------------------
/docs/guide/releases/ed7-rotation.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zverik/everydoor-website/main/docs/guide/releases/ed7-rotation.avif
--------------------------------------------------------------------------------
/docs/guide/releases/ed7-preset-icons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zverik/everydoor-website/main/docs/guide/releases/ed7-preset-icons.png
--------------------------------------------------------------------------------
/docs/develop/images/micromapping-legend.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zverik/everydoor-website/main/docs/develop/images/micromapping-legend.png
--------------------------------------------------------------------------------
/docs/plugins/metadata/amenity-bench-type.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zverik/everydoor-website/main/docs/plugins/metadata/amenity-bench-type.jpg
--------------------------------------------------------------------------------
/docs/plugins/metadata/roof-shape-field.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zverik/everydoor-website/main/docs/plugins/metadata/roof-shape-field.jpg
--------------------------------------------------------------------------------
/docs/develop/images/weblate-translation-pane.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zverik/everydoor-website/main/docs/develop/images/weblate-translation-pane.png
--------------------------------------------------------------------------------
/docs/plugins/publish.md:
--------------------------------------------------------------------------------
1 | # Publishing a Plugin
2 |
3 | We have a central repository for Every Door plugins: [plugins.every-door.app](https://plugins.every-door.app/).
4 |
--------------------------------------------------------------------------------
/docs/plugins/code/index.md:
--------------------------------------------------------------------------------
1 | # Plugin Code
2 |
3 | Every Door will support compiled Dart code for overriding or extending functions.
4 | This section will be documented when we have an API.
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Website for Every Door
2 |
3 | This is the source code for [every-door-app](https://every-door.app) about the [Every Door](https://github.com/Zverik/every_door) editor.
4 |
5 | Please write issues [there](https://github.com/Zverik/every_door/issues), or better, make pull requests.
6 |
7 | Made by Ilya Zverev, licensed CC-BY 4.0.
8 |
--------------------------------------------------------------------------------
/docs/guide/index.md:
--------------------------------------------------------------------------------
1 | # User's Guide
2 |
3 | ## Supported Platforms
4 |
5 | The app supports all operating systems that are
6 | [supported by the latest Flutter framework](https://docs.flutter.dev/reference/supported-platforms).
7 | For the latest version, this means:
8 |
9 | * Android 7.0 or later (released in 2016).
10 | * iOS 13 or later (released in 2019, supports iPhone 6s and newer).
11 |
--------------------------------------------------------------------------------
/docs/stylesheets/extra.css:
--------------------------------------------------------------------------------
1 | .md-content a {
2 | text-decoration: underline;
3 | text-decoration-color: color-mix(in srgb, currentcolor 50%, transparent);
4 | }
5 |
6 | .app-stores {
7 | list-style: 0;
8 | padding: 0 !important;
9 | margin: 0 !important;
10 | }
11 |
12 | .app-stores li {
13 | display: inline-block;
14 | padding: 0 !important;
15 | margin: 0 10px 0 0 !important;
16 | }
17 |
18 | .app-stores img {
19 | height: 40px;
20 | }
21 |
--------------------------------------------------------------------------------
/ru/privacy_policy.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Политика конфиденциальности Every Door
3 | ---
4 | # Политика конфиденциальности Every Door
5 |
6 | Мы не храним ваши данные, точка.
7 |
8 | У этого приложения нет серверной части, куда оно могло бы отправлять данные.
9 | Оно лишь отсылает ваши правки в [OpenStreetMap](https://www.openstreetmap.org).
10 | Владельцы этого сайта не делятся никакой идентифицирующей информацией
11 | о своих пользователях.
12 |
13 | Если остались вопросы, пишите [Илье, автору приложения](mailto:ilya@zverev.info).
14 |
--------------------------------------------------------------------------------
/fr/privacy_policy.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Every Door Politique de Confidentialité
3 | ---
4 | # Every Door Politique de Confidentialité
5 |
6 | Nous ne conservons pas vos données, point.
7 |
8 | Cette application n’a aucun serveur où envoyer des données, à l’exception des éléments que vous modifiez qui sont envoyés vers [OpenStreetMap](https://www.openstreetmap.org) qui ne partagent aucune donnée d’identification des personnes en faisant usage.
9 |
10 | Si vous avez des questions, contactez [Ilya, le développeur](mailto:ilya@zverev.info).
11 |
--------------------------------------------------------------------------------
/docs/plugins/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Every Door Plugins
3 | ---
4 | Since version 6.0, the editor can be extended, thanks to the
5 | [NGI0 grant](https://izv.ee/everydoor/ngi0/customization).
6 | You can add new modes, new imagery, replace presets and communicate with third-party API.
7 |
8 | A plugin is a zip-archive with an `edp` extension, which includes a `plugin.yaml` file
9 | inside at the top level. All other files are optional.
10 |
11 | These sections explain how to use and write plugins:
12 |
13 | * [Installation](install.md)
14 | * [Metadata](metadata/index.md)
15 | * [Code](code/index.md)
16 | * [Publishing](publish.md)
17 |
--------------------------------------------------------------------------------
/.well-known/apple-app-site-association:
--------------------------------------------------------------------------------
1 | {
2 | "applinks": {
3 | "details": [
4 | {
5 | "appIDs": ["TM4TW7N79V.info.zverev.everydoor"],
6 | "components": [
7 | {
8 | "/": "/nav/*",
9 | "comment": "Navigate to a location or an OSM object"
10 | },
11 | {
12 | "/": "/plugin/*",
13 | "comment": "Install a plugin"
14 | }
15 | ]
16 | }
17 | ]
18 | },
19 | "webcredentials": {
20 | "apps": [ "TM4TW7N79V.info.zverev.everydoor" ]
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/assets/images/icon-rocket.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/images/icon-target.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/images/bars.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/workflows/docs.yml:
--------------------------------------------------------------------------------
1 | name: docs
2 | on:
3 | push:
4 | branches:
5 | - main
6 | permissions:
7 | contents: write
8 | jobs:
9 | deploy:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: actions/checkout@v4
13 | - name: Configure Git Credentials
14 | run: |
15 | git config user.name github-actions[bot]
16 | git config user.email 41898282+github-actions[bot]@users.noreply.github.com
17 | - uses: actions/setup-python@v5
18 | with:
19 | python-version: 3.x
20 | - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
21 | - uses: actions/cache@v4
22 | with:
23 | key: mkdocs-material-${{ env.cache_id }}
24 | path: .cache
25 | restore-keys: |
26 | mkdocs-material-
27 | - run: pip install mkdocs-material
28 | - run: mkdocs gh-deploy --force
29 |
--------------------------------------------------------------------------------
/assets/images/logo-icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/privacy_policy.md:
--------------------------------------------------------------------------------
1 | # Privacy Policy
2 |
3 | ## You Upload To OpenStreetMap
4 |
5 | With this app you make actual and direct
6 | contributions to [OpenStreetMap](https://www.openstreetmap.org).
7 | There is no third party in-between the app and OSM infrastructure.
8 |
9 | Editing OpenStreetMap anonymously is not possible. Any changes you make
10 | (and their date and location) are attributed to your OSM user account
11 | and publicly visible on the openstreetmap.org website. Because Every Door
12 | should only be used for on-site survey, this reveals where and when you have used the app.
13 |
14 | ## Location
15 |
16 | The app does not share your GPS location with anyone.
17 | It is used to focus the map around your location, optionally downloading map tiles.
18 |
19 | ## Contact Me
20 |
21 | If you have any questions, ask [Ilya, the author](mailto:ilya@zverev.info).
22 |
23 | _Portions of this text were adapted from [StreetComplete's statement](https://www.westnordost.de/streetcomplete/privacy.html)._
24 |
--------------------------------------------------------------------------------
/.well-known/assetlinks.json:
--------------------------------------------------------------------------------
1 | [{
2 | "relation": ["delegate_permission/common.handle_all_urls"],
3 | "target": {
4 | "namespace": "android_app",
5 | "package_name": "info.zverev.ilya.every_door",
6 | "sha256_cert_fingerprints": [
7 | "9F:FC:A7:0F:77:A8:5E:F6:82:90:27:66:02:BB:5B:4C:92:A6:54:67:C5:4F:F6:FB:89:C4:B2:02:39:50:62:03",
8 | "16:C8:1C:74:3F:75:20:F5:85:9D:EB:25:C0:DA:DB:63:1F:A3:97:3C:D2:B2:88:A9:54:6D:C3:4D:8B:71:C6:97",
9 | "29:90:21:68:8B:04:21:91:A0:90:65:B9:A7:46:3B:72:62:85:40:72:8C:31:C6:C5:2D:8D:BE:B8:21:53:31:FB",
10 | "61:5D:43:AC:81:08:3C:D9:1D:98:16:50:74:76:36:F6:7C:7C:EC:02:33:5A:F2:51:A4:DD:B2:53:53:35:4C:02"
11 | ]
12 | }
13 | },
14 | {
15 | "relation": ["delegate_permission/common.handle_all_urls"],
16 | "target": {
17 | "namespace": "android_app",
18 | "package_name": "info.zverev.ilya.every_door.beta",
19 | "sha256_cert_fingerprints": [
20 | "29:90:21:68:8B:04:21:91:A0:90:65:B9:A7:46:3B:72:62:85:40:72:8C:31:C6:C5:2D:8D:BE:B8:21:53:31:FB"
21 | ]
22 | }
23 | }]
24 |
--------------------------------------------------------------------------------
/en/privacy_policy.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Every Door Privacy Policy
3 | ---
4 | # Every Door Privacy Policy
5 |
6 | ## You Upload To OpenStreetMap
7 |
8 | With this app you make actual and direct
9 | contributions to [OpenStreetMap](https://www.openstreetmap.org).
10 | There is no third party in-between the app and OSM infrastructure.
11 |
12 | Editing OpenStreetMap anonymously is not possible. Any changes you make
13 | (and their date and location) are attributed to your OSM user account
14 | and publicly visible on the openstreetmap.org website. Because Every Door
15 | should only be used for on-site survey, this reveals where and when you have used the app.
16 |
17 | ## Location
18 |
19 | The app does not share your GPS location with anyone.
20 | It is used to focus the map around your location, optionally downloading map tiles.
21 |
22 | ## Contact Me
23 |
24 | If you have any questions, ask [Ilya, the author](mailto:ilya@zverev.info).
25 |
26 | _Portions of this text were adapted from [StreetComplete's statement](https://www.westnordost.de/streetcomplete/privacy.html)._
27 |
--------------------------------------------------------------------------------
/docs/guide/quick_start.md:
--------------------------------------------------------------------------------
1 | # Quick Start
2 |
3 | Every Door is closer to JOSM than to StreetComplete, MapComplete or iD.
4 | In this editor, you download data, edit it without connecting to the net,
5 | and regularly upload changes back to OpenStreetMap.
6 |
7 | Similarly to JOSM or MapComplete, you do not see everything at once, but
8 | choose a layer, a mode to work with. Mode buttons are at the bottom
9 | of the screen:
10 |
11 | - Micromapping. Here you map benches, trees, lamp posts, post boxes,
12 | and pedestrian crossings.
13 | - Amenities. Things or venues that provide services, often for money
14 | or for external funding. Shops, museums, vending machines.
15 | - Buildings. Collect addresses and building attributes like height.
16 | Also for entrances, especially useful for big apartment buildings.
17 | - Notes. Both OSM notes and GeoScribbles: draw geometry on the screen
18 | with your finger to trace it later with a proper device.
19 |
20 | During a walk you may feel a need to switch a layer every minute.
21 | It will be tiring, and you can burn out this way. We recommend focusing
22 | on a narrow set of things to collect: like shops, or benches. Mapping
23 | should feel relaxing and fulfilling, a joy of a pastime.
24 |
25 | ## Setting Up
26 |
27 | ## Micromapping
28 |
29 | ## Object Editor
30 |
31 | ## Amenities
32 |
33 | ## Buildings
34 |
35 | ## Notes
36 |
--------------------------------------------------------------------------------
/docs/develop/index.md:
--------------------------------------------------------------------------------
1 | # Contributor's Guide
2 |
3 | Every Door needs your help!
4 |
5 | There are multiple ways you can contribute. The main one being, take the app and
6 | go outside to map! Walk around a shopping district, map everything at a playground,
7 | bike into a forest and try drawing forest paths. That's the best way to test
8 | everything the app has to offer, and also gain ideas on how it may help you better.
9 |
10 | Other that that,.. everything still. Starting with the icon: imperfect, sketchy, like
11 | the app itself. Maybe it's time to become more serious? Same with this website: the landing
12 | page needs to be more inviting. And maybe in more languages than one.
13 |
14 | And code. The road map has like a hundred items on it, and people are always asking for more.
15 | Look into plugins, and if they don't cover what you want, try cloning the repository,
16 | learning Dart and Flutter, and improving the app.
17 |
18 | This section guides you around all the ways you can contribute.
19 |
20 | * [How to report bugs and request features](bugs.md)
21 | * [Translating the app, presets, and everything](translate.md)
22 | * [Adding more presets and fields](presets.md)
23 | * [General design principles](design.md)
24 | * [Downloading the code and setting up an IDE](build.md)
25 | * [Navigate yourself around the code](structure.md)
26 | * [Guidelines on hacking specific things](cases.md)
27 |
--------------------------------------------------------------------------------
/mkdocs.yml:
--------------------------------------------------------------------------------
1 | site_name: Every Door
2 | site_url: https://every-door.app/docs/
3 | site_description: Every Door Documentation
4 | theme:
5 | name: material
6 | language: en
7 | favicon: favicon.png
8 | logo: favicon.png
9 | features:
10 | - navigation.tracking
11 | - navigation.tabs
12 | - navigation.top
13 | - navigation.expand
14 | - navigation.indexes
15 |
16 | markdown_extensions:
17 | - attr_list
18 | - pymdownx.highlight
19 | - pymdownx.superfences
20 |
21 | extra_css:
22 | - stylesheets/extra.css
23 |
24 | extra:
25 | social:
26 | - icon: fontawesome/brands/github
27 | link: https://github.com/Zverik/every_door
28 | - icon: fontawesome/brands/mastodon
29 | link: https://en.osm.town/@everydoor
30 |
31 | nav:
32 | - User Guide:
33 | - guide/index.md
34 | - OpenStreetMap: guide/preface.md
35 | - Quick Start: guide/quick_start.md
36 | - FAQ: guide/faq.md
37 | - Releases:
38 | - 6.0: guide/releases/6.0.md
39 | - 7.0: guide/releases/7.0.md
40 | - Contributor Guide:
41 | - develop/index.md
42 | - Reporting Bugs: develop/bugs.md
43 | - Translating: develop/translate.md
44 | - Adding Presets: develop/presets.md
45 | - Developing: develop/build.md
46 | - Design Principles: develop/design.md
47 | - Project Structure: develop/structure.md
48 | - Finding Code: develop/cases.md
49 | - Plugins:
50 | - plugins/index.md
51 | - Installation: plugins/install.md
52 | - Writing a Plugin:
53 | - plugins/metadata/index.md
54 | - Element Kinds: plugins/metadata/element_kinds.md
55 | - Editor Modes: plugins/metadata/modes.md
56 | - Presets: plugins/metadata/presets.md
57 | - Imagery: plugins/metadata/imagery.md
58 | - Programming:
59 | - plugins/code/index.md
60 | - Publishing: plugins/publish.md
61 |
--------------------------------------------------------------------------------
/docs/plugins/install.md:
--------------------------------------------------------------------------------
1 | # Installation
2 |
3 | Plugins are not meant to sit on your computer and do nothing. How to load them
4 | onto your phone, and make them available to thousands of Every Door users (if
5 | you want that)?
6 |
7 | You have four options for that.
8 |
9 | 1. Share an `.edp` file. For example, send it to yourself with a messenger, and
10 | open it on a device. This way you don't have to publish it, and you can
11 | iterate on the development quickly. One issue is, it might not work on iOS.
12 |
13 | 2. Upload it to the [public repository](https://plugins.every-door.app/). It would
14 | validate the package on upload, reserve a plugin identifier, and make it available
15 | in the app. Just go to "Settings → Plugins → (+) button" and find it there.
16 | You only need an OpenStreetMap account to publish plugins. Initially you can
17 | mark your plugin "experimental", so it won't appear in public lists.
18 |
19 | 3. Upload it somewhere open, like to Github or your own web server. This option works
20 | best for programmatically built plugins, e.g. for mapping party settings.
21 | The file name should be equal to the plugin identifier.
22 | To share it, create a QR code with the link to the file, and scan it with the
23 | phone from the "Settings → Plugins → (+) → the button at the top right".
24 |
25 | 4. If some of your devices do not support reading QR codes, or you're publishing
26 | plugins on a website intended to be used from a phone, then construct a plugin
27 | installation link. It looks like this:
28 |
29 | `https://plugins.every-door.app/i/plugin_id?url=https%3A%2F%2Fexample.com%2F...%2Fplugin_id.edp`
30 |
31 | The `plugin_id` in the base url should match the file name and the identifier
32 | from `plugin.yaml`, but it would also match against the plugin repository list.
33 | You can use `my` instead, like `/i/my?...`.
34 |
35 | The link can also have query parameters: `version` to [versionize plugins](metadata/index.md#versioning-plugins)
36 | (useful when you update a published plugin), `update=true` to force an
37 | update even when a newer version of the plugin has been installed.
38 |
39 | ## Troubleshooting
40 |
41 | If the installation fails, check the system log: press the button on screen,
42 | or find those in "Settings → About → System Log".
43 |
44 | To delete a plugin, open it in the settings panel, and tap "Delete".
45 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | hide: [toc]
3 | ---
4 | # Every Door { style="font-family: PT Serif Caption, serif; font-weight: bold; font-size: 3em; margin-bottom: 0;" }
5 |
6 | The best OpenStreetMap editor for POIs and entrances.
7 |
8 | ## Get The App
9 |
10 |
16 |
17 | ## Features
18 |
19 | * 100% OpenStreetMap editor with no dependencies on third-party endpoints.
20 | * See all the shops and amenities nearby, without geospatial displacement.
21 | * Engage the `check_date` tag to confirm shops' existence.
22 | * Edit buildings and add entrances with apartment numbers.
23 | * Map every manhole, bench, and street lamp in the micro-mapping mode.
24 | * Pre-load imagery tiles and work offline.
25 |
26 |
27 |
28 |
29 |
30 | ## Resources
31 |
32 | * [Source Code @GitHub](https://github.com/Zverik/every_door)
33 | * [Translations @Weblate](https://hosted.weblate.org/projects/every-door/app/)
34 | * [Telegram Group (rus)](https://t.me/everydoor_ru)
35 | * [Privacy Policy](privacy_policy.md)
36 |
37 | ## Stay Connected
38 |
39 | * [Mastodon](https://en.osm.town/@everydoor)
40 | * [Twitter](https://twitter.com/EveryDoorOSM)
41 |
42 | Ilja Zverev
43 | Tallinn, Estonia
44 |
45 | [ilya@zverev.info](mailto:ilya@zverev.info)
46 |
47 | ## Please Help!
48 |
49 | This page looks bare-bones. I would really love to improve its design. Please mail
50 | me or create a [pull request](https://github.com/Zverik/everydoor-website)!
51 |
--------------------------------------------------------------------------------
/assets/images/icon-cogs.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/js/flipster-custom.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function() {
2 |
3 | /* jQuery Flipster plugin */
4 | /* Ref: https://github.com/drien/jquery-flipster/ */
5 | $('#flipster-carousel').flipster({
6 | itemContainer: '.flip-items',
7 | // [string|object]
8 | // Selector for the container of the flippin' items.
9 |
10 | itemSelector: '.flip-item',
11 | // [string|object]
12 | // Selector for children of `itemContainer` to flip
13 |
14 | start: 'center',
15 | // ['center'|number]
16 | // Zero based index of the starting item, or use 'center' to start in the middle
17 |
18 | fadeIn: 400,
19 | // [milliseconds]
20 | // Speed of the fade in animation after items have been setup
21 |
22 | loop: true,
23 | // [true|false]
24 | // Loop around when the start or end is reached
25 |
26 | autoplay: 6000,
27 | // [false|milliseconds]
28 | // If a positive number, Flipster will automatically advance to next item after that number of milliseconds
29 |
30 | pauseOnHover: true,
31 | // [true|false]
32 | // If true, autoplay advancement will pause when Flipster is hovered
33 |
34 | style: 'coverflow',
35 | // [coverflow|carousel|flat|...]
36 | // Adds a class (e.g. flipster--coverflow) to the flipster element to switch between display styles
37 | // Create your own theme in CSS and use this setting to have Flipster add the custom class
38 |
39 | spacing: -0.5,
40 | // [number]
41 | // Space between items relative to each item's width. 0 for no spacing, negative values to overlap
42 |
43 | click: true,
44 | // [true|false]
45 | // Clicking an item switches to that item
46 |
47 | keyboard: true,
48 | // [true|false]
49 | // Enable left/right arrow navigation
50 |
51 | scrollwheel: false,
52 | // [true|false]
53 | // Enable mousewheel/trackpad navigation; up/left = previous, down/right = next
54 |
55 | touch: true,
56 | // [true|false]
57 | // Enable swipe navigation for touch devices
58 |
59 | nav: false,
60 | // [true|false|'before'|'after']
61 | // If not false, Flipster will build an unordered list of the items
62 | // Values true or 'before' will insert the navigation before the items, 'after' will append the navigation after the items
63 |
64 | buttons: true,
65 | // [true|false|'custom']
66 | // If true, Flipster will insert Previous / Next buttons with SVG arrows
67 | // If 'custom', Flipster will not insert the arrows and will instead use the values of `buttonPrev` and `buttonNext`
68 |
69 | buttonPrev: 'Previous',
70 | // [text|html]
71 | // Changes the text for the Previous button
72 |
73 | buttonNext: 'Next',
74 | // [text|html]
75 | // Changes the text for the Next button
76 |
77 | onItemSwitch: false
78 | // [function]
79 | // Callback function when items are switched
80 | // Arguments received: [currentItem, previousItem]
81 | });
82 |
83 |
84 |
85 | });
--------------------------------------------------------------------------------
/ru/faq.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Every Door ЧаВО
3 | ---
4 | # Вопросы и ответы
5 |
6 | ## Почему карта такая маленькая?
7 |
8 | Потому что не она главная. На карте нужно проверить только
9 | своё местоположение, и подвинуть, если оно не там. Смотрите
10 | на список заведений внизу, упорядоченный по расстоянию от вас.
11 |
12 | Карта становится больше, когда вы правите заведения вдали
13 | от себя. Хотя приложение сделано для правки того, что вы
14 | видите своими глазами.
15 |
16 | ## Для чего галочки в списке?
17 |
18 | Это отметка, что заведение проверено. Добавляет к объекту
19 | тег `check_date` с текущей датой.
20 |
21 | Суть галочки в том, что ты, скажем, обошёл полгорода в первый раз.
22 | А потом вернулся туда через месяц, решил снова обойти.
23 | И тебе нужно как-то отметить, что ты проверил, что заведение
24 | на месте, но ничего не изменилось. Это и есть галочка:
25 | нажал — и пошёл дальше.
26 |
27 | Галочка держится две недели после проверки. Потом можно будет
28 | обойти заведения заново.
29 |
30 | ## Как добавить подъезд?
31 |
32 | Внизу экрана есть кнопки для переключения режимов: микромаппинг,
33 | заведения, подъезды.
34 |
35 | В режиме подъездов нажмите или перетяните кнопку с дверью
36 | снизу на карту.
37 |
38 | ## Как ввести буквы в номер квартиры?
39 |
40 | Если в вашей цифровой клавиатуре нет переключателя на полную
41 | клавиатуру с буквами, загляните в настройки приложения.
42 | Они под кнопкой слева вверху на главном экране. Включите там
43 | «заменить цифровую клавиатуру».
44 |
45 | ## Этажи "3" и "/3" — одно и то же?
46 |
47 | Нет. В первом заполнен тег `addr:floor=3`. Это этаж, как он
48 | написан в навигации и используется в жизни. Во втором этот тег
49 | пуст, но есть `level=3`. Это число — номер этажа в последовательной
50 | нумерации от нуля до `building:levels - 1`. То есть, в трёхэтажном
51 | доме `addr:floor` зависит от страны, а `level` всегда 0, 1 или 2.
52 |
53 | Вот как условное обозначение в редакторе зависит от этих тегов:
54 |
55 | * `2`: `addr:floor=2` и непустой `level=*`.
56 | * `4/`: `addr:floor=4`, тег `level` отсутствует.
57 | * `/1`: `level=1`, тег `addr:floor` отсутствует.
58 | * `1/0`: `addr:floor=1` + `level=0` (и рядом есть объект с тем же
59 | `addr:floor`, но другим `level`, или наоборот).
60 |
61 | ## Как отменить правку?
62 |
63 | В списке правок, доступном из настроек, просто смахните нужную строчку влево.
64 |
65 | ## Как поменять тип заведения?
66 |
67 | Нажмите на заголовок редактора, где написан этот тип.
68 |
69 | ## Любые вопросы по тегам
70 |
71 | Почему объект отсутствует в редакторе? Когда выводятся белые точки
72 | на объектах в режиме микромаппинга? Как сортируются объекты?
73 |
74 | Ответы на все эти вопросы в
75 | [good\_tags.dart](https://github.com/Zverik/every_door/blob/main/lib/helpers/good_tags.dart).
76 | Вот на что обратить внимание:
77 |
78 | * Порядок определения главного тега — список `kMainKeys`.
79 | * Какие объекты загружаются — функция `isGoodTags`.
80 | * Что считается заведением — функция `isAmenityTags`.
81 | * Какие точки прилепляются к линиям, и каким — функция `detectSnap`.
82 | * Когда объект микромаппинга неполон — функция `needsMoreInfo`.
83 |
84 | ## Как поправить или перевести поля в заготовке?
85 |
86 | Редактор использует заготовки из редактора iD. Чтобы их изменить,
87 | сделайте пул-реквест в [этот репозиторий](https://github.com/openstreetmap/id-tagging-schema).
88 |
89 | Переводят заготовки [на Transifex](https://www.transifex.com/openstreetmap/id-editor/translate/#ru/presets/).
90 |
91 | Чтобы перевести варианты значений, нужно сначала сделать пул-реквест
92 | в репозиторий заготовок, добавив нужные варианты,
93 | [как тут](https://github.com/openstreetmap/id-tagging-schema/blob/main/data/fields/camera/type.json).
94 | Потом, когда перевод перезальют на transifex, появятся строки для перевода.
95 | [Как здесь](https://www.transifex.com/openstreetmap/id-editor/translate/#ru/presets/101711314?q=key%3Apresets.fields.camera%2Ftype).
96 |
--------------------------------------------------------------------------------
/docs/guide/preface.md:
--------------------------------------------------------------------------------
1 | # Surveying for OpenStreetMap
2 |
3 | To use Every Door efficiently and understand its design choices, you must first
4 | learn what OpenStreetMap is, how data for it is collected, and why the app
5 | was created in the first place. For that, we start with a bit of background.
6 |
7 | ## OpenStreetMap Basics
8 |
9 | You must know this already: OSM has a very simple [data model](https://wiki.openstreetmap.org/wiki/Elements),
10 | which consists of
11 | tags, nodes, ways, and relations. Every entity can contain some number of any
12 | previous entities: nodes have tags, ways have tags and nodes, and so on. Also
13 | only nodes have any geometry, and areas can be represented as closed ways or
14 | multipolygon relations.
15 |
16 | The model simplicity leads to utter complexity of both editing the data and using it.
17 | Loading it into a conventional data store means downloading an extract and
18 | processing it with [Osmium](https://osmcode.org/) in some form. Clicking
19 | through a geometry is simple — but choosing a correct tag is a pain. What suits better,
20 | `natural=wood` or `landuse=forest`? Don't answer, it's a running joke.
21 |
22 | In most editors the latter problem is circumvented with _presets_: a huge
23 | mapping of real-world entities to OSM tags, each with a list of attribute tags.
24 | It makes decisions simpler, but still does not solve all the issues: for
25 | example, an object can be multiple things at once in OSM (like a fence and
26 | a school ground), or have no meaning without a secondary tag (`amenity=recycling`
27 | comes to mind).
28 |
29 | ### Points of Interest
30 |
31 | All those issues become more apparent when you are adding a shop or a waste basket.
32 | I'd recommend [watching this talk](https://www.youtube.com/watch?v=WQwO-vbGre0)
33 | on the subject. To summarize it:
34 |
35 | * Venues can be represented with points and polygons. Sometimes both.
36 | * Finding a correct tag is often hard. There are many duplicates and nuances.
37 | * Some shops have multiple types, while OSM allows for one.
38 | * Even seemingly straightforward attributes can have subjective values.
39 | * Addresses go on everything, not standardized, and often missing.
40 | * Coverage is patchy, freshness unknown, mapping is hard.
41 |
42 | In general, points of interest are the hardest thing to map, because there
43 | are no good third-party sources. You have to go around and collect the data
44 | yourself. And when you're back, you can spend hours on adding objects to the map,
45 | and the result will be indistinguishable from before. Truly, tracing roads
46 | and forests is much more gratifying — albeit possible to automate.
47 |
48 | That's one reason mapping points of interest is important to OpenStreetMap, and
49 | why this app in particular appeared. Another, there hasn't been any good ways
50 | to keep the map fresh and collect data at speed.
51 |
52 | ## Sourcing the Data
53 |
54 | Every Door comes from a decade of experiments with optimizing data collection.
55 | Which is good, because it makes it the best in class, but also bad, because
56 | high efficiency means steep learning curve. To understand those decisions, we
57 | need to look back.
58 |
59 | ### Before Times
60 |
61 | We used GPS loggers, pen and paper, and photo cameras. You walk around, take photos
62 | or record all the shops or trees you see. When at home, you open JOSM, add a GPX
63 | track from your logger, georeference pictures from the camera, put your walking
64 | papers nearby, and start adding collected features one by one.
65 |
66 | If it sounds tedious and super slow, well, it was. But the sense of power it brought
67 | made us going.
68 |
69 | _TODO_
70 |
71 | ### Apps
72 |
73 | Editing map on a phone rids you of extra work when you get home. You just add everything
74 | you see on the go, and then forget about it. Alas, mobile phones have different
75 | issues: mainly, from the small screen size and imprecise controls.
76 |
77 | _TODO_
78 |
79 | ## Unsolved Problems
80 |
--------------------------------------------------------------------------------
/fr/faq.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Every Door FAQ
3 | ---
4 | # Foire Aux Questions
5 |
6 | ## Pourquoi la carte est si petite ?
7 |
8 | Parce que ce n’est pas le but. La carte sert uniquement à vous positionner et afficher une liste des points d’intérêts à proximité triés en fonction de leur distance par rapport à votre position.
9 |
10 | La carte est agrandie lors de l’édition de points d’intérêts éloignés de votre position.
11 | Bien que l’application est avant tout destinée à vous aider à éditer ce que vous voyez de vous même.
12 |
13 | ## À quoi servent les marqueurs de validation ?
14 |
15 | Ces marqueurs indiquent que les données ont été confirmées, ils ajoutent la clé `check_date` avec la date actuelle.
16 |
17 | L’idée de ces marqueurs est que, dans l’exemple où vous auriez répertorié la moitié de la ville sur un premier trajet, qu’il vous soit possible de revenir sur ces points quelques mois plus tard et d’indiquer que rien n’a changé. Un marqueur et c’est validé.
18 |
19 | Le marqueur reste affiché pour deux semaines, après quoi il sera de nouveau possible de les repointer.
20 |
21 | ## Pourquoi l’application est-elle en allemand ?
22 |
23 | Si vous souhaitez de l’anglais, essayez d’aller dans les paramètres du téléphone, section « Système » et « Langues ». Ajoutez l’anglais à la liste et redémarrez l’application.
24 |
25 | Un sélecteur de langue sera disponible dans une future version.
26 |
27 | ## Comment ajouter l’entrée d’un bâtiment ?
28 |
29 | En haut à droite, un bouton permet de basculer entre différent modes d’édition : points d’intérêts, micromapping et entrées.
30 |
31 | Dans le mode « Entrées », appuyez ou faites glisser l’icône de porte, dans le coin inférieur droit, vers la carte.
32 |
33 | ## Comment utiliser des lettres dans les numéros d’adresse ?
34 |
35 | Si votre clavier numérique ne peut pas basculer vers un clavier complet, vérifiez les paramètres de l’application. Appuyez sur le bouton du coin supérieur gauche où vous trouverez le « clavier numérique étendu ».
36 |
37 | ## Quelle est la différence entre les étages « 3 » et « /3 » ?
38 |
39 | Le premier correspond à l’attribut `addr:floor=3`, c’est l’étage comme indiqué lors de la navigation et généralement utilisé mais dépend de la localité, tandis que le second correspond à `level=3` selon le schéma `building:level` où le rez-de-chaussée est l’étage 0.
40 |
41 | Ainsi, les valeurs suivantes indiqueront :
42 |
43 | * `2` : `addr:floor=2` et `level=*` ;
44 | * `4/` : `addr:floor=4`, sans `level` ;
45 | * `/1` : `level=1`, sans `addr:floor` ;
46 | * `1/0` : `addr:floor=1` et `level=0`.
47 |
48 | ## Questions relatives aux attributs
49 |
50 | Pourquoi un élément est manquant dans l’éditeur ? Quand ces points blancs sont-ils affiché en mode Micromapping ? Comment sont triés les éléments ?
51 |
52 | Les réponses à toutes ces questions sont dans [good\_tags.dart](https://github.com/Zverik/every_door/blob/main/lib/helpers/good_tags.dart) dont les thèmes principaux :
53 |
54 | * L’ordre des attributs : list `kMainKeys` ;
55 | * Les éléments sont téléchargés : function `isGoodTags` ;
56 | * Ce qui est considéré comme un point d’intérêt : function `isAmenityTags` ;
57 | * Les points qui sont aimantés : function `detectSnap` ;
58 | * Quand un objet micro-cartographié est incomplet : function `needsMoreInfo`.
59 |
60 | ## Comment changer ou traduire les champs d’un préréglage ?
61 |
62 | L’éditeur est basé sur les préréglages de l’éditeur iD. Pour les modifier, allez sur [ce dépot](https://github.com/openstreetmap/id-tagging-schema).
63 |
64 | La traduction passe par [Transifex](https://www.transifex.com/openstreetmap/id-editor/translate/#ru/presets/).
65 |
66 | Pour traduire les valeurs, indiquez les options désirées au dépot comme dans [cet exemple](https://github.com/openstreetmap/id-tagging-schema/blob/main/data/fields/camera/type.json).
67 | Une fois la source mise à jour sur Transifex, elle sera disponible pour traduction, [comme ici](https://www.transifex.com/openstreetmap/id-editor/translate/#ru/presets/101711314?q=key%3Apresets.fields.camera%2Ftype).
68 |
--------------------------------------------------------------------------------
/docs/guide/faq.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Every Door FAQ
3 | ---
4 | # Frequently Asked Questions
5 |
6 | ## Why the map is so tiny?
7 |
8 | Because it's not the point. You only check your positioning on the map,
9 | and pan it to adjust. Watch the amenity list below, sorted by distance
10 | from you.
11 |
12 | The map gets bigger when you edit amenities far from your location.
13 | Although the app was made to edit things you see with your eyes.
14 |
15 | ## What are the checkmarks for?
16 |
17 | These are marks that amenity data was confirmed. They add the
18 | `check_date` tag with the current date.
19 |
20 | The idea behind the checkmarks is that, say, you surveyed half
21 | the city the first time. Then after a month you came back and
22 | went to survey again. You need to somehow mark that you see
23 | the amenity, but nothing has changed about it. That's the checkmark:
24 | you tap it and continue.
25 |
26 | The mark stays checked for two weeks. After that you may survey
27 | the amenities again.
28 |
29 | ## How to add a building entrance?
30 |
31 | At the top right there's a button for switching editing modes.
32 | It changes modes between amenities, micromapping, and entrances.
33 |
34 | In the entrance mode, tap or drag the door button in the bottom
35 | right corner onto the map.
36 |
37 | ## Can I type letters into an apartment number?
38 |
39 | If your numeric keyboard cannot be switched to a full one, check
40 | the app settings. They are behind the button at the top left corner.
41 | Switch on the "extended numeric keyboard" there.
42 |
43 | ## Are floors "3" and "/3" the same?
44 |
45 | No. The first one has `addr:floor=3` tag filled. That's the floor
46 | as it is printed on navigation and commonly used. The second one
47 | does not have this tag, but has `level=3`. That number is a sequential
48 | floor number from zero to `building:levels - 1`. That is, in a
49 | three-storey building `addr:floor` value depends on a country,
50 | but `level` is always 0, 1, or 2.
51 |
52 | Here is how the notation in the editor related to these tags:
53 |
54 | * `2`: `addr:floor=2` and non-empty `level=*`.
55 | * `4/`: `addr:floor=4`, but there's no `level` tag.
56 | * `/1`: `level=1`, but there's no `addr:floor` tag.
57 | * `1/0`: `addr:floor=1` + `level=0` (and there's an object nearby
58 | with the same `addr:floor`, but different `level`, or vice-versa).
59 |
60 | ## How to undo an edit?
61 |
62 | In the changes list available from Settings, just swipe the item to the left.
63 |
64 | ## How to change an amenity type?
65 |
66 | Tap on the editor title, where the type is written.
67 |
68 | ## All tagging questions
69 |
70 | Why an object is missing in the editor? When these white dots are
71 | displayed in the micromapping mode? How objects are sorted?
72 |
73 | Answers to all these questions are in
74 | [element\_kind\_std.dart](https://github.com/Zverik/every_door/blob/main/lib/helpers/tags/element_kind_std.dart).
75 | Here's what you can look at:
76 |
77 | * Which objects are downloaded — class `_EverythingKind`.
78 | * What is considered an amenity — class `_AmenityKind`.
79 | * When a micromapping object is incomplete — class `_NeedsMoreInfo`.
80 | * Which points are snapped to what ways — function `detectSnap` in [snap\_tags.dart](https://github.com/Zverik/every_door/blob/main/lib/helpers/tags/snap_tags.dart).
81 | * The key order for the main tag — list `kMainKeys` in [main\_keys.dart](https://github.com/Zverik/every_door/blob/main/lib/helpers/tags/main_key.dart).
82 |
83 | ## How to change or translate preset fields?
84 |
85 | The editor relies on iD editor presets. To modify these, submit
86 | a pull request to [this repo](https://github.com/openstreetmap/id-tagging-schema).
87 |
88 | The presets are translated at [Transifex](https://www.transifex.com/openstreetmap/id-editor/translate/#ru/presets/).
89 |
90 | To translate value options, first make a pull request to the repo
91 | adding desired options, [like here](https://github.com/openstreetmap/id-tagging-schema/blob/main/data/fields/camera/type.json).
92 | Then, when the translation source on Transifex is updated, there
93 | will be strings to translate.
94 | [Like here](https://www.transifex.com/openstreetmap/id-editor/translate/#ru/presets/101711314?q=key%3Apresets.fields.camera%2Ftype).
95 |
--------------------------------------------------------------------------------
/docs/develop/build.md:
--------------------------------------------------------------------------------
1 | # Development Environment
2 |
3 | ## Installing Everything
4 |
5 | Every Door is a Flutter app, and I cannot beat the conscise step-by-step
6 | [setting up walkthrough](https://docs.flutter.dev/get-started/install) on the Flutter
7 | website. Please follow it through.
8 |
9 | My IDE of choice is the standard Android Studio: it includes an Android emulator
10 | and all tools to build and package Android apps. On macOS it would make sense
11 | to use XCode instead. There's no point in downloading VSCode just to install Flutter:
12 | the alternative is just unzipping a file and adding the result to `PATH`.
13 |
14 | For small changes I use Vim with
15 | [YouCompleteMe](https://github.com/ycm-core/YouCompleteMe) for LSP
16 | ([see here](https://github.com/ycm-core/lsp-examples))
17 | and [dart-vim-plugin](https://github.com/dart-lang/dart-vim-plugin) for formatting.
18 | Note that Dart LSP is huge and slow to load, so there isn't much memory benefit from
19 | using Vim over other IDEs.
20 |
21 | Also keep in mind when installing Flutter SDK that despite it being 2025, it is still
22 | risky using directories with spaces in them.
23 |
24 | ## Building Every Door
25 |
26 | First, clone the repository:
27 |
28 | git clone https://github.com/Zverik/every_door.git
29 |
30 | You can add `--recursive` if you plan on testing vendored Flutter SDK, but there's generally
31 | no need.
32 |
33 | Then you would need a preset database asset. For releases, it is
34 | [downloaded](https://textual.ru/presets.db). Put it in the `assets/` directory.
35 | For developing, the proper way would be to download
36 | [taginfo-db.db](https://taginfo.openstreetmap.org/download) and unpack it somewhere (it's ~9 GB).
37 | Then enter the `tools` directory and run:
38 |
39 | ./update.sh /path/to/taginfo.db
40 |
41 | Now you need to create an language file `lib/l10n/app_zh.arb` with no content (`{}`),
42 | because Flutter i18n has problems with absent parent language packs:
43 |
44 | echo '{}' > lib/l10n/app_zh.arb
45 |
46 | And you're all set! Open the project in your IDE and run it, or build it from console:
47 |
48 | ```sh
49 | flutter pub get
50 | dart run build_runner build
51 | flutter build
52 | flutter run # if you have a phone connected or an emulator running
53 | ```
54 |
55 | The `build_runner` step creates a `lib/commit_info.g.dart` file with a current git commit hash.
56 | You do not need to re-run it unless you're publishing an apk for others to test, and want them
57 | to copy the full version (which is located on the About pane).
58 |
59 | ## Submitting Changes
60 |
61 | _Before_ starting work on a large feature, please consult with [design principles](design.md),
62 | or maybe [contact Ilya](mailto:ilya@zverev.info). It would be a pity to leave a big pull request
63 | rejected because of a disagreement. Of course that hasn't happened yet, and we strive to
64 | accept all contributions.
65 |
66 | If you're looking for a task to work on, check [the roadmap](https://github.com/users/Zverik/projects/1).
67 | Anything on it is a wanted feature or a bug fix. An assigned milestone means higher priority.
68 |
69 | Now, creating a pull request is pretty easy, you don't need to collect much data for it,
70 | unlike a bug report. If the change is visual, a screenshot or a video would be appreciated.
71 | Please keep changes to a minimum: e.g. don't reformat the entire code base. Note that we
72 | use the standard default Dart format rules.
73 |
74 | The one rule to have your changes merged is, **please respond to comments** and update
75 | your code accordingly. We would like you to do all the needed changes, not do that ourselves.
76 | Please rebase your branch onto `main` yourself if there are possible merge conflicts.
77 | Unless there are conceptual issues with a pull request, and if you keep replying, your
78 | work won't get lost, and you will be mentioned in a change log.
79 |
80 | It's possible maintaner(s) might forget about your pull requests. Please wait a few days
81 | and post a comment to your pull request to remind them. Every Door is a hobby project,
82 | and maintainers might be busy with their jobs or family. Help in reviewing other pull
83 | requests is appreciated!
84 |
85 | Every Door is licensed under the ISC License. You should make every effort to ensure
86 | you only submit patches which are unencumbered by conflicting intellectual property rights.
87 |
--------------------------------------------------------------------------------
/en/faq.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Every Door FAQ
3 | ---
4 | # Frequently Asked Questions
5 |
6 | ## Why the map is so tiny?
7 |
8 | Because it's not the point. You only check your positioning on the map,
9 | and pan it to adjust. Watch the amenity list below, sorted by distance
10 | from you.
11 |
12 | The map gets bigger when you edit amenities far from your location.
13 | Although the app was made to edit things you see with your eyes.
14 |
15 | ## What are the checkmarks for?
16 |
17 | These are marks that amenity data was confirmed. They add the
18 | `check_date` tag with the current date.
19 |
20 | The idea behind the checkmarks is that, say, you surveyed half
21 | the city the first time. Then after a month you came back and
22 | went to survey again. You need to somehow mark that you see
23 | the amenity, but nothing has changed about it. That's the checkmark:
24 | you tap it and continue.
25 |
26 | The mark stays checked for two weeks. After that you may survey
27 | the amenities again.
28 |
29 | ## Why the app is in German?
30 |
31 | If you expect English, try going to the phone Settings. There find
32 | "System", and "Languages". Try adding the English language to the list
33 | and restarting the editor.
34 |
35 | There'll be a language switcher in the app later.
36 |
37 | ## How to add a building entrance?
38 |
39 | At the top right there's a button for switching editing modes.
40 | It changes modes between amenities, micromapping, and entrances.
41 |
42 | In the entrance mode, tap or drag the door button in the bottom
43 | right corner onto the map.
44 |
45 | ## Can I type letters into an apartment number?
46 |
47 | If your numeric keyboard cannot be switched to a full one, check
48 | the app settings. They are behind the button at the top left corner.
49 | Switch on the "extended numeric keyboard" there.
50 |
51 | ## Are floors "3" and "/3" the same?
52 |
53 | No. The first one has `addr:floor=3` tag filled. That's the floor
54 | as it is printed on navigation and commonly used. The second one
55 | does not have this tag, but has `level=3`. That number is a sequential
56 | floor number from zero to `building:levels - 1`. That is, in a
57 | three-storey building `addr:floor` value depends on a country,
58 | but `level` is always 0, 1, or 2.
59 |
60 | Here is how the notation in the editor related to these tags:
61 |
62 | * `2`: `addr:floor=2` and non-empty `level=*`.
63 | * `4/`: `addr:floor=4`, but there's no `level` tag.
64 | * `/1`: `level=1`, but there's no `addr:floor` tag.
65 | * `1/0`: `addr:floor=1` + `level=0` (and there's an object nearby
66 | with the same `addr:floor`, but different `level`, or vice-versa).
67 |
68 | ## How to undo an edit?
69 |
70 | In the changes list available from Settings, just swipe the item to the left.
71 |
72 | ## How to change an amenity type?
73 |
74 | Tap on the editor title, where the type is written.
75 |
76 | ## All tagging questions
77 |
78 | Why an object is missing in the editor? When these white dots are
79 | displayed in the micromapping mode? How objects are sorted?
80 |
81 | Answers to all these questions are in
82 | [good\_tags.dart](https://github.com/Zverik/every_door/blob/main/lib/helpers/good_tags.dart).
83 | Here's what you can look at:
84 |
85 | * The key order for the main tag — list `kMainKeys`.
86 | * Which objects are downloaded — function `isGoodTags`.
87 | * What is considered an amenity — function `isAmenityTags`.
88 | * Which points are snapped to what ways — function `detectSnap`.
89 | * When a micromapping object is incomplete — function `needsMoreInfo`.
90 |
91 | ## How to change or translate preset fields?
92 |
93 | The editor relies on iD editor presets. To modify these, submit
94 | a pull request to [this repo](https://github.com/openstreetmap/id-tagging-schema).
95 |
96 | The presets are translated at [Transifex](https://www.transifex.com/openstreetmap/id-editor/translate/#ru/presets/).
97 |
98 | To translate value options, first make a pull request to the repo
99 | adding desired options, [like here](https://github.com/openstreetmap/id-tagging-schema/blob/main/data/fields/camera/type.json).
100 | Then, when the translation source on Transifex is updated, there
101 | will be strings to translate.
102 | [Like here](https://www.transifex.com/openstreetmap/id-editor/translate/#ru/presets/101711314?q=key%3Apresets.fields.camera%2Ftype).
103 |
--------------------------------------------------------------------------------
/docs/plugins/metadata/modes.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Overriding Modes
3 | ---
4 | Modes are listed in the `modes` entry as maps: keys are mode identifiers, and values are maps of key-value mode settings.
5 |
6 | There are four mode types which are also the names of the four pre-defined modes: `micro`, `amenity`, `entrances`, `notes`. When your mode identifier is one of those, it doesn't add a new mode, but alters parameters of an existing mode.
7 |
8 | You can hide an existing mode by adding `hide: true` option. Like this:
9 |
10 | ```yaml
11 | modes:
12 | entrances:
13 | hide: true
14 | notes:
15 | hide: true
16 | ```
17 |
18 | For a new mode, you should specify `icon` and `iconActive` with a mode icon. The second one is optional.
19 |
20 | Note that not all parameters that you specify for a new mode can be adjusted for an existing mode.
21 |
22 | ## Micromapping
23 |
24 | Things you can adjust:
25 |
26 | * `kinds` (or `kind`, a string or a list of strings): objects that are edited in this mode. `micro` by default.
27 | * `otherKinds` (or `otherKind`): objects that are shown as black dots on the map. `amenity` by default.
28 | * `defaultPresets` (a list of strings): preset names for the list appearing after you tap the (+) button.
29 | * `markers`: a map of preset name → marker definition, for overriding colors and icons in the legend and on the map. The definition can be either a `icon: icon_name` (see above), or a `color: color_name`.
30 | * We use [this library](https://pub.dev/packages/material_color_names) to resolve color names. Also several `ed`-prefixed colors are available, for those pre-built into the micromapping mode. For example, `edRed` and `edTeal`.
31 | * `iconsInLegend`: when assigning an icon to a preset, it might be obvious from its appearance on the map. So when you do it at scale, the legend might become redundant. Setting this flag to `false` removes iconized items from the legend.
32 |
33 | ## Amenity
34 |
35 | This mode is technically similar to the micromapping mode, hence some settings are similar:
36 |
37 | * `kinds` (or `kind`, a string or a list of strings): objects that are edited in this mode. `amenity` by default.
38 | * `otherKinds` (or `otherKind`): objects that are shown as black dots on the map. `micro` by default (yes, the opposite of the Micromapping set up).
39 | * `defaultPresets` (a list of strings): preset names for the list appearing after you tap the (+) button.
40 |
41 | But there are new ones:
42 |
43 | * `checkIntervals`: a mapping of day intervals for various element kinds: how often one could return and confirm the amenity by pressing a ✓ checkmark in the tile. By default it has two entries: `structure: 360` and `amenity: 60`. The latter is a catch-all, it's not exactly matched against the `amenity` kind.
44 |
45 | Currently you cannot create new instances of this mode.
46 |
47 | ## Entrances
48 |
49 | This mode can be duplicated. Actually, it cannot be modified at the moment, since there are no replaceable attributes, so copying is the only mode of operation.
50 |
51 | Fields for a new mode:
52 |
53 | * `kinds`: list of element kinds this mode supports.
54 | * `primary`: a mapping for setting up the primary type button (bottom right for the right-hand operation):
55 | * `preset`: a preset name that's the editor is open with.
56 | * `icon`: what's drawn on the button.
57 | * `tooltip`: a tooltip for the icon.
58 | * `adjustZoom`: if different from 0.0, when you start dragging the button onto the map, it temporarily changes zoom level inwards. For example, the default entrances button has this set to 0.7.
59 | * `secondary`: the same for the second button.
60 | * `markers`: a mapping for element kind → representation definition. Each one can have those keys:
61 | * `requiredKeys`: list of tag keys that need to be non-empty in order for the object to be considered fully surveyed. For example, a tree could have `[leaf_type, leaf_cycle]`.
62 | * `icon`: whether to draw an icon here. Add `iconPartial` to notice missing keys.
63 | * `label`: a template to print on the marker, e.g. `{capacity}` for bicycle parking. Keys should be enclosed in figure quotes.
64 | * If nothing is specified, a round marker would be used, filled yellow for "complete" and white otherwise.
65 |
66 | ## Notes
67 |
68 | Currently cannot be customized much, and because of this, cannot be duplicated. You can only change one property of the `notes` mode:
69 |
70 | * `locked`: whether the drawing is locked when you open the mode screen. Note that it changes the state at the moment of plugin loading, but does not persist when the app is active. Hence it affects only the initial state when the app is open.
71 |
--------------------------------------------------------------------------------
/docs/develop/bugs.md:
--------------------------------------------------------------------------------
1 | # Bugs and Wishes
2 |
3 | Every Door issues are collected and processed [on Github](https://github.com/Zverik/every_door/issues).
4 | In order to submit or comment a report, you need to register and login. Just press "New Issue" and
5 | fill in the form.
6 |
7 | Mind the application part you're reporting about:
8 |
9 | * If it's about an object type or fields on the editing panel, that is most likely about presets.
10 | See the [presets page](presets.md) about contributing.
11 | * If something is wrong with a map layer underneath markers, you mind need to contact
12 | [OSM-Carto](https://github.com/gravitystorm/openstreetmap-carto/) map layer developers.
13 | * If translations are incorrect, you most likely know how to improve them.
14 | [This guide](translate.md) will help you.
15 |
16 | Before reporting, first open Settings (the three-line button at the top left) → About Every Door.
17 | Make sure the version is the latest one available in app stores for your platform.
18 |
19 | Also, try disabling all plugins (Settings → Plugins). If it helps, please
20 | [report a plugin issue](#plugin-issues).
21 |
22 | ## Best Practices
23 |
24 | When reporting an issue, please provide as much information as possible. It would help
25 | if you include:
26 |
27 | * Every Door version, platform, and from where you got the app.
28 | * What you expected, and what you got instead. Possibly with reasons for your expectations.
29 | * Relevant parts, or an entire system log, available in Settings → About → System Log.
30 | * A screenshot or two.
31 |
32 | Please do not be intimidated with the list: often the bug is pretty straighforward and
33 | does not need many details to be triangulated. But the more details developers get,
34 | the better.
35 |
36 | One important thing is not to report multiple issues in a single ticket. Even if they are
37 | tiny. This helps developers be productive and mentally healthy. Opening multiple tickets
38 | is fine, please do not lump them into a single one.
39 |
40 | ## Asking for Features
41 |
42 | Mapping varies from country to country, and it is entirely possible Every Door does not
43 | have a feature that is important for surveyors somewhere. Feature requests are welcome!
44 |
45 | With that, please take note of [design principles](design.md). Every Door is not a
46 | general-purpose editor, and it cannot be everything. We have Vespucci and Go Map for that.
47 | So please be prepared to explain your request deeper, and for it to possibly be rejected.
48 | We do not close tickets without explanation, but sometimes it is impossible to cram
49 | everything into a single app.
50 |
51 | It is quite hard to determine how complex a feature is, so please be patient. Some
52 | features may take years to be implemented. The editor is developed in free time as a hobby
53 | project, so long development cycles are to be expected. Generally, the more fun or useful your
54 | request is, the eager developers are to work on it. Alas usefulness does not equate fun,
55 | and developers have a weird definition of "fun", so it's nearly impossible to predict. Sorry.
56 |
57 | You may try to create your feature [as a plugin](../plugins/index.md) instead.
58 |
59 | ## Road Map
60 |
61 | Every Door development is tracked in [this project](https://github.com/users/Zverik/projects/1).
62 | It's split by milestones (that is, versions). It is unlikely that your bug or a feature
63 | would get worked on if they are not assigned a milestone, or do not have any labels.
64 |
65 | The road map should not be taken as a firm list of features that will be released with
66 | the new app version. It mostly sorts tickets into priorities: which should be worked on
67 | now, and which could be postponed when maintainers have more time, or a developers comes
68 | eager to work on something.
69 |
70 | ## Issues With Websites
71 |
72 | This documentation website (which doubles as a landing page) is also maintained
73 | [on Github](https://github.com/Zverik/everydoor-website). You technically can create
74 | issues there. Maybe I have missed something important in guides, so I'd be happy
75 | to be reminded. Obviously you can create a pull request instead.
76 |
77 | The plugin repository source code [is here](https://github.com/Zverik/everydoor-plugin-repo).
78 | It is pretty raw, so bugs are to be expected. Please create issues in that repo,
79 | not in Every Door's. Code is also welcome.
80 |
81 | ## Plugin Issues
82 |
83 | Alas we cannot fix any issues with plugins, regardless of where they came from.
84 | One exception is when you are a plugin author, and the issue actually comes from Every Door.
85 | But that case has been outlined above.
86 |
87 | You have two options for reporting a plugin issue:
88 |
89 | 1. On the plugin repository page for that plugin, there might be a link to the plugin
90 | home page (which might be a Github repository). That page would direct you to means
91 | of reporting issues.
92 | 2. Since only OpenStreetMap users can upload plugins, the author's name there is actually
93 | an OSM display name, for which you can search. Try writing them a private message
94 | via the OSM website.
95 |
96 | As a last resort, you might try creating a topic on the OpenStreetMap community forum.
97 | Somebody might help you with your problem then. But alas no guarantees.
98 |
--------------------------------------------------------------------------------
/docs/plugins/metadata/imagery.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Custom Imagery
3 | ---
4 | Adding extra imagery layers is simple. In the `imagery` section, specify imagery layers as a map of maps:
5 |
6 | ```yaml
7 | imagery:
8 | IPR-orotofoto-last-tms:
9 | name: "Praha IPR latest orthophoto"
10 | url: "https://osm-{switch:a,b,c}.zby.cz/tiles_ipr_last.php/{zoom}/{x}/{y}.jpg"
11 | maxZoom: 20
12 | attribution: "IPR Praha; OSM CZ"
13 | turkuOrto:
14 | name: "City of Turku ortophoto"
15 | type: wms
16 | url: "https://opaskartta.turku.fi/TeklaOGCWeb/WMS.ashx?FORMAT=image/png&TRANSPARENT=TRUE&VERSION=1.1.1&SERVICE=WMS&REQUEST=GetMap&LAYERS=Ilmakuva 2021&STYLES=&SRS={proj}&WIDTH={width}&HEIGHT={height}&BBOX={bbox}"
17 | minZoom: 4
18 | maxZoom: 20
19 | attribution: "© Turun kaupunki"
20 | nommeTest:
21 | url: nomme-test.mbtiles
22 | maxZoom: 18
23 | ```
24 |
25 | Available keys are:
26 |
27 | * `url`: the only required key, layer URL templated the same as in the [editor layer index](https://github.com/osmlab/editor-layer-index/blob/gh-pages/CONTRIBUTING.md).
28 | * `name`: how the layer is listed on the imagery panel.
29 | * `type`: one of those:
30 | * `tms`: a regular tile service with URLs usually ending in `/{zoom}/{x}/{y}.png`
31 | * `wms`: a WMS service, like the `turkuOrto` in the example. This type is implied when the URL contains `SERVICE=WMS`.
32 | * `mbtiles`: a packaged [MBTiles](https://wiki.openstreetmap.org/wiki/MBTiles) file. This type is implied when the url (which should point to the file) ends with `.mbtiles`. Only raster tile packages are supported. A web URL would probably fail.
33 | * `vector`: a vector imagery layer, [see below](#vector-tiles).
34 | * `icon`: an icon to show on the imagery panel.
35 | * `attribution`: the string displayed on the screen when the layer is active.
36 | * `minZoom` and `maxZoom`: self-explanatory, integer numbers.
37 | * `wms4326`: a boolean field that should be true for WMS layers which support EPSG:4326, but not 3857.
38 | * `tileSize`: for TMS layers, defaults to 256.
39 | * `opacity`: layer opacity, between 0.0 and 1.0 (_since API 1.1_). Not all layer types support this. It is possible to have semi-transparent base tiles, and it would look weird.
40 | * `headers`: HTTP headers to add when requesting tiles.
41 | * `force`: when set to `true`, forces this imagery to be enabled when the plugin is installed, and on every app restart.
42 |
43 | To change the base map layer, use `base` for an imagery key. For example:
44 |
45 | ```yaml
46 | imagery:
47 | base:
48 | name: "Topo Map"
49 | url: ...
50 | ```
51 |
52 | ## Overlays
53 |
54 | Initially Every Door displays a single map layer: either OpenStreetMap-based for the base map, or an imagery layer. For thematic or directed mapping you might need to add more layers: for example, a semi-transparent tile layer with a heatmap, or display polygons for an area to confine the mapping effort.
55 |
56 | With plugins, it's pretty simple: add an `overlays` key with a list of layers in the same format.
57 |
58 | ```yaml
59 | overlays:
60 | - url: "https://tile.waymarkedtrails.org/cycling/{zoom}/{x}/{y}.png"
61 | maxZoom: 17
62 | - url: map.geojson
63 | ```
64 |
65 | With overlays, you can also use a `geojson` type. It is automatically inferred when the URL ends with a `.geojson` or a `.json`. URLs _are_ supported, but if the `url` value does not start with `http`, it is assumed to be a file inside the plugin.
66 |
67 | ## Vector Tiles
68 |
69 | _Since API 1.1_
70 |
71 | You can reference vector tiles, and even package them, saving on space compared to raster tiles.
72 | Those are added like regular imagery (anywhere: as a base layer, overlay, or even satellite),
73 | and require at least two keys:
74 |
75 | * `type: vector` is required.
76 | * `url`: name of the style JSON file, either an URL or a file name inside the plugin.
77 | * `name`, `icon`, `attribution`, `headers`: same as for raster layers.
78 | * `key`: API key, should be referenced in style URLs as `{key}`.
79 | * `fast`: if `true` (default), tiles are rendered into raster tiles, if `false` — they are
80 | re-rendered all the time, allowing for labels to be rotated, for example. As the name
81 | implies, non-fast mode is slow when there is a lot to draw.
82 |
83 | Here is an example adding two layers: one external for the base layer, and one packaged
84 | overlay:
85 |
86 | ```yaml
87 | imagery:
88 | base:
89 | name: Positron
90 | url: https://tiles.openfreemap.org/styles/positron
91 | type: vector
92 | attribution: OpenFreeMap
93 |
94 | overlays:
95 | - url: tallinn-overlay.json
96 | type: vector
97 | ```
98 |
99 | A style can reference both external and packaged tiles (as MBTiles). Sprites can also
100 | be packaged. Glyphs are not supported. Here is a sample style for the overlay mentioned above:
101 |
102 | ```json
103 | {
104 | "id": "tallinn-overlay",
105 | "sources": {
106 | "mbtiles": {
107 | "type": "vector",
108 | "tiles": ["greater_tallinn.mbtiles"],
109 | "minzoom": 1,
110 | "maxzoom": 14
111 | }
112 | },
113 | "sprite": "sprite",
114 | "layers": [...]
115 | }
116 | ```
117 |
118 | It references `greater_tallinn.mbtiles`, `sprite.json`, and `sprite.png` packaged into the
119 | root of the plugin archive.
120 |
--------------------------------------------------------------------------------
/docs/develop/design.md:
--------------------------------------------------------------------------------
1 | # Design Principles
2 |
3 | Every Door is a highly opinionated editor. Which means, it makes a lot of assumptions
4 | on behalf of the user, and pushes for a few optimized workflows. Core principles are
5 | described in the [readme](https://github.com/Zverik/every_door/blob/main/README.md#design):
6 |
7 | 1. ED displays and edits only tagged nodes and polygons represented with their centerpoints. No roads.
8 | 2. ED focuses on surveying: adding and detailing things that you can see around you. Not map maintenance.
9 | 3. Fewer buttons and menus: heuristic is preferable to a setting, and every button benefits the surveyor.
10 |
11 | Those principles can be circumvented with plugins, but they regulate the core experience.
12 |
13 | ## Data Complexity
14 |
15 | The first principle says: we're editing only points. There are multiple reasons for this:
16 |
17 | 1. Easier to process data and relations between objects.
18 | 2. The screen is small, editing geometry would complicate everything while being inferior to desktop editing (and we have Vespucci).
19 | 3. We can customize markers for every goal, not so much lines and polygons.
20 |
21 | Not having geometry restricts what you can do. For example, no drawing building contours or
22 | setting addresses to enclosed amenities. No detecting nearest streets and no painting
23 | downloaded OpenStreetMap data. All you have from OSM is a `OsmElement` object that has
24 | a point location. That's by design.
25 |
26 | If you think that to be limiting, consider also options for circumventing that. Like,
27 | instead of tracing streets (from imagery), you have a free-form drawing in the Notes mode,
28 | less consequential and hence more freeing.
29 |
30 | OpenStreetMap data model is unfortunately too complex in regard to object interdependencies.
31 | Adding `way` and `relation` processing would require support for splitting, adjusting,
32 | straightening, and also correctly processing restriction and route relations. As a result,
33 | we would have the second Vespucci or Go Map, and that's not the goal.
34 |
35 | Instead, we are focusing on representation and _hiding_ the data model. Users edit not nodes
36 | and tags, but buildings and shops. That's why we have multiple modes: while pedestrian crossings
37 | and building entrances are denoted by nodes in ways, they belong to totally different classes
38 | and need to be considered differently. We are thinking in terms, not what is possible to do,
39 | but what exactly and with which purpose a user wants to do something. And from that, we
40 | devise a user interface.
41 |
42 | ## Screen Estate
43 |
44 | Most phones are smaller than a computer screen. Actually, often we have a 5" or 6" rectangle.
45 | How do we fit an entire geospatial editor inside? QGIS has 74 buttons by default just on the
46 | toolbar. JOSM has ~40 on two, plus multiple side panels. iD looks lean: it only has 20 buttons
47 | and one permanent sidebar.
48 | That is too much context one has to keep in their head, and too much controls for a small screen.
49 |
50 | Every Door does not approach this as an excercise of hiding things behind other things.
51 | No infinitely deep menus like in OsmAnd, no buttons behind buttons like in OsmTracker.
52 | It's not a general purpose editor, and that allows us to shrink focus, to allow for less
53 | at any given time, and thus opening more of the screen to the task at hand.
54 |
55 | The third principle says, instead of a switch, just choose a state based on the context.
56 | Instead of a button, try finding an interaction that comes naturally and does not require
57 | an always-on control. If an interactive control is not used in ten minutes of hardcore mapping,
58 | it should go.
59 |
60 | That's why every new thing on the screen has to be properly thought out, maybe gaining extra
61 | functions and proving itself over months of field testing, before it goes into the app.
62 | It has to be useful for every user, not in specific circumstances. For everything else,
63 | we've got plugins.
64 |
65 | Note that some people use tablets or rotate their phones sideways. Are screen elements
66 | laid out effectively in the landscape orientation?
67 |
68 | ## Flow
69 |
70 | Surveying should bring a mapper joy. They are walking around and with each tap on the screen,
71 | they are improving the map. Nothing should stay in the way, so those sessions last
72 | longer. The mapper is feeling productive, and the app supports and encourages them
73 | to map more.
74 |
75 | That is the flow, and StreetComplete would be the best example of riding it. No hard
76 | choices, no mode switching, just an unending series of questions and answers. On the
77 | other end would be general purpose mobile editors with the constant "wait what did I just
78 | press" feeling.
79 |
80 | Every Door strives to be the most effective editor, allowing to collect one shop per minute,
81 | with all the details, or survey a village for addresses from a moving car. Nothing should
82 | stand in the way or slow the mapper down. Like:
83 |
84 | * an important field too far down the form.
85 | * a list of options too long to scroll.
86 | * the mode sometimes wrong, making you consider the state.
87 | * a common action inaccessible for non-obvious reason.
88 |
89 | Those are all issues I have encountered with Every Door, and we need to have less of those,
90 | not add to the list. Everything should be "at the fingertips", lowering the time
91 | a mapper stares at the screen in favor of walking around and finding more things to map.
92 |
--------------------------------------------------------------------------------
/docs/guide/releases/7.0.md:
--------------------------------------------------------------------------------
1 | # Every Door 7.0
2 |
3 | _Released on 24 September 2025_
4 |
5 | The main thing in this release is...
6 |
7 | ## Imagery Improvements
8 |
9 | ### Vector Tiles
10 |
11 | 
12 |
13 | To be fair, Every Door does not need vector map tiles. Its base mode of operation is,
14 | you look at amenities around you and find those in the list. Same way, other modes
15 | often work better with a satellite imagery.
16 |
17 | Except when you have no imagery. Or are inside a building, and mapping shops while staring
18 | at a roof is not fun. Or the GPS is failing, and you have to find your location manually.
19 | There can be many reasons why people resort to using [obsolete] OSM tiles while mapping,
20 | dealing with discrepancy between what's on the server, and what's on the phone. The main
21 | reason I was keeping in mind was offline work.
22 |
23 | For a rectangular area roughly 1×1 km you would need to pre-download ~1400 tiles,
24 | amounting to ~40 megabytes for a city. Same would take only 200 kilobytes with a vector
25 | tile, of which you would need just one (at zoom 14). Which is 200 times less data and
26 | thousand times less load on the server.
27 |
28 | This enables Every Door to work offline by pre-downloading tiles: each vector tile covers
29 | an 1×1 km area, which means, you need very few of them to map even a big rural area.
30 | And tile downloading limits won't pose an issue.
31 |
32 | Alas at the last moment I've decided to not make vector tiles the default. Since the
33 | MapLibre package is not yet of production quality, the app uses a slower library, and
34 | in both rendering options it provides, rendering was too slow, and had some weird artifacts.
35 | So to enable vector tiles, please open the plugins pane, and install the
36 | [Vector Base Map](https://plugins.every-door.app/vector_base) plugin. You can enable and
37 | disable it at any time, the cache and the plugin stay on your phone and available offline.
38 |
39 | ### Predictable Caching
40 |
41 | Another thing enabling offline work, is that you can know exactly when the cache is cleared,
42 | and download tiles for an area at will.
43 |
44 | 
45 |
46 | The new data management panel includes the old button for clearing the downloaded OSM data,
47 | but also adds multiple buttons for monitoring and clearing tile caches, for raster and vector
48 | tiles separately.
49 |
50 | Tap the "Download Tiles" button to open a map, on which you can select up to 20 rectangles
51 | (equal to zoom 15 tiles, ~0.2–1 km²), and bulk download OSM data, base map tiles, and satellite
52 | imagery tiles for those. Obviously data and vector tiles cover all the zoom levels, while
53 | raster tiles are downloaded up to zoom 18 (which makes it 85 tiles downloaded for each selected
54 | rectangle).
55 |
56 | Everything downloaded stays in a separate cache, so even when you pan and zoom the map too much,
57 | nothing explicitly requested will be silently deleted, like it happens with the regular
58 | tile cache.
59 |
60 | _Note:_ the bottom button for downloading tiles might be hidden by the phone UI on Android.
61 | This will be fixed in the 7.1 update soon.
62 |
63 | ### Compass Button
64 |
65 | { width="400" }
66 |
67 | Many people have asked for a button to reset the map rotation. Previously you have to
68 | long-press on the location button for that. Which was very obscure. Now we get
69 | a special compass button that both shows the rotation angle, and makes it zero
70 | when tapped.
71 |
72 | ### Building Contours
73 |
74 | 
75 |
76 | Having vector tiles helped fix one issue with adding entrances to buildings.
77 | To make them snap to correct location, you need to drag them as close to the building
78 | contour as possible. But with a satellite layer enabled, you have no idea where the
79 | contour in OSM is.
80 |
81 | Now when adding an entrance, you can see white outlines for every building on the screen.
82 | Those may have some artifacts on tile lines, but generally you can rely on those.
83 |
84 | The outlines are not added on the separate map panel that appears when you tap a button
85 | in the buildings mode. There you can switch a layer at will. It is only drawn on the map,
86 | so that when you _drag_ a button onto the map, you see where you are dragging it to.
87 |
88 | ## Other Things
89 |
90 | ### Preset Icons
91 |
92 | 
93 |
94 | The amazing [iD Tagging Schema](https://github.com/openstreetmap/id-tagging-schema)
95 | repository has an icon associated with most of the presets, and you must have seen
96 | the iD editor displaying those. Now you can enjoy the icons in Every Door!
97 |
98 | Obviously this works for plugins too, so you can have custom icons for your custom presets.
99 |
100 | ### Tap To Undo
101 |
102 | { width="400" }
103 |
104 | Finally instead of video I can just put a static image here. When you experiment with
105 | the editing, and need to revert some changes, it was not obvious how to do that.
106 | The "Pending Changes" panel had a tiny hint at the bottom, but few people have noticed it.
107 | Now I've decided to get rid of type icons, and instead add proper "delete" buttons
108 | to every change.
109 |
110 | Don't be afraid to delete a change accidentally: after you do, a panel appears giving
111 | you a change to restore the change.
112 |
113 | ## Thanks to NLNet
114 |
115 | This release was once again
116 | funded through the [NGI0 Commons Fund](https://nlnet.nl/commonsfund), a fund
117 | established by [NLnet](https://nlnet.nl) with financial support from the
118 | European Commission's [Next Generation Internet](https://ngi.eu) programme,
119 | under the aegis of
120 | [DG Communications Networks, Content and Technology](https://commission.europa.eu/about-european-commission/departments-and-executive-agencies/communications-networks-content-and-technology_en)
121 | under grant agreement No [101135429](https://cordis.europa.eu/project/id/101135429).
122 | Additional funding is made available by the
123 | [Swiss State Secretariat for Education, Research and Innovation](https://www.sbfi.admin.ch/sbfi/en/home.html) (SERI).
124 |
--------------------------------------------------------------------------------
/docs/plugins/metadata/index.md:
--------------------------------------------------------------------------------
1 | # Plugin Metadata
2 |
3 | A plugin is a zip-archive with an `edp` extension, which includes a `plugin.yaml` file
4 | inside at the top level. This section explains how to write it.
5 |
6 | The `plugin.yaml` file is a simple key-value dictionary in YAML format.
7 | There are some top-level keys, like a plugin name, and sections relating to
8 | various configurable subsystems.
9 |
10 | Top level keys are:
11 |
12 | * `id`: the plugin identifier. Should be different from other identifiers (otherwise this plugin
13 | would replace another with the same id), and consist of latin characters, numbers, dashes,
14 | and underscores. This is the only required key.
15 | * `name`: plugin name. Can be translated (see below).
16 | * `version`: numeric version (see below).
17 | * `api`: supported API versions: either a list of two versions (minimum and maximum, exclusive):
18 | e.g. `[1.1, 3.0]` supports 2.1, but doesn't support 3.0; or a single version, in which case
19 | the next major version won't be supported.
20 | * `description`: long-form description of what this plugin does. Split paragraphs with double newlines.
21 | * `author`: who wrote the plugin.
22 | * `icon`: an icon for the plugin (see below).
23 | * `experimental`: `true` if the plugin should be hidden from the repository lists, `false` otherwise.
24 | * `homepage`: a link to GitHub or another website to read about the plugin.
25 | * `source`: a link to download the recent version of the plugin.
26 | * `intro`: a text that will be shown after installing the plugin (not when installing from a file),
27 | and also available from the plugin page. Can contain any markdown, including images and links.
28 |
29 | While only the `id` key is required, it's best to provide as many values as possible, at least
30 | for the first four: including `name`, `version`, and `description`. Here's for an example:
31 |
32 | ```yaml
33 | id: cycling_infra
34 | name: Cycling Infrastructure
35 | version: 2
36 | author: Ilya Zverev
37 | icon: cycling.svg
38 | description: |
39 | Testing plugin that adds a new mode to the editor, related to bicycle infrastructure.
40 |
41 | It resembles the building mode, but the primary (right) button adds a cycling barrier,
42 | and the secondary adds a bicycle parking stand. For the latter, capacity is shown
43 | on the map.
44 | experimental: false
45 | ```
46 |
47 | ## Versioning Plugins
48 |
49 | Plugin versions internally are all positive numbers, so it is perfectly valid to
50 | use a through enumeration: `1`, `2`, and so on.
51 |
52 | On the other hand, people are used to splitting major and minor releases, to
53 | differentiate between big improvements and bug fixes. With that, you can use
54 | that scheme for versioning, in the form of `.`. For example,
55 | `0.1`, `1.0`, `1.1`, and so on.
56 |
57 | Internally those versions are converted into a single number by multiplying the
58 | major version by a thousand, and adding a thousand. So `0.1` becomes `1001`,
59 | and `2.0` — `3000`. This also means that after version `999` your plugin
60 | might suddenly gain version `0.0`: that would probably be a good time
61 | to switch to `1000.0`.
62 |
63 | ## Icons
64 |
65 | Some sections expect an `icon` key. The value should be a file name of an image packaged with the plugin, in the `icons` subdirectory. For example, if you specify `icon: cycling.svg`, then the editor would look for `icons/cycling.svg` file in the plugin archive.
66 |
67 | Formats supported are SVG, PNG, GIF, and WebP.
68 | Good sources for SVG icons are [Material Icons](https://fonts.google.com/icons?icon.size=24&icon.color=%231f1f1f),
69 | and [Maki](https://github.com/mapbox/maki/tree/main).
70 | See [this list](https://github.com/ideditor/schema-builder/blob/main/ICONS.md) for
71 | additional sources.
72 |
73 | Note that to make an SVG file re-colorable, you would need to add an attribute to either its elements, or to the `` outer tag: `stroke="currentColor"` and/or `fill="currentColor"`. This "current color" is what will be replaced with the icon color value.
74 |
75 | Raster images are converted to black-and-white on its transparency layer, and the color is set to all non-transparent pixels.
76 |
77 | Another option for fast prototyping is to use an emoji character for an icon. Two drawbacks of that are, emoji
78 | are not recolorable, and the alignment is slighly off. To use a character, find one
79 | in [Emojipedia](https://emojipedia.org/), switch to the "Techinical information" tab,
80 | and copy the codepoint sequence in form of `U+1F525` to the icon value.
81 |
82 | ## Translations
83 |
84 | You can provide labels in many languages for a plugin. To add a translation
85 | into a language, create a top-level directory in the plugin package named `langs`,
86 | and inside it, files named with language codes, e.g. `es.yaml`, `pt-BR.yaml`.
87 |
88 | Each file should have the same structure as the `plugin.yaml`, but keeping
89 | just keys that need translation. Those usually are `name`, `label`, `labels`,
90 | `placeholder` etc. Some keys contain lists of strings instead of single
91 | string values, e.g. `labels` for preset fields. Translate them as usual,
92 | keeping the list in order.
93 |
94 | ## Imagery
95 |
96 | Read the [imagery](imagery.md) section when you want to:
97 |
98 | * Add a new base or overlay raster tile or WMS layer.
99 | * Include a GeoJSON file and display it in the app.
100 | * Package an MBTiles raster tile database with the plugin.
101 |
102 | ## Element Kinds
103 |
104 | Read the [element kinds](element_kinds.md) section to:
105 |
106 | * Add support for non-amenity tags, e.g. indoor or parking.
107 | * Understand why some objects are not displayed.
108 | * Define tag groups for some editing modes.
109 |
110 | ## Modes
111 |
112 | Read the [modes](modes.md) section to:
113 |
114 | * Customize colors and markers in the micromapping mode.
115 | * Update the default preset lists.
116 | * Create a custom entrances-like mode for dropping objects on the map.
117 |
118 | ## Presets and Fields
119 |
120 | Read the [presets](presets.md) section to:
121 |
122 | * Add a custom preset that shouldn't go into the global presets repository.
123 | * Add a custom field and employ it in some presets.
124 | * Define fields for a new entrances-like mode.
125 |
--------------------------------------------------------------------------------
/docs/develop/translate.md:
--------------------------------------------------------------------------------
1 | # Translating Every Door
2 |
3 | OpenStreetMap is used and created in virtually every country of the world by people
4 | of hundreds languages. While we abstract the data model in Every Door to make editing
5 | more accessible, we cannot abstract words. Thus, we need your help with translating
6 | every word in the editor to your own language.
7 |
8 | ## User Interface
9 |
10 | The app is translated at [Weblate](https://hosted.weblate.org/projects/every-door/app/),
11 | just like Go Map, MapComplete, and Organic Maps. All those projects will benefit from
12 | your knowledge of this translation website.
13 |
14 | Usually people open the Weblate page, then choose their language (there is an option
15 | to add one if it's missing, and you won't need an approval), and start translating
16 | strings one by one in the order suggested by the website.
17 |
18 | ### Weblate
19 |
20 | Let's have a quick look at the translation panel. "Acquiring location" are the first
21 | words people see when opening Every Door, so it's a good candidate for a showcase.
22 |
23 | 
24 |
25 | Here we're translating to Esperanto, and you can see the string is already there.
26 | Above it is English: it is the source, reference language, and it has a string key
27 | coming from the app, and a description in white-on-black. This description helps
28 | understand where this string is displayed in the app. Russian and Estonian are
29 | my secondary languages, which I have enabled in
30 | [preferences](https://hosted.weblate.org/accounts/profile/#languages).
31 |
32 | If you have no idea how to translate the string, click "Skip" or press "Ctrl+↓" (⌘↓ on Mac)
33 | to show the next one. Otherwise simply type the translated text and press "Ctrl+Enter"
34 | (⌘+Return) to move to the next line. It might help to look at comments and translation
35 | history below the form.
36 |
37 | You can find the complete [documentation](https://docs.weblate.org/en/latest/user/translating.html)
38 | on translating with Weblate on their website.
39 |
40 | ### Parameters
41 |
42 | Some strings contain words in figure brackets, e.g. `{count}`. **Do not translate those**!
43 | Those are placeholders for values that come from the app. For example, in the line
44 | "by {user} at {datetime}", the `{user}` part will be replaced with a user name, and
45 | `{datetime}` — with a date. If you translate words inside brackets, that would be
46 | an error preventing the app from compiling.
47 |
48 | Plurals are even more tricky. Some lines need to have different translations based
49 | on a number: e.g. "1 year", but "2 years". Conside this:
50 |
51 | {count,plural, =1{{count} year} few{{count} years} other{{count} years}}
52 |
53 | Here you should translate only "year(s)", but not `count,plural`, `few`, `other`, and
54 | not `{count}`. So in Ukrainian, it becomes:
55 |
56 | {count,plural, =1{{count} рік} few{{count} роки} other{{count} років}}
57 |
58 | Please be wary of these cases when translating.
59 |
60 | ### Process
61 |
62 | You can search for specific strings and translate just a section of the app. For example,
63 | all items in the Settings panel naturally have keys that start with `settings`, and
64 | string keys for the opening hours editor start with `fieldHours`. However I would advise
65 | translating everything in whatever order: some days or weeks later you will have dealt with
66 | each of ~350 strings and the order won't matter.
67 |
68 | Additionally there is a [Metadata](https://hosted.weblate.org/projects/every-door/metadata/)
69 | component: there you can translate short and long descriptions, and a change log, into
70 | your language for F-Droid store listings. Later it might be employed for other stores as well.
71 |
72 | Translation services are offered to Every Door by Weblate for free, and we're grateful for that.
73 |
74 | ## Presets and Fields
75 |
76 | The editor uses [presets from iD](https://github.com/openstreetmap/id-tagging-schema):
77 | they are managed in a dedicated repository and translated
78 | on [Transifex](https://app.transifex.com/openstreetmap/id-editor/presets/).
79 | To translate, open the link, login if needed, choose your language and hit "Translate".
80 | If you need a specific preset or a field, note the "Key" in the string context panel,
81 | and search for something like `key:living_street` or `key:wheelchair`. Also note
82 | the "Developer Notes" hint to the right.
83 |
84 | If you have suddenly learned there is no preset or field to translate, see
85 | [how to add those](presets.md).
86 |
87 | Translating options for combo fields is tricky. First, you need to make sure those
88 | are known. Find the field in the repository and check the `strings/options` map.
89 | It should look [like here](https://github.com/openstreetmap/id-tagging-schema/blob/main/data/fields/camera/type.json).
90 | If it is missing all or some options you think are required, please submit a pull
91 | request there and wait until it is merged.
92 |
93 | Then, when the translation source on Transifex is updated, there will be strings to translate.
94 | Search for `key:fields.`, e.g.
95 | [key:fields.camera/type](https://app.transifex.com/openstreetmap/id-editor/translate/#fr/presets?q=key%3Afields.camera%2Ftype)
96 | for `data/fields/camera/type.json`.
97 | You can see both the label and the options there, ready for translating.
98 |
99 | Presets from the Name Suggestion Index are considered local and are not translated.
100 |
101 | ## Plugins
102 |
103 | Currently plugins can only be translated by their authors. You can manually download one
104 | though, unpack it, and prepare a YAML file with a translation into your language.
105 | Later it will be automated with the plugin repository, which will enable plugin translations
106 | via Weblate.
107 |
108 | See the [plugin translation](../plugins/metadata/index.md) section for the file format.
109 |
110 | ## Documentation
111 |
112 | This website is made with MkDocs and hosted [on Github](https://github.com/Zverik/everydoor-website/tree/main/docs),
113 | so it is easy to edit the contents. The Material theme also
114 | [supports switching languages](https://squidfunk.github.io/mkdocs-material/setup/changing-the-language/#site-language-selector).
115 | But alas it is pretty hard to set up when you don't have a paid subscription. If you know
116 | how to do that, please submit a pull request. We would of course like to make this documentation
117 | translatable.
118 |
--------------------------------------------------------------------------------
/docs/images/appstore-android.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/images/appstore-android.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/plugins/metadata/presets.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Presets
3 | ---
4 | Every Door allows for adding and redefining presets and fields. By _presets_, we mean a set of tags that define an object, and a set of fields that appear in its editor panels. And _fields_ are items on those panels, like input fields or choice buttons.
5 |
6 | ## Presets
7 |
8 | All presets go under the `presets` key in the `plugin.yaml` file, as "id→definition" maps. It's worth looking at the [iD preset schema](https://github.com/ideditor/schema-builder?tab=readme-ov-file#presets) documentation to understand the structure. Here's an example:
9 |
10 | ```yaml
11 | presets:
12 | taaraautomaat:
13 | name: "Taaraautomaat"
14 | terms: [prügi]
15 | icon: taara.svg
16 | tags:
17 | amenity: vending_machine
18 | vending: bottle_return
19 | addTags:
20 | name: Taaraautomaat
21 | amenity: vending_machine
22 | vending: bottle_return
23 | "recycling:cans": yes
24 | "recycling:glass_bottles": yes
25 | "recycling:plastic_bottles": yes
26 | "recycling:refund_bottles": yes
27 | area: true
28 | fields:
29 | - roofShape
30 | - '@amenity/vending_machine/bottle_return'
31 | ```
32 |
33 | Here it defines a preset with an identifier `taaraautomaat` (not present in the packaged database). What do the keys mean:
34 |
35 | * `name`: a string label for the preset, displayed in the app bar of the editor panel, and on a tile in the type search panel.
36 | * `terms`: additional search terms for the preset, so it's easier to find with the autocomplete search.
37 | * `icon`: an icon to display in the search results tile. Can be an URL.
38 | * `area`: whether this preset applies to closed polygons as well as points. `true` is the default.
39 | * `tags`: a set of tags (as a key-value map) used to identify whether an object is of the given preset. In the example, it would mean that objects having `amenity=vending_machine` and `vending=bottle_return` tags will have this preset assigned to them, e.g. the editor will use the fields from this definition.
40 | * `addTags`: which tags to add when creating the object with this preset. Should include the `tags` content.
41 | * `removeTags`: which tags to remove when changing the type of the object to another preset.
42 | * `fields`: a list of string identifiers of fields to present in an editor. Can include a reference to fields of another preset, starting with "@": in the example, it adds a custom field on top of the standard fields of a `bottle_return` preset. Currently you cannot reference plugin-packaged presets here.
43 | * `moreFields`: same, but for the initially collapsed extended field list. If omitted, and when `fields` contain a reference to a preset, it will be populated from the `moreFields` list of that preset.
44 | * `standard`: by default, the editor panel constructs a third group of fields, "standard fields". Those contain an address and a level for everything, and a name, wheelchair access and other stuff for amenities. For custom forms that could be undesired, so when this key is set to `false`, fields will be presented as-is.
45 |
46 | If the `fields` list is missing, the preset is considered to be a part of a [name suggestion index](https://github.com/osmlab/name-suggestion-index): it will appear in a differently-colored tile in search results, and will have its fields retrieved from a matching normal preset.
47 |
48 | Plugin presets take priority over bundled presets, so it is possible to override some of those. For example, this snippet adds a custom `benchType` field to the bench preset (while losing the translations and custom search terms):
49 |
50 | ```yaml
51 | amenity/bench:
52 | name: Bench
53 | tags:
54 | amenity: bench
55 | fields:
56 | - backrest
57 | - armrest
58 | - material
59 | - benchType
60 | - seats
61 | moreFields:
62 | - '@amenity/bench'
63 | ```
64 |
65 | ## Fields
66 |
67 | Fields are commonly used in presets, and also share large parts of the schema with [iD presets](https://github.com/ideditor/schema-builder?tab=readme-ov-file#fields). In a plugin definition they go under a `fields` key, and just like presets, those are "id→definition" maps. Here is how the `benchType` field from the example above is defined:
68 |
69 | ```yaml
70 | fields:
71 | benchType:
72 | label: Bench Type
73 | key: 'bench:type'
74 | type: combo
75 | options:
76 | - seated
77 | - stand_up
78 | - block
79 | - lounger
80 | - swing
81 | - platform
82 | - log
83 | - canton
84 | - circular
85 | ```
86 |
87 | With the preset overridden, it looks like this in the object editor:
88 |
89 | { width="300" }
90 |
91 | What keys can go in a field definition:
92 |
93 | * `key`: which tag key does this field edit. Make sure to parenthesize keys with semicolons.
94 | * `label`: field label, will be displayed alongside it on an editor page.
95 | * `placeholder`: a faint grey label for text input fields.
96 | * `prerequisiteTag`: tags that this field depends upon (see [here](https://github.com/ideditor/schema-builder?tab=readme-ov-file#prerequisitetag)).
97 | * `type`: field type, which defines how it looks and what tags it affects.
98 |
99 | Types are mostly the same as listed in the upstream schema, since the code shares the type resolver. There is one extra type supported for plugins: `inlineCombo` (can be abbreviated to `inline`). It is the same as a one-choice `combo`, but with a fixed limited set of options that are displayed all at once, not trimmed to three items. And when you press a "custom" option, it transforms into a text input field instead of opening a separate pane. See fields in the buildings and entrances mode pop-up editors for examples.
100 |
101 | Combo fields have those keys as well:
102 |
103 | * `customValues`: whether to allow custom values.
104 | * `numeric`: whether custom values should be non-negative integer numbers (only applies to inline combos, `true` by default).
105 | * `options`: a list of available values, presented as a set of buttons or a pop-up list.
106 | * `labels`: a list of human-readable labels for each option, in order. For an inline combo, some or all labels can reference icons instead. For example:
107 |
108 | ```yaml
109 | fields:
110 | roofShape:
111 | label: Roof
112 | key: "roof:shape"
113 | type: inlineCombo
114 | customValues: false
115 | options:
116 | - flat
117 | - gabled
118 | - hipped
119 | - pyramidal
120 | - skillion
121 | - half-hipped
122 | - round
123 | - gambrel
124 | - mansard
125 | labels:
126 | - roofs/flat.png
127 | - roofs/gabled.png
128 | - roofs/hipped.png
129 | - roofs/pyramidal.png
130 | - roofs/skillion.png
131 | - roofs/half-hipped.png
132 | - roofs/round.png
133 | - roofs/gambrel.png
134 | - roofs/mansard.png
135 | ```
136 |
137 | And it looks like this in an editor:
138 |
139 | { width="300" }
140 |
141 | Note that while a list of options defines all possible options one can choose in the editor, OSM data can have different values, and those will be displayed as textual labels when a matching icon is not found.
142 |
--------------------------------------------------------------------------------
/assets/plugins/jquery-flipster/dist/jquery.flipster.min.css:
--------------------------------------------------------------------------------
1 | /*! jQuery.Flipster, v1.1.2 (built 2017-11-10) */.flipster{display:block;overflow-x:hidden;overflow-y:visible;position:relative}.flipster:focus{outline:none}.flipster__container,.flipster__item{margin:0;padding:0;list-style-type:none;position:relative}.flipster__container{display:block;white-space:nowrap;word-spacing:-0.25em;transform-origin:50% 50%;backface-visibility:hidden}.flipster__item{display:inline-block;white-space:normal;word-spacing:normal;vertical-align:bottom}.flipster--click .flipster__item--past,.flipster--click .flipster__item--future{cursor:pointer}.flipster__item img{max-width:100%}.flipster__button{position:absolute;top:50%;display:block;appearance:none;background:none;border:none;padding:0;z-index:999;cursor:pointer;font-size:15px;opacity:.5;transition:opacity 500ms ease;margin:-1em 2em}.flipster__button svg{width:2em;stroke:currentColor;fill:transparent;stroke-width:3;stroke-linecap:round}.flipster__button:hover,.flipster__button:focus{opacity:1}.flipster__button--prev{left:0}.flipster__button--next{right:0}.flipster__nav,.flipster__nav__item{list-style-type:none;margin:0;padding:0}.flipster__nav{display:block;margin:0 0 4em;text-align:center;position:relative}.flipster__nav__item{display:inline-block;margin:0 .25em}.flipster__nav__link{display:block;color:inherit;padding:.5em 1em;position:relative;overflow:hidden;transition:all 250ms ease-out;transition-timing-function:cubic-bezier(.56, .12, .12, .98)}.flipster__nav__link::after{content:'';display:block;background:#232221;position:absolute;top:0;left:0;width:100%;height:100%;z-index:-1;transform:translateY(100%) translateY(-0.25em);transition:inherit}.flipster__nav__item--current>.flipster__nav__link,.flipster__nav__link:hover,.flipster__nav__link:focus{color:#fff}.flipster__nav__item--current>.flipster__nav__link::after,.flipster__nav__link:hover::after,.flipster__nav__link:focus::after{transform:translateY(0)}.flipster__nav__child{display:none;position:absolute;top:100%;left:0;right:0;margin-top:-1px;padding:.5em;background:#4e4441;z-index:1}.flipster__nav__child .flipster__nav__link{color:#fff}.flipster__nav__child .flipster__nav__link::after{background:#fff}.flipster__nav__child .flipster__nav__item--current>.flipster__nav__link,.flipster__nav__child .flipster__nav__link:hover,.flipster__nav__child .flipster__nav__link:focus{color:#232221}.flipster__nav__item--current .flipster__nav__child{display:block}.flipster--carousel .flipster__container,.flipster--carousel .flipster__item,.flipster--carousel .flipster__item__content{transition:all 350ms ease-in-out;transition-timing-function:cubic-bezier(.56, .12, .12, .98)}.flipster--carousel .flipster__item{perspective:800px}.flipster--carousel .flipster__item--past,.flipster--carousel .flipster__item--future{opacity:0;transition-delay:115ms}.flipster--carousel .flipster__item--past-2,.flipster--carousel .flipster__item--future-2{opacity:.6;transition-delay:90ms}.flipster--carousel .flipster__item--past-1,.flipster--carousel .flipster__item--future-1{opacity:.8;transition-delay:60ms}.flipster--carousel .flipster__item--past .flipster__item__content{transform:translateX(100%) rotateY(-20deg) scale(.5)}.flipster--carousel .flipster__item--past-2 .flipster__item__content{transform:translateX(25%) rotateY(40deg) scale(.65)}.flipster--carousel .flipster__item--past-1 .flipster__item__content{transform:rotateY(45deg) scale(.8)}.flipster--carousel .flipster__item--future .flipster__item__content{transform:translateX(-100%) rotateY(20deg) scale(.5)}.flipster--carousel .flipster__item--future-2 .flipster__item__content{transform:translateX(-25%) rotateY(-40deg) scale(.65)}.flipster--carousel .flipster__item--future-1 .flipster__item__content{transform:rotateY(-45deg) scale(.8)}.flipster--carousel.no-rotate .flipster__item--past .flipster__item__content{transform:translateX(175%) scale(.5)}.flipster--carousel.no-rotate .flipster__item--past-2 .flipster__item__content{transform:translateX(25%) scale(.65)}.flipster--carousel.no-rotate .flipster__item--past-1 .flipster__item__content{transform:translateX(0) scale(.8)}.flipster--carousel.no-rotate .flipster__item--future .flipster__item__content{transform:translateX(-175%) scale(.5)}.flipster--carousel.no-rotate .flipster__item--future-2 .flipster__item__content{transform:translateX(-25%) scale(.65)}.flipster--carousel.no-rotate .flipster__item--future-1 .flipster__item__content{transform:translateX(0) scale(.8)}.flipster--carousel .flipster__item--current .flipster__item__content{transform:translateX(0) rotateY(0deg) scale(1);transition-delay:60ms}.flipster--coverflow .flipster__container,.flipster--coverflow .flipster__item,.flipster--coverflow .flipster__item__content{transition:all 350ms ease-in-out;transition-timing-function:cubic-bezier(.56, .12, .12, .98)}.flipster--coverflow .flipster__item{perspective:800px}.flipster--coverflow .flipster__container{padding-bottom:5%}.flipster--coverflow .flipster__item__content{transform-origin:50% 100%;box-reflect:below 0 -webkit-gradient(linear, left bottom, left top, color-stop(.05, rgba(255,255,255,0.12)), color-stop(.2, transparent));-webkit-box-reflect:below 0 -webkit-gradient(linear, left bottom, left top, color-stop(.05, rgba(255,255,255,0.12)), color-stop(.2, transparent))}.flipster--coverflow .flipster__item__content img:only-child{display:block}.flipster--coverflow .flipster__item--past .flipster__item__content{transform-origin:0 50%;transform:scale(.75) rotateY(55deg)}.flipster--coverflow .flipster__item--future .flipster__item__content{transform-origin:100% 50%;transform:scale(.75) rotateY(-55deg)}.flipster--coverflow .flip-current .flipster__item__content{transform:rotateY(0deg)}.flipster--flat .flipster__container,.flipster--flat .flipster__item,.flipster--flat .flipster__item__content{transition:all 400ms ease-in-out}.flipster--flat .flipster__item--past,.flipster--flat .flipster__item--future{opacity:.5}.flipster--flat .flipster__item--past .flipster__item__content{transform:scale(.75)}.flipster--flat .flipster__item--future .flipster__item__content{transform:scale(.75)}.flipster--wheel{overflow:hidden}.flipster--wheel .flipster__container,.flipster--wheel .flipster__item__content{transition:all 400ms ease-in-out;transition-timing-function:cubic-bezier(.56, .12, .12, .98)}.flipster--wheel .flipster__container{padding-bottom:20%}.flipster--wheel .flipster__item__content{transform-origin:50% 100%}.flipster--wheel .flipster__item--past .flipster__item__content{transform-origin:100% 100%}.flipster--wheel .flipster__item--future .flipster__item__content{transform-origin:0 100%}.flipster--wheel .flipster__item__content img:only-child{display:block}.flipster--wheel .flipster__item--past .flipster__item__content{opacity:0;transform:rotateZ(-80deg) translate(-170%, 110%)}.flipster--wheel .flipster__item--future .flipster__item__content{opacity:0;transform:rotateZ(80deg) translate(170%, 110%)}.flipster--wheel .flipster__item--past-3 .flipster__item__content{opacity:1;transform:rotateZ(-60deg) translate(-70%, 75%)}.flipster--wheel .flipster__item--future-3 .flipster__item__content{opacity:1;transform:rotateZ(60deg) translate(70%, 75%)}.flipster--wheel .flipster__item--past-2 .flipster__item__content{opacity:1;transform:rotateZ(-40deg) translate(-17%, 30%)}.flipster--wheel .flipster__item--future-2 .flipster__item__content{opacity:1;transform:rotateZ(40deg) translate(17%, 30%)}.flipster--wheel .flipster__item--past-1 .flipster__item__content{opacity:1;transform:rotateZ(-20deg)}.flipster--wheel .flipster__item--future-1 .flipster__item__content{opacity:1;transform:rotateZ(20deg)}.flipster--wheel .flip-current .flipster__item__content{transform:rotateX(0deg)}
--------------------------------------------------------------------------------
/assets/plugins/jquery-flipster/dist/jquery.flipster.min.js:
--------------------------------------------------------------------------------
1 | /*! jQuery.Flipster, v1.1.2 (built 2017-11-10) */
2 | !function(a,b,c){"use strict";function d(a,b){var c=null;return function(){var d=this,e=arguments;null===c&&(c=setTimeout(function(){a.apply(d,e),c=null},b))}}var e=function(){var a={};return function(b){if(a[b]!==c)return a[b];var d=document.createElement("div"),e=d.style,f=b.charAt(0).toUpperCase()+b.slice(1),g=["webkit","moz","ms","o"],h=(b+" "+g.join(f+" ")+f).split(" ");for(var i in h)if(h[i]in e)return a[b]=h[i];return a[b]=!1}}(),f="http://www.w3.org/2000/svg",g=function(){var a;return function(){if(a!==c)return a;var b=document.createElement("div");return b.innerHTML=" ",a=b.firstChild&&b.firstChild.namespaceURI===f}}(),h=a(b),i=e("transform"),j={itemContainer:"ul",itemSelector:"li",start:"center",fadeIn:400,loop:!1,autoplay:!1,pauseOnHover:!0,style:"coverflow",spacing:-.6,click:!0,keyboard:!0,scrollwheel:!0,touch:!0,nav:!1,buttons:!1,buttonPrev:"Previous",buttonNext:"Next",onItemSwitch:!1},k={main:"flipster",active:"flipster--active",container:"flipster__container",nav:"flipster__nav",navChild:"flipster__nav__child",navItem:"flipster__nav__item",navLink:"flipster__nav__link",navCurrent:"flipster__nav__item--current",navCategory:"flipster__nav__item--category",navCategoryLink:"flipster__nav__link--category",button:"flipster__button",buttonPrev:"flipster__button--prev",buttonNext:"flipster__button--next",item:"flipster__item",itemCurrent:"flipster__item--current",itemPast:"flipster__item--past",itemFuture:"flipster__item--future",itemContent:"flipster__item__content"},l=new RegExp("\\b("+k.itemCurrent+"|"+k.itemPast+"|"+k.itemFuture+")(.*?)(\\s|$)","g"),m=new RegExp("\\s\\s+","g");a.fn.flipster=function(b){if("string"==typeof b){var e=Array.prototype.slice.call(arguments,1);return this.each(function(){var c=a(this).data("methods");return c[b]?c[b].apply(this,e):this})}var n=a.extend({},j,b);return this.each(function(){function b(a){var b="next"===a?n.buttonNext:n.buttonPrev;return"custom"!==n.buttons&&g?''+b+' ":b}function e(c){return c=c||"next",a(' ').html(b(c)).on("click",function(a){v(c),a.preventDefault()})}function j(){n.buttons&&J.length>1&&(O.find("."+k.button).remove(),O.append(e("prev"),e("next")))}function o(){var b={};!n.nav||J.length<=1||(L&&L.remove(),L=a(''),N=a(""),J.each(function(c){var d=a(this),e=d.data("flip-category"),f=d.data("flip-title")||d.attr("title")||c,g=a(''+f+" ").data("index",c);if(N=N.add(g),e){if(!b[e]){var h=a(''),i=a(''+e+" ").data("category",e).data("index",c);b[e]=a(''),N=N.add(i),h.append(i,b[e]).appendTo(L)}b[e].append(g)}else L.append(g);g.wrap(' ')}),L.on("click","a",function(b){var c=a(this).data("index");c>=0&&(v(c),b.preventDefault())}),"after"===n.nav?O.append(L):O.prepend(L),M=L.find("."+k.navItem))}function p(){if(n.nav){var b=K.data("flip-category");M.removeClass(k.navCurrent),N.filter(function(){return a(this).data("index")===Q||b&&a(this).data("category")===b}).parent().addClass(k.navCurrent)}}function q(){O.css("transition","none"),G.css("transition","none"),J.css("transition","none")}function r(){O.css("transition",""),G.css("transition",""),J.css("transition","")}function s(){var b,c=0;return J.each(function(){(b=a(this).height())>c&&(c=b)}),c}function t(b){if(b&&q(),H=G.width(),G.height(s()),!H)return void(I=I||setInterval(function(){t(b)},500));I&&(clearInterval(I),I=!1),J.each(function(c){var d,e,f=a(this);f.attr("class",function(a,b){return b&&b.replace(l,"").replace(m," ")}),d=f.outerWidth(),0!==n.spacing&&f.css("margin-right",d*n.spacing+"px"),e=f.position().left,P[c]=-1*(e+d/2-H/2),c===J.length-1&&(u(),b&&setTimeout(r,1))})}function u(){var b,d,e,f=J.length;J.each(function(c){b=a(this),d=" ",c===Q?(d+=k.itemCurrent,e=f+1):c=0&&(H&&P[Q]!==c||t(!0),i?G.css("transform","translateX("+P[Q]+"px)"):G.css({left:P[Q]+"px"})),p()}function v(a){var b=Q;if(!(J.length<=1))return"prev"===a?Q>0?Q--:n.loop&&(Q=J.length-1):"next"===a?Q ')}),n.click&&J.on("click.flipster touchend.flipster",function(b){S||(a(this).hasClass(k.itemCurrent)||b.preventDefault(),v(this))}),j(),o(),Q>=0&&v(Q),O}function B(a){n.keyboard&&(a[0].tabIndex=0,a.on("keydown.flipster",d(function(a){var b=a.which;37!==b&&39!==b||(v(37===b?"prev":"next"),a.preventDefault())},250,!0)))}function C(a){if(n.scrollwheel){var b,c,e=!1,f=0,g=0,i=0,j=/mozilla/.test(navigator.userAgent.toLowerCase())&&!/webkit/.test(navigator.userAgent.toLowerCase());a.on("mousewheel.flipster wheel.flipster",function(){e=!0}).on("mousewheel.flipster wheel.flipster",d(function(a){clearTimeout(g),g=setTimeout(function(){f=0,i=0},300),a=a.originalEvent,i+=a.wheelDelta||-1*(a.deltaY+a.deltaX),Math.abs(i)<25&&!j||(f++,b=i>0?"prev":"next",c!==b&&(f=0),c=b,(f<6||f%3==0)&&v(b),i=0)},50)),h.on("mousewheel.flipster wheel.flipster",function(a){e&&(a.preventDefault(),e=!1)})}}function D(a){if(n.touch){var b,c,d,e,f,g;a.on({"touchstart.flipster":function(a){a=a.originalEvent,b=a.touches?a.touches[0].clientX:a.clientX,c=a.touches?a.touches[0].clientY:a.clientY},"touchmove.flipster":function(a){a=a.originalEvent,d=a.touches?a.touches[0].clientX:a.clientX,e=a.touches?a.touches[0].clientY:a.clientY,g=d-b,f=e-c,Math.abs(g)>30&&Math.abs(f)<100&&a.preventDefault()},"touchend.flipster touchcancel.flipster ":function(){g=d-b,f=e-c,Math.abs(g)>30&&Math.abs(f)<100&&v(g>0?"prev":"next")}})}}function E(){var a;if(O.css("visibility","hidden"),A(),J.length<=1)return void O.css("visibility","");a=!!n.style&&"flipster--"+n.style.split(" ").join(" flipster--"),O.addClass([k.main,i?"flipster--transform":" flipster--no-transform",a,n.click?"flipster--click":""].join(" ")),n.start&&(Q="center"===n.start?Math.floor(J.length/2):n.start),v(Q);var b=O.find("img");if(b.length){var c=0;b.on("load",function(){++c>=b.length&&z()}),setTimeout(z,750)}else z();h.on("resize.flipster",d(t,400)),n.autoplay&&w(),n.pauseOnHover&&G.on("mouseenter.flipster",function(){R?y(!0):x()}).on("mouseleave.flipster",function(){-1===R&&w()}),B(O),C(G),D(G)}var F,G,H,I,J,K,L,M,N,O=a(this),P=[],Q=0,R=!1,S=!1;F={jump:v,next:function(){return v("next")},prev:function(){return v("prev")},play:w,stop:x,pause:y,index:A},O.data("methods",F),O.hasClass(k.active)||E()})}}(jQuery,window);
--------------------------------------------------------------------------------
/docs/plugins/metadata/element_kinds.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Element Kinds
3 | ---
4 | An "element kind" is a set of rules that apply to tags to split objects into groups. Before the refactoring, some groups were made to non-intersect, but that can be untrue now. Each element kind has a string name, and a set of tag matching rules.
5 |
6 | We have multiple pre-defined element kinds:
7 |
8 | * `amenity`: objects that are editable in the "Amenity" mode. Usually they have opening hours, and deliver some services. Almost always it's for money. Shops, offices, parcel points, ATMs go here.
9 | * `needsCheck`: default to the `amenity` kind, indicates if the object benefits from regular assessment. Manifests as a checkmark in the POI editor mode.
10 | * `structure`: a subset of amenities that usually exist for decades or centuries once built. Examples are schools, churches, and stadiums.
11 | * `micro`: objects in the micromapping mode. Defined as "not amenity", and with a list of allowed keys.
12 | * `needsInfo`: lists of important missing tags for micromapping-related objects.
13 | * `building`: basically `building=*`, except for `building=entrance`.
14 | * `entrance`: basically `entrance=*` or `building=entrance`.
15 | * `address`: an address node. It should have no other use (no "main tag"), and either `addr:housenumber` or `addr:housename`.
16 | * `everything`: every key-value combination by which objects are filtered from the downloaded OSM extract. A rule of thumb is, no linear feature tags, and no polygons that are usually too big to grasp from being there.
17 | * `empty`: no meaningful tags except `source` and `note`.
18 | * `unknown`: a nothing-kind that's returned when an object does not match other kinds.
19 |
20 | ## Main Key
21 |
22 | Before everything else, we need to clarify what "main key" means. Every Door works on an assumption that every object in OSM data represents one separate entity. This is not always correct (e.g. shops on buildings, or fences and school areas), but mostly checks out: it is exceptionally rare to find a `shop` and `amenity` on a single POI object.
23 |
24 | To detect the main key, Every Door iterates over [a list of keys](https://github.com/Zverik/every_door/blob/main/lib/helpers/tags/main_key.dart), taking the first one found. So for a polygon with `amenity=school` and `barrier=fence`, it would choose the first one. It does consider [lifecycle prefixes](https://wiki.openstreetmap.org/wiki/Lifecycle_prefix), so changing `shop` to `disused:shop` changes nothing with regard to the main key.
25 |
26 | It is not possible to extend the main key list through a plugin, you would need to submit a pull request.
27 |
28 | Now, some standard element kinds apply only to the main tag (key and value). Those are `amenity`, `needsCheck`, `structure`, `micro`, and `everything`. Others either don't care for an object type (like `empty`), or acknowledge an object can be multiple things at once (like `building`).
29 |
30 | ## Defining Kinds
31 |
32 | A simple `ElementKind` looks like this:
33 |
34 | ```yaml
35 | kinds:
36 | cycleBarrier:
37 | matcher:
38 | barrier:
39 | only: [cycle_barrier]
40 | ```
41 |
42 | The `cycleBarrier` element kind matches only a single tag, `barrier=cycle_barrier`, and only as a main key. If an object has more important defining tag, like `amenity=post_box`, the matcher won't pick up the barrier tag.
43 |
44 | To look for matches in every tag, you can set `onMainKey: false` for the element kind definition. As mentioned earlier, it is rarely needed, so you must know what you're doing.
45 |
46 | The only other thing in a kind is a tag matcher. It is defined in the `matcher` key when we're defining a new element kind, or completely replacing an existing one. For updating an existing element kind, e.g. for adding a support for a new tag, use instead the `update` key:
47 |
48 | ```yaml
49 | kinds:
50 | everything:
51 | update:
52 | amenity:
53 | replace: true
54 | except:
55 | - parking
56 | - parking_entrance
57 | - loading_dock
58 | - waste_dump_site
59 | - waste_transfer_station
60 | ```
61 |
62 | You might think, this looks exactly like the [current definition](https://github.com/Zverik/every_door/blob/main/lib/helpers/tags/element_kind_std.dart#L306-L313) of the `amenity` tag handling, but here we skipped the `parking_space` value, allowing for editing its properties.
63 |
64 | Note that the editor won't touch linear features, so there is no point in enabling, for example, `waterway=river` or `highway=residential`.
65 |
66 | ## Matchers
67 |
68 | A tag matcher (the one you specify for an element kind) looks at tag keys, like `amenity` or `man_made`. It's the first layer of testing: if a key is not in its dictionary, it fails the check.
69 |
70 | The definition for a matcher is a map with tag keys for keys, and matching rules for values. Those matching rules can have those keys:
71 |
72 | * `only`: a list of values that can match. If it's not empty, all other values or an absence of the key would fail the check.
73 | * `except`: a list of forbidden values. The check will fail if the tag is present, and its value is in this list.
74 | * `when`: a map of "value: tag matcher". It invokes a nested matcher when the tag has the given value. It allows for testing secondary tags, e.g. `recycling_type=*` for `amenity=recycling`.
75 | * `replace`: when redefining a matcher, this boolean flag (`true` by default) controls whether we're replacing all the rules, or updating the lists. Matchers in `when` get replaced in any case. Note that you cannot _remove_ entries from `only` and `except`, only append to the lists. To remove, just copy a list without some entries, like we did above in the `amenity=parking_space` example.
76 |
77 | ### Matching on the Main Key
78 |
79 | If an element kind containing tag matcher works on main keys, the matcher can automatically accept an object when certain keys are present. A list of those keys goes into `$good` attribute. It looks like this:
80 |
81 | ```yaml
82 | kinds:
83 | amenityKind:
84 | matcher:
85 | "$good":
86 | - shop
87 | - craft
88 | - office
89 | - healthcare
90 | - club
91 | amenity:
92 | except: [parking, ...]
93 | when:
94 | recycling:
95 | recycling_type:
96 | only: [centre]
97 | ```
98 |
99 | This example illustrates both keys that are considered amenities for every possible values, and a conditional `amenity=recycling` handling.
100 |
101 | ### Missing Tags
102 |
103 | There is also a `$missing` tag matcher list, which behaves weirdly. It passes only when at least one of the listed keys are missing. That is, if we have `"$missing": [leaf_type, leaf_cycle]`, then the matched will pass only when the object does not have at least one of those two tags.
104 |
105 | Only one element kind uses the `$missing` list, and it's `needsInfo`. The micromapping mode uses it to display a white dot on objects that miss some important information. You can add that indication to new types of objects (based on their main key) using this example of how it's done for bus stops and pedestrian crossings:
106 |
107 | ```yaml
108 | kinds:
109 | needsInfo:
110 | matcher:
111 | highway:
112 | crossing:
113 | when:
114 | "$missing": [crossing]
115 | bus_stop:
116 | when:
117 | "$missing":
118 | - bench
119 | - shelter
120 | ```
121 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Creative Commons Legal Code
2 |
3 | CC0 1.0 Universal
4 |
5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
12 | HEREUNDER.
13 |
14 | Statement of Purpose
15 |
16 | The laws of most jurisdictions throughout the world automatically confer
17 | exclusive Copyright and Related Rights (defined below) upon the creator
18 | and subsequent owner(s) (each and all, an "owner") of an original work of
19 | authorship and/or a database (each, a "Work").
20 |
21 | Certain owners wish to permanently relinquish those rights to a Work for
22 | the purpose of contributing to a commons of creative, cultural and
23 | scientific works ("Commons") that the public can reliably and without fear
24 | of later claims of infringement build upon, modify, incorporate in other
25 | works, reuse and redistribute as freely as possible in any form whatsoever
26 | and for any purposes, including without limitation commercial purposes.
27 | These owners may contribute to the Commons to promote the ideal of a free
28 | culture and the further production of creative, cultural and scientific
29 | works, or to gain reputation or greater distribution for their Work in
30 | part through the use and efforts of others.
31 |
32 | For these and/or other purposes and motivations, and without any
33 | expectation of additional consideration or compensation, the person
34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she
35 | is an owner of Copyright and Related Rights in the Work, voluntarily
36 | elects to apply CC0 to the Work and publicly distribute the Work under its
37 | terms, with knowledge of his or her Copyright and Related Rights in the
38 | Work and the meaning and intended legal effect of CC0 on those rights.
39 |
40 | 1. Copyright and Related Rights. A Work made available under CC0 may be
41 | protected by copyright and related or neighboring rights ("Copyright and
42 | Related Rights"). Copyright and Related Rights include, but are not
43 | limited to, the following:
44 |
45 | i. the right to reproduce, adapt, distribute, perform, display,
46 | communicate, and translate a Work;
47 | ii. moral rights retained by the original author(s) and/or performer(s);
48 | iii. publicity and privacy rights pertaining to a person's image or
49 | likeness depicted in a Work;
50 | iv. rights protecting against unfair competition in regards to a Work,
51 | subject to the limitations in paragraph 4(a), below;
52 | v. rights protecting the extraction, dissemination, use and reuse of data
53 | in a Work;
54 | vi. database rights (such as those arising under Directive 96/9/EC of the
55 | European Parliament and of the Council of 11 March 1996 on the legal
56 | protection of databases, and under any national implementation
57 | thereof, including any amended or successor version of such
58 | directive); and
59 | vii. other similar, equivalent or corresponding rights throughout the
60 | world based on applicable law or treaty, and any national
61 | implementations thereof.
62 |
63 | 2. Waiver. To the greatest extent permitted by, but not in contravention
64 | of, applicable law, Affirmer hereby overtly, fully, permanently,
65 | irrevocably and unconditionally waives, abandons, and surrenders all of
66 | Affirmer's Copyright and Related Rights and associated claims and causes
67 | of action, whether now known or unknown (including existing as well as
68 | future claims and causes of action), in the Work (i) in all territories
69 | worldwide, (ii) for the maximum duration provided by applicable law or
70 | treaty (including future time extensions), (iii) in any current or future
71 | medium and for any number of copies, and (iv) for any purpose whatsoever,
72 | including without limitation commercial, advertising or promotional
73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
74 | member of the public at large and to the detriment of Affirmer's heirs and
75 | successors, fully intending that such Waiver shall not be subject to
76 | revocation, rescission, cancellation, termination, or any other legal or
77 | equitable action to disrupt the quiet enjoyment of the Work by the public
78 | as contemplated by Affirmer's express Statement of Purpose.
79 |
80 | 3. Public License Fallback. Should any part of the Waiver for any reason
81 | be judged legally invalid or ineffective under applicable law, then the
82 | Waiver shall be preserved to the maximum extent permitted taking into
83 | account Affirmer's express Statement of Purpose. In addition, to the
84 | extent the Waiver is so judged Affirmer hereby grants to each affected
85 | person a royalty-free, non transferable, non sublicensable, non exclusive,
86 | irrevocable and unconditional license to exercise Affirmer's Copyright and
87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the
88 | maximum duration provided by applicable law or treaty (including future
89 | time extensions), (iii) in any current or future medium and for any number
90 | of copies, and (iv) for any purpose whatsoever, including without
91 | limitation commercial, advertising or promotional purposes (the
92 | "License"). The License shall be deemed effective as of the date CC0 was
93 | applied by Affirmer to the Work. Should any part of the License for any
94 | reason be judged legally invalid or ineffective under applicable law, such
95 | partial invalidity or ineffectiveness shall not invalidate the remainder
96 | of the License, and in such case Affirmer hereby affirms that he or she
97 | will not (i) exercise any of his or her remaining Copyright and Related
98 | Rights in the Work or (ii) assert any associated claims and causes of
99 | action with respect to the Work, in either case contrary to Affirmer's
100 | express Statement of Purpose.
101 |
102 | 4. Limitations and Disclaimers.
103 |
104 | a. No trademark or patent rights held by Affirmer are waived, abandoned,
105 | surrendered, licensed or otherwise affected by this document.
106 | b. Affirmer offers the Work as-is and makes no representations or
107 | warranties of any kind concerning the Work, express, implied,
108 | statutory or otherwise, including without limitation warranties of
109 | title, merchantability, fitness for a particular purpose, non
110 | infringement, or the absence of latent or other defects, accuracy, or
111 | the present or absence of errors, whether or not discoverable, all to
112 | the greatest extent permissible under applicable law.
113 | c. Affirmer disclaims responsibility for clearing rights of other persons
114 | that may apply to the Work or any use thereof, including without
115 | limitation any person's Copyright and Related Rights in the Work.
116 | Further, Affirmer disclaims responsibility for obtaining any necessary
117 | consents, permissions or other rights required for any use of the
118 | Work.
119 | d. Affirmer understands and acknowledges that Creative Commons is not a
120 | party to this document and has no duty or obligation with respect to
121 | this CC0 or use of the Work.
122 |
--------------------------------------------------------------------------------
/docs/develop/structure.md:
--------------------------------------------------------------------------------
1 | # Code Navigation
2 |
3 | The directory structure has been devised many years ago when the author has been learning
4 | Flutter development, so it's not the most effective, but it works. This page walks you through
5 | it, so you understand what goes where.
6 |
7 | ## Root
8 |
9 | * `android`: Android build files go here. Of most importance are `app/build.gradle`
10 | and `app/src/main/AndroidManifest.xml`. If you don't know why, please stay away from those.
11 | * Built apk and aab files are put into `android/app/prod/release`.
12 | * Note that published apk's on Github use Ilya's personal certificate,
13 | while all beta apk's, including those published to Releases,
14 | are built with a secret certificate for Actions.
15 | * `ios`: iOS build files. In XCode, you open `Runner.xcworkspace`.
16 | * Built distribution package is put into `build/ios/archive/Runner.xcarchive`.
17 | Open it with XCode to upload it to AppStore.
18 | * `assets`: files that are packaged with the app. Mostly presets and images.
19 | * The production version of presets is [uploaded to Textual](https://textual.ru/presets.db).
20 | * `vendor`: here are git submodules for building. Currently just Flutter SDK.
21 | * `metadata`: text files for F-Droid, translated on Weblate.
22 | Might be good to go full Fastlane.
23 | * `tools`: scripts in Python, Dart, and Bash to process data for the editor.
24 | * `test`: yup, tests. Currently mostly unit tests for algorithmic helpers.
25 | * `lib`: code.
26 | * `pubspec.yaml`: The most important file for a Dart project, lists dependencies and stuff.
27 |
28 | ## Tools
29 |
30 | * `common_hours.py`: the opening hours panel offers common starting and endind times.
31 | This script find those in the TagInfo database.
32 | * `encode_url.dart`: encodes URLs with keys for imagery constants.
33 | * `print_common_keys.py`: this script prepares the `lib/helpers/tags/common_keys.dart`,
34 | used in the raw tag editor.
35 | * `test_sqlite_tags.py`: preset queries are pretty complex (see `lib/providers/presets.dart`),
36 | so this script was used to test those.
37 |
38 | ### Language Codes
39 |
40 | * `language_names.py`: I've extracted the table from
41 | [this Wikipedia page](https://simple.wikipedia.org/wiki/List_of_ISO_639-1_codes)
42 | to a CSV (`language_codes.csv`), and extracted language names and ISO codes to a Dart constant.
43 | * `match_country_langs.py`: this script build a reference table for languages in each
44 | country. The Unicode CLDR data might have been better, but this one uses
45 | [Organic Maps data](https://github.com/organicmaps/organicmaps/blob/master/data/countries_meta.txt).
46 |
47 | ### Building the Database
48 |
49 | In short, run `update.sh` passing it a path to `taginfo-db.db` and wait.
50 | It does five things:
51 |
52 | 1. Creates a Python virtual environment to run other scripts.
53 | 2. Runs `json_to_sqlite.py`: it downloads or reads distribution files from
54 | two repositories, [Tagging Schema](https://github.com/openstreetmap/id-tagging-schema/tree/main/dist)
55 | and [NSI](https://github.com/osmlab/name-suggestion-index/tree/main/dist),
56 | and repackages the info into an SQLite database. All preset processing,
57 | translations, and search indices are built there.
58 | 3. Runs `add_taginfo.py`. It requests keys for combo fields from this
59 | SQLite database, then runs queries on the TagInfo database (which is
60 | very big, so the queries are slow) to get the most popular values
61 | for those keys, and store them into presets.
62 | 4. Runs `add_imagery.py`. It stores the JSON data from the
63 | [Layer Index](https://github.com/osmlab/editor-layer-index/)
64 | repository in the SQLite database almost 1:1. Coverage polygons are
65 | converted into a geohash lookup table.
66 | 5. Packages NSI polygon collection into a constant string inside the code.
67 |
68 | ## Lib
69 |
70 | * `main.dart`: the main executable file for the app. Contains the `MaterialApp`
71 | with necessary wrappers. Logging, colors, and Let's Encrypt certificate
72 | are all set up here.
73 | * `constants.dart`: all the constants for various parts of the app. Including
74 | the app title and version, and API endpoints.
75 | * `l10n`: localization `arb` files, translated with Weblate. The `app_en.arb`
76 | is the source and the only one you should edit.
77 | * During the build phase, those are compiled into `lib/generated`.
78 |
79 | There is also `commit_info.g.dart` generated into the `lib` root with the
80 | [commit\_info](https://pub.dev/packages/commit_info) package.
81 |
82 | ### Models and Controllers
83 |
84 | * `models`: classes that are passed between the parts. The most important one
85 | is in `amenity.dart` with the POI definition. Everything editable is
86 | an `OsmChange`. Also note `field.dart` with two long functions to
87 | create a field from a preset record.
88 | * `helpers`: non-visual functions and classes, and sometimes dictionaries.
89 | Most algorithmic stuff goes here, and into providers too. Frankly it's
90 | a mess, there's even a provider in there (`legend.dart`).
91 | * `geometry`: geometric and geodetic functions, e.g. distance calculation,
92 | or snapping points to lines.
93 | * `tags`: everything related to tags and tag filtering. Some of it is
94 | [described here](../plugins/metadata/element_kinds.md).
95 | * `providers`: all the [Riverpod](https://riverpod.dev/) providers. They
96 | basically keep an application-wide state, and often are used for a
97 | pure storage (tied to an app context). Some providers (like `uploader.dart`)
98 | do not have a state, but link multiple providers together for convenience.
99 |
100 | ### Views
101 |
102 | * `screens`: all the panes from the app. The app starts with the `loading.dart`,
103 | then switches to `browser.dart`, which displays the current mode page.
104 | * `modes`: mode pages that rely on corresponding `definitions`. The idea
105 | being, you can override a definition to create or modify a mode.
106 | There are four base modes, plus `navigate.dart` when you zoom out
107 | too far.
108 | * `editor`: panes and sheets used not only from the editor pane, but
109 | also from modes. E.g. `building` and `entrance` are displayed when
110 | you tap a button in the entrances mode. They all edit an `OsmChange`
111 | or display information related to it.
112 | * `settings`: all the panes accessible from the Settings menu.
113 | * `widgets`: building blocks for the app: buttons, markers, info blocks,
114 | forms. The biggest thing is `map.dart` with a universal map widget.
115 | * `fields`: classes inheriting `PresetField` that implement editors for
116 | various field types. Custom fields should go here.
117 | * `hours`: the opening hours editor is the most complex in the app,
118 | and all its parts are here.
119 | * `helpers`: helpers and panes that some fields open, e.g. a direction
120 | chooser with a map.
121 |
122 | ### Data
123 |
124 | Not exactly about the code, but the important thing to understand is, where the
125 | data is stored. In the app, it is distributed among four sources:
126 |
127 | 1. Android secure storage and shared preferences. Mostly for settings and tokens.
128 | For example, switches state from the Settings panel is stored there.
129 | 2. Presets SQLite database. It is packaged with the app and is read-only. It is
130 | accessed solely through `PresetProvider`.
131 | 3. App SQLite database. Mostly for downloaded OSM data, but also for location-dependent
132 | indices and settings, e.g. payment tags. See the `DatabaseHelper` for the schema
133 | and access.
134 | 4. Transient in-memory storage, in virtually every provider. Mostly caches.
135 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Every Door
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
49 |
50 |
51 |
52 |
Features
53 |
54 | 100% OpenStreetMap editor with no dependencies on third-party endpoints.
55 | See all the shops and amenities nearby, without geospatial displacement.
56 | Engage the `check_date` tag to confirm shops' existence.
57 | Edit buildings and add entrances with apartment numbers.
58 | Map every manhole, bench, and street lamp in the micro-mapping mode.
59 | Pre-load imagery tiles and work offline.
60 |
61 |
62 |
63 |
64 |
65 |
66 |
72 |
73 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/docs/guide/releases/6.0.md:
--------------------------------------------------------------------------------
1 | # Every Door 6.0
2 |
3 | _Released on 26 June 2025_
4 |
5 | This release is focused on one thing people (and the author too) have been waiting since 2022:
6 |
7 | ## Plugins
8 |
9 | What is a plugin? The lines between configuration files, plugins, extensions,
10 | and DLC are very thin. People have asked for more configurability, and for
11 | custom builds for specific use cases. Every Door is very opinionated, and
12 | hence is not as much configurable as some would prefer. Well, it got
13 | more open now, with the introduction of plugins.
14 |
15 | At the first stage, a plugin is a YAML file in an archive, directing which
16 | tags to use, how things look, and what editing modes there are. While not
17 | very flexible, it allows for custom imagery, custom presets and fields, and
18 | entire custom workflows, for which you might have needed dedicated apps.
19 |
20 | For example, the prototype [mapping pie dispencer](https://pie.osmz.ee/1)
21 | makes it easy to download mapping area boundaries to Every Door, to know
22 | where to map. In the future it could advise on imagery layers, show
23 | a surveying manual, and even track the completion and share locations
24 | with other participants.
25 |
26 | Plugins are collected in [the Repository](https://plugins.every-door.app/).
27 | It is accessible right from the app: go to Settings → Plugins → (+) button.
28 | Uploading plugins is easy: you only need an OpenStreetMap account. But
29 | there are also other ways of installing plugins, e.g. from a QR code.
30 |
31 | See the [Plugins](../../plugins/index.md) section to learn how to use and how
32 | to develop those.
33 |
34 | ## Amenity Editing
35 |
36 | ### Green Markers
37 |
38 | 
39 |
40 | After you have done the initial survey, the re-surveying often consists
41 | of a single step: tapping the checkmark, confirming shops are still there.
42 | "Yup, yup, still there, this one too, and this one..." The idea was, you look
43 | at the tiles below the map and ignore the map. But when something's off, like
44 | a shop missing, cross-referencing the legend with the map becomes hard.
45 |
46 | So in this release, I tried to color confirmed amenities green. And it
47 | made surveying faster and more fun!
48 |
49 | ### Dragging the Button
50 |
51 | 
52 |
53 | Did you know that in the entrances and notes modes, you could not only tap
54 | (+) buttons, but also drag them onto the map? That would save you a second,
55 | which is important when you're in a car, for example, collecting all the
56 | addresses in a village.
57 |
58 | Now the code has been restructured for the plugins, and this dragging
59 | behaviour has also been added to the first two modes. Try dragging the button
60 | next time you add a bench!
61 |
62 | ### Weekdays
63 |
64 | 
65 |
66 | Dmitry from Israel pointed out that the day order (and translations for
67 | weekdays) were off. Turns out, in some countries days start not from
68 | Monday, and some have a different set of weekends! Now Every Door knows
69 | of local rules, and adjusts the opening hours panel accordingly.
70 |
71 | ### Fixme Objects
72 |
73 | When you cannot find a correct type for a shop, you could type something
74 | free-form into the search field, and tap on the red box to create
75 | a special kind of amenity, `amenity=fixme`. It would record all the data,
76 | so that later somebody could find the correct type and retag the object,
77 | keeping the name, opening hours, phone numbers etc.
78 |
79 | Alas the second step rarely happened, and mappers were complaining. To fix
80 | that, Every Door will now convert such fixme amenity to an OSM note, in case
81 | nothing but the name is provided. It will also highlight fixme amenities
82 | marking them as objects to improve.
83 |
84 | As for other objects with non-empty fixme values, which have been highlighted,
85 | it is now easier to clear the `fixme` tag with a single tap. Thanks to Soham
86 | Dixit, who has implemented the feature.
87 |
88 | ### Wrong State
89 |
90 | Want to change the type of a shop? It's easy: tap the title in the header.
91 | Presets specify which tags need to be removed and which to add. Alas, the
92 | app forgot to remove the tags first, which resulted in some weird tagging
93 | after a type switch. Not anymore.
94 |
95 | Did not know you could change the object type? I have underlined the title
96 | to make it more discoverable.
97 |
98 | Note that when changing a type, now you won't get a full list of type suggestions.
99 | This also is a result from restructuring the code, but feels to be a correct
100 | way to go: I've never found a correct _replacement_ in those lists, because
101 | they were made for initial surveying, not map gardening.
102 |
103 | See a shop closed, but with a sign still there? Mark it disused by tapping
104 | the orange button in the editor. It would add the `disused:` prefix to
105 | its main tag, producing e.g. `disused:shop=clothes`. Alas with the
106 | advancements to our tagging, and having multiple competing tagging
107 | schemas, sometimes one prefix was not enough. In this release, Every Door
108 | correctly manages prefixes for hospitals tagged with both `amenity=hospital`
109 | and `healthcare=hospital`.
110 |
111 | ## Other
112 |
113 | ### Compass
114 |
115 | 
116 |
117 | Finally you can know where you are looking! Thanks to Siarhei Fedartsou,
118 | the location marker has got a direction triangle.
119 |
120 | ### Profile
121 |
122 | { width="300" }
123 |
124 | And Soham Dixit has improved the look of the OSM profile page. Nothing
125 | new has been added there though, it's already perfect.
126 |
127 | Note that due to a library update, you might need to re-login. In some
128 | cases, even reinstall the app, although I don't expect that to happen.
129 |
130 | ### Buildings
131 |
132 | Turns out "Cancel" buttons for buildings and entrances kept the changes.
133 | That was very wrong and I have no idea how nobody caught it in three years.
134 |
135 | Mxdanger has also updated roof shape images appearing in a building
136 | editor form. Turns out they have made
137 | [much more](https://commons.wikimedia.org/wiki/Category:Illustrations_of_roof_forms_(red_on_grey)) icons than we have seen!
138 |
139 | ### Translations
140 |
141 | First, mappers in Serbia should have an easier time adding local names,
142 | because thanks to Alnzrv, cyrillic and latin alphabets are now properly
143 | split between `name:sr` and `name:sr-Latn`, which both appear by default
144 | when you edit an amenity.
145 |
146 | Also thanks to Yurt Page, app metadata, namely the description and changelogs,
147 | can be translated. Those are used only for F-Droid for now, but in the future
148 | someday I might add a Fastlane tool to use those translations when uploading
149 | to other stores.
150 |
151 | Finally, this release has added multiple strings, mostly related to plugins,
152 | so I'm grateful to everyone who's translated those into their own languages.
153 | Special thanks goes to Mandeep and Kim Kats for vastly improving Punjabi and
154 | Greek localizations.
155 |
156 | ### System Changes
157 |
158 | Every Door 6.0 now supports only Android 6 ("Marshmallow") or newer. Sorry to those two
159 | users on 5.1 who's been left behind. Vespucci has still got you covered. But really,
160 | it's over ten years old, and you can easily find newer phones for a few bucks,
161 | or even free.
162 |
163 | We also have a new QR code scanner. The previous one depended on proprietary MLKit,
164 | not available on de-googled phones or in the F-Droid build. Now the app uses
165 | an alternative open-source library that depends on ZXing for Android and
166 | MTBBarcodescanner for iOS. Alas both libraries are in maintenance mode, but
167 | they work good enough, at least the Android one. If you encounter any problems
168 | scanning QR codes, please [report them](../../develop/bugs.md).
169 |
170 | ## New Website
171 |
172 | This website has been migrated to Material for MkDocs, and its sections
173 | are gradually filling in. We have a guide on [plugins](../../plugins/index.md)
174 | and on [contributing in general](../../develop/index.md). User's guide and
175 | video tutorials to follow this Summer.
176 |
177 | ## Thanks to NLNet
178 |
179 | This release and the huge code restructuring and development work that went into it
180 | were funded through the [NGI0 Commons Fund](https://nlnet.nl/commonsfund), a fund
181 | established by [NLnet](https://nlnet.nl) with financial support from the
182 | European Commission's [Next Generation Internet](https://ngi.eu) programme,
183 | under the aegis of
184 | [DG Communications Networks, Content and Technology](https://commission.europa.eu/about-european-commission/departments-and-executive-agencies/communications-networks-content-and-technology_en)
185 | under grant agreement No [101135429](https://cordis.europa.eu/project/id/101135429).
186 | Additional funding is made available by the
187 | [Swiss State Secretariat for Education, Research and Innovation](https://www.sbfi.admin.ch/sbfi/en/home.html) (SERI).
188 |
--------------------------------------------------------------------------------
/docs/develop/presets.md:
--------------------------------------------------------------------------------
1 | # Developing Presets
2 |
3 | TL;DR:
4 |
5 | * Presets: [repository](https://github.com/openstreetmap/id-tagging-schema/tree/main/data/presets), [schema](https://github.com/ideditor/schema-builder?tab=readme-ov-file#presets), mind the `fields`.
6 | * Fields: [repository](https://github.com/openstreetmap/id-tagging-schema/tree/main/data/fields), [schema](https://github.com/ideditor/schema-builder?tab=readme-ov-file#fields), consider `strings/options` for combos.
7 | * Brand Suggestions: [repository](https://github.com/osmlab/name-suggestion-index) and [wiki](https://github.com/osmlab/name-suggestion-index/wiki/Contributing).
8 | * Local: see [presets in plugins](../plugins/metadata/presets.md).
9 |
10 | ## Global Presets
11 |
12 | The editor uses [presets from iD](https://github.com/openstreetmap/id-tagging-schema).
13 | If you find something missing: an object type, a field in an editing form — you should
14 | take it upstream, to that repository, preferably in form of a pull request. This does
15 | sound complex, and this page would help you through it.
16 |
17 | You would benefit from keeping the [preset schema](https://github.com/ideditor/schema-builder?tab=readme-ov-file#presets)
18 | at hand: it documents everything that goes into preset and field definitions.
19 |
20 | ### Presets
21 |
22 | A preset is a named set of fixed and editable tags. For example, the
23 | [amenity/bench](https://github.com/openstreetmap/id-tagging-schema/blob/main/data/presets/amenity/bench.json) preset
24 | defines the fixed `amenity=bench` tag — that's how an object is deemed to be a bench.
25 | Every Door uses those fixed tags to split objects by types in the micromapping mode,
26 | and of course to get a list of fields for the editor.
27 |
28 | { width="300" }
29 |
30 | Lists `fields` and `moreFields` define editable tags, split by importance (which usually
31 | depends on usage frequency). Those reference [fields](#fields) by names. It is important
32 | to have as few fields in the first list as possible — but also every field that can be
33 | quickly assessed and provides useful, practical information.
34 |
35 | Finally, a preset needs to be searchable. When a mapper sees a fish shop, they would
36 | most likely search for "fish", and it doesn't matter that the OSM tag is `shop=seafood`.
37 | That's why [the preset](https://github.com/openstreetmap/id-tagging-schema/blob/main/data/presets/shop/seafood.json)
38 | includes an alias starting with "fish": search engines look at `name`, `aliases`, and `terms`
39 | properties, including their [translations](translate.md#presets-and-fields).
40 |
41 | That's basically it. Try [looking for the preset](https://github.com/openstreetmap/id-tagging-schema/tree/main/data/presets)
42 | based on its tags, main and additional. If you find it there, then maybe consider adding
43 | search terms so that other people won't have to do the same. If not — write the JSON file
44 | according to the [schema](https://github.com/ideditor/schema-builder?tab=readme-ov-file#presets)
45 | and using other files for reference, and submit a pull request.
46 |
47 | You will see the update in Every Door after the request is merged, and a new editor release
48 | is published. In the meantime, you could also make a [local preset](#personal-presets)
49 | for yourself.
50 |
51 | ### Fields
52 |
53 | Every input field and button you see on the object editing page is defined in some
54 | field, referenced from a preset. Usually, barring very few special cases hard-coded
55 | in Every Door, a field edits a single key value. Like for this
56 | [backrest=\*](https://github.com/openstreetmap/id-tagging-schema/blob/main/data/fields/backrest.json)
57 | field, usually all you need for a field is that key, a label, and a type.
58 |
59 | { width="300" }
60 |
61 | If there is something wrong with a field, you can find it by locating the preset it is in,
62 | reading the `fields` or `moreFields` list, and locating the field JSON source in the
63 | [repository](https://github.com/openstreetmap/id-tagging-schema/tree/main/data/fields).
64 | Often you would do this to add
65 | [translatable options](https://github.com/ideditor/schema-builder?tab=readme-ov-file#strings)
66 | to a combo field.
67 |
68 | Before adding a new field that a preset requires, confirm it is indeed absent. Not all
69 | fields are listed: sometimes people just forget that e.g. `capacity=*` fits not only
70 | bicycle racks, but also benches. Note that there can be multiple fields for a single
71 | key, when the context differs. For `capacity`, there are three, technically differing
72 | only by labels:
73 | [parking spaces](https://github.com/openstreetmap/id-tagging-schema/blob/main/data/fields/capacity_parking.json),
74 | [countable capacity](https://github.com/openstreetmap/id-tagging-schema/blob/main/data/fields/capacity.json),
75 | and [volume](https://github.com/openstreetmap/id-tagging-schema/blob/main/data/fields/capacity_volume.json).
76 |
77 | As mentioned above, a new field might only need three properties:
78 |
79 | ```json
80 | {
81 | "key": "tactile_paving",
82 | "type": "check",
83 | "label": "Tactile Paving"
84 | }
85 | ```
86 |
87 | Read the [schema definition](https://github.com/ideditor/schema-builder?tab=readme-ov-file#fields)
88 | to learn where to put the file, and how to choose the `type`. It's the single most
89 | important property with ~30 possible values, defining how the field looks and behaves.
90 |
91 | Often you might want to add restrictions and details with other properties, e.g.
92 | `placeholder` for text fields, `minValue` for numbers, `strings` for combo fields.
93 | Those are also listed in the schema.
94 |
95 | Note that by default, only `label` and `placeholder` are translatable.
96 | For combo and checkbox fields you might want to make options translatable
97 | too by listing the most common ones in the
98 | [strings](https://github.com/ideditor/schema-builder?tab=readme-ov-file#strings) property.
99 |
100 | As with presets, Every Door will see your change only after it's been merged and included
101 | in the published build. And you can also [define a field](../plugins/metadata/presets.md#fields)
102 | in your own plugin.
103 |
104 | ## Name Suggestion Index
105 |
106 | When you map a KFC or a Shell fuel station, you would add many tags that are common to other
107 | KFC or Shell objects not only in your country, but in the whole world. Like the name,
108 | brand, wikipedia and wikidata links, cuisine, fuel types etc. And you might make typos
109 | in the process. To avoid this redundant work, the
110 | [Name Suggestion Index](https://github.com/osmlab/name-suggestion-index) was created to
111 | catalogue tagging for common franchises and brands, both local and global.
112 |
113 | At the base level, an NSI entry is just a name and a list of tags to put on an object.
114 | And maybe some terms to make searching easier. In Every Door, you search for a brand,
115 | get a gray tile with it, tap it, and get an editor pane with all tags pre-filled.
116 | Entries also include an area where the brand is active, `"001"` meaning the entire world.
117 | It commonly looks like this:
118 |
119 | ```json
120 | {
121 | "displayName": "Frasers",
122 | "id": "frasers-3fbcc0",
123 | "locationSet": {"include": ["na", "za"]},
124 | "tags": {
125 | "brand": "Frasers",
126 | "brand:wikidata": "Q116740926",
127 | "name": "Frasers",
128 | "shop": "bag"
129 | }
130 | }
131 | ```
132 |
133 | To contribute to NSI, you must know the project structure and the meaning of properties.
134 | They are documented on the wiki: see the [Overview](https://github.com/osmlab/name-suggestion-index/wiki/Contributing),
135 | [Category Files](https://github.com/osmlab/name-suggestion-index/wiki/Category-Files)
136 | for the schema, and a guide on
137 | [Adding missing entities](https://github.com/osmlab/name-suggestion-index/wiki/Adding-Wikidata-Tags#adding-missing-entities).
138 |
139 | Locally, you can have an NSI preset in a plugin. For that, simply omit the `fields` list.
140 | Note that NSI presets do not participate in type detection, so you will see "Post Box"
141 | in the micromapping legend for any post box, even a branded one that has an NSI entry for it.
142 |
143 | ## Personal Presets
144 |
145 | Some presets are not meant to go into iD or other public instances: they are too local,
146 | too focused on the task. For example, when you have a town-wide project to map the state
147 | of waste baskets, adding many auxillary tags. Or a proposal is not yet accepted, so there
148 | is low chance of your pull request being merged to the global tagging.
149 |
150 | You can have personal presets in Every Door, and even share them with other people. That
151 | would be a part of a plugin. Read on [adding presets to plugins](../plugins/metadata/presets.md).
152 |
--------------------------------------------------------------------------------
/assets/images/appstore-fdroid.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
9 |
10 |
12 |
13 |
16 |
17 |
21 |
25 |
29 |
33 |
38 |
39 |
40 |
43 |
44 |
45 |
46 |
47 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
74 |
75 |
76 |
78 |
79 |
81 |
83 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
121 |
122 |
123 |
124 |
125 |
--------------------------------------------------------------------------------
/docs/images/appstore-fdroid.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
9 |
10 |
12 |
13 |
16 |
17 |
21 |
25 |
29 |
33 |
38 |
39 |
40 |
43 |
44 |
45 |
46 |
47 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
74 |
75 |
76 |
78 |
79 |
81 |
83 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
121 |
122 |
123 |
124 |
125 |
--------------------------------------------------------------------------------
/assets/plugins/jquery-flipster/dist/jquery.flipster.css:
--------------------------------------------------------------------------------
1 | /*! jQuery.Flipster, v1.1.2 (built 2017-11-10) */
2 | /* @group Flipster Essential Styles */
3 | .flipster {
4 | display: block;
5 | overflow-x: hidden;
6 | overflow-y: visible;
7 | position: relative;
8 | }
9 | .flipster:focus {
10 | outline: none;
11 | }
12 | .flipster__container,
13 | .flipster__item {
14 | margin: 0;
15 | padding: 0;
16 | list-style-type: none;
17 | position: relative;
18 | }
19 | .flipster__container {
20 | display: block;
21 | white-space: nowrap;
22 | word-spacing: -0.25em;
23 | transform-origin: 50% 50%;
24 | backface-visibility: hidden;
25 | }
26 | .flipster__item {
27 | display: inline-block;
28 | white-space: normal;
29 | word-spacing: normal;
30 | vertical-align: bottom;
31 | }
32 | .flipster--click .flipster__item--past,
33 | .flipster--click .flipster__item--future {
34 | cursor: pointer;
35 | }
36 | .flipster__item img {
37 | max-width: 100%;
38 | }
39 | /* @end */
40 |
41 | /* @group Flipster Previous & Next Buttons */
42 | .flipster__button {
43 | position: absolute;
44 | top: 50%;
45 | display: block;
46 | appearance: none;
47 | background: none;
48 | border: none;
49 | padding: 0;
50 | z-index: 999;
51 | cursor: pointer;
52 | font-size: 15px;
53 | opacity: 0.5;
54 | transition: opacity 500ms ease;
55 | margin: -1em 2em;
56 | }
57 | .flipster__button svg {
58 | width: 2em;
59 | stroke: currentColor;
60 | fill: transparent;
61 | stroke-width: 3;
62 | stroke-linecap: round;
63 | }
64 | .flipster__button:hover,
65 | .flipster__button:focus {
66 | opacity: 1;
67 | }
68 | .flipster__button--prev {
69 | left: 0;
70 | }
71 | .flipster__button--next {
72 | right: 0;
73 | }
74 | /* @end */
75 |
76 | /* @group Flipster Navigation */
77 | .flipster__nav,
78 | .flipster__nav__item {
79 | list-style-type: none;
80 | margin: 0;
81 | padding: 0;
82 | }
83 | .flipster__nav {
84 | display: block;
85 | margin: 0 0 4em;
86 | text-align: center;
87 | position: relative;
88 | }
89 | .flipster__nav__item {
90 | display: inline-block;
91 | margin: 0 0.25em;
92 | }
93 | .flipster__nav__link {
94 | display: block;
95 | color: inherit;
96 | padding: 0.5em 1em;
97 | position: relative;
98 | overflow: hidden;
99 | transition: all 250ms ease-out;
100 | transition-timing-function: cubic-bezier(0.56, 0.12, 0.12, 0.98);
101 | }
102 | .flipster__nav__link::after {
103 | content: '';
104 | display: block;
105 | background: #232221;
106 | position: absolute;
107 | top: 0;
108 | left: 0;
109 | width: 100%;
110 | height: 100%;
111 | z-index: -1;
112 | transform: translateY(100%) translateY(-0.25em);
113 | transition: inherit;
114 | }
115 | .flipster__nav__item--current > .flipster__nav__link,
116 | .flipster__nav__link:hover,
117 | .flipster__nav__link:focus {
118 | color: #FFF;
119 | }
120 | .flipster__nav__item--current > .flipster__nav__link::after,
121 | .flipster__nav__link:hover::after,
122 | .flipster__nav__link:focus::after {
123 | transform: translateY(0);
124 | }
125 | .flipster__nav__child {
126 | display: none;
127 | position: absolute;
128 | top: 100%;
129 | left: 0;
130 | right: 0;
131 | margin-top: -1px;
132 | padding: 0.5em;
133 | background: #4e4441;
134 | z-index: 1;
135 | }
136 | .flipster__nav__child .flipster__nav__link {
137 | color: #FFF;
138 | }
139 | .flipster__nav__child .flipster__nav__link::after {
140 | background: #FFF;
141 | }
142 | .flipster__nav__child .flipster__nav__item--current > .flipster__nav__link,
143 | .flipster__nav__child .flipster__nav__link:hover,
144 | .flipster__nav__child .flipster__nav__link:focus {
145 | color: #232221;
146 | }
147 | .flipster__nav__item--current .flipster__nav__child {
148 | display: block;
149 | }
150 | /* @end */
151 |
152 | /* @group Flipster Carousel Theme */
153 | .flipster--carousel .flipster__container,
154 | .flipster--carousel .flipster__item,
155 | .flipster--carousel .flipster__item__content {
156 | transition: all 350ms ease-in-out;
157 | transition-timing-function: cubic-bezier(0.56, 0.12, 0.12, 0.98);
158 | }
159 | .flipster--carousel .flipster__item {
160 | perspective: 800px;
161 | }
162 | .flipster--carousel .flipster__item--past,
163 | .flipster--carousel .flipster__item--future {
164 | opacity: 0;
165 | transition-delay: 115ms;
166 | }
167 | .flipster--carousel .flipster__item--past-2,
168 | .flipster--carousel .flipster__item--future-2 {
169 | opacity: 0.6;
170 | transition-delay: 90ms;
171 | }
172 | .flipster--carousel .flipster__item--past-1,
173 | .flipster--carousel .flipster__item--future-1 {
174 | opacity: 0.8;
175 | transition-delay: 60ms;
176 | }
177 | .flipster--carousel .flipster__item--past .flipster__item__content {
178 | transform: translateX(100%) rotateY(-20deg) scale(0.5);
179 | }
180 | .flipster--carousel .flipster__item--past-2 .flipster__item__content {
181 | transform: translateX(25%) rotateY(40deg) scale(0.65);
182 | }
183 | .flipster--carousel .flipster__item--past-1 .flipster__item__content {
184 | transform: rotateY(45deg) scale(0.8);
185 | }
186 | .flipster--carousel .flipster__item--future .flipster__item__content {
187 | transform: translateX(-100%) rotateY(20deg) scale(0.5);
188 | }
189 | .flipster--carousel .flipster__item--future-2 .flipster__item__content {
190 | transform: translateX(-25%) rotateY(-40deg) scale(0.65);
191 | }
192 | .flipster--carousel .flipster__item--future-1 .flipster__item__content {
193 | transform: rotateY(-45deg) scale(0.8);
194 | }
195 | .flipster--carousel.no-rotate .flipster__item--past .flipster__item__content {
196 | transform: translateX(175%) scale(0.5);
197 | }
198 | .flipster--carousel.no-rotate .flipster__item--past-2 .flipster__item__content {
199 | transform: translateX(25%) scale(0.65);
200 | }
201 | .flipster--carousel.no-rotate .flipster__item--past-1 .flipster__item__content {
202 | transform: translateX(0%) scale(0.8);
203 | }
204 | .flipster--carousel.no-rotate .flipster__item--future .flipster__item__content {
205 | transform: translateX(-175%) scale(0.5);
206 | }
207 | .flipster--carousel.no-rotate .flipster__item--future-2 .flipster__item__content {
208 | transform: translateX(-25%) scale(0.65);
209 | }
210 | .flipster--carousel.no-rotate .flipster__item--future-1 .flipster__item__content {
211 | transform: translateX(0%) scale(0.8);
212 | }
213 | .flipster--carousel .flipster__item--current .flipster__item__content {
214 | transform: translateX(0) rotateY(0deg) scale(1);
215 | transition-delay: 60ms;
216 | }
217 | /* @end */
218 |
219 | /* @group Flipster Coverflow Theme */
220 | .flipster--coverflow .flipster__container,
221 | .flipster--coverflow .flipster__item,
222 | .flipster--coverflow .flipster__item__content {
223 | transition: all 350ms ease-in-out;
224 | transition-timing-function: cubic-bezier(0.56, 0.12, 0.12, 0.98);
225 | }
226 | .flipster--coverflow .flipster__item {
227 | perspective: 800px;
228 | }
229 | .flipster--coverflow .flipster__container {
230 | padding-bottom: 5%;
231 | }
232 | .flipster--coverflow .flipster__item__content {
233 | transform-origin: 50% 100%;
234 | box-reflect: below 0 -webkit-gradient(linear, left bottom, left top, color-stop(0.05, rgba(255, 255, 255, 0.12)), color-stop(0.2, transparent));
235 | -webkit-box-reflect: below 0 -webkit-gradient(linear, left bottom, left top, color-stop(0.05, rgba(255, 255, 255, 0.12)), color-stop(0.2, transparent));
236 | }
237 | .flipster--coverflow .flipster__item__content img:only-child {
238 | display: block;
239 | }
240 | .flipster--coverflow .flipster__item--past .flipster__item__content {
241 | transform-origin: 0% 50%;
242 | transform: scale(0.75) rotateY(55deg);
243 | }
244 | .flipster--coverflow .flipster__item--future .flipster__item__content {
245 | transform-origin: 100% 50%;
246 | transform: scale(0.75) rotateY(-55deg);
247 | }
248 | .flipster--coverflow .flip-current .flipster__item__content {
249 | transform: rotateY(0deg);
250 | }
251 | /* @end */
252 |
253 | /* @group Flat */
254 | .flipster--flat .flipster__container,
255 | .flipster--flat .flipster__item,
256 | .flipster--flat .flipster__item__content {
257 | transition: all 400ms ease-in-out;
258 | }
259 | .flipster--flat .flipster__item--past,
260 | .flipster--flat .flipster__item--future {
261 | opacity: 0.5;
262 | }
263 | .flipster--flat .flipster__item--past .flipster__item__content {
264 | transform: scale(0.75);
265 | }
266 | .flipster--flat .flipster__item--future .flipster__item__content {
267 | transform: scale(0.75);
268 | }
269 | /* @end */
270 |
271 | /* @group Flipster Wheel Theme */
272 | .flipster--wheel {
273 | overflow: hidden;
274 | }
275 | .flipster--wheel .flipster__container,
276 | .flipster--wheel .flipster__item__content {
277 | transition: all 400ms ease-in-out;
278 | transition-timing-function: cubic-bezier(0.56, 0.12, 0.12, 0.98);
279 | }
280 | .flipster--wheel .flipster__container {
281 | padding-bottom: 20%;
282 | }
283 | .flipster--wheel .flipster__item__content {
284 | transform-origin: 50% 100%;
285 | }
286 | .flipster--wheel .flipster__item--past .flipster__item__content {
287 | transform-origin: 100% 100%;
288 | }
289 | .flipster--wheel .flipster__item--future .flipster__item__content {
290 | transform-origin: 0% 100%;
291 | }
292 | .flipster--wheel .flipster__item__content img:only-child {
293 | display: block;
294 | }
295 | .flipster--wheel .flipster__item--past .flipster__item__content {
296 | opacity: 0;
297 | transform: rotateZ(-80deg) translate(-170%, 110%);
298 | }
299 | .flipster--wheel .flipster__item--future .flipster__item__content {
300 | opacity: 0;
301 | transform: rotateZ(80deg) translate(170%, 110%);
302 | }
303 | .flipster--wheel .flipster__item--past-3 .flipster__item__content {
304 | opacity: 1;
305 | transform: rotateZ(-60deg) translate(-70%, 75%);
306 | }
307 | .flipster--wheel .flipster__item--future-3 .flipster__item__content {
308 | opacity: 1;
309 | transform: rotateZ(60deg) translate(70%, 75%);
310 | }
311 | .flipster--wheel .flipster__item--past-2 .flipster__item__content {
312 | opacity: 1;
313 | transform: rotateZ(-40deg) translate(-17%, 30%);
314 | }
315 | .flipster--wheel .flipster__item--future-2 .flipster__item__content {
316 | opacity: 1;
317 | transform: rotateZ(40deg) translate(17%, 30%);
318 | }
319 | .flipster--wheel .flipster__item--past-1 .flipster__item__content {
320 | opacity: 1;
321 | transform: rotateZ(-20deg);
322 | }
323 | .flipster--wheel .flipster__item--future-1 .flipster__item__content {
324 | opacity: 1;
325 | transform: rotateZ(20deg);
326 | }
327 | .flipster--wheel .flip-current .flipster__item__content {
328 | transform: rotateX(0deg);
329 | }
330 | /* @end */
331 |
--------------------------------------------------------------------------------
/docs/develop/cases.md:
--------------------------------------------------------------------------------
1 | # How To Find Things
2 |
3 | The size of the code might be daunting (it is for me, the author), so this section
4 | is intended to help with finding, where exactly to contribute when you want to change
5 | something.
6 |
7 | Note that the code is in a constant (but glacial) flux, so some of those might be
8 | possible to change with a plugin in the future.
9 |
10 | ## Editing Standard Fields
11 |
12 | As mentioned in the [plugin docs](../plugins/metadata/presets.md), "standard fields" is
13 | a third group of fields that gets added on top of "fields" and "more fields" for every
14 | object in the editor panel. This chapter traces its addition, marking what and where
15 | can be improved.
16 |
17 | ### OsmChange
18 |
19 | First we must mention that the single most important class in the app is
20 | [`OsmChange`](https://github.com/Zverik/every_door/blob/v6.0/lib/models/amenity.dart).
21 | It defines a set of changes over the base `OsmElement` received from OpenStreetMap,
22 | and a few methods to manipulate an object. For example, it acts as a `Map`
23 | for tags, but keeps the changes separate.
24 |
25 | It can calculate an age based on the `check_date`
26 | tag (but note that it's a bit inconsistent with the overridden values for the
27 | `amenity` mode). There are methods to confirm an object (`check()`) and to toggle
28 | its disused status. The one most important method that's used everywhere returns
29 | full tags in a map: `getFullTags()`. It is of course cached.
30 |
31 | ### Detecting a Preset
32 |
33 | Now, to learn whether we need to add and shuffle fields, we first need to detect
34 | a preset. Let's look at `PoiEditorPage`'s state. In the `initState()`, the `amenity`
35 | (the object we edit) is either copied or created anew, and
36 | [`updatePreset()`](https://github.com/Zverik/every_door/blob/v6.0/lib/screens/editor.dart#L101)
37 | is called. For an already existing object (or a newly created from an NSI preset),
38 | we call [`getPresetForTags()`](https://github.com/Zverik/every_door/blob/v6.0/lib/providers/presets.dart#L231)
39 | from a preset provider.
40 |
41 | That method has got a lot of steps: checking for empty tags and `amenity=fixme` tags,
42 | asks plugins for an answer. But the main step is running a huge SQL query against
43 | the local SQLite database, which through clever CTE and sorting returns the one result.
44 |
45 | Is it good to have a single big SQL query? Felt like a clever idea at the time, but
46 | now I'm not so sure. But this method gets called dozens of times per second in the
47 | micromapping mode, so this could be considered optimizing.
48 |
49 | ### Localization
50 |
51 | All presets and fields are translated, so we pass the current `Locale` to preset
52 | provider methods. The plugin subsystem too requires it — and that's basically it.
53 | App localization is handled by the [intl](https://docs.flutter.dev/ui/accessibility-and-internationalization/internationalization)
54 | package.
55 |
56 | Passing locales to SQL queries in the preset provider works relatively simple.
57 | We [create a CTE](https://github.com/Zverik/every_door/blob/v6.0/lib/providers/presets.dart#L92)
58 | for a `langs` table that contains two columns, language
59 | code and a rank, starting with 1. And we join the results with this table,
60 | ordered by the language rank. Since window functions do not work in some
61 | SQLite versions, we just query all the results and keep the first one for
62 | each preset or field.
63 |
64 | ### Querying Fields
65 |
66 | After we have a preset, we call [`getFields()`](https://github.com/Zverik/every_door/blob/v6.0/lib/providers/presets.dart#L460)
67 | Initially a preset is returned with empty fields, because its name and title
68 | can be all we need (e.g. for the micromapping mode). But for the editor, we need
69 | the fields. And we do another SQL query to the presets database,
70 | querying the `fields` table with the list from the `preset_fields`.
71 |
72 | Besides checking for a location, sorting languages, and sorting into two
73 | lists ("fields" and "more fields", based on the `required` flag), it does two
74 | more things.
75 |
76 | First is building the combo options. While needed only for combo fields,
77 | it is a very resource-intensive operation, since it conflates three sources:
78 |
79 | 1. Options listed in the field definition.
80 | 2. Popular tag values from TagInfo.
81 | 3. Popular tag values from all the downloaded data.
82 |
83 | The result is stored in a database table, to not do this again. But still, it is
84 | another database query, so make it four for cache misses.
85 |
86 | That's why the `getFields()` method implements its own in-memory caching. You
87 | can notice how long the first loading of the editor pane takes. That's because
88 | in the collapsed "more fields" section there are dozens of combo fields.
89 |
90 | Finally, the method calls the long `fieldFromJson` function from
91 | [`field.dart`](https://github.com/Zverik/every_door/blob/main/lib/models/field.dart).
92 | It has some overrides for common keys, and for others, it uses the type.
93 | It is pretty straightforward. When you're adding a field, do not forget
94 | to create it _twice_ in this file, in both functions.
95 |
96 | ### Built-in Fields
97 |
98 | For some OSM keys (not preset names, and not field types) there are specific
99 | classes instantiated in the `fieldFromJson()`. For example, `NamePresetField`
100 | for a name, or a `WebsiteField` for a website. Those provide unique experience
101 | in Every Door, often with shortcuts to edit tags faster, or set multiple tags
102 | at once considering the context.
103 |
104 | ### Postcode and Opening Hours
105 |
106 | Note that field processing (this section, standard fields etc) happens only
107 | when the object "[needs address](https://github.com/Zverik/every_door/blob/v6.0/lib/screens/editor.dart#L93)".
108 | Which means, it's either an amenity, a building, or an address point.
109 |
110 | First thing, an opening hours field is added unconditionally. Things just tend
111 | to have those.
112 |
113 | Then, a postal code (zip code) field is added. It is partially a hack: the address
114 | field in the default presets includes everything, but is not used. Instead, a custom
115 | field is added in Every Door, but it
116 | does not set a postcode (because it's a building property, not an amenity's).
117 | But some mappers might need it. For buildings and address points it is added to the
118 | main fields list, for other objects — to the additional list.
119 |
120 | ### Standard Fields
121 |
122 | An amenity is considered to need the full standard fields set when its preset mentions
123 | both `opening_hours` and `phone` anywhere. Otherwise a shorter list of just two
124 | fields is added, for an address and a floor.
125 |
126 | You can find the list of fields in
127 | [`kStandardPoiFields`](https://github.com/Zverik/every_door/blob/v6.0/lib/providers/presets.dart#L612).
128 | Note that it is constant, not dependent on anything. Each field is constructed
129 | alike to the `getFields()` method: queried from the preset database, injected
130 | with combo options, and cached. Plugins of course contribute to the results.
131 |
132 | When we don't need the full set, but a preset mentions some fields from the
133 | list, they are moved to the standard fields section as well.
134 |
135 | ### Sorting Fields
136 |
137 | At this point, we have three lists of `PresetField` instances:
138 | pre-filled `stdFields`, and empty `fields` and `moreFields`.
139 | The [`extractFields()`](https://github.com/Zverik/every_door/blob/v6.0/lib/screens/editor.dart#L191)
140 | method copies field instances from the preset to the latter two lists.
141 |
142 | With two exceptions: first, the standard fields are obviously skipped.
143 | Second, any fields from the `moreFields` are moved to `fields` if their
144 | key is present on the object, or they have a matching
145 | [prerequisite](https://github.com/ideditor/schema-builder?tab=readme-ov-file#prerequisitetag).
146 |
147 | After this we have all three list prepared, and can re-render the editor page,
148 | displaying them to the user.
149 |
150 | ## Zooming Out
151 |
152 | Every Door uses [flutter\_map](https://pub.dev/packages/flutter_map) library for its mapping.
153 | Over the years it's been doing pretty complex things with it (but not "going native" complex).
154 | This section is mostly about providers and components: what happens when you change modes
155 | implicitly.
156 |
157 | ### Map Controllers
158 |
159 | Flutter map instances report their state and can be controller via `MapController` objects.
160 | Note that when you use it for yourself, there are
161 | [certain troubles](https://docs.fleaflet.dev/usage/programmatic-interaction/external-custom-controllers)
162 | you have to go through.
163 |
164 | When you use the [`CustomMap`](https://github.com/Zverik/every_door/blob/main/lib/widgets/map.dart)
165 | widget in Every Door code, for bi-directional conversation
166 | you would pass the `CustomMapController`, which gets connected to the internal fields
167 | of the widget. With it, you can:
168 |
169 | * Access the `MapController` itself, so that you can access and affect the map state
170 | from outer listeners.
171 | * Access the `GlobalKey` for the `FlutterMap` widget. It is used once, for detecting
172 | its geometry on the screen.
173 | * Zoom the map to a list of locations. Useful for amenities and micromapping modes.
174 |
175 | In the `CustomMap` itself, there is a lengthy `MapEvent` listener. It only processes
176 | user-initiated events, and does this:
177 |
178 | * After moving the map, it updates the center location in `effectiveLocationProvider`.
179 | * After rotating, it updated the angle in `rotationProvider` (the value is commonly
180 | used for `initialRotation` property of the `FlutterMap` constructor).
181 | * During the map movement initiated by the user, it disables GPS tracking
182 | (in `trackingProvider`), and updates the zoom level in `zoomProvider`.
183 |
184 | And when the `switchToNavigate` flag is set, it also controls the navigation mode switch.
185 |
186 | ### Modes and the Browser
187 |
188 | ### Interactivity
189 |
190 | _Decisions on zoom levels and interactivity_
191 |
192 | ## Uploading to OpenStreetMap
193 |
194 | This section traces what happens when a user taps the upload button, but does not explain
195 | the entire uploading algorithm: it's a bit too complex. It would be useful to you to
196 | understand how providers interact, and how the data is packaged.
197 |
198 | _This section will be completed later._
199 |
200 | 1. Nav panel, upload button
201 | 2. Upload provider
202 | 3. Locking
203 | 4. Uploading OSM changes
204 | * Splitting changes
205 | * Downloading data
206 | * Uploading data
207 | * Updating the inner storage
208 | 5. Uploading notes
209 | 6. Uploading scribbles
210 | 7. Notification
211 |
--------------------------------------------------------------------------------