Compare commits

..

80 Commits

Author SHA1 Message Date
zyphlar
6dc3036fcf htmldir
Signed-off-by: zyphlar <zyphlar@noreply.codeberg.org>
2026-01-01 06:08:10 +01:00
zyphlar
36a65945ba remove branch and unused vars
Signed-off-by: zyphlar <zyphlar@noreply.codeberg.org>
2026-01-01 00:01:28 +01:00
zyphlar
5c53a3cad6 actually use cities.txt
Signed-off-by: zyphlar <zyphlar@noreply.codeberg.org>
2025-12-31 22:50:15 +01:00
zyphlar
3bea0b32a2 change arguments
Signed-off-by: zyphlar <zyphlar@noreply.codeberg.org>
2025-12-31 08:23:53 +01:00
zyphlar
925ce544bc use test branch
Signed-off-by: zyphlar <zyphlar@noreply.codeberg.org>
2025-12-31 06:57:52 +01:00
zyphlar
599b3b81ec typo
Signed-off-by: zyphlar <zyphlar@noreply.codeberg.org>
2025-12-30 15:27:04 -08:00
zyphlar
2d981cde05 clone main repo too
Signed-off-by: zyphlar <zyphlar@noreply.codeberg.org>
2025-12-30 15:27:04 -08:00
zyphlar
8670cb7b43 update pbf
Either move to o5m for subways or remove from here

Signed-off-by: zyphlar <zyphlar@noreply.codeberg.org>
2025-12-30 15:27:04 -08:00
zyphlar
a73ffe96c5 fix cicd
Signed-off-by: zyphlar <zyphlar@noreply.codeberg.org>
2025-12-30 15:27:04 -08:00
Jean-Baptiste
899df496ba [android] Rework some styles text
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-30 20:57:03 +01:00
Jean-Baptiste
47f959ec07 [android] Show error message behind text field instead in a floating view
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-30 20:56:46 +01:00
Jean-Baptiste
6e8a0f22e6 [android] Improve color of icons in settings
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-30 20:47:00 +01:00
Jean-Baptiste
2a2007a473 [android] Move url translations to do not translate file
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-30 18:06:24 +01:00
Jean-Baptiste
db91e3ea92 [android] Fix camera cutout offset in navigation
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-30 17:41:10 +01:00
Jean-Baptiste
3705abbbd6 [android] Use M3 background in dark mode
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-30 17:40:51 +01:00
Bastian Greshake Tzovaras
f33bfffbe6 resolve conflicts
Signed-off-by: Bastian Greshake Tzovaras <bgreshake@googlemail.com>
2025-12-30 17:38:05 +01:00
Jean-Baptiste
72eeceb021 [android] Simplify toolbar styles and themes
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-30 17:27:10 +01:00
map-per
372a7f47d3 [search] Add German search strings
Signed-off-by: map-per <map-per@gmx.de>
2025-12-30 16:36:01 +01:00
map-per
49f4971015 [editor] More types can be marked as vacant
Signed-off-by: map-per <map-per@gmx.de>
2025-12-30 12:31:08 +01:00
map-per
45224d1bd0 [editor] More reliable check for deprecated and moved features
Signed-off-by: map-per <map-per@gmx.de>
2025-12-30 11:48:54 +01:00
Jean-Baptiste
26ec203e41 [android] Remove old properties used in booking ads implementation
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-30 11:10:52 +01:00
zyphlar
ee1081bc7d subway check
Signed-off-by: zyphlar <zyphlar@gmail.com>
2025-12-30 09:14:17 +01:00
Konstantin Pastbin
5050dea70f [android][build] Run configure.sh for publish* gradle tasks
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-12-30 07:58:37 +01:00
Codeberg Translate
9bb29578d0 [strings] Update from Codeberg Translate
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: Diabolo68 <diabolo68@noreply.codeberg.org>
Co-authored-by: ERYpTION <eryption@noreply.codeberg.org>
Co-authored-by: Edgarsons <edgarsons@noreply.codeberg.org>
Co-authored-by: Fjuro <fjuro@alius.cz>
Co-authored-by: JanezPavelZebovec <janezpavelzebovec@noreply.codeberg.org>
Co-authored-by: Juan M Sevilla <jumase@noreply.codeberg.org>
Co-authored-by: Mickael81 <mickael81@noreply.codeberg.org>
Co-authored-by: N4ta <codeberg@n4ta.anonaddy.me>
Co-authored-by: Prefill add-on <noreply-addon-prefill@weblate.org>
Co-authored-by: Priit Jõerüüt <jrtcdbrg@noreply.codeberg.org>
Co-authored-by: Schmerling <schmerling@noreply.codeberg.org>
Co-authored-by: Stephan-P <stephan-p@noreply.codeberg.org>
Co-authored-by: Supaplextw <supaplextw@noreply.codeberg.org>
Co-authored-by: Weblate <noreply-mt-weblate@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: ZeljkoBG <zeljkobg@noreply.codeberg.org>
Co-authored-by: aoxa <aoxa@noreply.codeberg.org>
Co-authored-by: arnyminerz <arnyminerz@noreply.codeberg.org>
Co-authored-by: artnay <artnay@noreply.codeberg.org>
Co-authored-by: astro-ray <astro-ray@noreply.codeberg.org>
Co-authored-by: baurzhanm <baurzhanm@noreply.codeberg.org>
Co-authored-by: codebergian42 <codebergian42@noreply.codeberg.org>
Co-authored-by: eBug <ebug@noreply.codeberg.org>
Co-authored-by: gedankenstuecke <gedankenstuecke@noreply.codeberg.org>
Co-authored-by: ggs <ggs@noreply.codeberg.org>
Co-authored-by: in-Dev <in-dev@noreply.codeberg.org>
Co-authored-by: jimkats <jimkats@noreply.codeberg.org>
Co-authored-by: ldmpub <ldmpub@noreply.codeberg.org>
Co-authored-by: loscati <loscati@noreply.codeberg.org>
Co-authored-by: ma12vlad <ma12vlad@noreply.codeberg.org>
Co-authored-by: mcliquid <mcliquid@noreply.codeberg.org>
Co-authored-by: metehan <metehan@noreply.codeberg.org>
Co-authored-by: ovl-005 <ovl-005@noreply.codeberg.org>
Co-authored-by: patepelo <patepelo@noreply.codeberg.org>
Co-authored-by: phama <phama@noreply.codeberg.org>
Co-authored-by: rimas <rimas@noreply.codeberg.org>
Co-authored-by: teletext <teletext@noreply.codeberg.org>
Translate-URL: https://translate.codeberg.org/projects/comaps/search-synonyms-aliases/
Translation: CoMaps/Android - Map Feature Types
Translation: CoMaps/Android UI Strings
Translation: CoMaps/Android UI Strings (SDK)
Translation: CoMaps/Countries and regions names
Translation: CoMaps/F-Droid app description
Translation: CoMaps/Google Play and Huawei AppGallery descriptions
Translation: CoMaps/Search synonyms / aliases
Translation: CoMaps/Voice announcements for navigation (TTS)
Translation: CoMaps/iOS - Map Feature Types
Translation: CoMaps/iOS Plurals
Translation: CoMaps/iOS UI Strings
2025-12-29 22:39:31 +00:00
Yannik Bloscheck
33e4894a56 [core] Add language data to world files
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-12-29 16:13:18 +01:00
Bastian Greshake Tzovaras
aa34159ce8 [taginfo] update tags
Signed-off-by: Bastian Greshake Tzovaras <bgreshake@googlemail.com>
2025-12-28 17:38:17 -03:00
Konstantin Pastbin
1ccea5928f [planet] Update map data to 251227
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-12-28 23:14:55 +07:00
map-per
ec59698f4a [editor] Add more complex types and support healthcare and education
Signed-off-by: map-per <map-per@gmx.de>
2025-12-28 16:48:57 +01:00
Jean-Baptiste
0c2763f3ce [doc] Create an security markdown file
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-27 21:53:01 +01:00
Jean-Baptiste
c9a4483f50 [android] Re-organize charging station sockets by power
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-26 16:21:53 +01:00
Jean-Baptiste
0eafe3482e [android] Remove TextAppearance styles text
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-26 14:56:15 +01:00
x7z4w
e4275cdd3c [search] Add synonyms
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-12-24 17:32:23 +01:00
Chris H. Meyer
4ef9395442 [desktop] Update Fedora dependencies (#2957)
Signed-off-by: Chris H. Meyer <christian.h.meyer@t-online.de>
Co-authored-by: Chris H. Meyer <christian.h.meyer@t-online.de>
Co-committed-by: Chris H. Meyer <christian.h.meyer@t-online.de>
2025-12-24 14:19:00 +01:00
Yannik Bloscheck
30cf2b5770 [styles] Fix wrong filename for car pooling parking
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-12-22 12:24:45 +01:00
Yannik Bloscheck
6aed26c48e [ios] Extend opening hours button in editor
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-12-22 12:04:00 +01:00
Jean-Baptiste
dad91b82a6 [android] Remove custom properties in M3 styles
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-21 19:04:59 +01:00
Jean-Baptiste
7024aace6f [android] Remove ToolbarButton styles
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-21 10:40:54 +01:00
Jean-Baptiste
6291133a69 [android] Remove grey background on some views
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-21 10:39:38 +01:00
Jean-Baptiste
1c5121d447 [android] Remove tab time picker view
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-20 14:23:24 +01:00
Yannik Bloscheck
4398e492b8 [iOS] Added new editor files to their Xcode projects
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-12-19 19:45:31 +01:00
map-per
1907e039e3 [editor] Support complex POI types in the editor (#2855)
Signed-off-by: map-per <map-per@gmx.de>
2025-12-19 19:45:31 +01:00
map-per
26bad5dffb [editor] 'discard' and 'delete' buttons only available when nothing was uploaded to OSM
Signed-off-by: map-per <map-per@gmx.de>
2025-12-19 17:37:36 +01:00
Konstantin Pastbin
4f2b479b2c December R2 release notes
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-12-19 16:38:10 +01:00
Viktor Govako
a972552155 [drape] Refactor UpdateVisualScale.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-12-19 16:26:51 +01:00
Konstantin Pastbin
dc54c45482 [planet] Update map data to 251217
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-12-19 16:01:17 +01:00
Codeberg Translate
1975b6a0f0 [strings] Update from Codeberg Translate
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: ERYpTION <eryption@noreply.codeberg.org>
Co-authored-by: Edgarsons <edgarsons@noreply.codeberg.org>
Co-authored-by: JanezPavelZebovec <janezpavelzebovec@noreply.codeberg.org>
Co-authored-by: Outbreak2096 <outbreak2096@noreply.codeberg.org>
Co-authored-by: Priit Jõerüüt <jrtcdbrg@noreply.codeberg.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: patepelo <patepelo@noreply.codeberg.org>
Translation: CoMaps/Android - Map Feature Types
Translation: CoMaps/Android UI Strings
Translation: CoMaps/iOS - Map Feature Types
Translation: CoMaps/iOS UI Strings
2025-12-19 12:49:54 +00:00
map-per
8683853f46 [search] Check for empty/nullptr to fix editor crash (#2904)
Signed-off-by: map-per <map-per@gmx.de>
2025-12-19 13:49:30 +01:00
Yannik Bloscheck
d7e34c2685 [search] Fix search for vegan and vegetarian places
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-12-19 13:11:05 +01:00
Konstantin Pastbin
0028306b26 [search] Fix compilation (add missing comma)
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-12-19 12:36:51 +07:00
x7z4w
b5354fd1e3 [search] Add synonyms
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-12-19 04:12:12 +01:00
x7z4w
964f82510a [drape] Set Harfbuzz language to map language
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-12-19 04:09:13 +01:00
Konstantin Pastbin
faf49fc574 [tts] Revert values changes done in #2752 4f739d98b
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-12-19 09:25:00 +07:00
Jean-Baptiste
60b1ad232a [android] Clean background color in views
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-18 21:31:25 +01:00
Jean-Baptiste
1bac0fd4fc [search] Improve search terms in french
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-18 20:35:30 +01:00
Codeberg Translate
ed6dcc5cb2 [strings] Update from Codeberg Translate
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: JanezPavelZebovec <janezpavelzebovec@noreply.codeberg.org>
Co-authored-by: N4ta <codeberg@n4ta.anonaddy.me>
Co-authored-by: Prefill add-on <noreply-addon-prefill@weblate.org>
Co-authored-by: Priit Jõerüüt <jrtcdbrg@noreply.codeberg.org>
Co-authored-by: Stephan-P <stephan-p@noreply.codeberg.org>
Co-authored-by: Stzyxh <stzyxh@noreply.codeberg.org>
Co-authored-by: Weblate <noreply-mt-weblate@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: aoxa <aoxa@noreply.codeberg.org>
Co-authored-by: dobridabar <dobridabar@noreply.codeberg.org>
Co-authored-by: map-per <map-per@noreply.codeberg.org>
Co-authored-by: metehan <metehan@noreply.codeberg.org>
Co-authored-by: ovl-005 <ovl-005@noreply.codeberg.org>
Co-authored-by: patepelo <patepelo@noreply.codeberg.org>
Co-authored-by: teletext <teletext@noreply.codeberg.org>
Translate-URL: https://translate.codeberg.org/projects/comaps/android-typestrings/
Translate-URL: https://translate.codeberg.org/projects/comaps/ios-typestrings/
Translation: CoMaps/Android - Map Feature Types
Translation: CoMaps/Android UI Strings
Translation: CoMaps/Apple AppStore description
Translation: CoMaps/Countries and regions names
Translation: CoMaps/Voice announcements for navigation (TTS)
Translation: CoMaps/iOS - Map Feature Types
Translation: CoMaps/iOS UI Strings
2025-12-18 14:24:02 +00:00
Jean-Baptiste
33b440dd71 [android] Remove custom attrs fonts styles
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-18 15:23:52 +01:00
map-per
6a20269819 [editor] Rename button to 'Discard changes'
Signed-off-by: map-per <map-per@gmx.de>
2025-12-18 11:52:47 +01:00
NoelClick
8cd1b41cd2 [android] Update connection failure dialog cancellation behavior
- Update the connection failure dialog in the world download view based on reviewers' feedback.

Signed-off-by: NoelClick <dev@noel.click>
2025-12-18 09:41:55 +01:00
NoelClick
2b630964d0 [android] Unify custom map server dialog logic and UI
- Add setting icon for custom map server download option.
- Extract shared custom map server dialog helper.
- Clean up based on reviewers' feedback.

Signed-off-by: NoelClick <dev@noel.click>
2025-12-18 09:41:55 +01:00
NoelClick
76ecd8209e [android] Improve custom map server dialog UX
Signed-off-by: NoelClick <dev@noel.click>
2025-12-18 09:41:55 +01:00
NoelClick
82d2932ba0 [android] Add validation for custom map download URL
- Add validation for custom map download URL.
- Re-enable advanced server button after failed or paused downloads.

Signed-off-by: NoelClick <dev@noel.click>
2025-12-18 09:41:55 +01:00
NoelClick
85540133b3 [android] Clarify custom map download URL strings
Signed-off-by: NoelClick <dev@noel.click>
2025-12-18 09:41:55 +01:00
NoelClick
6ded75de9c [core] Treat custom map download URL as CDN base, not meta server
- Update `MapFilesDownloader::LoadMetaConfig()` to skip the metaserver when a
  custom base URL is set and build MetaConfig with that URL as the only server.
- Keep the existing metaserver-based behavior when no custom base URL is set.

Signed-off-by: NoelClick <dev@noel.click>
2025-12-18 09:41:55 +01:00
NoelClick
08e8ebd434 [android] Add custom world map download URL option
- Allow setting a custom map download URL in the "world-download" screen.

Signed-off-by: NoelClick <dev@noel.click>
2025-12-18 09:41:55 +01:00
NoelClick
6c92264fb0 [android] Add custom map download URL setting
Signed-off-by: NoelClick <dev@noel.click>
2025-12-18 09:41:55 +01:00
NoelClick
4ba0fc51a5 [android] Make it possible to set a custom map download URL
Signed-off-by: NoelClick <dev@noel.click>
2025-12-18 09:41:55 +01:00
NoelClick
29c363a581 [core] Allow overriding map metaserver URL and reset downloader cache
- Add custom meta server API.
- Implement override.
- Add reset hook and implement reset.
- Expose reset from Storage.
- Let JNI set URL and reset cache.

Signed-off-by: NoelClick <dev@noel.click>
2025-12-18 09:41:55 +01:00
map-per
4973f4fed2 [editor] Lower priority for building in changeset comments
Signed-off-by: map-per <map-per@gmx.de>
2025-12-18 07:53:52 +01:00
map-per
8cffa508f3 [android] Use separate function to check for MapTooOldToEdit
Signed-off-by: map-per <map-per@gmx.de>
2025-12-17 21:07:12 +01:00
map-per
3511dbb692 [android] Adjust margin in editor layout
Signed-off-by: map-per <map-per@gmx.de>
2025-12-16 21:35:31 +01:00
Codeberg Translate
e238a317f1 [strings] Update from Codeberg Translate
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: ERYpTION <eryption@noreply.codeberg.org>
Co-authored-by: Edgarsons <edgarsons@noreply.codeberg.org>
Co-authored-by: Fjuro <fjuro@alius.cz>
Co-authored-by: JanezPavelZebovec <janezpavelzebovec@noreply.codeberg.org>
Co-authored-by: Juno Takano <jutty@noreply.codeberg.org>
Co-authored-by: Mickael81 <mickael81@noreply.codeberg.org>
Co-authored-by: N4ta <codeberg@n4ta.anonaddy.me>
Co-authored-by: Outbreak2096 <outbreak2096@noreply.codeberg.org>
Co-authored-by: Prefill add-on <noreply-addon-prefill@weblate.org>
Co-authored-by: Priit Jõerüüt <jrtcdbrg@noreply.codeberg.org>
Co-authored-by: Stephan-P <stephan-p@noreply.codeberg.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: aoxa <aoxa@noreply.codeberg.org>
Co-authored-by: arnyminerz <arnyminerz@noreply.codeberg.org>
Co-authored-by: artnay <artnay@noreply.codeberg.org>
Co-authored-by: cirilla <cirilla@noreply.codeberg.org>
Co-authored-by: demode <demode@noreply.codeberg.org>
Co-authored-by: gimse <gimse@noreply.codeberg.org>
Co-authored-by: jeanbaptisteC <jeanbaptistec@noreply.codeberg.org>
Co-authored-by: ldmpub <ldmpub@noreply.codeberg.org>
Co-authored-by: loscati <loscati@noreply.codeberg.org>
Co-authored-by: ma12vlad <ma12vlad@noreply.codeberg.org>
Co-authored-by: mnalis <mnalis@noreply.codeberg.org>
Co-authored-by: ovl-005 <ovl-005@noreply.codeberg.org>
Co-authored-by: patepelo <patepelo@noreply.codeberg.org>
Co-authored-by: rimas <rimas@noreply.codeberg.org>
Translate-URL: https://translate.codeberg.org/projects/comaps/android-typestrings/
Translate-URL: https://translate.codeberg.org/projects/comaps/ios-typestrings/
Translation: CoMaps/Android - Map Feature Types
Translation: CoMaps/Android UI Strings
Translation: CoMaps/Countries and regions names
Translation: CoMaps/F-Droid app description
Translation: CoMaps/Google Play and Huawei AppGallery descriptions
Translation: CoMaps/Voice announcements for navigation (TTS)
Translation: CoMaps/iOS - Map Feature Types
Translation: CoMaps/iOS UI Strings
2025-12-16 18:10:27 +00:00
x7z4w
2e85899fcb [search] Add synonym
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-12-16 12:48:48 +01:00
pablogila
ce978d8ede [styles] Add amenity=hydrant
Signed-off-by: pablogila <pablo.gila.herranz@gmail.com>
Co-authored-by: pablogila <pablo.gila.herranz@gmail.com>
Co-committed-by: pablogila <pablo.gila.herranz@gmail.com>
2025-12-16 10:40:18 +01:00
thesupertechie
d56f9700f5 [tts] [routing] further revert out-of-scope changes
Signed-off-by: thesupertechie <thesupertechie1@gmail.com>
2025-12-16 07:27:59 +01:00
thesupertechie
cc042c3d1c [tts] [routing] revert out-of-scope changes
Signed-off-by: thesupertechie <thesupertechie1@gmail.com>
2025-12-16 07:27:59 +01:00
thesupertechie
4f739d98b0 [tts] Change notification to 400-700 m
Signed-off-by: thesupertechie <thesupertechie1@gmail.com>
2025-12-16 07:27:59 +01:00
Dobri Dabar
4691de7a66 [desktop] Display type names
Signed-off-by: Dobri Dabar <dobridabar@noreply.codeberg.org>
Co-authored-by: Dobri Dabar <dobridabar@noreply.codeberg.org>
Co-committed-by: Dobri Dabar <dobridabar@noreply.codeberg.org>
2025-12-15 19:36:29 +01:00
Jean-Baptiste
3c082b0629 [android] Rework shape of zoom buttons
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-15 18:59:54 +01:00
Jean-Baptiste
a468bd3fab [docs] Update docs and funding config
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-15 13:09:27 +01:00
x7z4w
fc87316184 [search] Fix apartment blocks search
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-12-14 20:52:17 +00:00
625 changed files with 12834 additions and 10335 deletions

View File

@@ -1,69 +1,55 @@
# All non-assigned.
* @organicmaps/mergers
# Visual design. # Visual design.
/android/app/src/main/res/drawable*/ @organicmaps/design /android/app/src/main/res/drawable*/ @comaps/design
/android/app/src/main/res/font/ @organicmaps/design /android/app/src/main/res/font/ @comaps/design
/android/app/src/main/res/mipmap*/ @organicmaps/design /android/app/src/main/res/mipmap*/ @comaps/design
/data/*.ttf @organicmaps/design /data/*.ttf @comaps/design
/data/resources-svg/ @organicmaps/design /data/resources-svg/ @comaps/design
/data/search-icons/ @organicmaps/design /data/search-icons/ @comaps/design
/iphone/Maps/Images.xcassets/ @organicmaps/design /iphone/Maps/Images.xcassets/ @comaps/design
# Android. # Android.
/android/ @organicmaps/android /android/ @comaps/android
/android/app/src/main/java/app/organicmaps/car/ @organicmaps/android-auto /android/app/src/main/java/app/comaps/car/ @comaps/android-auto
/docs/ANDROID_LOCATION_TEST.md @organicmaps/android /docs/ANDROID_LOCATION_TEST.md @comaps/android
/docs/JAVA_STYLE.md @organicmaps/android /docs/JAVA_STYLE.md @comaps/android
# no owner for translation changes # no owner for translation changes
/android/app/src/main/res/values*/strings.xml /android/app/src/main/res/values*/strings.xml
# iOS. # iOS.
/iphone/ @organicmaps/ios /iphone/ @comaps/ios
/xcode/ @organicmaps/ios /xcode/ @comaps/ios
/docs/OBJC_STYLE.md @organicmaps/ios /docs/OBJC_STYLE.md @comaps/ios
# no owner for translation changes # no owner for translation changes
/iphone/plist.txt /iphone/plist.txt
/iphone/Maps/LocalizedStrings/ /iphone/Maps/LocalizedStrings/
# Qt
/qt/ @organicmaps/qt
# Rendering
/drape/ @organicmaps/rendering
/drape_frontend/ @organicmaps/rendering
# Map Data.
/tools/python/maps_generator/ @organicmaps/data
/generator/ @organicmaps/data
/topography_generator/ @organicmaps/data
/data/borders/ @organicmaps/data
/data/conf/isolines/ @organicmaps/data
/docs/SUBWAY_GENERATION.md @organicmaps/data
/docs/MAPS.md @organicmaps/data
/docs/EXPERIMENTAL_PUBLIC_TRANSPORT_SUPPORT.md @organicmaps/data
# no owner (changed often to add a new POI) # no owner (changed often to add a new POI)
/generator/generator_tests/osm_type_test.cpp /generator/generator_tests/osm_type_test.cpp
# Map Styles. # Map Styles.
/data/styles/ @organicmaps/styles /data/styles/ @comaps/styles
/data/types.txt @organicmaps/styles /data/types.txt @comaps/styles
/data/visibility.txt @organicmaps/styles /data/visibility.txt @comaps/styles
/data/mapcss-mapping.csv @organicmaps/styles /data/mapcss-mapping.csv @comaps/styles
/data/replaced_tags.txt @organicmaps/styles /data/replaced_tags.txt @comaps/styles
/data/classificator.txt @organicmaps/styles /data/classificator.txt @comaps/styles
/data/drules_* @organicmaps/styles /data/drules_* @comaps/styles
/docs/STYLES.md /docs/STYLES.md
/tools/kothic/ @organicmaps/styles /tools/kothic/ @comaps/styles
# DevOps. # DevOps.
/.forgejo/workflows @organicmaps/devops /.forgejo/workflows @comaps/devops
/android/*gradle* @organicmaps/devops /android/*gradle* @comaps/devops
/docs/RELEASE_MANAGEMENT.md @organicmaps/devops /docs/RELEASE_MANAGEMENT.md @comaps/devops
/xcode/fastlane/ @organicmaps/devops /xcode/fastlane/ @comaps/devops
# Growth. /tools/python/maps_generator/ @comaps/devops
README.md @organicmaps/growth /generator/ @comaps/devops
/.forgejo/FUNDING.yml @organicmaps/growth /topography_generator/ @comaps/devops
/android/app/src/fdroid/play/ @organicmaps/growth /data/borders/ @comaps/devops
/android/app/src/google/play/ @organicmaps/growth /data/conf/isolines/ @comaps/devops
/iphone/metadata/ @organicmaps/growth /docs/SUBWAY_GENERATION.md @comaps/devops
/docs/MAPS.md @comaps/devops
/docs/EXPERIMENTAL_PUBLIC_TRANSPORT_SUPPORT.md @comaps/devops
# Legal. # Legal.
LEGAL @organicmaps/legal LEGAL @comaps/admins
LICENSE @organicmaps/legal LICENSE @comaps/admins
NOTICE @organicmaps/legal NOTICE @comaps/admins
CONTRIBUTORS @organicmaps/legal CONTRIBUTORS @comaps/admins
/docs/CODE_OF_CONDUCT.md @organicmaps/legal /docs/CODE_OF_CONDUCT.md @comaps/admins
/docs/DCO.md @organicmaps/legal /docs/DCO.md @comaps/admins
/docs/GOVERNANCE.md @organicmaps/legal /docs/GOVERNANCE.md @comaps/admins

View File

@@ -1 +1,3 @@
open_collective: comaps open_collective: comaps
liberapay: comaps
custom: ["https://comaps.app/donate/"]

View File

@@ -0,0 +1,177 @@
name: process_subways
on:
workflow_dispatch: # Manual trigger
env:
#PLANET: /home/planet/planet/planet-latest.pbf
#TMPDIR: /tmp
#HTML_DIR: "/mnt/4tbexternal/osm-planet/subway/validator"
#DUMP: "$HTML_DIR"
#SKIP_PLANET_UPDATE: "1"
DEBIAN_FRONTEND: nonnteractive
TZ: Etc/UTC
# /var/www/html/subways is mapped as a volume on cdn-fi-1
# as is /tmp/planet
jobs:
clone-repos:
name: Clone Git Repos
runs-on: mapfilemaker
container:
image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes:
- /mnt/4tbexternal:/mnt/4tbexternal
concurrency:
group: ${{ github.workflow }}-process-subways-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- uses: actions/cache@v4
with:
path: "~"
key: cache-${{ github.run_id }}-${{ github.run_attempt }}}
- name: Checkout main repo
shell: bash
run: |
echo "Cloning $FORGEJO_SERVER_URL/$FORGEJO_REPOSITORY branch $FORGEJO_REF_NAME"
cd ~
git clone --depth 1 --recurse-submodules --shallow-submodules -b $FORGEJO_REF_NAME --single-branch $FORGEJO_SERVER_URL/$FORGEJO_REPOSITORY.git comaps
- name: Checkout subways repo (TODO zy-fix-validation)
shell: bash
run: |
cd ~
git clone --depth 1 --single-branch https://codeberg.org/comaps/subways.git
update-planet-pbf:
name: Update PBF Planet
runs-on: mapfilemaker
container:
image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes:
- /mnt/4tbexternal/:/mnt/4tbexternal/
- /mnt/4tbexternal/osm-planet:/home/planet
concurrency:
group: ${{ github.workflow }}-process-subways-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- name: Download Planet File if Absent
shell: bash
# TODO: replace wget2 with curl -Z
run: |
if [ ! -d /home/planet/planet/ ]; then
mkdir -p /home/planet/planet/
fi
if [ ! -f /home/planet/planet/planet-latest.osm.pbf ]; then
cd /home/planet/planet/
wget2 --verbose --progress=bar --continue https://ftpmirror.your.org/pub/openstreetmap/pbf/planet-latest.osm.pbf
else
echo "planet-latest.osm.pbf was found, raw download not required."
fi
- name: Update PBF Planet
shell: bash
run: |
cd /home/planet/planet/
rm -f planet-latest-new.osm.pbf
pyosmium-up-to-date planet-latest.osm.pbf -o planet-latest-new.osm.pbf -v --size 16384
mv planet-latest-new.osm.pbf planet-latest.osm.pbf
- name: Notify Zulip
run: |
curl -X POST https://comaps.zulipchat.com/api/v1/messages \
-u $ZULIP_BOT_EMAIL:$ZULIP_API_KEY \
--data-urlencode type=stream \
--data-urlencode 'to="DevOps"' \
--data-urlencode topic=codeberg-bot \
--data-urlencode 'content=PBF planet update is done!'
update-planet-o5m:
if: false
name: Update O5M Planet
runs-on: mapfilemaker
container:
image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes:
- /mnt/4tbexternal/:/mnt/4tbexternal/
- /mnt/4tbexternal/osm-planet:/home/planet
concurrency:
group: ${{ github.workflow }}-process-subways-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- name: Check for O5M Planet File
shell: bash
run: |
if [ ! -f /home/planet/planet/planet.o5m ]; then
echo "WARN: No file at /home/planet/planet/planet.o5m"
if [ ! -f /home/planet/planet/planet-latest.osm.pbf ]; then
echo "ERROR: No file at /home/planet/planet/planet-latest.osm.pbf"
ls -al /home/planet/
ls -al /home/planet/planet/
exit 1
fi
echo "Converting planet-latest.osm.pbf to planet.o5m"
cd /home/planet/planet/
osmconvert -v --drop-author --drop-version --hash-memory=4000 planet-latest.osm.pbf -o=planet.o5m
echo "Conversion is done."
fi
- name: Update O5M planet
run: |
echo "Starting..."
cd /home/planet/planet/
rm -f planet-new.o5m
osmupdate -v --drop-author --drop-version --hash-memory=4000 --max-merge=32 --out-o5m planet.o5m planet-new.o5m
mv planet-new.o5m planet.o5m
echo "Done."
- name: Notify Zulip
run: |
curl -X POST https://comaps.zulipchat.com/api/v1/messages \
-u $ZULIP_BOT_EMAIL:$ZULIP_API_KEY \
--data-urlencode type=stream \
--data-urlencode 'to="DevOps"' \
--data-urlencode topic=codeberg-bot \
--data-urlencode 'content=O5M planet update is done!'
update-subways:
name: Update Subways
runs-on: mapfilemaker
needs:
- clone-repos
container:
image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes:
- /mnt/4tbexternal/:/mnt/4tbexternal/
- /mnt/4tbexternal/osm-planet:/home/planet
concurrency:
group: ${{ github.workflow }}-processs-subways-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- uses: actions/cache@v4
with:
path: "~"
key: cache-${{ github.run_id }}-${{ github.run_attempt }}
- name: Update Subways
shell: bash
run: |
cd ~/comaps/
cp tools/unix/maps/settings.sh.prod tools/unix/maps/settings.sh
./tools/unix/maps/generate_subways.sh
- name: Compare with VK validation
shell: bash
run: |
cd ~/subways
export HTML_DIR=/mnt/4tbexternal/osm-planet/subway/validator
if [ -f "$HTML_DIR/cities.txt" ]; then
echo "Comparing local validation with VK's validation..."
python3 ./scripts/compare_html_validation.py "$HTML_DIR/cities.txt" \
--remote-url "https://maps.vk.com/osm/tools/subways/latest/cities.txt"
else
echo "Local cities.txt not found at $HTML_DIR/cities.txt"
exit 1
fi
- name: Notify Zulip
run: |
curl -X POST https://comaps.zulipchat.com/api/v1/messages \
-u $ZULIP_BOT_EMAIL:$ZULIP_API_KEY \
--data-urlencode type=stream \
--data-urlencode 'to="DevOps"' \
--data-urlencode topic=codeberg-bot \
--data-urlencode 'content=Subways are done!'

View File

@@ -2,5 +2,3 @@
480fa6c2fcf53be296504ac6ba8e6b3d70f92b42 480fa6c2fcf53be296504ac6ba8e6b3d70f92b42
a6ede2b1466f0c9d8a443600ef337ba6b5832e58 a6ede2b1466f0c9d8a443600ef337ba6b5832e58
1377b81bf1cac72bb6da192da7fed6696d5d5281 1377b81bf1cac72bb6da192da7fed6696d5d5281
0288b97b1367bb971eded1018f560598ea274e6c
bf30165b5f5de0907c3c64524a3bf8121624b0b7

3
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,3 @@
open_collective: comaps
liberapay: comaps
custom: ["https://comaps.app/donate/"]

2
.gitignore vendored
View File

@@ -155,6 +155,8 @@ android/huawei-appgallery.json
android/res/xml/network_security_config.xml android/res/xml/network_security_config.xml
./server/ ./server/
iphone/Maps/app.omaps/ iphone/Maps/app.omaps/
# Generated file
libs/indexer/localized_types_map.cpp
*.li *.li

View File

@@ -1,83 +0,0 @@
///////////////////////// ankerl::unordered_dense::{map, set} /////////////////////////
// A fast & densely stored hashmap and hashset based on robin-hood backward shift deletion.
// Version 4.8.1
// https://github.com/martinus/unordered_dense
//
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 Martin Leitner-Ankerl <martin.ankerl@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef ANKERL_STL_H
#define ANKERL_STL_H
#include <array> // for array
#include <cstdint> // for uint64_t, uint32_t, std::uint8_t, UINT64_C
#include <cstring> // for size_t, memcpy, memset
#include <functional> // for equal_to, hash
#include <initializer_list> // for initializer_list
#include <iterator> // for pair, distance
#include <limits> // for numeric_limits
#include <memory> // for allocator, allocator_traits, shared_ptr
#include <optional> // for optional
#include <stdexcept> // for out_of_range
#include <string> // for basic_string
#include <string_view> // for basic_string_view, hash
#include <tuple> // for forward_as_tuple
#include <type_traits> // for enable_if_t, declval, conditional_t, ena...
#include <utility> // for forward, exchange, pair, as_const, piece...
#include <vector> // for vector
// <memory_resource> includes <mutex>, which fails to compile if
// targeting GCC >= 13 with the (rewritten) win32 thread model, and
// targeting Windows earlier than Vista (0x600). GCC predefines
// _REENTRANT when using the 'posix' model, and doesn't when using the
// 'win32' model.
#if defined __MINGW64__ && defined __GNUC__ && __GNUC__ >= 13 && !defined _REENTRANT
// _WIN32_WINNT is guaranteed to be defined here because of the
// <cstdint> inclusion above.
# ifndef _WIN32_WINNT
# error "_WIN32_WINNT not defined"
# endif
# if _WIN32_WINNT < 0x600
# define ANKERL_MEMORY_RESOURCE_IS_BAD() 1 // NOLINT(cppcoreguidelines-macro-usage)
# endif
#endif
#ifndef ANKERL_MEMORY_RESOURCE_IS_BAD
# define ANKERL_MEMORY_RESOURCE_IS_BAD() 0 // NOLINT(cppcoreguidelines-macro-usage)
#endif
#if defined(__has_include) && !defined(ANKERL_UNORDERED_DENSE_DISABLE_PMR)
# if __has_include(<memory_resource>) && !ANKERL_MEMORY_RESOURCE_IS_BAD()
# define ANKERL_UNORDERED_DENSE_PMR std::pmr // NOLINT(cppcoreguidelines-macro-usage)
# include <memory_resource> // for polymorphic_allocator
# elif __has_include(<experimental/memory_resource>)
# define ANKERL_UNORDERED_DENSE_PMR std::experimental::pmr // NOLINT(cppcoreguidelines-macro-usage)
# include <experimental/memory_resource> // for polymorphic_allocator
# endif
#endif
#if defined(_MSC_VER) && defined(_M_X64)
# include <intrin.h>
# pragma intrinsic(_umul128)
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -10,6 +10,7 @@ CoMaps contributors:
Bastian Greshake Tzovaras Bastian Greshake Tzovaras
clover sage clover sage
Harry Bond <me@hbond.xyz> Harry Bond <me@hbond.xyz>
NoelClick
thesupertechie thesupertechie
vikiawv vikiawv
Yannik Bloscheck Yannik Bloscheck

17
SECURITY.md Normal file
View File

@@ -0,0 +1,17 @@
## Reporting Vulnerabilities
You can report a security vulnerability by creating an issue or send mail to security@comaps.app
## Verifying Fingerprints
To [verify](https://developer.android.com/studio/command-line/apksigner#usage-verify) the APK, use the following signing certificate fingerprints:
```
SHA-256: 4894e8e6963627ef660031d8593fe77297f835acb4e23810003e926135023b4c
SHA-1: 8b7b5739f917e9f7c681671ced0c9c8562123ade
MD5: 9cce0ffea281dc2f0e0a154d6d2e281e
```
To verify CoMaps via [AppVerifier](https://github.com/soupslurpr/AppVerifier), use the following signing certificate fingerprint:
```
app.comaps
48:94:E8:E6:96:36:27:EF:66:00:31:D8:59:3F:E7:72:97:F8:35:AC:B4:E2:38:10:00:3E:92:61:35:02:3B:4C
```

View File

@@ -1,10 +1,8 @@
• OpenStreetMap-Daten vom 9. Dezember • OpenStreetMap Daten vom 17. Dezember
• Material 3 Design • Map download server nun wählbar
Im OSM-Editor können nun Ladestationen hinzugefügt werden Warnung über veraltete Karten hinzugefügt + Knopf zum updaten
Schuko und Typ E Ladestationen hinzugefügt Vermeidung von Parkplatzwegen im Routing
Verbesserte Suchvorschläge Neuer Zoombutton
Litauische und lettische Sprachankündigungen Verbesserte Französchische Suchsynonme
Die Fahranweisungen wurden vergrößert OSM editor: Maximale Länge für OSM-Tags werden nun geprüft
• Der Zoomlevel passt sich an die Distanz zur nächsten Abbiegung an Mehr auf codeberg.org/comaps/comaps/releases
• Neue Anordnung der Einstellungen
Weitere Einzelheiten auf codeberg.org/comaps/comaps/releases

View File

@@ -1,10 +1,8 @@
• OpenStreetMap data as of December 9 • OpenStreetMap data as of December 17
Use Material 3 themes Make map download server configurable
Support charging sockets in OSM Editor Added info about outdated maps and an update button to the selected place info card
• Added schuko/type-E charge sockets • Avoid using parking aisles for routing
Improved search results ranking Changed shape of zoom buttons
Enabled Lithuanian and Latvian in voice announcements Improved French search synonyms
Improved size of driving indications OSM editor: check length limit for OSM tags in value validation
• Base zoom level on distance to next turn
• Reordered settings
More details on codeberg.org/comaps/comaps/releases More details on codeberg.org/comaps/comaps/releases

View File

@@ -1,11 +0,0 @@
• Datos de OpenStreetMap a fecha 9/12.
• Uso de temas Material 3.
• Compatibilidad con enchufes de recarga en Editor.
• Se añaden enchufes de recarga schuko/tipo E.
• Se mejora la búsqueda.
• Se habilitan el lituano y el letón en las indicaciones de voz.
• Se aumenta el tamaño de las indicaciones de conducción.
• Nivel de zoom base según la distancia al siguiente giro.
• Se han reordenado los ajustes.
Más detalles en codeberg.org/comaps/comaps/releases

View File

@@ -1,10 +1,8 @@
• Données OpenStreetMap du 9 Décembre • Données OpenStreetMap du 17 décembre
Utilisation de Material 3 Serveur de téléchargement de cartes configurable
Support de l'édition des bornes de recharge dans l'éditeur OSM Ajout d'un message d'avertissement pour les cartes trop anciennes
Ajout du type de prise schuko/type-E Évitement des allées de parking dans les itinéraires
Amélioration de l'ordre des résultats de recherche Mise à jour de l'apparence des boutons de zooms
• Ajout du lituanien et du letton dans le guidage vocal • Amélioration des synonymes de recherche en français
Amélioration de la taille des instructions dans la navigation Editeur OSM: vérification de la taille limite des tags OSM
• Niveau de zoom basé sur la distance jusquau prochain virage Plus d'informations sur codeberg.org/comaps/comaps/releases
• Réorganisation des paramètres
Plus de détails sur codeberg.org/comaps/comaps/releases

View File

@@ -1,10 +0,0 @@
• Podaci OpenStreetMap karte od 9. prosinca
• Korištenje Material 3 tema
• Podrška za utičnice za punjenje u OSM Editoru
• Dodane šuko/tip-E utičnice
• Poboljšano rangiranje rezultata pretraživanja
• Omogućeni litvanski i latvijski jezici u glasovnim najavama
• Povećana veličina indikatora vožnje
• Razina zumiranja se mijenja ovisno o udaljenosti do sljedećeg skretanja
• Promijenjen redoslijed postavki
Više detalja na codeberg.org/comaps/comaps/releases

View File

@@ -0,0 +1,32 @@
Bendruomenės vystoma nemokama atvirojo kodo žemėlapių programa, pagrįsta „OpenStreetMap“ duomenimis ir sustiprinta įsipareigojimu užtikrinti skaidrumą, privatumą ir pelno nesiekimą. „CoMaps“ programa yra kilusi iš „Organic Maps“, o pastaroji iš programos „Maps.ME“.
Apie šio projekto kilmę, jos priežastis ir palaikomą kryptį galite paskaityti adresu <b><i>codeberg.org/comaps</i></b>.
Prisijunkite prie bendruomenės ir padėkite sukurti geriausią žemėlapių programą
• Naudokitės programa ir paskleiskite žinią apie ją
• Teikite atsiliepimus ir praneškite apie problemas
• Atnaujinkite žemėlapių duomenis programoje arba „OpenStreetMap“ svetainėje
‣ <b>Skirta naudoti neprisijungus prie interneto</b>: planuokite maršrutus ir keliaukite užsienyje be mobiliojo ryšio, ieškokite kelionės taškų tolimuose žygiuose ir pan. Visos programos funkcijos yra pritaikytos veikti be interneto ryšio.
‣ <b>Gerbia privatumą</b>: programėlė sukurta, teikiant prioritetą privatumui: neidentifikuoja žmonių, neseka ir nerenka asmeninės informacijos. Be reklamų.
‣ <b>Paprasta ir išbaigta</b>: esminės, lengvai naudojamos funkcijos, kurios tiesiog veikia.
‣ <b>Taupo bateriją ir vietą</b>: neišsekina baterijos kaip kitos navigacijos programos. Kompaktiški žemėlapiai tausoja vietą jūsų telefone.
‣ <b>Nemokama ir kuriama bendruomenės</b>: paprasti žmonės kaip jūs padėjo sukurti šią programą, pildydami „OpenStreetMap“ žemėlapį, išbandydami ir pateikdami atsiliepimus apie funkcijas bei prisidėdami savo programavimo įgūdžiais ir pinigais.
‣ <b>Atviras ir skaidrus sprendimų priėmimas ir finansai, ne pelno siekianti ir visiškai atviro kodo programa.</b>
<b>Pagrindinės funkcijos</b>:
• Atsisiunčiami išsamūs žemėlapiai su vietomis, kurių nėra „Google Maps“;
• Žygių pėsčiomis veiksena su pažymėtais pėsčiųjų takais, stovyklavietėmis, vandens šaltiniais, kalnų viršūnėmis, reljefo linijomis ir kt.;
• Pėsčiųjų ir dviračių takai;
• Potencialūs kelionės taškai, kaip antai restoranai, degalinės, viešbučiai, parduotuvės, lankytinos vietos ir daugelis kitų;
• Paieška pagal pavadinimą, adresą arba lankytinos vietos kategoriją;
• Navigacija su balso instrukcijomis pėstiesiems, dviratininkams ir motorinio transporto vairuotojams;
• Mėgstamų vietų įsiminimas vienu bakstelėjimu;
• „Vikipedijos“ straipsniai, prieinami neprisijungus prie interneto;
• Kelionių metro sluoksnis ir maršrutai;
• Trasų įrašymas;
• Žymių ir trasų eksportavimas ir importavimas KML, KMZ, GPX formatais;
• Tamsaus žemėlapio veiksena, skirta naudoti naktį;
• Galimybė papildyti žemėlapio duomenis visiems, naudojantis įtaisytuoju baziniu redaktoriumi.
<b>Laisvė yra čia</b>
Atraskite savo kelionę ir keliaukite po pasaulį, kuriame privatumas ir bendruomenė yra svarbiausia!

View File

@@ -1 +1 @@
Paprasta ir patogi navigacija Turiningos kelionės Vystoma bendruomenės Paprasta ir patogi navigacija Turiningesnės kelionės Vystoma bendruomenės

View File

@@ -1,10 +0,0 @@
• Dane OpenStreetMap z 9 grudnia
• Użycie motywów Material 3
• Obsługa gniazd ładowania w Edytorze OSM
• Dodane gniazda ładowania schuko/type-E
• Poprawiony ranking wyników wyszukiwania
• Dodane litewskie i łotewskie komunikaty głosowe
• Poprawiony rozmiar znaków drogowych
• Poziom powiększenia oparty na odległości do następnego manewru
• Zmieniona kolejność ustawień
Więcej szczegółów na codeberg.org/comaps/comaps/releases

View File

@@ -1,10 +1,8 @@
• Dados OpenStreetMap atualizados em 9 de dezembro • Dados OSM de 17/12
Uso do estilo Material 3 Servidor de download de mapas configurável
Suporte para tomadas de carregamento no Editor OSM Adição de informações sobre mapas desatualizados e um botão de atualização ao cartão de informações do local selecionado
Adição de tomadas de carregamento Schuko/Tipo E Evita o uso de corredores de estacionamento para roteamento
Melhoria na classificação dos resultados de busca Formato dos botões de zoom alterado
Adição dos idiomas letão e lituano nas orientações por voz Sinônimos de busca em francês aprimorados
Melhoria no tamanho das indicações de direção Editor OSM: verificação do limite de comprimento das tags do OSM na validação de valores
• Nível de zoom baseado em distância até a próxima curva
• Configurações reordenadas
Mais detalhes em codeberg.org/comaps/comaps/releases Mais detalhes em codeberg.org/comaps/comaps/releases

View File

@@ -0,0 +1,8 @@
• Карты OpenStreetMap от 17 декабря
• Возможность настройки сервера для скачивания карт
• Добавлена ​​информация об устаревании карт и ​​кнопка обновления (при выборе места на карте)
• Парковочные проезды больше не используются для транзитной маршрутизации
• Изменены кнопки масштабирования карты
На карту добавлены ирригационные гидранты
• Редактор OSM: проверка максимальной длины OSM тегов
Подробнее на codeberg.org/comaps/comaps/releases

View File

@@ -1,31 +1,31 @@
Brezplačno in odprtokodno zemljevidno orodje, ki ga vodi skupnost, temelji na podatkih OpenStreetMap in je okrepljena s predanostjo transparentnosti, zasebnosti in nedobičkonosnosti. CoMaps je izpeljanka OrganicMaps, ta pa je izpeljanka Maps.ME. Brezplačno in odprtokodno zemljevidno orodje, ki ga vodi skupnost, temelji na podatkih OpenStreetMap in je okrepljena s predanostjo transparentnosti, zasebnosti in nepridobitnosti. CoMaps je izpeljanka OrganicMaps, ta pa je izpeljanka Maps.ME.
Preverite si o razlogih za ta projekt in njegovi usmerjenosti na <b><i>codeberg.org/comaps</i></b>. Preberite si o razlogih za ta projekt in njegovi usmerjenosti na <b><i>codeberg.org/comaps</i></b>.
Pridružite se skupnosti in pomagajte narediti najboljše zemljevidno orodje Pridružite se skupnosti in pomagajte narediti najboljše zemljevidno orodje
• Uporabljajte orodje in širite glas o njem • Uporabljajte orodje in širite glas o njem
• Dajajte povratne informacije in poročajte o napakah • Dajajte povratne informacije in poročajte o napakah
• Posodabljajte podatke zemljevida v tem orodju ali na spletni strani OpenStreetMap • Posodabljajte podatke zemljevida v tem orodju ali na spletni strani OpenStreetMap
‣ <b>Osredotočeno na uporabo brez povezave</b>: Načrtujte in se usmerjajte na vašem potovanju v tujini vrez potrebe po mobilnih podatkih, iščite vmesne točke potocanja ko ste na daljšem pohodu ipd. Vse zmogljivosti orodja so zasnovane za delo brez povezave. ‣ <b>Osredotočeno na uporabo brez povezave</b>: Načrtujte in se usmerjajte na vašem potovanju v tujini vrez potrebe po mobilnih podatkih, iščite vmesne točke potovanja ko ste na daljšem pohodu ipd. Vse zmogljivosti orodja so zasnovane za delo brez povezave.
‣ <b>Spoštovanje zasebnosti</b>: orodje je zasnovano z mislijo na zasebnost ne prepoznava oseb, ne sledi in ne zbira osebnih podatkov. Brez oglasov. ‣ <b>Spoštovanje zasebnosti</b>: orodje je zasnovano z mislijo na zasebnost ne prepoznava oseb, ne sledi in ne zbira osebnih podatkov. Brez oglasov.
‣ <b>Preprosto in dodelano</b>: nujne zmogljivosti, enostavne za uporabo, ki preprosto delujejo. ‣ <b>Preprosto in dodelano</b>: nujne zmogljivosti, enostavne za uporabo, ki preprosto delujejo.
‣ <b>Prihrani vašo baterijo in prostor.</b>: ne izčrpava vaše baterije kakor druga usmerjevalna orodja. Strnjeni zemljevidi prihranijo dragocen prostor na vašem telefonu. ‣ <b>Prihrani vašo baterijo in prostor.</b>: ne izčrpava vaše baterije kakor druga usmerjevalna orodja. Strnjeni zemljevidi prihranijo dragocen prostor na vašem telefonu.
‣ <b>Brezplačno in ustvarjeno v skupnosti</b>: ljudje kot ste vi pomagajo ustvarjati to orodje, tako da dodajajo kraje na OpenStreetMap, preizkušajo in dajejo povratne informacije o zmogljivostih in prispevajo svoje razvijalske sposobnosti in sredstva. ‣ <b>Brezplačno in ustvarjeno v skupnosti</b>: ljudje kot ste vi pomagajo ustvarjati to orodje, tako da dodajajo kraje na OpenStreetMap, preizkušajo in dajejo povratne informacije o zmogljivostih in prispevajo svoje razvijalske sposobnosti in sredstva.
‣ <b>Odprto in transparentno odločanje in finance, nedobičkonosno in popolnoma odprtokodno.</b> ‣ <b>Odprto in transparentno odločanje in finance, nepridobitno in popolnoma odprtokodno.</b>
<b>Glavne zmogljivosti</b>: <b>Glavne zmogljivosti</b>:
• Prenosljivi podrobni zemljevidi s kraji, ki na Googlovoh zemljevidih niso na voljo. • Prenosljivi podrobni zemljevidi s kraji, ki na Googlovih zemljevidih niso na voljo.
• Prikaz za dejavnosti na prostem s poudarjenimi pohodniškimi potmi, tabornimi prostori, vodnimi viri, vrhovi, plastnicami itd. • Prikaz za dejavnosti na prostem s poudarjenimi pohodniškimi potmi, tabornimi prostori, vodnimi viri, vrhovi, plastnicami itd.
• Pešpoti in kolesarke poti • Pešpoti in kolesarke poti
• Kraji zanimanja, npr. restavracije, bencinske črpalke, hoteli, trgovine, znamenitosti in mnogo več • Kraji zanimanja, npr. restavracije, bencinske črpalke, hoteli, trgovine, znamenitosti in mnogo več
• Iščite po imenu, hišnemu naslovu ali po vrsti • Iščite po imenu, hišnemu naslovu ali po vrsti
• Usmerjanje z glasovnimi obvestili za hojo, kolesarjenje ali vožnjo avtomobila. • Usmerjanje z glasovnimi navodili za hojo, kolesarjenje ali vožnjo avtomobila.
• Zaznamujte svoje najljubše kraje s preprostim dotikom • Zaznamujte svoje najljubše kraje s preprostim dotikom
• Wikipedijini članki brez povezave • Wikipedijini članki brez povezave
• Prometna plast podzemne železnice z usmerjanjem • Prometna plast podzemne železnice z usmerjanjem
• Izvozite ali uvozite zaznamke in sledi v oblikah KML, KMZ, GPX • Izvozite ali uvozite zaznamke in sledi v oblikah KML, KMZ, GPX
• Temni prikaz za uporabo ponoči • Temni prikaz za uporabo ponoči
• Izboljšajtw podatke zemljevida za vse z uporabo vgrajenega urejevalnika • Izboljšajte podatke zemljevida za vse z uporabo vgrajenega urejevalnika
<b>Svoboda je tu</b> <b>Svoboda je tu</b>
Odkijte več o vašem potovanju, usmerjajte se po svetu s poudarkom na zasebnosti in skupnostnem delovanju! Odkijte več o vašem potovanju, usmerjajte se po svetu s poudarkom na zasebnosti in skupnostnem delovanju!

View File

@@ -1 +1 @@
Enostavno usmerjanje Odkrij več o svojem potovanju Podprto v skupnosti Enostavno usmerjanje Odkrijte več o svojem potovanju Podprto v skupnosti

View File

@@ -1 +1 @@
CoMapsHodi, kolesari, vozi brez povezave, zasebno CoMaps hodi in vozi brez povezave, zasebno

View File

@@ -0,0 +1,36 @@
Bendruomenės vystoma nemokama atvirojo kodo žemėlapių programa, pagrįsta „OpenStreetMap“ duomenimis ir sustiprinta įsipareigojimu užtikrinti skaidrumą, privatumą ir pelno nesiekimą.
Prisijunkite prie bendruomenės ir padėkite sukurti geriausią žemėlapių programą
• Naudokitės programa ir paskleiskite žinią apie ją
• Teikite atsiliepimus ir praneškite apie problemas
• Atnaujinkite žemėlapių duomenis programoje arba „OpenStreetMap“ svetainėje
<i>Jūsų atsiliepimai ir 5 žvaigždučių vertinimai yra geriausias palaikymas mums!</i>
‣ <b>Paprasta ir išbaigta</b>: esminės, lengvai naudojamos funkcijos, kurios tiesiog veikia.
‣ <b>Skirta naudoti neprisijungus prie interneto</b>: planuokite maršrutus ir keliaukite užsienyje be mobiliojo ryšio, ieškokite kelionės taškų tolimuose žygiuose ir pan. Visos programos funkcijos yra pritaikytos veikti be interneto ryšio.
‣ <b>Gerbia privatumą</b>: programėlė sukurta, teikiant prioritetą privatumui: neidentifikuoja žmonių, neseka ir nerenka asmeninės informacijos. Be reklamų.
‣ <b>Taupo bateriją ir vietą</b>: neišsekina baterijos kaip kitos navigacijos programos. Kompaktiški žemėlapiai tausoja vietą jūsų telefone.
‣ <b>Nemokama ir kuriama bendruomenės</b>: paprasti žmonės kaip jūs padėjo sukurti šią programą, pildydami „OpenStreetMap“ žemėlapį, išbandydami ir pateikdami atsiliepimus apie funkcijas bei prisidėdami savo programavimo įgūdžiais ir pinigais.
‣ <b>Atviras ir skaidrus sprendimų priėmimas ir finansai, ne pelno siekianti ir visiškai atviro kodo programa.</b>
<b>Pagrindinės funkcijos</b>:
• Atsisiunčiami išsamūs žemėlapiai su vietomis, kurių nėra „Google Maps“;
• Žygių pėsčiomis veiksena su pažymėtais pėsčiųjų takais, stovyklavietėmis, vandens šaltiniais, kalnų viršūnėmis, reljefo linijomis ir kt.;
• Pėsčiųjų ir dviračių takai;
• Potencialūs kelionės taškai, kaip antai restoranai, degalinės, viešbučiai, parduotuvės, lankytinos vietos ir daugelis kitų;
• Paieška pagal pavadinimą, adresą arba lankytinos vietos kategoriją;
• Navigacija su balso instrukcijomis pėstiesiems, dviratininkams ir motorinio transporto vairuotojams;
• Mėgstamų vietų įsiminimas vienu bakstelėjimu;
• „Vikipedijos“ straipsniai, prieinami neprisijungus prie interneto;
• Kelionių metro sluoksnis ir maršrutai;
• Trasų įrašymas;
• Žymių ir trasų eksportavimas ir importavimas KML, KMZ, GPX formatais;
• Tamsaus žemėlapio veiksena, skirta naudoti naktį;
• Galimybė papildyti žemėlapio duomenis visiems, naudojantis įtaisytuoju baziniu redaktoriumi;
• „Android Auto“ palaikymas.
Praneškite apie programos problemas, siūlykite idėjas ir prisijunkite prie mūsų bendruomenės svetainėje <b><i>comaps.app</i></b>.
<b>Laisvė yra čia</b>
Atraskite savo kelionę ir keliaukite po pasaulį, kuriame privatumas ir bendruomenė yra svarbiausia!

View File

@@ -1 +1 @@
Paprasta ir patogi navigacija Turiningos kelionės Vystoma bendruomenės Paprasta ir patogi navigacija Turiningesnės kelionės Vystoma bendruomenės

View File

@@ -1 +1 @@
Enostavno usmerjanje Odkrij več o svojem potovanju Podprto v skupnosti Enostavno usmerjanje Odkrijte več o svojem potovanju Podprto v skupnosti

View File

@@ -1 +1 @@
CoMaps - Usmerjajte zasebno CoMaps - Usmerjajte se zasebno

View File

@@ -28,6 +28,7 @@ import com.github.mikephil.charting.formatter.IAxisValueFormatter;
import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
import com.google.android.material.textview.MaterialTextView; import com.google.android.material.textview.MaterialTextView;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;

View File

@@ -18,6 +18,7 @@ import android.location.Location;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
@@ -25,7 +26,15 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.core.view.ViewCompat; import androidx.core.view.ViewCompat;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.checkbox.MaterialCheckBox;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.progressindicator.LinearProgressIndicator;
import com.google.android.material.textview.MaterialTextView;
import app.organicmaps.base.BaseMwmFragmentActivity; import app.organicmaps.base.BaseMwmFragmentActivity;
import app.organicmaps.dialog.CustomMapServerDialog;
import app.organicmaps.downloader.MapManagerHelper; import app.organicmaps.downloader.MapManagerHelper;
import app.organicmaps.intent.Factory; import app.organicmaps.intent.Factory;
import app.organicmaps.sdk.Framework; import app.organicmaps.sdk.Framework;
@@ -38,11 +47,7 @@ import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.util.UiUtils; import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener; import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.checkbox.MaterialCheckBox;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.progressindicator.LinearProgressIndicator;
import com.google.android.material.textview.MaterialTextView;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@@ -54,6 +59,7 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
private MaterialTextView mTvMessage; private MaterialTextView mTvMessage;
private LinearProgressIndicator mProgress; private LinearProgressIndicator mProgress;
private MaterialButton mBtnDownload; private MaterialButton mBtnDownload;
private MaterialButton mBtnAdvanced;
private MaterialCheckBox mChbDownloadCountry; private MaterialCheckBox mChbDownloadCountry;
private String mCurrentCountry; private String mCurrentCountry;
@@ -253,7 +259,7 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
mProgress.setMax(bytes); mProgress.setMax(bytes);
// Start progress at 1% according to M3 guidelines // Start progress at 1% according to M3 guidelines
mProgress.setProgressCompat(bytes / 100, true); mProgress.setProgressCompat(bytes/100, true);
} }
else else
finishFilesDownload(bytes); finishFilesDownload(bytes);
@@ -267,6 +273,14 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
mProgress = findViewById(R.id.progressbar); mProgress = findViewById(R.id.progressbar);
mBtnDownload = findViewById(R.id.btn_download_resources); mBtnDownload = findViewById(R.id.btn_download_resources);
mChbDownloadCountry = findViewById(R.id.chb_download_country); mChbDownloadCountry = findViewById(R.id.chb_download_country);
mBtnAdvanced = findViewById(R.id.btn_advanced);
mBtnAdvanced.setOnClickListener(v -> {
CustomMapServerDialog.show(this, url -> {
prepareFilesDownload(false);
});
});
mBtnAdvanced.setEnabled(true);
mBtnListeners = new View.OnClickListener[BTN_COUNT]; mBtnListeners = new View.OnClickListener[BTN_COUNT];
mBtnNames = new String[BTN_COUNT]; mBtnNames = new String[BTN_COUNT];
@@ -291,6 +305,11 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
{ {
mBtnDownload.setOnClickListener(mBtnListeners[action]); mBtnDownload.setOnClickListener(mBtnListeners[action]);
mBtnDownload.setText(mBtnNames[action]); mBtnDownload.setText(mBtnNames[action]);
// Allow changing server only when idle or after an error.
boolean advancedEnabled = (action == DOWNLOAD || action == TRY_AGAIN || action == RESUME);
mBtnAdvanced.setEnabled(advancedEnabled);
mBtnAdvanced.setAlpha(advancedEnabled ? 1f : 0.5f);
} }
private void doDownload() private void doDownload()
@@ -359,6 +378,9 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
private void finishFilesDownload(int result) private void finishFilesDownload(int result)
{ {
mBtnAdvanced.setEnabled(true);
mBtnAdvanced.setAlpha(1f);
if (result == ERR_NO_MORE_FILES) if (result == ERR_NO_MORE_FILES)
{ {
// World and WorldCoasts has been downloaded, we should register maps again to correctly add them to the model. // World and WorldCoasts has been downloaded, we should register maps again to correctly add them to the model.
@@ -372,7 +394,7 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
mTvMessage.setText(getString(R.string.downloading_country_can_proceed, item.name, fileSizeString)); mTvMessage.setText(getString(R.string.downloading_country_can_proceed, item.name, fileSizeString));
mProgress.setMax((int) item.totalSize); mProgress.setMax((int) item.totalSize);
// Start progress at 1% according to M3 guidelines // Start progress at 1% according to M3 guidelines
mProgress.setProgressCompat((int) (item.totalSize / 100), true); mProgress.setProgressCompat((int) (item.totalSize/100), true);
mCountryDownloadListenerSlot = MapManager.nativeSubscribe(mCountryDownloadListener); mCountryDownloadListenerSlot = MapManager.nativeSubscribe(mCountryDownloadListener);
MapManagerHelper.startDownload(mCurrentCountry); MapManagerHelper.startDownload(mCurrentCountry);
@@ -424,17 +446,21 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
default -> throw new AssertionError("Unexpected result code = " + result); default -> throw new AssertionError("Unexpected result code = " + result);
}; };
mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog) mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(titleId) .setTitle(titleId)
.setMessage(messageId) .setMessage(messageId)
.setCancelable(true) .setCancelable(true)
.setOnCancelListener((dialog) -> setAction(PAUSE)) .setOnCancelListener((dialog) -> setAction(RESUME))
.setPositiveButton(R.string.try_again, .setPositiveButton(R.string.try_again,
(dialog, which) -> { (dialog, which) -> {
setAction(TRY_AGAIN); setAction(TRY_AGAIN);
onTryAgainClicked(); onTryAgainClicked();
}) })
.setOnDismissListener(dialog -> mAlertDialog = null) .setNegativeButton(R.string.cancel,
.show(); (dialog, which) -> {
setAction(RESUME);
})
.setOnDismissListener(dialog -> mAlertDialog = null)
.show();
} }
} }

View File

@@ -38,9 +38,8 @@ public class OsmUploadWork extends Worker
{ {
final Constraints c = new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build(); final Constraints c = new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build();
OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest.Builder(OsmUploadWork.class).setConstraints(c); OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest.Builder(OsmUploadWork.class).setConstraints(c);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
{ builder.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST);
builder.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST);
} }
final OneTimeWorkRequest wr = builder.build(); final OneTimeWorkRequest wr = builder.build();
WorkManager.getInstance(context).beginUniqueWork("UploadOsmChanges", ExistingWorkPolicy.KEEP, wr).enqueue(); WorkManager.getInstance(context).beginUniqueWork("UploadOsmChanges", ExistingWorkPolicy.KEEP, wr).enqueue();

View File

@@ -17,6 +17,7 @@ import androidx.annotation.NonNull;
import androidx.documentfile.provider.DocumentFile; import androidx.documentfile.provider.DocumentFile;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.util.log.Logger; import app.organicmaps.sdk.util.log.Logger;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;

View File

@@ -10,6 +10,7 @@ import androidx.fragment.app.DialogFragment;
public class BaseMwmDialogFragment extends DialogFragment public class BaseMwmDialogFragment extends DialogFragment
{ {
protected int getStyle() protected int getStyle()
{ {
return STYLE_NORMAL; return STYLE_NORMAL;

View File

@@ -282,13 +282,11 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
{ {
if (isEmptySearchResults()) if (isEmptySearchResults())
{ {
requirePlaceholder().setContent(R.string.search_not_found, R.string.search_not_found_query, requirePlaceholder().setContent(R.string.search_not_found, R.string.search_not_found_query, R.drawable.ic_search_fail);
R.drawable.ic_search_fail);
} }
else if (isEmpty()) else if (isEmpty())
{ {
requirePlaceholder().setContent(R.string.bookmarks_empty_list_title, R.string.bookmarks_empty_list_message, requirePlaceholder().setContent(R.string.bookmarks_empty_list_title, R.string.bookmarks_empty_list_message, R.drawable.ic_bookmarks);
R.drawable.ic_bookmarks);
} }
boolean isEmptyRecycler = isEmpty() || isEmptySearchResults(); boolean isEmptyRecycler = isEmpty() || isEmptySearchResults();

View File

@@ -23,6 +23,7 @@ import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import app.organicmaps.widget.recycler.RecyclerClickListener; import app.organicmaps.widget.recycler.RecyclerClickListener;
import app.organicmaps.widget.recycler.RecyclerLongClickListener; import app.organicmaps.widget.recycler.RecyclerLongClickListener;
import com.google.android.material.button.MaterialButton; import com.google.android.material.button.MaterialButton;
import com.google.android.material.checkbox.MaterialCheckBox; import com.google.android.material.checkbox.MaterialCheckBox;
import com.google.android.material.imageview.ShapeableImageView; import com.google.android.material.imageview.ShapeableImageView;
@@ -457,12 +458,10 @@ public class Holders
String formattedDesc = desc.replace("\n", "<br>"); String formattedDesc = desc.replace("\n", "<br>");
Spanned spannedDesc = Utils.fromHtml(formattedDesc); Spanned spannedDesc = Utils.fromHtml(formattedDesc);
if (!TextUtils.isEmpty(spannedDesc)) if (!TextUtils.isEmpty(spannedDesc)) {
{
mDescText.setText(spannedDesc); mDescText.setText(spannedDesc);
} }
else else {
{
mDescText.setText(R.string.list_description_empty); mDescText.setText(R.string.list_description_empty);
} }
} }

View File

@@ -50,8 +50,8 @@ public final class IntentUtils
} }
// https://developer.android.com/reference/androidx/car/app/CarContext#startCarApp(android.content.Intent) // https://developer.android.com/reference/androidx/car/app/CarContext#startCarApp(android.content.Intent)
private static void processNavigationIntent(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer, private static void processNavigationIntent(@NonNull CarContext carContext,
@NonNull Intent intent) @NonNull Renderer surfaceRenderer, @NonNull Intent intent)
{ {
// TODO (AndrewShkrob): This logic will need to be revised when we introduce support for adding stops during // TODO (AndrewShkrob): This logic will need to be revised when we introduce support for adding stops during
// navigation or route planning. Skip navigation intents during navigation // navigation or route planning. Skip navigation intents during navigation

View File

@@ -31,7 +31,7 @@ public final class RoutingHelpers
default -> Distance.UNIT_METERS; default -> Distance.UNIT_METERS;
}; };
return Distance.create(distance.mDistance, displayUnit); return Distance.create(distance.mDistance, displayUnit);
} }
@NonNull @NonNull
@@ -52,7 +52,7 @@ public final class RoutingHelpers
default -> LaneDirection.SHAPE_UNKNOWN; default -> LaneDirection.SHAPE_UNKNOWN;
}; };
return LaneDirection.create(shape, isRecommended); return LaneDirection.create(shape, isRecommended);
} }
@NonNull @NonNull
@@ -77,7 +77,7 @@ public final class RoutingHelpers
case EXIT_HIGHWAY_TO_LEFT -> Maneuver.TYPE_OFF_RAMP_SLIGHT_LEFT; case EXIT_HIGHWAY_TO_LEFT -> Maneuver.TYPE_OFF_RAMP_SLIGHT_LEFT;
case EXIT_HIGHWAY_TO_RIGHT -> Maneuver.TYPE_OFF_RAMP_SLIGHT_RIGHT; case EXIT_HIGHWAY_TO_RIGHT -> Maneuver.TYPE_OFF_RAMP_SLIGHT_RIGHT;
}; };
final Maneuver.Builder builder = new Maneuver.Builder(maneuverType); final Maneuver.Builder builder = new Maneuver.Builder(maneuverType);
if (maneuverType == Maneuver.TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW) if (maneuverType == Maneuver.TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW)
builder.setRoundaboutExitNumber(roundaboutExitNum > 0 ? roundaboutExitNum : 1); builder.setRoundaboutExitNumber(roundaboutExitNum > 0 ? roundaboutExitNum : 1);
builder.setIcon(new CarIcon.Builder(createManeuverIcon(context, carDirection, roundaboutExitNum)).build()); builder.setIcon(new CarIcon.Builder(createManeuverIcon(context, carDirection, roundaboutExitNum)).build());
@@ -85,8 +85,7 @@ public final class RoutingHelpers
} }
@NonNull @NonNull
private static IconCompat createManeuverIcon(@NonNull final CarContext context, @NonNull CarDirection carDirection, private static IconCompat createManeuverIcon(@NonNull final CarContext context, @NonNull CarDirection carDirection, int roundaboutExitNum)
int roundaboutExitNum)
{ {
if (!CarDirection.isRoundAbout(carDirection) || roundaboutExitNum == 0) if (!CarDirection.isRoundAbout(carDirection) || roundaboutExitNum == 0)
{ {

View File

@@ -39,7 +39,8 @@ public final class UiHelpers
} }
@NonNull @NonNull
public static ActionStrip createMapActionStrip(@NonNull CarContext context, @NonNull Renderer surfaceRenderer) public static ActionStrip createMapActionStrip(@NonNull CarContext context,
@NonNull Renderer surfaceRenderer)
{ {
final CarIcon iconPlus = new CarIcon.Builder(IconCompat.createWithResource(context, R.drawable.ic_plus)).build(); final CarIcon iconPlus = new CarIcon.Builder(IconCompat.createWithResource(context, R.drawable.ic_plus)).build();
final CarIcon iconMinus = new CarIcon.Builder(IconCompat.createWithResource(context, R.drawable.ic_minus)).build(); final CarIcon iconMinus = new CarIcon.Builder(IconCompat.createWithResource(context, R.drawable.ic_minus)).build();
@@ -58,13 +59,15 @@ public final class UiHelpers
} }
@NonNull @NonNull
public static MapController createMapController(@NonNull CarContext context, @NonNull Renderer surfaceRenderer) public static MapController createMapController(@NonNull CarContext context,
@NonNull Renderer surfaceRenderer)
{ {
return new MapController.Builder().setMapActionStrip(createMapActionStrip(context, surfaceRenderer)).build(); return new MapController.Builder().setMapActionStrip(createMapActionStrip(context, surfaceRenderer)).build();
} }
@NonNull @NonNull
public static Action createSettingsAction(@NonNull BaseMapScreen mapScreen, @NonNull Renderer surfaceRenderer) public static Action createSettingsAction(@NonNull BaseMapScreen mapScreen,
@NonNull Renderer surfaceRenderer)
{ {
return createSettingsAction(mapScreen, surfaceRenderer, null); return createSettingsAction(mapScreen, surfaceRenderer, null);
} }
@@ -78,7 +81,8 @@ public final class UiHelpers
} }
@NonNull @NonNull
private static Action createSettingsAction(@NonNull BaseMapScreen mapScreen, @NonNull Renderer surfaceRenderer, private static Action createSettingsAction(@NonNull BaseMapScreen mapScreen,
@NonNull Renderer surfaceRenderer,
@Nullable OnScreenResultListener onScreenResultListener) @Nullable OnScreenResultListener onScreenResultListener)
{ {
final CarContext context = mapScreen.getCarContext(); final CarContext context = mapScreen.getCarContext();
@@ -119,7 +123,8 @@ public final class UiHelpers
return null; return null;
final Row.Builder builder = new Row.Builder(); final Row.Builder builder = new Row.Builder();
builder.setImage(new CarIcon.Builder(IconCompat.createWithResource(context, R.drawable.ic_opening_hours)).build()); builder.setImage(
new CarIcon.Builder(IconCompat.createWithResource(context, R.drawable.ic_opening_hours)).build());
if (isEmptyTT) if (isEmptyTT)
builder.setTitle(ohStr); builder.setTitle(ohStr);

View File

@@ -0,0 +1,86 @@
package app.organicmaps.dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.PreferenceManager;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
import app.organicmaps.R;
import app.organicmaps.sdk.Framework;
public final class CustomMapServerDialog
{
public interface OnUrlAppliedListener
{
void onUrlApplied(@NonNull String url);
}
private CustomMapServerDialog() {}
public static void show(@NonNull Context context,
@Nullable OnUrlAppliedListener listener)
{
View dialogView = LayoutInflater.from(context)
.inflate(R.layout.dialog_custom_map_server, null);
TextInputLayout til = dialogView.findViewById(R.id.til_custom_map_server);
TextInputEditText edit = dialogView.findViewById(R.id.edit_custom_map_server);
SharedPreferences prefs =
PreferenceManager.getDefaultSharedPreferences(context);
String current = prefs.getString(context.getString(R.string.pref_custom_map_download_url), "");
edit.setText(current);
MaterialAlertDialogBuilder builder =
new MaterialAlertDialogBuilder(context, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.download_resources_custom_url_title)
.setMessage(R.string.download_resources_custom_url_message)
.setView(dialogView)
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.save, null);
AlertDialog dialog = builder.create();
dialog.setOnShowListener(dlg -> {
Button ok = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
ok.setOnClickListener(v -> {
String url = edit.getText() != null ? edit.getText().toString().trim() : "";
if (!url.isEmpty()
&& !url.startsWith("http://")
&& !url.startsWith("https://"))
{
til.setError(context.getString(R.string.download_resources_custom_url_error_scheme));
return;
}
til.setError(null);
String normalizedUrl = Framework.normalizeServerUrl(url);
prefs.edit()
.putString(context.getString(R.string.pref_custom_map_download_url), normalizedUrl)
.apply();
// Apply to native
Framework.applyCustomMapDownloadUrl(context, normalizedUrl);
if (listener != null)
listener.onUrlApplied(normalizedUrl);
dialog.dismiss();
});
});
dialog.show();
}
}

View File

@@ -125,8 +125,7 @@ public class EditTextDialogFragment extends BaseMwmDialogFragment
positiveButton.setOnClickListener(view -> { positiveButton.setOnClickListener(view -> {
final String result = mEtInput.getText().toString(); final String result = mEtInput.getText().toString();
if (validateInput(requireActivity(), result)) if (validateInput(requireActivity(), result)) {
{
processInput(result); processInput(result);
editTextDialog.dismiss(); editTextDialog.dismiss();
} }
@@ -153,7 +152,7 @@ public class EditTextDialogFragment extends BaseMwmDialogFragment
if (mInputValidator != null) if (mInputValidator != null)
{ {
final String maybeError = mInputValidator.validate(activity, input); final String maybeError = mInputValidator.validate(activity, input);
mEtInputLayout.getEditText().setError(maybeError); mEtInputLayout.setError(maybeError);
mEtInputLayout.requestFocus(); mEtInputLayout.requestFocus();
return maybeError == null; return maybeError == null;
} }

View File

@@ -4,6 +4,7 @@ import android.location.Location;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat; import androidx.core.view.ViewCompat;
import app.organicmaps.MwmActivity; import app.organicmaps.MwmActivity;
@@ -48,8 +49,7 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
@Override @Override
public void onStatusChanged(List<MapManager.StorageCallbackData> data) public void onStatusChanged(List<MapManager.StorageCallbackData> data)
{ {
if (mCurrentCountry == null) if (mCurrentCountry == null) {
{
updateOfflineExplanationVisibility(); updateOfflineExplanationVisibility();
return; return;
} }
@@ -109,13 +109,10 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
return enqueued || progress || applying; return enqueued || progress || applying;
} }
private void updateOfflineExplanationVisibility() private void updateOfflineExplanationVisibility() {
{ if (mOfflineExplanation == null) return;
if (mOfflineExplanation == null)
return;
// hide once threshold reached; safe to call repeatedly. // hide once threshold reached; safe to call repeatedly.
app.organicmaps.util.UiUtils.showIf(MapManager.nativeGetDownloadedCount() < (DEFAULT_MAP_BASELINE + HIDE_THRESHOLD), app.organicmaps.util.UiUtils.showIf(MapManager.nativeGetDownloadedCount() < (DEFAULT_MAP_BASELINE + HIDE_THRESHOLD), mOfflineExplanation);
mOfflineExplanation);
} }
private void updateProgressState(boolean shouldAutoDownload) private void updateProgressState(boolean shouldAutoDownload)

View File

@@ -15,6 +15,7 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.AutoCompleteTextView; import android.widget.AutoCompleteTextView;
import android.widget.GridLayout; import android.widget.GridLayout;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
import androidx.annotation.DrawableRes; import androidx.annotation.DrawableRes;
import androidx.annotation.IdRes; import androidx.annotation.IdRes;
@@ -195,10 +196,8 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
{ {
final Context context = mInputBuildingLevels.getContext(); final Context context = mInputBuildingLevels.getContext();
final boolean isValid = Editor.nativeIsLevelValid(s.toString()); final boolean isValid = Editor.nativeIsLevelValid(s.toString());
UiUtils.setInputError(mInputBuildingLevels, mInputBuildingLevels.setError(isValid ? null : context.getString(R.string.error_enter_correct_storey_number,
isValid ? null Editor.nativeGetMaxEditableBuildingLevels()));
: context.getString(R.string.error_enter_correct_storey_number,
Editor.nativeGetMaxEditableBuildingLevels()));
} }
}); });
@@ -397,7 +396,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
List<String> SOCKET_TYPES = Arrays.stream(getResources().getStringArray(R.array.charge_socket_types)).toList(); List<String> SOCKET_TYPES = Arrays.stream(getResources().getStringArray(R.array.charge_socket_types)).toList();
for (String socketType : SOCKET_TYPES) for (String socketType : SOCKET_TYPES)
{ {
ChargeSocketDescriptor socket = new ChargeSocketDescriptor(socketType, 0, 0); ChargeSocketDescriptor socket = new ChargeSocketDescriptor(socketType,0,0);
MaterialButton btn = (MaterialButton) inflater.inflate(R.layout.button_socket_type, typeBtns, false); MaterialButton btn = (MaterialButton) inflater.inflate(R.layout.button_socket_type, typeBtns, false);
@@ -405,16 +404,16 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
// load SVG icon converted into VectorDrawable in res/drawable // load SVG icon converted into VectorDrawable in res/drawable
@SuppressLint("DiscouragedApi") @SuppressLint("DiscouragedApi")
int resIconId = getResources().getIdentifier("ic_charge_socket_" + socket.visualType(), "drawable", int resIconId =
requireContext().getPackageName()); getResources().getIdentifier("ic_charge_socket_" + socket.visualType(), "drawable", requireContext().getPackageName());
if (resIconId != 0) if (resIconId != 0)
{ {
btn.setIcon(getResources().getDrawable(resIconId)); btn.setIcon(getResources().getDrawable(resIconId));
} }
@SuppressLint("DiscouragedApi") @SuppressLint("DiscouragedApi")
int resTypeId = getResources().getIdentifier("charge_socket_" + socket.visualType(), "string", int resTypeId =
requireContext().getPackageName()); getResources().getIdentifier("charge_socket_" + socket.visualType(), "string", requireContext().getPackageName());
if (resTypeId != 0) if (resTypeId != 0)
{ {
btn.setText(getResources().getString(resTypeId)); btn.setText(getResources().getString(resTypeId));
@@ -462,16 +461,13 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
// Add a TextWatcher to validate on text change // Add a TextWatcher to validate on text change
countView.addTextChangedListener(new TextWatcher() { countView.addTextChangedListener(new TextWatcher() {
@Override @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
{}
@Override @Override
public void onTextChanged(CharSequence s, int start, int before, int count) public void onTextChanged(CharSequence s, int start, int before, int count) {}
{}
@Override @Override
public void afterTextChanged(Editable s) public void afterTextChanged(Editable s) {
{
validatePositiveField(s.toString(), countInputLayout); validatePositiveField(s.toString(), countInputLayout);
} }
}); });
@@ -486,16 +482,13 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
// Add a TextWatcher to validate on text change // Add a TextWatcher to validate on text change
powerView.addTextChangedListener(new TextWatcher() { powerView.addTextChangedListener(new TextWatcher() {
@Override @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
{}
@Override @Override
public void onTextChanged(CharSequence s, int start, int before, int count) public void onTextChanged(CharSequence s, int start, int before, int count) {}
{}
@Override @Override
public void afterTextChanged(Editable s) public void afterTextChanged(Editable s) {
{
validatePositiveField(s.toString(), powerInputLayout); validatePositiveField(s.toString(), powerInputLayout);
} }
}); });
@@ -503,82 +496,74 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
return new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog) return new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setTitle(R.string.editor_socket) .setTitle(R.string.editor_socket)
.setView(dialogView) .setView(dialogView)
.setPositiveButton( .setPositiveButton(R.string.save,
R.string.save, (dialog, which) -> {
(dialog, which) -> { String socketType = "";
String socketType = ""; for (MaterialButton b : buttonList)
for (MaterialButton b : buttonList) {
{ if (b.isChecked())
if (b.isChecked()) {
{ socketType = b.getTag(R.id.socket_type).toString();
socketType = b.getTag(R.id.socket_type).toString(); break;
break; }
} }
}
int countValue = 0; // 0 means 'unknown count' int countValue = 0; // 0 means 'unknown count'
try try
{ {
countValue = Integer.parseInt(countView.getText().toString()); countValue = Integer.parseInt(countView.getText().toString());
} }
catch (NumberFormatException ignored) catch (NumberFormatException ignored)
{ {
Logger.w(CHARGE_SOCKETS_TAG, "Invalid count value for socket:" + countView.getText().toString()); Logger.w(CHARGE_SOCKETS_TAG, "Invalid count value for socket:" + countView.getText().toString());
} }
if (countValue < 0) if (countValue < 0)
{ {
countValue = 0; countValue = 0;
Logger.w(CHARGE_SOCKETS_TAG, "Invalid count value for socket:" + countView.getText().toString()); Logger.w(CHARGE_SOCKETS_TAG, "Invalid count value for socket:" + countView.getText().toString());
} }
double powerValue = 0; // 0 means 'unknown power' double powerValue = 0; // 0 means 'unknown power'
try try
{ {
powerValue = Double.parseDouble(powerView.getText().toString()); powerValue = Double.parseDouble(powerView.getText().toString());
} }
catch (NumberFormatException ignored) catch (NumberFormatException ignored)
{ {
Logger.w(CHARGE_SOCKETS_TAG, "Invalid power value for socket:" + powerView.getText().toString()); Logger.w(CHARGE_SOCKETS_TAG, "Invalid power value for socket:" + powerView.getText().toString());
} }
if (powerValue < 0) if (powerValue < 0)
{ {
powerValue = 0; powerValue = 0;
Logger.w(CHARGE_SOCKETS_TAG, "Invalid power value for socket:" + powerView.getText().toString()); Logger.w(CHARGE_SOCKETS_TAG, "Invalid power value for socket:" + powerView.getText().toString());
} }
ChargeSocketDescriptor socket = new ChargeSocketDescriptor(socketType, countValue, powerValue); ChargeSocketDescriptor socket =
new ChargeSocketDescriptor(socketType, countValue, powerValue);
updateChargeSockets(socketIndex, socket); updateChargeSockets(socketIndex, socket);
}) })
.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss()); .setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
} }
// Helper method for validation logic // Helper method for validation logic
private boolean validatePositiveField(String text, TextInputLayout layout) private boolean validatePositiveField(String text, TextInputLayout layout) {
{ if (text.isEmpty()) {
if (text.isEmpty())
{
layout.setError(null); // No error if empty (assuming 0 is the default) layout.setError(null); // No error if empty (assuming 0 is the default)
return true; return true;
} }
try try {
{
double value = Double.parseDouble(text); double value = Double.parseDouble(text);
if (value < 0) if (value < 0) {
{
layout.setError(getString(R.string.error_value_must_be_positive)); layout.setError(getString(R.string.error_value_must_be_positive));
return false; return false;
} else {
layout.setError(null);
return true;
} }
else } catch (NumberFormatException e) {
{
layout.setError(null);
return true;
}
}
catch (NumberFormatException e)
{
layout.setError(getString(R.string.error_invalid_number)); layout.setError(getString(R.string.error_invalid_number));
return false; return false;
} }
@@ -598,8 +583,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
{ {
sockets[socketIndex] = socket; sockets[socketIndex] = socket;
} }
else else {
{
List<ChargeSocketDescriptor> list = new ArrayList<>(Arrays.asList(sockets)); List<ChargeSocketDescriptor> list = new ArrayList<>(Arrays.asList(sockets));
list.add(socket); list.add(socket);
sockets = list.toArray(new ChargeSocketDescriptor[0]); sockets = list.toArray(new ChargeSocketDescriptor[0]);
@@ -617,8 +601,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
GridLayout socketsGrid = mChargeSockets.findViewById(R.id.socket_grid_editor); GridLayout socketsGrid = mChargeSockets.findViewById(R.id.socket_grid_editor);
socketsGrid.removeAllViews(); socketsGrid.removeAllViews();
for (int i = 0; i < sockets.length; i++) for (int i = 0; i < sockets.length; i++) {
{
final int currentIndex = i; final int currentIndex = i;
ChargeSocketDescriptor socket = sockets[i]; ChargeSocketDescriptor socket = sockets[i];
@@ -629,30 +612,27 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
MaterialTextView power = itemView.findViewById(R.id.socket_power); MaterialTextView power = itemView.findViewById(R.id.socket_power);
MaterialTextView count = itemView.findViewById(R.id.socket_count); MaterialTextView count = itemView.findViewById(R.id.socket_count);
// load SVG icon converted into VectorDrawable in res/drawable // load SVG icon converted into VectorDrawable in res/drawable
@SuppressLint("DiscouragedApi") @SuppressLint("DiscouragedApi")
int resIconId = getResources().getIdentifier("ic_charge_socket_" + socket.visualType(), "drawable", int resIconId = getResources().getIdentifier("ic_charge_socket_" + socket.visualType(), "drawable",
requireContext().getPackageName()); requireContext().getPackageName());
if (resIconId != 0) if (resIconId != 0) {
{
icon.setImageResource(resIconId); icon.setImageResource(resIconId);
} }
@SuppressLint("DiscouragedApi") @SuppressLint("DiscouragedApi")
int resTypeId = getResources().getIdentifier("charge_socket_" + socket.visualType(), "string", int resTypeId =
requireContext().getPackageName()); getResources().getIdentifier("charge_socket_" + socket.visualType(), "string", requireContext().getPackageName());
if (resTypeId != 0) if (resTypeId != 0) {
{
type.setText(resTypeId); type.setText(resTypeId);
} }
if (socket.power() != 0) if (socket.power() != 0) {
{
DecimalFormat df = new DecimalFormat("#.##"); DecimalFormat df = new DecimalFormat("#.##");
power.setText(getString(R.string.kw_label, df.format(socket.power()))); power.setText(getString(R.string.kw_label, df.format(socket.power())));
} }
else if (socket.ignorePower()) else if (socket.ignorePower()) {
{
power.setVisibility(INVISIBLE); power.setVisibility(INVISIBLE);
} }
@@ -661,8 +641,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
count.setText(getString(R.string.count_label, socket.count())); count.setText(getString(R.string.count_label, socket.count()));
} }
itemView.setOnClickListener( itemView.setOnClickListener(v -> buildChargeSocketDialog(currentIndex, socket.type(), socket.count(), socket.power()).show());
v -> buildChargeSocketDialog(currentIndex, socket.type(), socket.count(), socket.power()).show());
socketsGrid.addView(itemView); socketsGrid.addView(itemView);
} }
@@ -808,8 +787,9 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
View lineContactBlock = View lineContactBlock =
initBlock(view, Metadata.MetadataType.FMD_CONTACT_LINE, R.id.block_line, R.drawable.ic_line_white, initBlock(view, Metadata.MetadataType.FMD_CONTACT_LINE, R.id.block_line, R.drawable.ic_line_white,
R.string.editor_line_social_network, InputType.TYPE_TEXT_VARIATION_URI); R.string.editor_line_social_network, InputType.TYPE_TEXT_VARIATION_URI);
View blueskyContactBlock = initBlock(view, Metadata.MetadataType.FMD_CONTACT_BLUESKY, R.id.block_bluesky, View blueskyContactBlock =
R.drawable.ic_bluesky, R.string.bluesky, InputType.TYPE_TEXT_VARIATION_URI); initBlock(view, Metadata.MetadataType.FMD_CONTACT_BLUESKY, R.id.block_bluesky, R.drawable.ic_bluesky,
R.string.bluesky, InputType.TYPE_TEXT_VARIATION_URI);
View operatorBlock = initBlock(view, Metadata.MetadataType.FMD_OPERATOR, R.id.block_operator, View operatorBlock = initBlock(view, Metadata.MetadataType.FMD_OPERATOR, R.id.block_operator,
R.drawable.ic_operator, R.string.editor_operator, 0); R.drawable.ic_operator, R.string.editor_operator, 0);
@@ -966,7 +946,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
mDisused.setVisibility(Editor.nativeCanMarkPlaceAsDisused() ? View.VISIBLE : View.GONE); mDisused.setVisibility(Editor.nativeCanMarkPlaceAsDisused() ? View.VISIBLE : View.GONE);
if (Editor.nativeIsMapObjectUploaded()) if (Editor.nativeAreSomeFeatureChangesUploaded())
{ {
mReset.setText(R.string.editor_place_doesnt_exist); mReset.setText(R.string.editor_place_doesnt_exist);
return; return;
@@ -984,7 +964,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
private void reset() private void reset()
{ {
if (Editor.nativeIsMapObjectUploaded()) if (Editor.nativeAreSomeFeatureChangesUploaded())
{ {
placeDoesntExist(); placeDoesntExist();
return; return;
@@ -1041,15 +1021,14 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
private void placeDisused() private void placeDisused()
{ {
new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog) new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setTitle(R.string.editor_mark_business_vacant_title) .setTitle(R.string.editor_mark_business_vacant_title)
.setMessage(R.string.editor_mark_business_vacant_description) .setMessage(R.string.editor_mark_business_vacant_description)
.setPositiveButton(R.string.editor_submit, .setPositiveButton(R.string.editor_submit, (dlg, which) -> {
(dlg, which) -> { Editor.nativeMarkPlaceAsDisused();
Editor.nativeMarkPlaceAsDisused(); mParent.processEditedFeatures();
mParent.processEditedFeatures(); })
}) .setNegativeButton(android.R.string.cancel, null)
.setNegativeButton(android.R.string.cancel, null) .show();
.show();
} }
private void commitPlaceDoesntExists(@NonNull String text) private void commitPlaceDoesntExists(@NonNull String text)

View File

@@ -13,6 +13,7 @@ import app.organicmaps.R;
import app.organicmaps.sdk.editor.data.FeatureCategory; import app.organicmaps.sdk.editor.data.FeatureCategory;
import app.organicmaps.sdk.util.StringUtils; import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.util.UiUtils; import app.organicmaps.util.UiUtils;
import com.google.android.material.button.MaterialButton; import com.google.android.material.button.MaterialButton;
import com.google.android.material.textfield.TextInputEditText; import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textview.MaterialTextView; import com.google.android.material.textview.MaterialTextView;
@@ -68,7 +69,8 @@ public class FeatureCategoryAdapter extends RecyclerView.Adapter<RecyclerView.Vi
} }
case TYPE_FOOTER -> case TYPE_FOOTER ->
{ {
return new FooterViewHolder(inflater.inflate(R.layout.item_feature_category_footer, parent, false), mFragment); return new FooterViewHolder(inflater.inflate(R.layout.item_feature_category_footer, parent, false),
mFragment);
} }
default -> throw new IllegalArgumentException("Unsupported viewType: " + viewType); default -> throw new IllegalArgumentException("Unsupported viewType: " + viewType);
} }
@@ -132,21 +134,26 @@ public class FeatureCategoryAdapter extends RecyclerView.Adapter<RecyclerView.Vi
mSendNoteButton = itemView.findViewById(R.id.send_note_button); mSendNoteButton = itemView.findViewById(R.id.send_note_button);
mSendNoteButton.setOnClickListener(v -> listener.onSendNoteClicked()); mSendNoteButton.setOnClickListener(v -> listener.onSendNoteClicked());
final ColorStateList bgButtonColor = new ColorStateList( final ColorStateList bgButtonColor = new ColorStateList(
new int[][] { new int[][]{
new int[] {android.R.attr.state_enabled}, // enabled new int[]{android.R.attr.state_enabled}, // enabled
new int[] {-android.R.attr.state_enabled} // disabled new int[]{-android.R.attr.state_enabled} // disabled
}, },
new int[] {ContextCompat.getColor(mSendNoteButton.getContext(), R.color.base_accent), new int[]{
ContextCompat.getColor(mSendNoteButton.getContext(), R.color.button_accent_disabled)}); ContextCompat.getColor(
mSendNoteButton.getContext(), R.color.base_accent),
ContextCompat.getColor(mSendNoteButton.getContext(), R.color.button_accent_disabled)
});
final ColorStateList textButtonColor = new ColorStateList( final ColorStateList textButtonColor = new ColorStateList(
new int[][] { new int[][]{
new int[] {android.R.attr.state_enabled}, // enabled new int[]{android.R.attr.state_enabled}, // enabled
new int[] {-android.R.attr.state_enabled} // disabled new int[]{-android.R.attr.state_enabled} // disabled
}, },
new int[] {ContextCompat.getColor(mSendNoteButton.getContext(), new int[]{
UiUtils.getStyledResourceId(mSendNoteButton.getContext(), ContextCompat.getColor(
android.R.attr.textColorPrimaryInverse)), mSendNoteButton.getContext(),
ContextCompat.getColor(mSendNoteButton.getContext(), R.color.button_accent_text_disabled)}); UiUtils.getStyledResourceId(mSendNoteButton.getContext(), android.R.attr.textColorPrimaryInverse)),
ContextCompat.getColor(mSendNoteButton.getContext(), R.color.button_accent_text_disabled)
});
mSendNoteButton.setBackgroundTintList(bgButtonColor); mSendNoteButton.setBackgroundTintList(bgButtonColor);
mSendNoteButton.setTextColor(textButtonColor); mSendNoteButton.setTextColor(textButtonColor);
mNoteEditText.addTextChangedListener(new StringUtils.SimpleTextWatcher() { mNoteEditText.addTextChangedListener(new StringUtils.SimpleTextWatcher() {

View File

@@ -2,16 +2,19 @@ package app.organicmaps.editor;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.res.Resources; import android.content.res.Resources;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import com.google.android.material.timepicker.MaterialTimePicker;
import com.google.android.material.timepicker.TimeFormat;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.editor.data.HoursMinutes; import app.organicmaps.sdk.editor.data.HoursMinutes;
import app.organicmaps.sdk.util.DateUtils; import app.organicmaps.sdk.util.DateUtils;
import com.google.android.material.timepicker.MaterialTimePicker;
import com.google.android.material.timepicker.TimeFormat;
public class FromToTimePicker public class FromToTimePicker
{ {
@@ -29,11 +32,18 @@ public class FromToTimePicker
private boolean mIsFromTimePicked; private boolean mIsFromTimePicked;
private int mInputMode; private int mInputMode;
public static void pickTime(@NonNull Fragment fragment, @NonNull FromToTimePicker.OnPickListener listener, public static void pickTime(@NonNull Fragment fragment,
@NonNull HoursMinutes fromTime, @NonNull HoursMinutes toTime, int id, @NonNull FromToTimePicker.OnPickListener listener,
@NonNull HoursMinutes fromTime,
@NonNull HoursMinutes toTime,
int id,
boolean startWithToTime) boolean startWithToTime)
{ {
FromToTimePicker timePicker = new FromToTimePicker(fragment, listener, fromTime, toTime, id); FromToTimePicker timePicker = new FromToTimePicker(fragment,
listener,
fromTime,
toTime,
id);
if (startWithToTime) if (startWithToTime)
timePicker.showToTimePicker(); timePicker.showToTimePicker();
@@ -41,8 +51,11 @@ public class FromToTimePicker
timePicker.showFromTimePicker(); timePicker.showFromTimePicker();
} }
private FromToTimePicker(@NonNull Fragment fragment, @NonNull FromToTimePicker.OnPickListener listener, private FromToTimePicker(@NonNull Fragment fragment,
@NonNull HoursMinutes fromTime, @NonNull HoursMinutes toTime, int id) @NonNull FromToTimePicker.OnPickListener listener,
@NonNull HoursMinutes fromTime,
@NonNull HoursMinutes toTime,
int id)
{ {
mActivity = fragment.requireActivity(); mActivity = fragment.requireActivity();
mFragmentManager = fragment.getChildFragmentManager(); mFragmentManager = fragment.getChildFragmentManager();
@@ -87,12 +100,15 @@ public class FromToTimePicker
private MaterialTimePicker buildFromTimePicker() private MaterialTimePicker buildFromTimePicker()
{ {
MaterialTimePicker timePicker = buildTimePicker(mFromTime, mResources.getString(R.string.editor_time_from), MaterialTimePicker timePicker = buildTimePicker(mFromTime,
mResources.getString(R.string.next_button), null); mResources.getString(R.string.editor_time_from),
mResources.getString(R.string.next_button),
null);
timePicker.addOnNegativeButtonClickListener(view -> finishTimePicking(false)); timePicker.addOnNegativeButtonClickListener(view -> finishTimePicking(false));
timePicker.addOnPositiveButtonClickListener(view -> { timePicker.addOnPositiveButtonClickListener(view ->
{
mIsFromTimePicked = true; mIsFromTimePicked = true;
saveState(timePicker, true); saveState(timePicker, true);
mFromTimePicker = null; mFromTimePicker = null;
@@ -106,10 +122,13 @@ public class FromToTimePicker
private MaterialTimePicker buildToTimePicker() private MaterialTimePicker buildToTimePicker()
{ {
MaterialTimePicker timePicker = buildTimePicker(mToTime, mResources.getString(R.string.editor_time_to), null, MaterialTimePicker timePicker = buildTimePicker(mToTime,
mResources.getString(R.string.editor_time_to),
null,
mResources.getString(R.string.back)); mResources.getString(R.string.back));
timePicker.addOnNegativeButtonClickListener(view -> { timePicker.addOnNegativeButtonClickListener(view ->
{
saveState(timePicker, false); saveState(timePicker, false);
mToTimePicker = null; mToTimePicker = null;
if (mIsFromTimePicked) if (mIsFromTimePicked)
@@ -118,7 +137,8 @@ public class FromToTimePicker
finishTimePicking(false); finishTimePicking(false);
}); });
timePicker.addOnPositiveButtonClickListener(view -> { timePicker.addOnPositiveButtonClickListener(view ->
{
saveState(timePicker, false); saveState(timePicker, false);
finishTimePicking(true); finishTimePicking(true);
}); });
@@ -129,18 +149,18 @@ public class FromToTimePicker
} }
@NonNull @NonNull
private MaterialTimePicker buildTimePicker(@NonNull HoursMinutes time, @NonNull String title, private MaterialTimePicker buildTimePicker(@NonNull HoursMinutes time,
@NonNull String title,
@Nullable String positiveButtonTextOverride, @Nullable String positiveButtonTextOverride,
@Nullable String negativeButtonTextOverride) @Nullable String negativeButtonTextOverride)
{ {
MaterialTimePicker.Builder builder = MaterialTimePicker.Builder builder = new MaterialTimePicker.Builder()
new MaterialTimePicker.Builder() .setTitleText(title)
.setTitleText(title) .setTimeFormat(mIs24HourFormat ? TimeFormat.CLOCK_24H : TimeFormat.CLOCK_12H)
.setTimeFormat(mIs24HourFormat ? TimeFormat.CLOCK_24H : TimeFormat.CLOCK_12H) .setInputMode(mInputMode)
.setInputMode(mInputMode) .setTheme(R.style.MwmTheme_MaterialTimePicker)
.setTheme(R.style.MwmTheme_MaterialTimePicker) .setHour((int) time.hours)
.setHour((int) time.hours) .setMinute((int) time.minutes);
.setMinute((int) time.minutes);
if (positiveButtonTextOverride != null) if (positiveButtonTextOverride != null)
builder.setPositiveButtonText(positiveButtonTextOverride); builder.setPositiveButtonText(positiveButtonTextOverride);

View File

@@ -7,6 +7,7 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.CompoundButton; import android.widget.CompoundButton;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import androidx.annotation.IdRes; import androidx.annotation.IdRes;
import androidx.annotation.IntRange; import androidx.annotation.IntRange;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@@ -121,14 +122,20 @@ class SimpleTimetableAdapter extends RecyclerView.Adapter<SimpleTimetableAdapter
notifyItemChanged(getItemCount() - 1); notifyItemChanged(getItemCount() - 1);
} }
private void pickTime(int position, @IntRange(from = ID_OPENING_TIME, to = ID_CLOSED_SPAN) int id, private void pickTime(int position,
@IntRange(from = ID_OPENING_TIME, to = ID_CLOSED_SPAN) int id,
boolean startWithToTime) boolean startWithToTime)
{ {
final Timetable data = mItems.get(position); final Timetable data = mItems.get(position);
mPickingPosition = position; mPickingPosition = position;
FromToTimePicker.pickTime(mFragment, this, data.workingTimespan.start, data.workingTimespan.end, id, FromToTimePicker.pickTime(mFragment,
startWithToTime); this,
data.workingTimespan.start,
data.workingTimespan.end,
id,
startWithToTime);
} }
@Override @Override
@@ -377,21 +384,26 @@ class SimpleTimetableAdapter extends RecyclerView.Adapter<SimpleTimetableAdapter
final String text = mFragment.getString(R.string.editor_time_add); final String text = mFragment.getString(R.string.editor_time_add);
mAdd.setEnabled(enable); mAdd.setEnabled(enable);
final ColorStateList bgButtonColor = new ColorStateList( final ColorStateList bgButtonColor = new ColorStateList(
new int[][] { new int[][]{
new int[] {android.R.attr.state_enabled}, // enabled new int[]{android.R.attr.state_enabled}, // enabled
new int[] {-android.R.attr.state_enabled} // disabled new int[]{-android.R.attr.state_enabled} // disabled
}, },
new int[] {ContextCompat.getColor(mAdd.getContext(), R.color.base_accent), new int[]{
ContextCompat.getColor(mAdd.getContext(), R.color.button_accent_disabled)}); ContextCompat.getColor(
mAdd.getContext(), R.color.base_accent),
ContextCompat.getColor(mAdd.getContext(), R.color.button_accent_disabled)
});
final ColorStateList textButtonColor = new ColorStateList( final ColorStateList textButtonColor = new ColorStateList(
new int[][] { new int[][]{
new int[] {android.R.attr.state_enabled}, // enabled new int[]{android.R.attr.state_enabled}, // enabled
new int[] {-android.R.attr.state_enabled} // disabled new int[]{-android.R.attr.state_enabled} // disabled
}, },
new int[] { new int[]{
ContextCompat.getColor(mAdd.getContext(), UiUtils.getStyledResourceId( ContextCompat.getColor(
mAdd.getContext(), android.R.attr.textColorPrimaryInverse)), mAdd.getContext(),
ContextCompat.getColor(mAdd.getContext(), R.color.button_accent_text_disabled)}); UiUtils.getStyledResourceId(mAdd.getContext(), android.R.attr.textColorPrimaryInverse)),
ContextCompat.getColor(mAdd.getContext(), R.color.button_accent_text_disabled)
});
mAdd.setBackgroundTintList(bgButtonColor); mAdd.setBackgroundTintList(bgButtonColor);
mAdd.setTextColor(textButtonColor); mAdd.setTextColor(textButtonColor);
mAdd.setText(enable ? text + " (" + TimeFormatUtils.formatWeekdays(mComplementItem) + ")" : text); mAdd.setText(enable ? text + " (" + TimeFormatUtils.formatWeekdays(mComplementItem) + ")" : text);

View File

@@ -9,8 +9,8 @@ import androidx.annotation.Nullable;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.base.BaseMwmRecyclerFragment; import app.organicmaps.base.BaseMwmRecyclerFragment;
public class SimpleTimetableFragment public class SimpleTimetableFragment extends BaseMwmRecyclerFragment<SimpleTimetableAdapter>
extends BaseMwmRecyclerFragment<SimpleTimetableAdapter> implements TimetableProvider implements TimetableProvider
{ {
private SimpleTimetableAdapter mAdapter; private SimpleTimetableAdapter mAdapter;
@Nullable @Nullable

View File

@@ -35,30 +35,25 @@ public class LayerBottomSheetItem
@DrawableRes @DrawableRes
int drawableResId = 0; int drawableResId = 0;
@StringRes @StringRes
int buttonTextResource = switch (mode) int buttonTextResource = switch (mode) {
{ case OUTDOORS -> {
case OUTDOORS -> drawableResId = R.drawable.ic_layers_outdoors;
{ yield R.string.button_layer_outdoor;
drawableResId = R.drawable.ic_layers_outdoors; }
yield R.string.button_layer_outdoor; case SUBWAY -> {
} drawableResId = R.drawable.ic_layers_subway;
case SUBWAY -> yield R.string.subway;
{ }
drawableResId = R.drawable.ic_layers_subway; case ISOLINES -> {
yield R.string.subway; drawableResId = R.drawable.ic_layers_isoline;
} yield R.string.button_layer_isolines;
case ISOLINES -> }
{ case TRAFFIC -> {
drawableResId = R.drawable.ic_layers_isoline; drawableResId = R.drawable.ic_layers_traffic;
yield R.string.button_layer_isolines; yield R.string.button_layer_traffic;
} }
case TRAFFIC ->
{
drawableResId = R.drawable.ic_layers_traffic;
yield R.string.button_layer_traffic;
}
}; };
return new LayerBottomSheetItem(drawableResId, buttonTextResource, mode, layerItemClickListener); return new LayerBottomSheetItem(drawableResId, buttonTextResource, mode, layerItemClickListener);
} }
@NonNull @NonNull

View File

@@ -5,9 +5,11 @@ import android.widget.ImageView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.textview.MaterialTextView;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.adapter.OnItemClickListener; import app.organicmaps.adapter.OnItemClickListener;
import com.google.android.material.textview.MaterialTextView;
class LayerHolder extends RecyclerView.ViewHolder class LayerHolder extends RecyclerView.ViewHolder
{ {

View File

@@ -395,7 +395,7 @@ public class MapButtonsController extends Fragment
0; 0;
// Allow offset tolerance for zoom buttons // Allow offset tolerance for zoom buttons
}; };
showButton(getViewTopOffset(translation, button) >= toleranceOffset, entry.getKey()); showButton(getViewTopOffset(translation, button) >= toleranceOffset, entry.getKey());
} }
} }
} }

View File

@@ -98,6 +98,11 @@ public class NavigationController implements TrafficManager.TrafficCallback, Nav
mSpeedLimit = topFrame.findViewById(R.id.nav_speed_limit); mSpeedLimit = topFrame.findViewById(R.id.nav_speed_limit);
mCurrentSpeed = topFrame.findViewById(R.id.nav_current_speed); mCurrentSpeed = topFrame.findViewById(R.id.nav_current_speed);
View mTopbar = topFrame.findViewById(R.id.statutbar);
ViewCompat.setOnApplyWindowInsetsListener(mTopbar,(v, windowInsets) -> {
UiUtils.setViewNavigationTopInsetsMargin(v, windowInsets);
return windowInsets;
});
// Show a blank view below the navbar to hide the menu content // Show a blank view below the navbar to hide the menu content
final View navigationBarBackground = mFrame.findViewById(R.id.nav_bottom_sheet_nav_bar); final View navigationBarBackground = mFrame.findViewById(R.id.nav_bottom_sheet_nav_bar);
final View nextTurnContainer = mFrame.findViewById(R.id.nav_next_turn_container); final View nextTurnContainer = mFrame.findViewById(R.id.nav_next_turn_container);

View File

@@ -43,6 +43,7 @@ import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import app.organicmaps.widget.recycler.DotDividerItemDecoration; import app.organicmaps.widget.recycler.DotDividerItemDecoration;
import app.organicmaps.widget.recycler.MultilineLayoutManager; import app.organicmaps.widget.recycler.MultilineLayoutManager;
import com.google.android.material.button.MaterialButton; import com.google.android.material.button.MaterialButton;
import com.google.android.material.imageview.ShapeableImageView; import com.google.android.material.imageview.ShapeableImageView;
import com.google.android.material.textview.MaterialTextView; import com.google.android.material.textview.MaterialTextView;
@@ -122,9 +123,9 @@ final class RoutingBottomMenuController implements View.OnClickListener
@NonNull View timeElevationLine, @NonNull View transitFrame, @NonNull View timeElevationLine, @NonNull View transitFrame,
@NonNull MaterialTextView error, @NonNull MaterialButton start, @NonNull MaterialTextView error, @NonNull MaterialButton start,
@NonNull ShapeableImageView altitudeChart, @NonNull MaterialTextView time, @NonNull ShapeableImageView altitudeChart, @NonNull MaterialTextView time,
@NonNull MaterialTextView altitudeDifference, @NonNull MaterialTextView altitudeDifference, @NonNull MaterialTextView timeVehicle,
@NonNull MaterialTextView timeVehicle, @Nullable MaterialTextView arrival, @Nullable MaterialTextView arrival, @NonNull View actionFrame,
@NonNull View actionFrame, @Nullable RoutingBottomMenuListener listener) @Nullable RoutingBottomMenuListener listener)
{ {
mContext = context; mContext = context;
mAltitudeChartFrame = altitudeChartFrame; mAltitudeChartFrame = altitudeChartFrame;

View File

@@ -12,6 +12,9 @@ import androidx.annotation.IdRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.view.ViewCompat; import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat; import androidx.core.view.WindowInsetsCompat;
import com.google.android.material.textview.MaterialTextView;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.Framework; import app.organicmaps.sdk.Framework;
@@ -26,7 +29,6 @@ import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener;
import app.organicmaps.widget.RoutingToolbarButton; import app.organicmaps.widget.RoutingToolbarButton;
import app.organicmaps.widget.ToolbarController; import app.organicmaps.widget.ToolbarController;
import app.organicmaps.widget.WheelProgressView; import app.organicmaps.widget.WheelProgressView;
import com.google.android.material.textview.MaterialTextView;
public class RoutingPlanController extends ToolbarController public class RoutingPlanController extends ToolbarController
{ {
@@ -262,7 +264,7 @@ public class RoutingPlanController extends ToolbarController
default -> throw new IllegalArgumentException("unknown router: " + router); default -> throw new IllegalArgumentException("unknown router: " + router);
}; };
RoutingToolbarButton button = mRouterTypes.findViewById(mRouterTypes.getCheckedRadioButtonId()); RoutingToolbarButton button = mRouterTypes.findViewById(mRouterTypes.getCheckedRadioButtonId());
button.progress(); button.progress();
updateProgressLabels(); updateProgressLabels();

View File

@@ -14,10 +14,12 @@ import androidx.annotation.NonNull;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.textview.MaterialTextView;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.search.DisplayedCategories; import app.organicmaps.sdk.search.DisplayedCategories;
import app.organicmaps.sdk.util.Language; import app.organicmaps.sdk.util.Language;
import com.google.android.material.textview.MaterialTextView;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.Locale; import java.util.Locale;

View File

@@ -10,12 +10,14 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.textview.MaterialTextView;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.search.SearchResult; import app.organicmaps.sdk.search.SearchResult;
import app.organicmaps.util.Graphics; import app.organicmaps.util.Graphics;
import app.organicmaps.util.ThemeUtils; import app.organicmaps.util.ThemeUtils;
import app.organicmaps.util.UiUtils; import app.organicmaps.util.UiUtils;
import com.google.android.material.textview.MaterialTextView;
class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.SearchDataViewHolder> class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.SearchDataViewHolder>
{ {
@@ -150,8 +152,7 @@ class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.SearchDataViewHol
{ {
final Resources resources = mSearchFragment.getResources(); final Resources resources = mSearchFragment.getResources();
if (result.description.openNow != SearchResult.OPEN_NOW_YES if (result.description.openNow != SearchResult.OPEN_NOW_YES && result.description.openNow != SearchResult.OPEN_NOW_NO)
&& result.description.openNow != SearchResult.OPEN_NOW_NO)
{ {
// Hide if unknown opening hours state // Hide if unknown opening hours state
UiUtils.hide(mOpen); UiUtils.hide(mOpen);
@@ -168,18 +169,15 @@ class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.SearchDataViewHol
{ {
final String minsToChangeStr = resources.getQuantityString( final String minsToChangeStr = resources.getQuantityString(
R.plurals.minutes_short, Math.max(minsToNextState, 1), Math.max(minsToNextState, 1)); R.plurals.minutes_short, Math.max(minsToNextState, 1), Math.max(minsToNextState, 1));
final String nextChangeFormatted = final String nextChangeFormatted = resources.getString(isOpen ? R.string.closes_in : R.string.opens_in, minsToChangeStr);
resources.getString(isOpen ? R.string.closes_in : R.string.opens_in, minsToChangeStr);
UiUtils.setTextAndShow(mOpen, nextChangeFormatted); UiUtils.setTextAndShow(mOpen, nextChangeFormatted);
mOpen.setTextColor(ContextCompat.getColor(mSearchFragment.getContext(), R.color.base_yellow)); mOpen.setTextColor(ContextCompat.getColor(mSearchFragment.getContext(), R.color.base_yellow));
} }
else else
{ {
UiUtils.setTextAndShow( UiUtils.setTextAndShow(mOpen, isOpen ? resources.getString(R.string.editor_time_open) : resources.getString(R.string.closed));
mOpen, isOpen ? resources.getString(R.string.editor_time_open) : resources.getString(R.string.closed)); mOpen.setTextColor(ContextCompat.getColor(mSearchFragment.getContext(), isOpen ? R.color.base_green : R.color.base_red));
mOpen.setTextColor(
ContextCompat.getColor(mSearchFragment.getContext(), isOpen ? R.color.base_green : R.color.base_red));
} }
} }

View File

@@ -273,8 +273,7 @@ public class SearchFragment extends BaseMwmFragment implements SearchListener, C
RecyclerView mResults = mResultsFrame.findViewById(R.id.recycler); RecyclerView mResults = mResultsFrame.findViewById(R.id.recycler);
setRecyclerScrollListener(mResults); setRecyclerScrollListener(mResults);
mResultsPlaceholder = mResultsFrame.findViewById(R.id.placeholder); mResultsPlaceholder = mResultsFrame.findViewById(R.id.placeholder);
mResultsPlaceholder.setContent(R.string.search_not_found, R.string.search_not_found_query, mResultsPlaceholder.setContent(R.string.search_not_found, R.string.search_not_found_query, R.drawable.ic_search_fail);
R.drawable.ic_search_fail);
mSearchAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() mSearchAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver()
{ {

View File

@@ -5,13 +5,15 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.textview.MaterialTextView;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.routing.RoutingController; import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.search.SearchRecents; import app.organicmaps.sdk.search.SearchRecents;
import app.organicmaps.util.Graphics; import app.organicmaps.util.Graphics;
import app.organicmaps.widget.SearchToolbarController; import app.organicmaps.widget.SearchToolbarController;
import com.google.android.material.textview.MaterialTextView;
class SearchHistoryAdapter extends RecyclerView.Adapter<SearchHistoryAdapter.ViewHolder> class SearchHistoryAdapter extends RecyclerView.Adapter<SearchHistoryAdapter.ViewHolder>
{ {

View File

@@ -6,12 +6,10 @@ import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.XmlRes; import androidx.annotation.XmlRes;
import androidx.core.content.ContextCompat;
import androidx.core.view.ViewCompat; import androidx.core.view.ViewCompat;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceFragmentCompat;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils.ScrollableContentInsetsListener; import app.organicmaps.util.WindowInsetUtils.ScrollableContentInsetsListener;
@@ -44,7 +42,6 @@ abstract class BaseXmlSettingsFragment extends PreferenceFragmentCompat
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
{ {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
view.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.bg_cards));
RecyclerView recyclerView = getListView(); RecyclerView recyclerView = getListView();
ViewCompat.setOnApplyWindowInsetsListener(recyclerView, new ScrollableContentInsetsListener(recyclerView)); ViewCompat.setOnApplyWindowInsetsListener(recyclerView, new ScrollableContentInsetsListener(recyclerView));
} }

View File

@@ -8,12 +8,14 @@ import android.view.ViewGroup;
import android.widget.CompoundButton; import android.widget.CompoundButton;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.material.materialswitch.MaterialSwitch;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.base.BaseMwmToolbarFragment; import app.organicmaps.base.BaseMwmToolbarFragment;
import app.organicmaps.sdk.routing.RoutingController; import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.routing.RoutingOptions; import app.organicmaps.sdk.routing.RoutingOptions;
import app.organicmaps.sdk.settings.RoadType; import app.organicmaps.sdk.settings.RoadType;
import com.google.android.material.materialswitch.MaterialSwitch;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;

View File

@@ -4,16 +4,23 @@ import static app.organicmaps.leftbutton.LeftButtonsHolder.DISABLE_BUTTON_CODE;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.preference.ListPreference; import androidx.preference.ListPreference;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceManager;
import androidx.preference.TwoStatePreference; import androidx.preference.TwoStatePreference;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.dialog.CustomMapServerDialog;
import app.organicmaps.downloader.OnmapDownloader; import app.organicmaps.downloader.OnmapDownloader;
import app.organicmaps.editor.LanguagesFragment; import app.organicmaps.editor.LanguagesFragment;
import app.organicmaps.editor.ProfileActivity; import app.organicmaps.editor.ProfileActivity;
@@ -35,7 +42,7 @@ import app.organicmaps.sdk.util.SharedPropertiesUtils;
import app.organicmaps.sdk.util.log.LogsManager; import app.organicmaps.sdk.util.log.LogsManager;
import app.organicmaps.util.ThemeSwitcher; import app.organicmaps.util.ThemeSwitcher;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@@ -73,6 +80,7 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment implements La
initScreenSleepEnabledPrefsCallbacks(); initScreenSleepEnabledPrefsCallbacks();
initShowOnLockScreenPrefsCallbacks(); initShowOnLockScreenPrefsCallbacks();
initLeftButtonPrefs(); initLeftButtonPrefs();
initCustomMapDownloadUrlPrefsCallbacks();
} }
private void initLeftButtonPrefs() private void initLeftButtonPrefs()
@@ -535,6 +543,34 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment implements La
}); });
} }
private void initCustomMapDownloadUrlPrefsCallbacks()
{
Preference customUrlPref = getPreference(getString(R.string.pref_custom_map_download_url));
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(requireContext());
String current = prefs.getString(getString(R.string.pref_custom_map_download_url), "");
String normalizedUrl = Framework.normalizeServerUrl(current);
// Initial summary
customUrlPref.setSummary(normalizedUrl.isEmpty()
? getString(R.string.download_resources_custom_url_summary_none)
: normalizedUrl);
// Sync native
Framework.applyCustomMapDownloadUrl(requireContext(), normalizedUrl);
// Show dialog
customUrlPref.setOnPreferenceClickListener(preference -> {
CustomMapServerDialog.show(requireContext(), url -> {
preference.setSummary(url.isEmpty()
? getString(R.string.download_resources_custom_url_summary_none)
: url);
});
return true;
});
}
private void removePreference(@NonNull String categoryKey, @NonNull Preference preference) private void removePreference(@NonNull String categoryKey, @NonNull Preference preference)
{ {
final PreferenceCategory category = getPreference(categoryKey); final PreferenceCategory category = getPreference(categoryKey);

View File

@@ -24,7 +24,6 @@ import androidx.annotation.ColorInt;
import androidx.annotation.IdRes; import androidx.annotation.IdRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.core.content.ContextCompat;
import androidx.core.content.res.ResourcesCompat; import androidx.core.content.res.ResourcesCompat;
import androidx.core.graphics.Insets; import androidx.core.graphics.Insets;
import androidx.core.view.WindowCompat; import androidx.core.view.WindowCompat;
@@ -196,7 +195,7 @@ public final class UiUtils
public static void showHomeUpButton(MaterialToolbar toolbar) public static void showHomeUpButton(MaterialToolbar toolbar)
{ {
toolbar.setNavigationIcon( toolbar.setNavigationIcon(
ThemeUtils.getResource(toolbar.getContext(), androidx.appcompat.R.attr.homeAsUpIndicator)); UiUtils.getStyledResourceId(toolbar.getContext(), androidx.appcompat.R.attr.homeAsUpIndicator));
} }
// this method returns the total height of the display (in pixels) including notch and other touchable areas // this method returns the total height of the display (in pixels) including notch and other touchable areas
@@ -209,15 +208,7 @@ public final class UiUtils
} }
public static void setInputError(@NonNull TextInputLayout layout, @StringRes int error) public static void setInputError(@NonNull TextInputLayout layout, @StringRes int error)
{ {
setInputError(layout, error == 0 ? null : layout.getContext().getString(error)); layout.setError(error == 0 ? null : layout.getContext().getString(error));
}
public static void setInputError(@NonNull TextInputLayout layout, String error)
{
layout.getEditText().setError(error);
layout.getEditText().setTextColor(error == null
? ThemeUtils.getColor(layout.getContext(), android.R.attr.textColorPrimary)
: ContextCompat.getColor(layout.getContext(), R.color.base_red));
} }
public static void setFullscreen(@NonNull Activity activity, boolean fullscreen) public static void setFullscreen(@NonNull Activity activity, boolean fullscreen)
@@ -281,6 +272,14 @@ public final class UiUtils
view.setPadding(systemInsets.left, systemInsets.top, systemInsets.right, view.getPaddingBottom()); view.setPadding(systemInsets.left, systemInsets.top, systemInsets.right, view.getPaddingBottom());
} }
public static void setViewNavigationTopInsetsMargin(View view, WindowInsetsCompat windowInsets)
{
final Insets systemInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
lp.topMargin = systemInsets.top;
view.setLayoutParams(lp);
}
public static void setupNavigationIcon(@NonNull MaterialToolbar toolbar, @NonNull View.OnClickListener listener) public static void setupNavigationIcon(@NonNull MaterialToolbar toolbar, @NonNull View.OnClickListener listener)
{ {
View customNavigationButton = toolbar.findViewById(R.id.back); View customNavigationButton = toolbar.findViewById(R.id.back);

View File

@@ -8,165 +8,165 @@ import android.graphics.Typeface;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
public abstract class BaseSignView extends View public abstract class BaseSignView extends View
{ {
private float mBorderWidthRatio = 0.1f; private float mBorderWidthRatio = 0.1f;
protected void setBorderWidthRatio(float ratio) protected void setBorderWidthRatio(float ratio) {
{ mBorderWidthRatio = ratio;
mBorderWidthRatio = ratio;
}
private float mBorderInsetRatio = 0f;
protected void setBorderInsetRatio(float ratio)
{
mBorderInsetRatio = ratio;
}
// colors
protected int mBackgroundColor;
protected int mBorderColor;
protected int mAlertColor;
protected int mTextColor;
protected int mTextAlertColor;
// paints
protected final Paint mBackgroundPaint;
protected final Paint mBorderPaint;
protected final Paint mTextPaint;
// geometry
protected float mWidth;
protected float mHeight;
protected float mRadius;
protected float mBorderWidth;
protected float mBorderRadius;
public BaseSignView(Context ctx, @Nullable AttributeSet attrs)
{
super(ctx, attrs);
mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBorderPaint.setStyle(Paint.Style.STROKE);
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
}
protected void setColors(int backgroundColor, int borderColor, int alertColor, int textColor, int textAlertColor)
{
mBackgroundColor = backgroundColor;
mBorderColor = borderColor;
mAlertColor = alertColor;
mTextColor = textColor;
mTextAlertColor = textAlertColor;
mBackgroundPaint.setColor(mBackgroundColor);
mBorderPaint.setColor(mBorderColor);
mTextPaint.setColor(mTextColor);
}
@Override
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight)
{
super.onSizeChanged(width, height, oldWidth, oldHeight);
final float paddingX = getPaddingLeft() + getPaddingRight();
final float paddingY = getPaddingTop() + getPaddingBottom();
mWidth = width - paddingX;
mHeight = height - paddingY;
mRadius = Math.min(mWidth, mHeight) / 2f;
mBorderWidth = mRadius * mBorderWidthRatio;
// subtract half the stroke PLUS the extra inset
final float gap = mRadius * mBorderInsetRatio;
mBorderRadius = mRadius - (mBorderWidth / 2f) - gap;
configureTextSize();
}
@Override
protected void onDraw(@NonNull Canvas canvas)
{
super.onDraw(canvas);
final String str = getValueString();
if (str == null)
return;
final float cx = mWidth / 2f;
final float cy = mHeight / 2f;
// background & border
boolean alert = isAlert();
mBackgroundPaint.setColor(alert ? mAlertColor : mBackgroundColor);
canvas.drawCircle(cx, cy, mRadius, mBackgroundPaint);
if (!alert)
{
mBorderPaint.setStrokeWidth(mBorderWidth);
mBorderPaint.setColor(mBorderColor);
canvas.drawCircle(cx, cy, mBorderRadius, mBorderPaint);
} }
// text private float mBorderInsetRatio = 0f;
mTextPaint.setColor(alert ? mTextAlertColor : mTextColor); protected void setBorderInsetRatio(float ratio) {
drawValueString(canvas, cx, cy, str); mBorderInsetRatio = ratio;
}
@Override
public boolean onTouchEvent(@NonNull MotionEvent e)
{
final float cx = mWidth / 2f, cy = mHeight / 2f;
final float dx = e.getX() - cx, dy = e.getY() - cy;
if ((dx * dx) + (dy * dy) <= (mRadius * mRadius))
{
performClick();
return true;
} }
return false;
}
@Override // colors
public boolean performClick() protected int mBackgroundColor;
{ protected int mBorderColor;
super.performClick(); protected int mAlertColor;
return false; protected int mTextColor;
} protected int mTextAlertColor;
private void drawValueString(Canvas c, float cx, float cy, String str) // paints
{ protected final Paint mBackgroundPaint;
Rect b = new Rect(); protected final Paint mBorderPaint;
mTextPaint.getTextBounds(str, 0, str.length(), b); protected final Paint mTextPaint;
final float y = cy - b.exactCenterY();
c.drawText(str, cx, y, mTextPaint);
}
void configureTextSize() // geometry
{ protected float mWidth;
String text = getValueString(); protected float mHeight;
if (text == null) protected float mRadius;
return; protected float mBorderWidth;
final float textRadius = mBorderRadius - mBorderWidth; protected float mBorderRadius;
final float maxTextSize = 2f * textRadius;
final float maxTextSize2 = maxTextSize * maxTextSize; public BaseSignView(Context ctx, @Nullable AttributeSet attrs)
float lo = 0f, hi = maxTextSize, sz = maxTextSize;
Rect b = new Rect();
while (lo <= hi)
{ {
sz = (lo + hi) / 2f; super(ctx, attrs);
mTextPaint.setTextSize(sz); mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.getTextBounds(text, 0, text.length(), b); mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
float area = b.width() * b.width() + b.height() * b.height(); mBorderPaint.setStyle(Paint.Style.STROKE);
if (area <= maxTextSize2) mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
lo = sz + 1f; mTextPaint.setTextAlign(Paint.Align.CENTER);
else mTextPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
hi = sz - 1f;
} }
mTextPaint.setTextSize(Math.max(1f, sz));
}
/** child must return the string to draw, or null if nothing */ protected void setColors(int backgroundColor,
@Nullable int borderColor,
protected abstract String getValueString(); int alertColor,
int textColor,
int textAlertColor)
{
mBackgroundColor = backgroundColor;
mBorderColor = borderColor;
mAlertColor = alertColor;
mTextColor = textColor;
mTextAlertColor = textAlertColor;
/** child decides if this is in “alert” state */ mBackgroundPaint.setColor(mBackgroundColor);
protected abstract boolean isAlert(); mBorderPaint.setColor(mBorderColor);
mTextPaint.setColor(mTextColor);
}
@Override
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
super.onSizeChanged(width, height, oldWidth, oldHeight);
final float paddingX = getPaddingLeft() + getPaddingRight();
final float paddingY = getPaddingTop() + getPaddingBottom();
mWidth = width - paddingX;
mHeight = height - paddingY;
mRadius = Math.min(mWidth, mHeight) / 2f;
mBorderWidth = mRadius * mBorderWidthRatio;
// subtract half the stroke PLUS the extra inset
final float gap = mRadius * mBorderInsetRatio;
mBorderRadius = mRadius - (mBorderWidth / 2f) - gap;
configureTextSize();
}
@Override
protected void onDraw(@NonNull Canvas canvas)
{
super.onDraw(canvas);
final String str = getValueString();
if (str == null) return;
final float cx = mWidth / 2f;
final float cy = mHeight / 2f;
// background & border
boolean alert = isAlert();
mBackgroundPaint.setColor(alert ? mAlertColor : mBackgroundColor);
canvas.drawCircle(cx, cy, mRadius, mBackgroundPaint);
if (!alert)
{
mBorderPaint.setStrokeWidth(mBorderWidth);
mBorderPaint.setColor(mBorderColor);
canvas.drawCircle(cx, cy, mBorderRadius, mBorderPaint);
}
// text
mTextPaint.setColor(alert ? mTextAlertColor : mTextColor);
drawValueString(canvas, cx, cy, str);
}
@Override
public boolean onTouchEvent(@NonNull MotionEvent e)
{
final float cx = mWidth / 2f, cy = mHeight / 2f;
final float dx = e.getX() - cx, dy = e.getY() - cy;
if ((dx * dx) + (dy * dy) <= (mRadius * mRadius))
{
performClick();
return true;
}
return false;
}
@Override
public boolean performClick()
{
super.performClick();
return false;
}
private void drawValueString(Canvas c, float cx, float cy, String str)
{
Rect b = new Rect();
mTextPaint.getTextBounds(str, 0, str.length(), b);
final float y = cy - b.exactCenterY();
c.drawText(str, cx, y, mTextPaint);
}
void configureTextSize()
{
String text = getValueString();
if (text == null) return;
final float textRadius = mBorderRadius - mBorderWidth;
final float maxTextSize = 2f * textRadius;
final float maxTextSize2 = maxTextSize * maxTextSize;
float lo = 0f, hi = maxTextSize, sz = maxTextSize;
Rect b = new Rect();
while (lo <= hi)
{
sz = (lo + hi) / 2f;
mTextPaint.setTextSize(sz);
mTextPaint.getTextBounds(text, 0, text.length(), b);
float area = b.width()*b.width() + b.height()*b.height();
if (area <= maxTextSize2)
lo = sz + 1f;
else
hi = sz - 1f;
}
mTextPaint.setTextSize(Math.max(1f, sz));
}
/** child must return the string to draw, or null if nothing */
@Nullable
protected abstract String getValueString();
/** child decides if this is in “alert” state */
protected abstract boolean isAlert();
} }

View File

@@ -4,7 +4,9 @@ import android.content.Context;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Pair; import android.util.Pair;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.util.StringUtils; import app.organicmaps.sdk.util.StringUtils;
@@ -20,18 +22,18 @@ public class CurrentSpeedView extends BaseSignView
setBorderWidthRatio(0.1f); setBorderWidthRatio(0.1f);
setBorderInsetRatio(0.05f); setBorderInsetRatio(0.05f);
try (TypedArray a = ctx.getTheme().obtainStyledAttributes( try (TypedArray a = ctx.getTheme()
attrs, R.styleable.CurrentSpeedView /* reuse same attrs or define new */, 0, 0)) .obtainStyledAttributes(attrs, R.styleable.CurrentSpeedView /* reuse same attrs or define new */ , 0, 0))
{ {
int bg = a.getColor(R.styleable.CurrentSpeedView_currentSpeedBackgroundColor, DefaultValues.BACKGROUND_COLOR); int bg = a.getColor(R.styleable.CurrentSpeedView_currentSpeedBackgroundColor, DefaultValues.BACKGROUND_COLOR);
int bd = a.getColor(R.styleable.CurrentSpeedView_currentSpeedBorderColor, DefaultValues.BORDER_COLOR); int bd = a.getColor(R.styleable.CurrentSpeedView_currentSpeedBorderColor, DefaultValues.BORDER_COLOR);
int tc = a.getColor(R.styleable.CurrentSpeedView_currentSpeedTextColor, DefaultValues.TEXT_COLOR); int tc = a.getColor(R.styleable.CurrentSpeedView_currentSpeedTextColor, DefaultValues.TEXT_COLOR);
setColors(bg, bd, 0, tc, 0); setColors(bg, bd, 0, tc, 0);
if (isInEditMode()) if (isInEditMode())
{ {
mSpeedMps = a.getInt(R.styleable.CurrentSpeedView_currentSpeedEditModeCurrentSpeed, 50); mSpeedMps = a.getInt(R.styleable.CurrentSpeedView_currentSpeedEditModeCurrentSpeed, 50);
mSpeedStr = Integer.toString((int) mSpeedMps); mSpeedStr = Integer.toString((int)mSpeedMps);
} }
} }
} }
@@ -45,7 +47,7 @@ public class CurrentSpeedView extends BaseSignView
} }
else else
{ {
Pair<String, String> su = StringUtils.nativeFormatSpeedAndUnits(mps); Pair<String,String> su = StringUtils.nativeFormatSpeedAndUnits(mps);
mSpeedStr = su.first; mSpeedStr = su.first;
} }
requestLayout(); requestLayout();
@@ -68,8 +70,8 @@ public class CurrentSpeedView extends BaseSignView
private interface DefaultValues private interface DefaultValues
{ {
int BACKGROUND_COLOR = 0xFFFFFFFF; int BACKGROUND_COLOR = 0xFFFFFFFF;
int BORDER_COLOR = 0xFF000000; int BORDER_COLOR = 0xFF000000;
int TEXT_COLOR = 0xFF000000; int TEXT_COLOR = 0xFF000000;
} }
} }

View File

@@ -12,11 +12,13 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import app.organicmaps.R;
import app.organicmaps.util.UiUtils;
import com.google.android.material.imageview.ShapeableImageView; import com.google.android.material.imageview.ShapeableImageView;
import com.google.android.material.textview.MaterialTextView; import com.google.android.material.textview.MaterialTextView;
import app.organicmaps.R;
import app.organicmaps.util.UiUtils;
public class PlaceholderView extends LinearLayout public class PlaceholderView extends LinearLayout
{ {
@SuppressWarnings("NullableProblems") @SuppressWarnings("NullableProblems")

View File

@@ -5,14 +5,16 @@ import android.content.res.TypedArray;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import android.util.AttributeSet; import android.util.AttributeSet;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import app.organicmaps.R; import app.organicmaps.R;
public class SpeedLimitView extends BaseSignView public class SpeedLimitView extends BaseSignView
{ {
private int mSpeedLimit = -1; private int mSpeedLimit = -1;
private boolean mAlert = false; private boolean mAlert = false;
private String mSpeedStr = "-1"; private String mSpeedStr = "-1";
private final int unlimitedBorderColor; private final int unlimitedBorderColor;
private final int unlimitedStripeColor; private final int unlimitedStripeColor;
@@ -25,22 +27,15 @@ public class SpeedLimitView extends BaseSignView
try (TypedArray styleAttrs = ctx.getTheme().obtainStyledAttributes(attrs, R.styleable.SpeedLimitView, 0, 0)) try (TypedArray styleAttrs = ctx.getTheme().obtainStyledAttributes(attrs, R.styleable.SpeedLimitView, 0, 0))
{ {
final int bgColor = final int bgColor = styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitBackgroundColor, DefaultValues.BACKGROUND_COLOR);
styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitBackgroundColor, DefaultValues.BACKGROUND_COLOR); final int borderColor = styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitBorderColor, DefaultValues.BORDER_COLOR);
final int borderColor = final int alertColor = styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitAlertColor, DefaultValues.ALERT_COLOR);
styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitBorderColor, DefaultValues.BORDER_COLOR); final int textColor = styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitTextColor, DefaultValues.TEXT_COLOR);
final int alertColor = final int txtAlertColor = styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitTextAlertColor, DefaultValues.TEXT_ALERT_COLOR);
styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitAlertColor, DefaultValues.ALERT_COLOR);
final int textColor =
styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitTextColor, DefaultValues.TEXT_COLOR);
final int txtAlertColor =
styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitTextAlertColor, DefaultValues.TEXT_ALERT_COLOR);
setColors(bgColor, borderColor, alertColor, textColor, txtAlertColor); setColors(bgColor, borderColor, alertColor, textColor, txtAlertColor);
unlimitedBorderColor = styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitUnlimitedBorderColor, unlimitedBorderColor = styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitUnlimitedBorderColor, DefaultValues.UNLIMITED_BORDER_COLOR);
DefaultValues.UNLIMITED_BORDER_COLOR); unlimitedStripeColor = styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitUnlimitedStripeColor, DefaultValues.UNLIMITED_STRIPE_COLOR);
unlimitedStripeColor = styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitUnlimitedStripeColor,
DefaultValues.UNLIMITED_STRIPE_COLOR);
if (isInEditMode()) if (isInEditMode())
{ {
@@ -56,7 +51,7 @@ public class SpeedLimitView extends BaseSignView
if (mSpeedLimit != limit) if (mSpeedLimit != limit)
{ {
mSpeedLimit = limit; mSpeedLimit = limit;
mSpeedStr = Integer.toString(limit); mSpeedStr = Integer.toString(limit);
requestLayout(); requestLayout();
} }
mAlert = alert; mAlert = alert;
@@ -80,7 +75,7 @@ public class SpeedLimitView extends BaseSignView
@Override @Override
protected void onDraw(Canvas canvas) protected void onDraw(Canvas canvas)
{ {
final float cx = mWidth / 2f, cy = mHeight / 2f; final float cx = mWidth/2f, cy = mHeight/2f;
if (mSpeedLimit == 0) // 0 means unlimited speed (maxspeed=none) if (mSpeedLimit == 0) // 0 means unlimited speed (maxspeed=none)
{ {
@@ -110,7 +105,7 @@ public class SpeedLimitView extends BaseSignView
stripe.setStrokeWidth(mBorderWidth * 0.4f); stripe.setStrokeWidth(mBorderWidth * 0.4f);
final float radius = mRadius * 0.8f; // Shorten to 80% of full radius final float radius = mRadius * 0.8f; // Shorten to 80% of full radius
final float diag = (float) (1 / Math.sqrt(2)); // 45 degrees final float diag = (float) (1/Math.sqrt(2)); // 45 degrees
final float dx = -diag, dy = +diag; final float dx = -diag, dy = +diag;
final float px = -dy, py = +dx; // Perpendicular final float px = -dy, py = +dx; // Perpendicular
final float step = radius * 0.15f; // Spacing final float step = radius * 0.15f; // Spacing
@@ -127,13 +122,14 @@ public class SpeedLimitView extends BaseSignView
} }
} }
private interface DefaultValues private interface DefaultValues
{ {
int BACKGROUND_COLOR = 0xFFFFFFFF; int BACKGROUND_COLOR = 0xFFFFFFFF;
int BORDER_COLOR = 0xFFFF0000; int BORDER_COLOR = 0xFFFF0000;
int ALERT_COLOR = 0xFFFF0000; int ALERT_COLOR = 0xFFFF0000;
int TEXT_COLOR = 0xFF000000; int TEXT_COLOR = 0xFF000000;
int TEXT_ALERT_COLOR = 0xFFFFFFFF; int TEXT_ALERT_COLOR = 0xFFFFFFFF;
int UNLIMITED_BORDER_COLOR = 0xFF000000; int UNLIMITED_BORDER_COLOR = 0xFF000000;
int UNLIMITED_STRIPE_COLOR = 0xFF000000; int UNLIMITED_STRIPE_COLOR = 0xFF000000;
} }

View File

@@ -72,7 +72,7 @@ public class MyPositionButton
case LocationState.FOLLOW_AND_ROTATE -> R.drawable.ic_follow_and_rotate; case LocationState.FOLLOW_AND_ROTATE -> R.drawable.ic_follow_and_rotate;
default -> throw new IllegalArgumentException("Invalid button mode: " + mode); default -> throw new IllegalArgumentException("Invalid button mode: " + mode);
}; };
image = ResourcesCompat.getDrawable(resources, drawableRes, context.getTheme()); image = ResourcesCompat.getDrawable(resources, drawableRes, context.getTheme());
mIcons.put(mode, image); mIcons.put(mode, image);
} }

View File

@@ -1,9 +1,9 @@
package app.organicmaps.widget.placepage; package app.organicmaps.widget.placepage;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import app.organicmaps.sdk.util.StringUtils; import app.organicmaps.sdk.util.StringUtils;
import com.github.mikephil.charting.charts.BarLineChartBase; import com.github.mikephil.charting.charts.BarLineChartBase;
import androidx.annotation.Nullable;
import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.formatter.IAxisValueFormatter;

View File

@@ -105,8 +105,7 @@ public class EditBookmarkFragment extends BaseMwmDialogFragment implements View.
public EditBookmarkFragment() {} public EditBookmarkFragment() {}
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) public void onCreate(@Nullable Bundle savedInstanceState) {
{
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NORMAL, R.style.MwmTheme_FullScreenDialog); setStyle(DialogFragment.STYLE_NORMAL, R.style.MwmTheme_FullScreenDialog);
} }
@@ -185,9 +184,10 @@ public class EditBookmarkFragment extends BaseMwmDialogFragment implements View.
{ {
super.onStart(); super.onStart();
Dialog dialog = getDialog(); Dialog dialog = getDialog();
if (dialog != null) if (dialog != null) {
{ dialog.getWindow().setLayout(
dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
} }
// Focus name and show keyboard for "Unknown Place" bookmarks // Focus name and show keyboard for "Unknown Place" bookmarks

View File

@@ -6,6 +6,9 @@ import android.widget.RelativeLayout;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.widget.NestedScrollView; import androidx.core.widget.NestedScrollView;
import com.google.android.material.textview.MaterialTextView;
import app.organicmaps.ChartController; import app.organicmaps.ChartController;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.Framework; import app.organicmaps.sdk.Framework;
@@ -14,7 +17,6 @@ import app.organicmaps.sdk.bookmarks.data.Track;
import app.organicmaps.sdk.bookmarks.data.TrackStatistics; import app.organicmaps.sdk.bookmarks.data.TrackStatistics;
import app.organicmaps.util.UiUtils; import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import com.google.android.material.textview.MaterialTextView;
import java.util.Objects; import java.util.Objects;
public class ElevationProfileViewRenderer implements PlacePageStateListener public class ElevationProfileViewRenderer implements PlacePageStateListener

View File

@@ -14,8 +14,7 @@ public class OpenStateTextFormatter
return String.format(Locale.ROOT, "%02d:%02d", hour, minute); return String.format(Locale.ROOT, "%02d:%02d", hour, minute);
int h = hour % 12; int h = hour % 12;
if (h == 0) if (h == 0) h = 12;
h = 12;
String ampm = (hour < 12) ? "AM" : "PM"; String ampm = (hour < 12) ? "AM" : "PM";
return String.format(Locale.ROOT, "%d:%02d %s", h, minute, ampm); return String.format(Locale.ROOT, "%d:%02d %s", h, minute, ampm);
} }
@@ -30,13 +29,21 @@ public class OpenStateTextFormatter
return t.getDayOfWeek().getDisplayName(TextStyle.SHORT, locale); return t.getDayOfWeek().getDisplayName(TextStyle.SHORT, locale);
} }
static String buildAtLabel(boolean opens, boolean isToday, String dayShort, String time, String opensAtLocalized, static String buildAtLabel(
String closesAtLocalized, String opensDayAtLocalized, String closesDayAtLocalized) boolean opens,
boolean isToday,
String dayShort,
String time,
String opensAtLocalized,
String closesAtLocalized,
String opensDayAtLocalized,
String closesDayAtLocalized
)
{ {
if (isToday) if (isToday)
return opens ? String.format(Locale.ROOT, opensAtLocalized, time) // Opens at %s return opens ? String.format(Locale.ROOT, opensAtLocalized, time) // Opens at %s
: String.format(Locale.ROOT, closesAtLocalized, time); // Closes at %s : String.format(Locale.ROOT, closesAtLocalized, time); // Closes at %s
return opens ? String.format(Locale.ROOT, opensDayAtLocalized, dayShort, time) // Opens %s at %s return opens ? String.format(Locale.ROOT, opensDayAtLocalized, dayShort, time) // Opens %s at %s
: String.format(Locale.ROOT, closesDayAtLocalized, dayShort, time); // Closes %s at %s : String.format(Locale.ROOT, closesDayAtLocalized, dayShort, time); // Closes %s at %s
} }
} }

View File

@@ -80,6 +80,6 @@ public class PlacePageButtonFactory
yield R.drawable.ic_more; yield R.drawable.ic_more;
} }
}; };
return new PlacePageButton(titleId, iconId, buttonType); return new PlacePageButton(titleId, iconId, buttonType);
} }
} }

View File

@@ -31,6 +31,7 @@ import androidx.fragment.app.FragmentFactory;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.Observer; import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import app.organicmaps.MwmActivity; import app.organicmaps.MwmActivity;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; import app.organicmaps.R;
@@ -699,20 +700,27 @@ public class PlacePageView extends Fragment
if (shouldEnableEditPlace) if (shouldEnableEditPlace)
{ {
mTvEditPlace.setEnabled(true);
mTvAddPlace.setEnabled(true);
mTvEditPlace.setOnClickListener(this); mTvEditPlace.setOnClickListener(this);
mTvAddPlace.setOnClickListener(this); mTvAddPlace.setOnClickListener(this);
} }
else else
{ {
mTvEditPlace.setOnClickListener(
(v) -> { Utils.showSnackbar(v.getContext(), v.getRootView(), R.string.place_page_too_old_to_edit); });
mTvAddPlace.setOnClickListener(
(v) -> { Utils.showSnackbar(v.getContext(), v.getRootView(), R.string.place_page_too_old_to_edit); });
String countryId = MapManager.nativeGetSelectedCountry(); String countryId = MapManager.nativeGetSelectedCountry();
if (countryId != null) if (countryId != null && MapManager.nativeIsMapTooOldToEdit(countryId))
{ {
// map editing is disabled because the map is too old
mTvEditPlace.setEnabled(true);
mTvAddPlace.setEnabled(true);
mTvEditPlace.setOnClickListener((v) -> {
Utils.showSnackbar(v.getContext(), v.getRootView(), R.string.place_page_too_old_to_edit);
});
mTvAddPlace.setOnClickListener((v) -> {
Utils.showSnackbar(v.getContext(), v.getRootView(), R.string.place_page_too_old_to_edit);
});
CountryItem map = CountryItem.fill(countryId); CountryItem map = CountryItem.fill(countryId);
if (map.status == CountryItem.STATUS_UPDATABLE || map.status == CountryItem.STATUS_DONE if (map.status == CountryItem.STATUS_UPDATABLE || map.status == CountryItem.STATUS_DONE
@@ -737,6 +745,12 @@ public class PlacePageView extends Fragment
mapTooOldDescription.setText(R.string.place_page_app_too_old_description); mapTooOldDescription.setText(R.string.place_page_app_too_old_description);
} }
} }
else
{
// map editing is disabled for other reasons
mTvEditPlace.setEnabled(false);
mTvAddPlace.setEnabled(false);
}
} }
final int editButtonColor = final int editButtonColor =
@@ -750,7 +764,9 @@ public class PlacePageView extends Fragment
mTvAddPlace.setTextColor(editButtonColor); mTvAddPlace.setTextColor(editButtonColor);
mTvEditPlace.setStrokeColor(ColorStateList.valueOf(editButtonColor)); mTvEditPlace.setStrokeColor(ColorStateList.valueOf(editButtonColor));
mTvAddPlace.setStrokeColor(ColorStateList.valueOf(editButtonColor)); mTvAddPlace.setStrokeColor(ColorStateList.valueOf(editButtonColor));
UiUtils.showIf(UiUtils.isVisible(mEditPlace) || UiUtils.isVisible(mAddPlace), mEditTopSpace); UiUtils.showIf(
UiUtils.isVisible(mEditPlace) || UiUtils.isVisible(mAddPlace),
mEditTopSpace);
} }
updateLinksView(); updateLinksView();
updateOpeningHoursView(); updateOpeningHoursView();
@@ -851,9 +867,10 @@ public class PlacePageView extends Fragment
} }
// Get colours // Get colours
final ForegroundColorSpan colorGreen = new ForegroundColorSpan(ContextCompat.getColor(context, R.color.base_green)); final ForegroundColorSpan colorGreen =
new ForegroundColorSpan(ContextCompat.getColor(context, R.color.base_green));
final ForegroundColorSpan colorYellow = final ForegroundColorSpan colorYellow =
new ForegroundColorSpan(ContextCompat.getColor(context, R.color.base_yellow)); new ForegroundColorSpan(ContextCompat.getColor(context, R.color.base_yellow));
final ForegroundColorSpan colorRed = new ForegroundColorSpan(ContextCompat.getColor(context, R.color.base_red)); final ForegroundColorSpan colorRed = new ForegroundColorSpan(ContextCompat.getColor(context, R.color.base_red));
// Get next state info // Get next state info
@@ -879,12 +896,13 @@ public class PlacePageView extends Fragment
if (nextStateTime > 0 && nextStateTime < Long.MAX_VALUE / 2) if (nextStateTime > 0 && nextStateTime < Long.MAX_VALUE / 2)
{ {
// NOTE: Timezone is currently device timezone. TODO: use feature-specific timezone. // NOTE: Timezone is currently device timezone. TODO: use feature-specific timezone.
nextChangeLocal = ZonedDateTime.ofInstant(Instant.ofEpochSecond(nextStateTime), ZoneId.systemDefault()); nextChangeLocal = ZonedDateTime.ofInstant(
Instant.ofEpochSecond(nextStateTime), ZoneId.systemDefault()
);
hasFiniteNextChange = true; hasFiniteNextChange = true;
} }
} }
catch (Throwable ignored) catch (Throwable ignored) {}
{}
} }
if (!hasFiniteNextChange) // No valid next change if (!hasFiniteNextChange) // No valid next change
@@ -899,7 +917,7 @@ public class PlacePageView extends Fragment
} }
String localizedTimeString = OpenStateTextFormatter.formatHoursMinutes( String localizedTimeString = OpenStateTextFormatter.formatHoursMinutes(
nextChangeLocal.getHour(), nextChangeLocal.getMinute(), DateUtils.is24HourFormat(context)); nextChangeLocal.getHour(), nextChangeLocal.getMinute(), DateUtils.is24HourFormat(context));
final boolean shortHorizonClosing = isOpen && minsToNextState >= 0 && minsToNextState <= SHORT_HORIZON_CLOSE_MIN; final boolean shortHorizonClosing = isOpen && minsToNextState >= 0 && minsToNextState <= SHORT_HORIZON_CLOSE_MIN;
final boolean shortHorizonOpening = !isOpen && minsToNextState >= 0 && minsToNextState <= SHORT_HORIZON_OPEN_MIN; final boolean shortHorizonOpening = !isOpen && minsToNextState >= 0 && minsToNextState <= SHORT_HORIZON_OPEN_MIN;
@@ -907,12 +925,12 @@ public class PlacePageView extends Fragment
if (shortHorizonClosing || shortHorizonOpening) // POI Opens/Closes in 60 mins • at 18:00 if (shortHorizonClosing || shortHorizonOpening) // POI Opens/Closes in 60 mins • at 18:00
{ {
final String minsToChangeStr = getResources().getQuantityString( final String minsToChangeStr = getResources().getQuantityString(
R.plurals.minutes_short, Math.max(minsToNextState, 1), Math.max(minsToNextState, 1)); R.plurals.minutes_short, Math.max(minsToNextState, 1), Math.max(minsToNextState, 1));
final String nextChangeFormatted = getString(isOpen ? R.string.closes_in : R.string.opens_in, minsToChangeStr); final String nextChangeFormatted = getString(isOpen ? R.string.closes_in : R.string.opens_in, minsToChangeStr);
openStateString.append(nextChangeFormatted, colorYellow, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) openStateString.append(nextChangeFormatted, colorYellow, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
.append("") // Add spacer .append("") // Add spacer
.append(getString(R.string.at, localizedTimeString)); .append(getString(R.string.at, localizedTimeString));
} }
else else
{ {
@@ -922,16 +940,18 @@ public class PlacePageView extends Fragment
final String closesDayAtStr = getString(R.string.closes_day_at); // "Closes %1$s at %2$s" final String closesDayAtStr = getString(R.string.closes_day_at); // "Closes %1$s at %2$s"
final boolean isToday = final boolean isToday =
OpenStateTextFormatter.isSameLocalDate(nextChangeLocal, ZonedDateTime.now(nextChangeLocal.getZone())); OpenStateTextFormatter.isSameLocalDate(nextChangeLocal, ZonedDateTime.now(nextChangeLocal.getZone()));
// Full weekday name per design feedback. // Full weekday name per design feedback.
final String dayName = nextChangeLocal.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.getDefault()); final String dayName =
nextChangeLocal.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.getDefault());
if (isOpen) // > 60 minutes OR negative (safety). Show “Open now • Closes at 18:00” if (isOpen) // > 60 minutes OR negative (safety). Show “Open now • Closes at 18:00”
{ {
openStateString.append(getString(R.string.open_now), colorGreen, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); openStateString.append(getString(R.string.open_now), colorGreen, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
final String atLabel = OpenStateTextFormatter.buildAtLabel( final String atLabel =
false, isToday, dayName, localizedTimeString, opensAtStr, closesAtStr, opensDayAtStr, closesDayAtStr); OpenStateTextFormatter.buildAtLabel(false, isToday, dayName, localizedTimeString,
opensAtStr, closesAtStr, opensDayAtStr, closesDayAtStr);
if (!TextUtils.isEmpty(atLabel)) if (!TextUtils.isEmpty(atLabel))
openStateString.append("").append(atLabel); openStateString.append("").append(atLabel);
@@ -940,8 +960,9 @@ public class PlacePageView extends Fragment
{ {
openStateString.append(getString(R.string.closed_now), colorRed, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); openStateString.append(getString(R.string.closed_now), colorRed, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
final String atLabel = OpenStateTextFormatter.buildAtLabel( final String atLabel =
true, isToday, dayName, localizedTimeString, opensAtStr, closesAtStr, opensDayAtStr, closesDayAtStr); OpenStateTextFormatter.buildAtLabel(true, isToday, dayName, localizedTimeString,
opensAtStr, closesAtStr, opensDayAtStr, closesDayAtStr);
if (!TextUtils.isEmpty(atLabel)) if (!TextUtils.isEmpty(atLabel))
openStateString.append("").append(atLabel); openStateString.append("").append(atLabel);

View File

@@ -3,7 +3,9 @@ package app.organicmaps.widget.placepage;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModel;
import app.organicmaps.sdk.bookmarks.data.MapObject; import app.organicmaps.sdk.bookmarks.data.MapObject;
import java.util.List; import java.util.List;
public class PlacePageViewModel extends ViewModel public class PlacePageViewModel extends ViewModel

View File

@@ -31,8 +31,7 @@ import app.organicmaps.widget.placepage.PlacePageViewModel;
import com.google.android.material.textview.MaterialTextView; import com.google.android.material.textview.MaterialTextView;
public class PlacePageBookmarkFragment extends Fragment implements View.OnClickListener, View.OnLongClickListener, public class PlacePageBookmarkFragment extends Fragment implements View.OnClickListener, View.OnLongClickListener,
Observer<MapObject>, Observer<MapObject>, EditBookmarkFragment.EditBookmarkListener
EditBookmarkFragment.EditBookmarkListener
{ {
private View mFrame; private View mFrame;
private MaterialTextView mTvBookmarkNote; private MaterialTextView mTvBookmarkNote;

View File

@@ -13,13 +13,15 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer; import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import com.google.android.material.imageview.ShapeableImageView;
import com.google.android.material.textview.MaterialTextView;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.Framework; import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.bookmarks.data.ChargeSocketDescriptor; import app.organicmaps.sdk.bookmarks.data.ChargeSocketDescriptor;
import app.organicmaps.sdk.bookmarks.data.MapObject; import app.organicmaps.sdk.bookmarks.data.MapObject;
import app.organicmaps.widget.placepage.PlacePageViewModel; import app.organicmaps.widget.placepage.PlacePageViewModel;
import com.google.android.material.imageview.ShapeableImageView;
import com.google.android.material.textview.MaterialTextView;
import java.text.DecimalFormat; import java.text.DecimalFormat;
public class PlacePageChargeSocketsFragment extends Fragment implements Observer<MapObject> public class PlacePageChargeSocketsFragment extends Fragment implements Observer<MapObject>
@@ -94,8 +96,8 @@ public class PlacePageChargeSocketsFragment extends Fragment implements Observer
} }
@SuppressLint("DiscouragedApi") @SuppressLint("DiscouragedApi")
int resTypeId = getResources().getIdentifier("charge_socket_" + socket.visualType(), "string", int resTypeId =
requireContext().getPackageName()); getResources().getIdentifier("charge_socket_" + socket.visualType(), "string", requireContext().getPackageName());
if (resTypeId != 0) if (resTypeId != 0)
{ {
type.setText(resTypeId); type.setText(resTypeId);
@@ -106,8 +108,7 @@ public class PlacePageChargeSocketsFragment extends Fragment implements Observer
DecimalFormat df = new DecimalFormat("#.##"); DecimalFormat df = new DecimalFormat("#.##");
power.setText(getString(R.string.kw_label, df.format(socket.power()))); power.setText(getString(R.string.kw_label, df.format(socket.power())));
} }
else if (socket.ignorePower()) else if (socket.ignorePower()) {
{
power.setVisibility(INVISIBLE); power.setVisibility(INVISIBLE);
} }

View File

@@ -191,9 +191,8 @@ public class PlacePageLinksFragment extends Fragment implements Observer<MapObje
case FMD_PANORAMAX -> null; // Don't add raw ID to list, as it's useless for users. case FMD_PANORAMAX -> null; // Don't add raw ID to list, as it's useless for users.
default -> mMapObject.getMetadata(type); default -> mMapObject.getMetadata(type);
}; };
// Add user names for social media if available // Add user names for social media if available
if (!TextUtils.isEmpty(title) && !title.equals(url) && !title.contains("/")) if (!TextUtils.isEmpty(title) && !title.equals(url) && !title.contains("/")) items.add(title);
items.add(title);
if (items.size() == 1) if (items.size() == 1)
PlacePageUtils.copyToClipboard(requireContext(), mFrame, items.get(0)); PlacePageUtils.copyToClipboard(requireContext(), mFrame, items.get(0));

View File

@@ -2,6 +2,6 @@
<shape <shape
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"> android:shape="rectangle">
<solid android:color="@color/bg_panel"/> <solid android:color="@color/bg_window"/>
<corners android:radius="100dp"/> <corners android:radius="100dp"/>
</shape> </shape>

View File

@@ -2,5 +2,5 @@
<shape <shape
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval"> android:shape="oval">
<solid android:color="@color/bg_panel"/> <solid android:color="@color/bg_window"/>
</shape> </shape>

View File

@@ -3,7 +3,7 @@
android:height="24dp" android:height="24dp"
android:viewportWidth="960" android:viewportWidth="960"
android:viewportHeight="960" android:viewportHeight="960"
android:tint="?colorControlNormal"> android:tint="?iconTint">
<path <path
android:pathData="M80,360v-160q0,-33 23.5,-56.5T160,120h640q33,0 56.5,23.5T880,200v160h-80v-160L160,200v160L80,360ZM160,720q-33,0 -56.5,-23.5T80,640v-200h80v200h640v-200h80v200q0,33 -23.5,56.5T800,720L160,720ZM40,840v-80h880v80L40,840ZM480,420ZM80,440v-80h240q11,0 21,6t15,16l47,93 123,-215q5,-9 14,-14.5t20,-5.5q11,0 21,5.5t15,16.5l49,98h235v80L620,440q-11,0 -21,-5.5T584,418l-26,-53 -123,215q-5,10 -15,15t-21,5q-11,0 -20.5,-6T364,578l-69,-138L80,440Z" android:pathData="M80,360v-160q0,-33 23.5,-56.5T160,120h640q33,0 56.5,23.5T880,200v160h-80v-160L160,200v160L80,360ZM160,720q-33,0 -56.5,-23.5T80,640v-200h80v200h640v-200h80v200q0,33 -23.5,56.5T800,720L160,720ZM40,840v-80h880v80L40,840ZM480,420ZM80,440v-80h240q11,0 21,6t15,16l47,93 123,-215q5,-9 14,-14.5t20,-5.5q11,0 21,5.5t15,16.5l49,98h235v80L620,440q-11,0 -21,-5.5T584,418l-26,-53 -123,215q-5,10 -15,15t-21,5q-11,0 -20.5,-6T364,578l-69,-138L80,440Z"
android:fillColor="#fff"/> android:fillColor="#fff"/>

View File

@@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:tint="?iconTint"
android:height="24dp"
android:width="24dp"
android:viewportHeight="960"
android:viewportWidth="960">
<path android:fillColor="@android:color/white"
android:pathData="M260,800Q169,800 104.5,737Q40,674 40,583Q40,505 87,444Q134,383 210,366Q227,294 295,229Q363,164 440,164Q473,164 496.5,187.5Q520,211 520,244L520,486L584,424L640,480L480,640L320,480L376,424L440,486L440,244Q364,258 322,317.5Q280,377 280,440L260,440Q202,440 161,481Q120,522 120,580Q120,638 161,679Q202,720 260,720L740,720Q782,720 811,691Q840,662 840,620Q840,578 811,549Q782,520 740,520L680,520L680,440Q680,392 658,350.5Q636,309 600,280L600,187Q674,222 717,290.5Q760,359 760,440L760,440L760,440Q829,448 874.5,499.5Q920,551 920,620Q920,695 867.5,747.5Q815,800 740,800L260,800ZM480,442Q480,442 480,442Q480,442 480,442L480,442Q480,442 480,442Q480,442 480,442L480,442Q480,442 480,442Q480,442 480,442L480,442Q480,442 480,442Q480,442 480,442Q480,442 480,442Q480,442 480,442L480,442Q480,442 480,442Q480,442 480,442Q480,442 480,442Q480,442 480,442L480,442L480,442Q480,442 480,442Q480,442 480,442Z"/>
</vector>

View File

@@ -3,7 +3,7 @@
android:height="24dp" android:height="24dp"
android:viewportWidth="960" android:viewportWidth="960"
android:viewportHeight="960" android:viewportHeight="960"
android:tint="?colorControlNormal"> android:tint="?iconTint">
<path <path
android:pathData="M480,840q-150,0 -255,-105T120,480q0,-150 105,-255t255,-105q14,0 27.5,1t26.5,3q-41,29 -65.5,75.5T444,300q0,90 63,153t153,63q55,0 101,-24.5t75,-65.5q2,13 3,26.5t1,27.5q0,150 -105,255T480,840ZM480,760q88,0 158,-48.5T740,585q-20,5 -40,8t-40,3q-123,0 -209.5,-86.5T364,300q0,-20 3,-40t8,-40q-78,32 -126.5,102T200,480q0,116 82,198t198,82ZM470,490Z" android:pathData="M480,840q-150,0 -255,-105T120,480q0,-150 105,-255t255,-105q14,0 27.5,1t26.5,3q-41,29 -65.5,75.5T444,300q0,90 63,153t153,63q55,0 101,-24.5t75,-65.5q2,13 3,26.5t1,27.5q0,150 -105,255T480,840ZM480,760q88,0 158,-48.5T740,585q-20,5 -40,8t-40,3q-123,0 -209.5,-86.5T364,300q0,-20 3,-40t8,-40q-78,32 -126.5,102T200,480q0,116 82,198t198,82ZM470,490Z"
android:fillColor="#fff"/> android:fillColor="#fff"/>

View File

@@ -3,7 +3,7 @@
android:height="24dp" android:height="24dp"
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24" android:viewportHeight="24"
android:tint="?colorControlNormal"> android:tint="?iconTint">
<path <path
android:pathData="M19,9h-4v-6h-6v6h-4l7,7 7,-7ZM5,18v2h14v-2h-14Z" android:pathData="M19,9h-4v-6h-6v6h-4l7,7 7,-7ZM5,18v2h14v-2h-14Z"
android:fillColor="#FFF"/> android:fillColor="#FFF"/>

View File

@@ -3,7 +3,7 @@
android:height="24dp" android:height="24dp"
android:viewportWidth="960" android:viewportWidth="960"
android:viewportHeight="960" android:viewportHeight="960"
android:tint="?colorControlNormal"> android:tint="?iconTint">
<path <path
android:pathData="M216,784q-45,-45 -70.5,-104T120,558q0,-63 24,-124.5T222,318q35,-35 86.5,-60t122,-39.5Q501,204 591.5,201t202.5,7q8,106 5,195t-16.5,160.5q-13.5,71.5 -38,125T684,778q-53,53 -112.5,77.5T450,880q-65,0 -127,-25.5T216,784ZM328,768q29,17 59.5,24.5T450,800q46,0 91,-18.5t86,-59.5q18,-18 36.5,-50.5t32,-85Q709,534 716,459.5t2,-177.5q-49,-2 -110.5,-1.5T485,290q-61,9 -116,29t-90,55q-45,45 -62,89t-17,85q0,59 22.5,103.5T262,714q42,-80 111,-153.5T534,440q-72,63 -125.5,142.5T328,768ZM328,768ZM328,768Z" android:pathData="M216,784q-45,-45 -70.5,-104T120,558q0,-63 24,-124.5T222,318q35,-35 86.5,-60t122,-39.5Q501,204 591.5,201t202.5,7q8,106 5,195t-16.5,160.5q-13.5,71.5 -38,125T684,778q-53,53 -112.5,77.5T450,880q-65,0 -127,-25.5T216,784ZM328,768q29,17 59.5,24.5T450,800q46,0 91,-18.5t86,-59.5q18,-18 36.5,-50.5t32,-85Q709,534 716,459.5t2,-177.5q-49,-2 -110.5,-1.5T485,290q-61,9 -116,29t-90,55q-45,45 -62,89t-17,85q0,59 22.5,103.5T262,714q42,-80 111,-153.5T534,440q-72,63 -125.5,142.5T328,768ZM328,768ZM328,768Z"
android:fillColor="#fff"/> android:fillColor="#fff"/>

View File

@@ -3,7 +3,7 @@
android:height="24dp" android:height="24dp"
android:viewportWidth="960" android:viewportWidth="960"
android:viewportHeight="960" android:viewportHeight="960"
android:tint="?colorControlNormal"> android:tint="?iconTint">
<path <path
android:pathData="M200,800v-280h-80v-80h240v80h-80v280h-80ZM200,360v-200h80v200h-80ZM360,360v-80h80v-120h80v120h80v80L360,360ZM440,800v-360h80v360h-80ZM680,800v-120h-80v-80h240v80h-80v120h-80ZM680,520v-360h80v360h-80Z" android:pathData="M200,800v-280h-80v-80h240v80h-80v280h-80ZM200,360v-200h80v200h-80ZM360,360v-80h80v-120h80v120h80v80L360,360ZM440,800v-360h80v360h-80ZM680,800v-120h-80v-80h240v80h-80v120h-80ZM680,520v-360h80v360h-80Z"
android:fillColor="#fff"/> android:fillColor="#fff"/>

View File

@@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:viewportWidth="960" android:viewportWidth="24"
android:viewportHeight="960"> android:viewportHeight="24">
<path <path
android:pathData="M240,520q-17,0 -28.5,-11.5T200,480q0,-17 11.5,-28.5T240,440h480q17,0 28.5,11.5T760,480q0,17 -11.5,28.5T720,520L240,520Z" android:pathData="M19,13H5v-2h14v2z"
android:fillColor="#ffffff"/> android:fillColor="#ffffff"/>
</vector> </vector>

View File

@@ -3,7 +3,7 @@
android:height="24dp" android:height="24dp"
android:viewportWidth="960" android:viewportWidth="960"
android:viewportHeight="960" android:viewportHeight="960"
android:tint="?colorControlNormal"> android:tint="?iconTint">
<path <path
android:pathData="M280,920q-33,0 -56.5,-23.5T200,840v-720q0,-33 23.5,-56.5T280,40h400q33,0 56.5,23.5T760,120v124q18,7 29,22t11,34v80q0,19 -11,34t-29,22v404q0,33 -23.5,56.5T680,920L280,920ZM280,840h400v-720L280,120v720ZM280,840v-720,720ZM394,640h172q14,0 24,-10t10,-24v-132q0,-14 -10,-24t-24,-10h-6v-40q0,-33 -23.5,-56.5T480,320q-33,0 -56.5,23.5T400,400v40h-6q-14,0 -24,10t-10,24v132q0,14 10,24t24,10ZM440,440v-40q0,-17 11.5,-28.5T480,360q17,0 28.5,11.5T520,400v40h-80Z" android:pathData="M280,920q-33,0 -56.5,-23.5T200,840v-720q0,-33 23.5,-56.5T280,40h400q33,0 56.5,23.5T760,120v124q18,7 29,22t11,34v80q0,19 -11,34t-29,22v404q0,33 -23.5,56.5T680,920L280,920ZM280,840h400v-720L280,120v720ZM280,840v-720,720ZM394,640h172q14,0 24,-10t10,-24v-132q0,-14 -10,-24t-24,-10h-6v-40q0,-33 -23.5,-56.5T480,320q-33,0 -56.5,23.5T400,400v40h-6q-14,0 -24,10t-10,24v132q0,14 10,24t24,10ZM440,440v-40q0,-17 11.5,-28.5T480,360q17,0 28.5,11.5T520,400v40h-80Z"
android:fillColor="#fff"/> android:fillColor="#fff"/>

View File

@@ -3,7 +3,7 @@
android:height="24dp" android:height="24dp"
android:viewportWidth="960" android:viewportWidth="960"
android:viewportHeight="960" android:viewportHeight="960"
android:tint="?colorControlNormal"> android:tint="?iconTint">
<path <path
android:pathData="M339,698q22,-22 49.5,-36t58.5,-19q-5,19 -8,38t-3,39q0,24 3.5,47t11.5,44L339,698ZM254,614 L170,528q62,-62 142,-95t168,-33q49,0 96,10.5t90,30.5q-44,8 -81.5,29T517,522q-9,-1 -18.5,-1.5T480,520q-64,0 -122.5,24.5T254,614ZM84,444 L0,360q95,-97 219.5,-148.5T480,160q136,0 260.5,51.5T960,360l-84,84q-79,-79 -181.5,-121.5T480,280q-112,0 -214.5,42.5T84,444ZM760,520 L772,580q12,5 22.5,10.5T816,604l58,-18 40,68 -46,40q2,12 2,26t-2,26l46,40 -40,68 -58,-18q-11,8 -21.5,13.5T772,860l-12,60h-80l-12,-60q-12,-5 -22.5,-10.5T624,836l-58,18 -40,-68 46,-40q-2,-12 -2,-26t2,-26l-46,-40 40,-68 58,18q11,-8 21.5,-13.5T668,580l12,-60h80ZM720,640q-33,0 -56.5,23.5T640,720q0,33 23.5,56.5T720,800q33,0 56.5,-23.5T800,720q0,-33 -23.5,-56.5T720,640Z" android:pathData="M339,698q22,-22 49.5,-36t58.5,-19q-5,19 -8,38t-3,39q0,24 3.5,47t11.5,44L339,698ZM254,614 L170,528q62,-62 142,-95t168,-33q49,0 96,10.5t90,30.5q-44,8 -81.5,29T517,522q-9,-1 -18.5,-1.5T480,520q-64,0 -122.5,24.5T254,614ZM84,444 L0,360q95,-97 219.5,-148.5T480,160q136,0 260.5,51.5T960,360l-84,84q-79,-79 -181.5,-121.5T480,280q-112,0 -214.5,42.5T84,444ZM760,520 L772,580q12,5 22.5,10.5T816,604l58,-18 40,68 -46,40q2,12 2,26t-2,26l46,40 -40,68 -58,-18q-11,8 -21.5,13.5T772,860l-12,60h-80l-12,-60q-12,-5 -22.5,-10.5T624,836l-58,18 -40,-68 46,-40q-2,-12 -2,-26t2,-26l-46,-40 40,-68 58,18q11,-8 21.5,-13.5T668,580l12,-60h80ZM720,640q-33,0 -56.5,23.5T640,720q0,33 23.5,56.5T720,800q33,0 56.5,-23.5T800,720q0,-33 -23.5,-56.5T720,640Z"
android:fillColor="#fff"/> android:fillColor="#fff"/>

View File

@@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:viewportWidth="960" android:viewportWidth="24"
android:viewportHeight="960"> android:viewportHeight="24">
<path <path
android:pathData="M440,520L240,520q-17,0 -28.5,-11.5T200,480q0,-17 11.5,-28.5T240,440h200v-200q0,-17 11.5,-28.5T480,200q17,0 28.5,11.5T520,240v200h200q17,0 28.5,11.5T760,480q0,17 -11.5,28.5T720,520L520,520v200q0,17 -11.5,28.5T480,760q-17,0 -28.5,-11.5T440,720v-200Z" android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"
android:fillColor="@android:color/white"/> android:fillColor="@android:color/white"/>
</vector> </vector>

View File

@@ -3,7 +3,7 @@
android:height="24dp" android:height="24dp"
android:viewportWidth="960" android:viewportWidth="960"
android:viewportHeight="960" android:viewportHeight="960"
android:tint="?colorControlNormal"> android:tint="?iconTint">
<path <path
android:pathData="M480,480q-66,0 -113,-47t-47,-113q0,-66 47,-113t113,-47q66,0 113,47t47,113q0,66 -47,113t-113,47ZM160,800v-112q0,-34 17.5,-62.5T224,582q62,-31 126,-46.5T480,520q66,0 130,15.5T736,582q29,15 46.5,43.5T800,688v112L160,800ZM240,720h480v-32q0,-11 -5.5,-20T700,654q-54,-27 -109,-40.5T480,600q-56,0 -111,13.5T260,654q-9,5 -14.5,14t-5.5,20v32ZM480,400q33,0 56.5,-23.5T560,320q0,-33 -23.5,-56.5T480,240q-33,0 -56.5,23.5T400,320q0,33 23.5,56.5T480,400ZM480,320ZM480,720Z" android:pathData="M480,480q-66,0 -113,-47t-47,-113q0,-66 47,-113t113,-47q66,0 113,47t47,113q0,66 -47,113t-113,47ZM160,800v-112q0,-34 17.5,-62.5T224,582q62,-31 126,-46.5T480,520q66,0 130,15.5T736,582q29,15 46.5,43.5T800,688v112L160,800ZM240,720h480v-32q0,-11 -5.5,-20T700,654q-54,-27 -109,-40.5T480,600q-56,0 -111,13.5T260,654q-9,5 -14.5,14t-5.5,20v32ZM480,400q33,0 56.5,-23.5T560,320q0,-33 -23.5,-56.5T480,240q-33,0 -56.5,23.5T400,320q0,33 23.5,56.5T480,400ZM480,320ZM480,720Z"
android:fillColor="#fff"/> android:fillColor="#fff"/>

View File

@@ -3,7 +3,7 @@
android:height="24dp" android:height="24dp"
android:viewportWidth="960" android:viewportWidth="960"
android:viewportHeight="960" android:viewportHeight="960"
android:tint="?colorControlNormal"> android:tint="?iconTint">
<path <path
android:pathData="m798,638 l-62,-62q44,-41 69,-97t25,-119q0,-63 -25,-118t-69,-96l62,-64q56,53 89,125t33,153q0,81 -33,153t-89,125ZM670,510l-64,-64q18,-17 29,-38.5t11,-47.5q0,-26 -11,-47.5T606,274l64,-64q32,29 50,67.5t18,82.5q0,44 -18,82.5T670,510ZM360,520q-66,0 -113,-47t-47,-113q0,-66 47,-113t113,-47q66,0 113,47t47,113q0,66 -47,113t-113,47ZM40,840v-112q0,-33 17,-62t47,-44q51,-26 115,-44t141,-18q77,0 141,18t115,44q30,15 47,44t17,62v112L40,840ZM120,760h480v-32q0,-11 -5.5,-20T580,694q-36,-18 -92.5,-36T360,640q-71,0 -127.5,18T140,694q-9,5 -14.5,14t-5.5,20v32ZM360,440q33,0 56.5,-23.5T440,360q0,-33 -23.5,-56.5T360,280q-33,0 -56.5,23.5T280,360q0,33 23.5,56.5T360,440ZM360,360ZM360,760Z" android:pathData="m798,638 l-62,-62q44,-41 69,-97t25,-119q0,-63 -25,-118t-69,-96l62,-64q56,53 89,125t33,153q0,81 -33,153t-89,125ZM670,510l-64,-64q18,-17 29,-38.5t11,-47.5q0,-26 -11,-47.5T606,274l64,-64q32,29 50,67.5t18,82.5q0,44 -18,82.5T670,510ZM360,520q-66,0 -113,-47t-47,-113q0,-66 47,-113t113,-47q66,0 113,47t47,113q0,66 -47,113t-113,47ZM40,840v-112q0,-33 17,-62t47,-44q51,-26 115,-44t141,-18q77,0 141,18t115,44q30,15 47,44t17,62v112L40,840ZM120,760h480v-32q0,-11 -5.5,-20T580,694q-36,-18 -92.5,-36T360,640q-71,0 -127.5,18T140,694q-9,5 -14.5,14t-5.5,20v32ZM360,440q33,0 56.5,-23.5T440,360q0,-33 -23.5,-56.5T360,280q-33,0 -56.5,23.5T280,360q0,33 23.5,56.5T360,440ZM360,360ZM360,760Z"
android:fillColor="#fff"/> android:fillColor="#fff"/>

View File

@@ -3,7 +3,7 @@
android:height="24dp" android:height="24dp"
android:viewportWidth="960" android:viewportWidth="960"
android:viewportHeight="960" android:viewportHeight="960"
android:tint="?colorControlNormal"> android:tint="?iconTint">
<path <path
android:pathData="M360,440h80v-160h-80v160ZM480,440h80v-160h-80v160ZM600,440h80v-160h-80v160ZM240,880q-33,0 -56.5,-23.5T160,800v-480l240,-240h320q33,0 56.5,23.5T800,160v640q0,33 -23.5,56.5T720,880L240,880ZM240,800h480v-640L434,160L240,354v446ZM240,800h480,-480Z" android:pathData="M360,440h80v-160h-80v160ZM480,440h80v-160h-80v160ZM600,440h80v-160h-80v160ZM240,880q-33,0 -56.5,-23.5T160,800v-480l240,-240h320q33,0 56.5,23.5T800,160v640q0,33 -23.5,56.5T720,880L240,880ZM240,800h480v-640L434,160L240,354v446ZM240,800h480,-480Z"
android:fillColor="#fff"/> android:fillColor="#fff"/>

View File

@@ -3,7 +3,7 @@
android:height="24dp" android:height="24dp"
android:viewportWidth="24" android:viewportWidth="24"
android:viewportHeight="24" android:viewportHeight="24"
android:tint="?colorControlNormal"> android:tint="?iconTint">
<path <path
android:fillColor="@android:color/white" android:fillColor="@android:color/white"
android:pathData="M13.26,3C8.17,2.86 4,6.95 4,12L2.21,12c-0.45,0 -0.67,0.54 -0.35,0.85l2.79,2.8c0.2,0.2 0.51,0.2 0.71,0l2.79,-2.8c0.31,-0.31 0.09,-0.85 -0.36,-0.85L6,12c0,-3.9 3.18,-7.05 7.1,-7 3.72,0.05 6.85,3.18 6.9,6.9 0.05,3.91 -3.1,7.1 -7,7.1 -1.61,0 -3.1,-0.55 -4.28,-1.48 -0.4,-0.31 -0.96,-0.28 -1.32,0.08 -0.42,0.42 -0.39,1.13 0.08,1.49C9,20.29 10.91,21 13,21c5.05,0 9.14,-4.17 9,-9.26 -0.13,-4.69 -4.05,-8.61 -8.74,-8.74zM12.75,8c-0.41,0 -0.75,0.34 -0.75,0.75v3.68c0,0.35 0.19,0.68 0.49,0.86l3.12,1.85c0.36,0.21 0.82,0.09 1.03,-0.26 0.21,-0.36 0.09,-0.82 -0.26,-1.03l-2.88,-1.71v-3.4c0,-0.4 -0.34,-0.74 -0.75,-0.74z"/> android:pathData="M13.26,3C8.17,2.86 4,6.95 4,12L2.21,12c-0.45,0 -0.67,0.54 -0.35,0.85l2.79,2.8c0.2,0.2 0.51,0.2 0.71,0l2.79,-2.8c0.31,-0.31 0.09,-0.85 -0.36,-0.85L6,12c0,-3.9 3.18,-7.05 7.1,-7 3.72,0.05 6.85,3.18 6.9,6.9 0.05,3.91 -3.1,7.1 -7,7.1 -1.61,0 -3.1,-0.55 -4.28,-1.48 -0.4,-0.31 -0.96,-0.28 -1.32,0.08 -0.42,0.42 -0.39,1.13 0.08,1.49C9,20.29 10.91,21 13,21c5.05,0 9.14,-4.17 9,-9.26 -0.13,-4.69 -4.05,-8.61 -8.74,-8.74zM12.75,8c-0.41,0 -0.75,0.34 -0.75,0.75v3.68c0,0.35 0.19,0.68 0.49,0.86l3.12,1.85c0.36,0.21 0.82,0.09 1.03,-0.26 0.21,-0.36 0.09,-0.82 -0.26,-1.03l-2.88,-1.71v-3.4c0,-0.4 -0.34,-0.74 -0.75,-0.74z"/>

View File

@@ -3,7 +3,7 @@
android:height="24dp" android:height="24dp"
android:viewportWidth="960" android:viewportWidth="960"
android:viewportHeight="960" android:viewportHeight="960"
android:tint="?colorControlNormal"> android:tint="?iconTint">
<path <path
android:pathData="M480,560q-33,0 -56.5,-23.5T400,480q0,-33 23.5,-56.5T480,400q33,0 56.5,23.5T560,480q0,33 -23.5,56.5T480,560ZM480,840q-139,0 -241,-91.5T122,520h82q14,104 92.5,172T480,760q117,0 198.5,-81.5T760,480q0,-117 -81.5,-198.5T480,200q-69,0 -129,32t-101,88h110v80L120,400v-240h80v94q51,-64 124.5,-99T480,120q75,0 140.5,28.5t114,77q48.5,48.5 77,114T840,480q0,75 -28.5,140.5t-77,114q-48.5,48.5 -114,77T480,840Z" android:pathData="M480,560q-33,0 -56.5,-23.5T400,480q0,-33 23.5,-56.5T480,400q33,0 56.5,23.5T560,480q0,33 -23.5,56.5T480,560ZM480,840q-139,0 -241,-91.5T122,520h82q14,104 92.5,172T480,760q117,0 198.5,-81.5T760,480q0,-117 -81.5,-198.5T480,200q-69,0 -129,32t-101,88h110v80L120,400v-240h80v94q51,-64 124.5,-99T480,120q75,0 140.5,28.5t114,77q48.5,48.5 77,114T840,480q0,75 -28.5,140.5t-77,114q-48.5,48.5 -114,77T480,840Z"
android:fillColor="#fff"/> android:fillColor="#fff"/>

View File

@@ -3,7 +3,7 @@
android:height="24dp" android:height="24dp"
android:viewportWidth="960" android:viewportWidth="960"
android:viewportHeight="960" android:viewportHeight="960"
android:tint="?colorControlNormal"> android:tint="?iconTint">
<path <path
android:pathData="M160,720q-33,0 -56.5,-23.5T80,640v-320q0,-33 23.5,-56.5T160,240h640q33,0 56.5,23.5T880,320v320q0,33 -23.5,56.5T800,720L160,720ZM160,640h640v-320L680,320v160h-80v-160h-80v160h-80v-160h-80v160h-80v-160L160,320v320ZM280,480h80,-80ZM440,480h80,-80ZM600,480h80,-80ZM480,480Z" android:pathData="M160,720q-33,0 -56.5,-23.5T80,640v-320q0,-33 23.5,-56.5T160,240h640q33,0 56.5,23.5T880,320v320q0,33 -23.5,56.5T800,720L160,720ZM160,640h640v-320L680,320v160h-80v-160h-80v160h-80v-160h-80v160h-80v-160L160,320v320ZM280,480h80,-80ZM440,480h80,-80ZM600,480h80,-80ZM480,480Z"
android:fillColor="#fff"/> android:fillColor="#fff"/>

View File

@@ -3,7 +3,7 @@
android:height="24dp" android:height="24dp"
android:viewportWidth="960" android:viewportWidth="960"
android:viewportHeight="960" android:viewportHeight="960"
android:tint="?colorControlNormal"> android:tint="?iconTint">
<path <path
android:pathData="M280,800v-520L80,280v-120h520v120L400,280v520L280,800ZM640,800v-320L520,480v-120h360v120L760,480v320L640,800Z" android:pathData="M280,800v-520L80,280v-120h520v120L400,280v520L280,800ZM640,800v-320L520,480v-120h360v120L760,480v320L640,800Z"
android:fillColor="#fff"/> android:fillColor="#fff"/>

View File

@@ -3,7 +3,7 @@
android:height="24dp" android:height="24dp"
android:viewportWidth="960" android:viewportWidth="960"
android:viewportHeight="960" android:viewportHeight="960"
android:tint="?colorControlNormal"> android:tint="?iconTint">
<path <path
android:pathData="M480,880q-83,0 -156,-31.5T197,763q-54,-54 -85.5,-127T80,480h80q0,115 72.5,203T418,794l-58,-58 56,-56L598,862q-29,10 -58.5,14T480,880ZM500,600v-240h120q17,0 28.5,11.5T660,400v160q0,17 -11.5,28.5T620,600L500,600ZM300,600v-60h100v-40h-60v-40h60v-40L300,420v-60h120q17,0 28.5,11.5T460,400v160q0,17 -11.5,28.5T420,600L300,600ZM560,540h40v-120h-40v120ZM800,480q0,-115 -72.5,-203T542,166l58,58 -56,56 -182,-182q29,-10 58.5,-14t59.5,-4q83,0 156,31.5T763,197q54,54 85.5,127T880,480h-80Z" android:pathData="M480,880q-83,0 -156,-31.5T197,763q-54,-54 -85.5,-127T80,480h80q0,115 72.5,203T418,794l-58,-58 56,-56L598,862q-29,10 -58.5,14T480,880ZM500,600v-240h120q17,0 28.5,11.5T660,400v160q0,17 -11.5,28.5T620,600L500,600ZM300,600v-60h100v-40h-60v-40h60v-40L300,420v-60h120q17,0 28.5,11.5T460,400v160q0,17 -11.5,28.5T420,600L300,600ZM560,540h40v-120h-40v120ZM800,480q0,-115 -72.5,-203T542,166l58,58 -56,56 -182,-182q29,-10 58.5,-14t59.5,-4q83,0 156,31.5T763,197q54,54 85.5,127T880,480h-80Z"
android:fillColor="#fff"/> android:fillColor="#fff"/>

View File

@@ -3,7 +3,7 @@
android:height="24dp" android:height="24dp"
android:viewportWidth="960" android:viewportWidth="960"
android:viewportHeight="960" android:viewportHeight="960"
android:tint="?colorControlNormal"> android:tint="?iconTint">
<path <path
android:pathData="m476,880 l182,-480h84L924,880h-84l-43,-122L603,758L560,880h-84ZM160,760l-56,-56 202,-202q-35,-35 -63.5,-80T190,320h84q20,39 40,68t48,58q33,-33 68.5,-92.5T484,240L40,240v-80h280v-80h80v80h280v80L564,240q-21,72 -63,148t-83,116l96,98 -30,82 -122,-125 -202,201ZM628,688h144l-72,-204 -72,204Z" android:pathData="m476,880 l182,-480h84L924,880h-84l-43,-122L603,758L560,880h-84ZM160,760l-56,-56 202,-202q-35,-35 -63.5,-80T190,320h84q20,39 40,68t48,58q33,-33 68.5,-92.5T484,240L40,240v-80h280v-80h80v80h280v80L564,240q-21,72 -63,148t-83,116l96,98 -30,82 -122,-125 -202,201ZM628,688h144l-72,-204 -72,204Z"
android:fillColor="#fff"/> android:fillColor="#fff"/>

View File

@@ -3,7 +3,7 @@
android:height="24dp" android:height="24dp"
android:viewportWidth="960" android:viewportWidth="960"
android:viewportHeight="960" android:viewportHeight="960"
android:tint="?colorControlNormal"> android:tint="?iconTint">
<path <path
android:pathData="m476,880 l182,-480h84L924,880h-84l-43,-122L603,758L560,880h-84ZM628,688h144l-72,-204 -72,204ZM254,640q-66,0 -123.5,-38.5T44,498l72,-36q21,42 58,70t79,28q38,0 62.5,-23.5T340,480q0,-33 -23.5,-56.5T260,400h-60v-80h60q25,0 42.5,-17.5T320,260q0,-25 -17,-42.5T261,200q-23,0 -41,15t-32,33l-63,-49q26,-32 60,-55.5t77,-23.5q57,0 97.5,40.5T400,259q0,27 -10,52.5T361,357q10,10 18.5,20.5T396,400h124v-200h-80v-80h240v80h-80v116l-61,164L420,480v4q0,63 -46,109.5T254,640Z" android:pathData="m476,880 l182,-480h84L924,880h-84l-43,-122L603,758L560,880h-84ZM628,688h144l-72,-204 -72,204ZM254,640q-66,0 -123.5,-38.5T44,498l72,-36q21,42 58,70t79,28q38,0 62.5,-23.5T340,480q0,-33 -23.5,-56.5T260,400h-60v-80h60q25,0 42.5,-17.5T320,260q0,-25 -17,-42.5T261,200q-23,0 -41,15t-32,33l-63,-49q26,-32 60,-55.5t77,-23.5q57,0 97.5,40.5T400,259q0,27 -10,52.5T361,357q10,10 18.5,20.5T396,400h124v-200h-80v-80h240v80h-80v116l-61,164L420,480v4q0,63 -46,109.5T254,640Z"
android:fillColor="#fff"/> android:fillColor="#fff"/>

View File

@@ -3,7 +3,7 @@
android:height="24dp" android:height="24dp"
android:viewportWidth="960" android:viewportWidth="960"
android:viewportHeight="960" android:viewportHeight="960"
android:tint="?colorControlNormal"> android:tint="?iconTint">
<path <path
android:pathData="M480,840 L0,359q93,-93 215.5,-146T480,160q142,0 264.5,53T960,359l-56,57q-81,-81 -190,-128.5T480,240q-103,0 -195,32.5T117,363l419,420 -56,57ZM864,800L761,698q-18,11 -38,16.5t-43,5.5q-68,0 -114,-46t-46,-114q0,-68 46,-114t114,-46q68,0 114,46t46,114q0,23 -5.5,43T818,641l102,103 -56,56ZM680,640q34,0 57,-23t23,-57q0,-34 -23,-57t-57,-23q-34,0 -57,23t-23,57q0,34 23,57t57,23ZM480,783Z" android:pathData="M480,840 L0,359q93,-93 215.5,-146T480,160q142,0 264.5,53T960,359l-56,57q-81,-81 -190,-128.5T480,240q-103,0 -195,32.5T117,363l419,420 -56,57ZM864,800L761,698q-18,11 -38,16.5t-43,5.5q-68,0 -114,-46t-46,-114q0,-68 46,-114t114,-46q68,0 114,46t46,114q0,23 -5.5,43T818,641l102,103 -56,56ZM680,640q34,0 57,-23t23,-57q0,-34 -23,-57t-57,-23q-34,0 -57,23t-23,57q0,34 23,57t57,23ZM480,783Z"
android:fillColor="#fff"/> android:fillColor="#fff"/>

View File

@@ -5,7 +5,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?cardBackground" android:background="?appBackground"
android:clipToPadding="false" android:clipToPadding="false"
android:fadeScrollbars="false" android:fadeScrollbars="false"
android:fillViewport="true"> android:fillViewport="true">
@@ -47,7 +47,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/about_headline" android:text="@string/about_headline"
android:textAlignment="center" android:textAlignment="center"
android:textAppearance="@style/MwmTextAppearance.Headline" android:textAppearance="@style/MwmTextAppearance.Headline6"
android:textColor="?android:textColorPrimary" android:textColor="?android:textColorPrimary"
app:layout_constraintTop_toTopOf="@id/version" /> app:layout_constraintTop_toTopOf="@id/version" />
</LinearLayout> </LinearLayout>

View File

@@ -13,7 +13,7 @@
android:id="@+id/scrollView" android:id="@+id/scrollView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?cardBackground" android:background="?appBackground"
android:fadeScrollbars="false" android:fadeScrollbars="false"
android:fillViewport="true" android:fillViewport="true"
android:clipToPadding="false"> android:clipToPadding="false">

View File

@@ -11,13 +11,12 @@
<FrameLayout <FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:id="@+id/statutbar" android:id="@+id/statutbar"
android:layout_height="15dp" android:layout_height="1dp"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView
android:id="@+id/street_frame" android:id="@+id/street_frame"
android:layout_width="500dp" android:layout_width="500dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_half_plus_eight"
android:layout_marginEnd="@dimen/margin_quarter" android:layout_marginEnd="@dimen/margin_quarter"
app:cardCornerRadius="@dimen/margin_half" app:cardCornerRadius="@dimen/margin_half"
android:elevation="@dimen/nav_elevation" android:elevation="@dimen/nav_elevation"
@@ -52,7 +51,6 @@
app:layout_constraintEnd_toStartOf="@+id/street_frame" app:layout_constraintEnd_toStartOf="@+id/street_frame"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/statutbar" app:layout_constraintTop_toBottomOf="@+id/statutbar"
android:layout_marginTop="@dimen/margin_half_plus_eight"
android:layout_marginStart="@dimen/margin_quarter" android:layout_marginStart="@dimen/margin_quarter"
android:clickable="true" android:clickable="true"
android:elevation="@dimen/nav_elevation"> android:elevation="@dimen/nav_elevation">

Some files were not shown because too many files have changed in this diff Show More