Compare commits

..

159 Commits

Author SHA1 Message Date
Harry Bond
674f681197 [android] Re-enable UI (disable fullscreen mode) when tapping a POI
Signed-off-by: Harry Bond <me@hbond.xyz>
2025-08-27 13:47:27 +01:00
Codeberg Translate
7be3164db7 [strings] Update from Codeberg Translate
Co-authored-by: B o d o <timtrek@noreply.codeberg.org>
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: Frz <frz@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: Priit Jõerüüt <jrtcdbrg@noreply.codeberg.org>
Co-authored-by: Stephan-P <stephan-p@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: and4po <and4po@noreply.codeberg.org>
Co-authored-by: ghose <ghose@noreply.codeberg.org>
Co-authored-by: hectodium <hectodium@noreply.codeberg.org>
Co-authored-by: ikanakova <ikanakova@noreply.codeberg.org>
Co-authored-by: ldmpub <ldmpub@noreply.codeberg.org>
Co-authored-by: matheusgomesms <matheusgomesms@noreply.codeberg.org>
Co-authored-by: patepelo <patepelo@noreply.codeberg.org>
Co-authored-by: stefanlinden <stefanlinden@noreply.codeberg.org>
Co-authored-by: sziatomi <sziatomi@noreply.codeberg.org>
Co-authored-by: xerini <xerini@noreply.codeberg.org>
Translate-URL: https://translate.codeberg.org/projects/comaps/android/
Translate-URL: https://translate.codeberg.org/projects/comaps/appstore-description/
Translate-URL: https://translate.codeberg.org/projects/comaps/tts/
Translation: CoMaps/Android - Map Feature Types
Translation: CoMaps/Android UI Strings
Translation: CoMaps/Android UI Strings (SDK)
Translation: CoMaps/Apple AppStore description
Translation: CoMaps/Countries and regions names
Translation: CoMaps/F-Droid app description
Translation: CoMaps/Voice announcements for navigation (TTS)
Translation: CoMaps/iOS - Map Feature Types
Translation: CoMaps/iOS Plist
Translation: CoMaps/iOS UI Strings
2025-08-27 08:12:02 +00:00
eisa01
20208cf892 [generator] Add branch key to map generator
Signed-off-by: eisa01 <eisa01@gmail.com>
2025-08-27 10:11:29 +02:00
Andrei Shkrob
9fd80ecf88 [android-auto] Fix theme issues
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-27 00:16:13 +07:00
Alexander Borsuk
bd97cb4ceb Do not autozoom to show the full route when adding stops
This should simplify route planning and avoid unnecessary zoom in back and back again

Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-08-27 00:13:26 +07:00
Konstantin Pastbin
dd2458d1b1 [styles][outdoor] Make waterways bolder
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-26 19:00:21 +02:00
Konstantin Pastbin
405025879e [styles] Display labels earlier for most amenities which were z19-
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-26 18:55:04 +02:00
Konstantin Pastbin
83d483eabb [styles] Make power substations icons visible earlier
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-26 18:55:04 +02:00
Konstantin Pastbin
31219ded29 Revert "[android] Display overlay layer state with icon"
This reverts commit d44f0ae7da.
2025-08-26 20:15:35 +07:00
Harry Bond
47936df79c [android] Rebase fixes for Add support for check_date & check_date:opening_hours
Following from https://codeberg.org/comaps/comaps/pulls/1572
Also add script for easy transfer of strings across modules

Signed-off-by: Harry Bond <me@hbond.xyz>
2025-08-26 09:42:08 +02:00
Harry Bond
73238a6e3c [android] increase location update freq from 1s to 0.5s, don't take 3s to update when not following position
supersedes #1022
I don't think there's much point in mode-dependent update frequencies, AFAIK it's from earlier maps.me days when phones were weaker.

Signed-off-by: Harry Bond <me@hbond.xyz>
2025-08-26 09:34:31 +02:00
Harry Bond
74a36bc49a [android] Fix navigation notification style
Signed-off-by: Harry Bond <me@hbond.xyz>
2025-08-25 21:00:17 +01:00
eisa01
7088489814 [core] Better check whether showing brand is redundant in subtitle
Previous implementation checked if brand was equal to name, better to check if it's located in name

Signed-off-by: eisa01 <eisa01@gmail.com>
2025-08-25 18:08:16 +02:00
Bastian Greshake Tzovaras
fbc844b19e add suggestions from harry
Signed-off-by: Bastian Greshake Tzovaras <bgreshake@googlemail.com>
2025-08-25 17:27:40 +02:00
Bastian Greshake Tzovaras
5a4f10a584 [docs] clarify politeness
Signed-off-by: Bastian Greshake Tzovaras <bgreshake@googlemail.com>
2025-08-25 17:27:40 +02:00
Bastian Greshake Tzovaras
0fa12070e0 [docs] add sentence on adding to CONTRIB file
Signed-off-by: Bastian Greshake Tzovaras <bgreshake@googlemail.com>
2025-08-25 17:27:40 +02:00
Bastian Greshake Tzovaras
dae2ce0caf [docs] add guidance for first-timeer review & template
Signed-off-by: Bastian Greshake Tzovaras <bgreshake@googlemail.com>
2025-08-25 17:27:40 +02:00
x7z4w
5a603ebfae [styles] Night mode bookmarks
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-08-25 12:17:35 +02:00
Jean-Baptiste
4861ae7e67 [android] Add new custom switch for preference
Signed-off-by: jeanbaptisteC <jeanbaptiste.charron@outlook.fr>
2025-08-25 10:32:10 +02:00
Jean-Baptiste
9425138782 [android] Migrate Manage route and save buttons to Material Components
Signed-off-by: jeanbaptisteC <jeanbaptiste.charron@outlook.fr>
2025-08-25 10:21:52 +02:00
Jean-Baptiste
beac6aa7bc [android] Revert changes about night themes
Signed-off-by: jeanbaptisteC <jeanbaptiste.charron@outlook.fr>
2025-08-25 06:51:52 +02:00
eisa01
33ad35206f [drape] Enable shift+swipe to zoom on macOS Catalyst app\
\
Matches functionality in Apple Maps. Discovered while discussing issue #1509\
\
Tested that pinch to zoom still work in iPad Simulator

Signed-off-by: eisa01 <eisa01@gmail.com>
2025-08-24 20:37:12 +02:00
Codeberg Translate
234f13abcc [strings] Update from Codeberg Translate
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: sziatomi <sziatomi@noreply.codeberg.org>
Translate-URL: https://translate.codeberg.org/projects/comaps/appstore-description/
Translation: CoMaps/Android - Map Feature Types
Translation: CoMaps/Android UI Strings
Translation: CoMaps/Apple AppStore description
Translation: CoMaps/F-Droid app description
Translation: CoMaps/iOS - Map Feature Types
Translation: CoMaps/iOS UI Strings
2025-08-24 17:16:58 +00:00
x7z4w
5e7bc37fb5 Fix crash
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-08-24 19:12:32 +02:00
Harry Bond
08abddc7fc [android] Add support for check_date & check_date:opening_hours
Signed-off-by: Harry Bond <me@hbond.xyz>
2025-08-24 16:58:56 +00:00
Harry Bond
ef9f4ceb1e [android] fix preview in android studio for opening_hours fragment
Signed-off-by: Harry Bond <me@hbond.xyz>
2025-08-24 16:58:11 +00:00
map-per
6c75604c38 Remove bookmark category from subtitle
Signed-off-by: map-per <map-per@gmx.de>
2025-08-24 18:18:04 +02:00
map-per
5edaa05129 Keep category list and direction arrow on bookmark place page
Signed-off-by: map-per <map-per@gmx.de>
2025-08-24 18:00:24 +02:00
map-per
c4491563b7 fix padding in place page
Signed-off-by: map-per <map-per@gmx.de>
2025-08-24 17:03:36 +02:00
Jean-Baptiste
c3d8f948ce [android] Migrate NavMenu to Material components
Signed-off-by: jeanbaptisteC <jeanbaptiste.charron@outlook.fr>
2025-08-24 17:02:18 +02:00
Konstantin Pastbin
008387b0cf [android] Reformat code with clang-format
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-24 21:58:44 +07:00
Konstantin Pastbin
3d450433e7 [android][sdk] Move rest of types_strings.xml
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-24 21:58:44 +07:00
Konstantin Pastbin
58cb8ecd9d [android] Fix BackupUtils deps
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-24 21:58:44 +07:00
Konstantin Pastbin
3e9b507acd [android][sdk] Move transport type drawables to SDK
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-24 21:58:44 +07:00
Konstantin Pastbin
c9a261dee5 [android][sdk] Move OhState to SDK
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-24 21:58:44 +07:00
Konstantin Pastbin
d609876c2d [android][sdk] Move strings to sdk follow-up
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-24 21:58:42 +07:00
Andrei Shkrob
80b616daf2 [android][sdk] Move required strings to sdk
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-24 21:56:52 +07:00
Andrei Shkrob
4dca45f74a [android][sdk] Disable proguard
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-24 21:56:52 +07:00
Andrei Shkrob
f5037a5ee2 [android][sdk] Fix lint
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-24 21:56:52 +07:00
Andrei Shkrob
802f54494a [android][sdk] Fix location provider
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-24 21:56:52 +07:00
Andrei Shkrob
d4863643f7 [android][sdk] Fix MapManager
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-24 21:56:52 +07:00
Andrei Shkrob
431e305a48 [android][sdk] Move getDonateUrl outside sdk
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-24 21:56:52 +07:00
Andrei Shkrob
d3c64a262b [android][sdk] Move PrefsManager call outside sdk
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-24 21:56:52 +07:00
Andrei Shkrob
06c35e729f [android][sdk] Move types strings
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-24 21:56:52 +07:00
Andrei Shkrob
b2743ab2ad [android][sdk] Add prefs strings
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-24 21:56:52 +07:00
Andrei Shkrob
c004f2ed7e [android][sdk] Add missing dimens
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-24 21:56:52 +07:00
Andrei Shkrob
abcc95710d [android][sdk] Replace app.organicmaps.R with app.organicmaps.sdk.R
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-24 21:56:52 +07:00
Andrei Shkrob
3a90f9783d [android][sdk] Add build config to sdk module
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-24 21:56:52 +07:00
Konstantin Pastbin
a8353a6a80 [android] Replace direct SDK deps with libs refs
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-24 21:56:52 +07:00
Andrei Shkrob
dc8d4e7da9 [android][sdk] add missing dependencies
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-24 21:56:52 +07:00
Andrei Shkrob
6a85526ac9 [android][sdk] Move java files into sdk module
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-24 21:56:51 +07:00
Andrei Shkrob
447266c328 [android][sdk] Fix ThemeUtils usage in sdk
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-24 21:56:51 +07:00
Andrei Shkrob
886d569895 [android][sdk] Fix StackedButtonDialogFragment usage in sdk
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-24 21:56:51 +07:00
Viktor Govako
c6cd23fb24 [android] openUri, failMessage may be null.
pastk: includes changes from OM 33c4e22246 and 10be769f62

Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-24 21:56:51 +07:00
Viktor Govako
c6040d8ce6 [android] setSound(null, null) for the Downloader notification channel.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-24 21:56:51 +07:00
Andrei Shkrob
0f5125c61c [android][sdk] Move UiUtils outside sdk package
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-24 21:56:51 +07:00
Jean-Baptiste
512475ec5c [android] Switch add phone button to FAB
Signed-off-by: jeanbaptisteC <jeanbaptiste.charron@outlook.fr>
2025-08-24 16:12:32 +02:00
map-per
66d5306717 Move bookmark description text view to bookmark section
Signed-off-by: map-per <map-per@gmx.de>
2025-08-24 15:53:25 +02:00
gekeleda
265e94edc3 [core] Fix remove passed points
Signed-off-by: gekeleda <git@davidgekeler.eu>
2025-08-24 14:48:19 +02:00
Codeberg Translate
4d6cecd9ba [strings] Update from Codeberg Translate
Co-authored-by: Codeberg Translate <translate@codeberg.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 <noreply-mt-weblate@weblate.org>
Co-authored-by: phama <phama@noreply.codeberg.org>
Co-authored-by: sziatomi <sziatomi@noreply.codeberg.org>
Translation: CoMaps/Android - Map Feature Types
Translation: CoMaps/Android UI Strings
Translation: CoMaps/Apple AppStore description
Translation: CoMaps/iOS - Map Feature Types
Translation: CoMaps/iOS Plist
Translation: CoMaps/iOS Plurals
Translation: CoMaps/iOS UI Strings
2025-08-24 15:35:17 +07:00
Codeberg Translate
46c9a015e5 [strings] Update from Codeberg Translate
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: Priit Jõerüüt <jrtcdbrg@noreply.codeberg.org>
Co-authored-by: phama <phama@noreply.codeberg.org>
Co-authored-by: sziatomi <sziatomi@noreply.codeberg.org>
Translation: CoMaps/Android - Map Feature Types
Translation: CoMaps/Android UI Strings
Translation: CoMaps/Apple AppStore description
Translation: CoMaps/iOS - Map Feature Types
Translation: CoMaps/iOS Plurals
Translation: CoMaps/iOS UI Strings
2025-08-24 10:29:18 +02:00
x7z4w
2e3efc0597 [generator] Add toll booth penalty
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-08-24 09:24:50 +02:00
Yannik Bloscheck
0b65c2ebff [ios] Fixed CarPlay panning not working
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-08-23 21:42:07 +02:00
Yannik Bloscheck
96a7b31f4b [ios] Replaced some CarPlay images with system versions
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-08-23 21:42:07 +02:00
Yannik Bloscheck
c11f007012 [ios] Fix issue with opening urls
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-08-23 21:41:05 +02:00
Jean-Baptiste
977a3b6734 [android] Remove useless fontFamily property
Signed-off-by: jeanbaptisteC <jeanbaptiste.charron@outlook.fr>
2025-08-23 20:34:13 +02:00
Codeberg Translate
c27b0dc6fb [strings] Update from Codeberg Translate
Co-authored-by: B o d o <timtrek@noreply.codeberg.org>
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: Fjuro <fjuro@alius.cz>
Co-authored-by: Prefill add-on <noreply-addon-prefill@weblate.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: matheusgomesms <matheusgomesms@noreply.codeberg.org>
Co-authored-by: yannikbloscheck <yannikbloscheck@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-08-23 17:02:59 +00:00
Harry Bond
e367fa6792 [android] Start LinearProgressBars at 1% to show initial dot
see https://m3.material.io/components/progress-indicators/guidelines#817a3dbd-9dd5-471f-a7d0-50eae6270ee0

Signed-off-by: Harry Bond <me@hbond.xyz>
2025-08-23 19:02:54 +02:00
mvglasow
06b6c3f794 [drape] Replace newline with space in StraightTextLayout and PathTextLayout
Signed-off-by: mvglasow <michael -at- vonglasow.com>
2025-08-23 18:39:24 +02:00
Jean-Baptiste
ca720d7712 [android] Move hint property to TextInputLayout
Signed-off-by: jeanbaptisteC <jeanbaptiste.charron@outlook.fr>
2025-08-23 17:37:37 +02:00
eisa01
661445a053 [ios] Fix shift+scroll wheel zooming out
When you press shift on macOS, the normal scroll wheel action on a mouse is changed to horizontal scroll instead of vertical

That meant this check never entered, and since translation.y = 0 you always zoom out

Signed-off-by: eisa01 <eisa01@gmail.com>
2025-08-23 12:14:07 +02:00
Yannik Bloscheck
c616e235a1 [ios] Update design of existence and opening hour confirmation for place page
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-08-23 10:37:18 +02:00
Eivind Samseth
d1f9806901 [iOS] Add Existence and Opening Hour confirmation to Place Page
Signed-off-by: eisa01 <your.email@example.com>
2025-08-23 10:37:18 +02:00
Codeberg Translate
795fe0ee09 [strings] Update from Codeberg Translate
Co-authored-by: Anonymous <anonymous@noreply.codeberg.org>
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: N4ta <codeberg@n4ta.anonaddy.me>
Co-authored-by: Prefill add-on <noreply-addon-prefill@weblate.org>
Co-authored-by: lihaisapossu <lihaisapossu@noreply.codeberg.org>
Translate-URL: https://translate.codeberg.org/projects/comaps/ios/
Translation: CoMaps/Android - Map Feature Types
Translation: CoMaps/Android UI Strings
Translation: CoMaps/iOS - Map Feature Types
Translation: CoMaps/iOS UI Strings
2025-08-23 08:24:09 +00:00
Konstantin Pastbin
ea588e7ece [strings] Fix Wicket gate to upper case
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-23 14:22:57 +07:00
aoxa
053855bd97 Translated using Weblate (Persian)
Currently translated at 100.0% (106 of 106 strings)

Translation: CoMaps/Voice announcements for navigation (TTS)
2025-08-23 09:00:02 +02:00
Codeberg Translate
f485830c51 [strings] Update from Codeberg Translate
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: Weblate <noreply-mt-weblate@weblate.org>
Co-authored-by: alexgabi <alexgabi@noreply.codeberg.org>
Co-authored-by: aoxa <aoxa@noreply.codeberg.org>
Co-authored-by: giopera <giopera@noreply.codeberg.org>
Co-authored-by: loscati <loscati@noreply.codeberg.org>
Translation: CoMaps/Android - Map Feature Types
Translation: CoMaps/Android UI Strings
Translation: CoMaps/Apple AppStore description
Translation: CoMaps/Countries and regions names
Translation: CoMaps/F-Droid app description
Translation: CoMaps/Voice announcements for navigation (TTS)
Translation: CoMaps/iOS - Map Feature Types
Translation: CoMaps/iOS Plist
Translation: CoMaps/iOS Plurals
Translation: CoMaps/iOS UI Strings
2025-08-23 09:00:02 +02:00
Jean-Baptiste
debea83908 [android] Keep AppCompat theme for radio button
Signed-off-by: jeanbaptisteC <jeanbaptiste.charron@outlook.fr>
2025-08-23 08:50:03 +02:00
Konstantin Pastbin
729808fd14 [core] Re-add MwmValue::GetRegionData()
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-23 08:32:06 +02:00
Viktor Govako
b85c11ea5a [feature] Added RouteRelation and linked it with FeatureType.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-23 08:32:06 +02:00
Viktor Govako
315bba2a22 Include fix.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-23 08:32:06 +02:00
Viktor Govako
550455a14a [feature] Added Feature V1 version with free Header2 bits.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-23 08:32:06 +02:00
Viktor Govako
588028c9eb [feature] Put m_metaDeserializer into SharedLoadInfo.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-23 08:32:06 +02:00
Viktor Govako
6beabb2fe1 [feature] Removed IndexFactory class.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>

^ Conflicts:
^	libs/indexer/data_source.cpp
^	libs/indexer/feature.cpp
^	libs/indexer/features_vector.cpp
^	libs/indexer/mwm_set.hpp
2025-08-23 08:32:06 +02:00
Viktor Govako
25a4a3b76f [coding] Added varint short arrays ser/des.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>

# Conflicts:
#	libs/coding/coding_tests/varint_test.cpp
2025-08-23 08:32:06 +02:00
Codeberg Translate
111e913478 [strings] Update from Codeberg Translate
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: giopera <giopera@noreply.codeberg.org>
Translation: CoMaps/Android - Map Feature Types
Translation: CoMaps/Android UI Strings
Translation: CoMaps/Countries and regions names
Translation: CoMaps/Voice announcements for navigation (TTS)
Translation: CoMaps/iOS - Map Feature Types
Translation: CoMaps/iOS Plist
Translation: CoMaps/iOS Plurals
Translation: CoMaps/iOS UI Strings
2025-08-23 08:31:18 +02:00
map-per
632d9c0d1d New icon and text for 'Volunteer and improve CoMaps'
Signed-off-by: map-per <map-per@gmx.de>
2025-08-23 08:18:03 +02:00
Jean-Baptiste
1e729e980d [android] Add default value for progress bar
Signed-off-by: jeanbaptisteC <jeanbaptiste.charron@outlook.fr>
2025-08-23 07:49:57 +02:00
Jean-Baptiste
339eca0bca [android] Simplify logic to change items color on the about screen
Signed-off-by: jeanbaptisteC <jeanbaptiste.charron@outlook.fr>
2025-08-23 07:48:04 +02:00
Andrei Shkrob
ac453e36ac [android] Fix predefined colors again
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-23 07:44:46 +02:00
kavikhalique
4052f0481e Hide PP category for other map objects other than track and bookmark
Signed-off-by: kavikhalique <kavikhalique3@gmail.com>
2025-08-23 07:44:46 +02:00
Andrei Shkrob
89d82be2b9 [android] Fix bookmark icon in place plage
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-23 07:44:46 +02:00
Konstantin Pastbin
e98ecce375 [android] Fix PlacePageView components OM mismatches
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-23 07:44:46 +02:00
Konstantin Pastbin
0eee3c4bf4 [android] Fix unity jni build issue
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-23 07:44:46 +02:00
kavikhalique
2684e2b278 Removed animated slow rendering and Nit picks
Signed-off-by: kavikhalique <kavikhalique3@gmail.com>
2025-08-23 07:44:46 +02:00
Konstantin Pastbin
bb88861256 [android] Add ppFloatingMarkerIconColor to material themes
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-23 07:44:46 +02:00
kavikhalique
f1628c70bc Implement Track Selection and elevation info display on PP
Signed-off-by: kavikhalique <kavikhalique3@gmail.com>
2025-08-23 07:44:46 +02:00
Jean-Baptiste
ebb7c45d1a [android] Improve button to add new phone number
Signed-off-by: jeanbaptisteC <jeanbaptiste.charron@outlook.fr>
2025-08-22 20:42:40 +02:00
Jean-Baptiste
ef77314d7a [android] Move styles for button search frame components
Signed-off-by: jeanbaptisteC <jeanbaptiste.charron@outlook.fr>
2025-08-22 20:35:08 +02:00
hb0nd
72520310e8 [ci] Use latest version of DCO validator
Signed-off-by: Harry Bond <me@hbond.xyz>
2025-08-22 20:30:19 +02:00
Jean-Baptiste
8e1c723b41 [android] Migrate about screen to Material Components
Signed-off-by: Jean-Baptiste Charron <jeanbaptiste.charron@outlook.fr>
2025-08-22 18:11:18 +02:00
x7z4w
b26deb3bb2 [ci] Use self-hosted runner for DCO
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-08-22 15:58:45 +02:00
Viktor Govako
e8e94744f0 [map] Fixed invalid route saving.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-22 19:24:41 +07:00
Viktor Govako
98689fbbf8 [android] Hack to suppress most frequent crash on startup.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-22 19:23:45 +07:00
Kiryl Kaveryn
6cccd32166 [ios] Fix place page memory leaks
Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
2025-08-22 19:22:06 +07:00
David Martinez
1b04524d68 [routing] Log all turn notifications TTS
Signed-off-by: David Martinez <47610359+dvdmrtnz@users.noreply.github.com>
2025-08-22 19:19:00 +07:00
Viktor Govako
1a6bbd756a [routing] Simplify notifications on roundabout.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-22 19:18:39 +07:00
Alexander Borsuk
836c39ff64 math::iround
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-08-22 19:03:38 +07:00
Alexander Borsuk
7781528263 Fixed C++20 deprecation warning for std::rel_ops::operator<=
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-08-22 19:03:16 +07:00
Alexander Borsuk
2aaf37e9ee C++ warning fixes
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-08-22 19:03:04 +07:00
Alexander Borsuk
a28d5d15ce [drape] Fixed signed/unsigned comparison warning by changing Resize interface to uint32_t
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-08-22 19:01:09 +07:00
Alexander Borsuk
55dc1e17e6 Correct is_space fix for Windows compatibility
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-08-22 18:59:37 +07:00
Andrei Shkrob
826b56cabc [drape] Fix gui text alignment
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-22 18:56:26 +07:00
Osyotr
9aa86fc703 Remove android include from public interface of VulkanContextFactory
Signed-off-by: Osyotr <Osyotr@users.noreply.github.com>
2025-08-22 18:44:08 +07:00
Yannik Bloscheck
4fe21ec6eb [styles] Move light animal shelter icon to the correct location
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-08-22 12:36:42 +02:00
David Martinez
cb2181a80e [styles] Convert remaining PNG icons to SVG
Signed-off-by: David Martinez <47610359+dvdmrtnz@users.noreply.github.com>
2025-08-22 12:22:44 +02:00
David Martinez
eeb53eb0c4 [styles] Convert PNG US road shield icons to SVG
Signed-off-by: David Martinez <47610359+dvdmrtnz@users.noreply.github.com>
2025-08-22 12:22:44 +02:00
David Martinez
887bc2c755 [styles] Convert PNG road warning icons to SVG
Signed-off-by: David Martinez <47610359+dvdmrtnz@users.noreply.github.com>
2025-08-22 12:22:44 +02:00
Alexander Borsuk
29d60c9af0 [ios] Fix opening websites with percent encoding characters
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-08-22 11:58:01 +02:00
Kiryl Kaveryn
e0c579634b [ios] Fix track recording points updates subscribe/unsubscribe
Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
2025-08-22 11:58:01 +02:00
Kiryl Kaveryn
266d62831f [ios] Skip elevation info current point updates when the data is nil
Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
2025-08-22 11:58:01 +02:00
Kiryl Kaveryn
d94351a8f1 [ios] Skip excessive elevation point updates
When the user drags the elevation chart it runs chart's `selected point` update mechanism by calling the `onSelectedPointChanged` inside the `ChartView`'s ` func chartPreviewView(_ view: ChartPreviewView, didChangeMinX minX: Int, maxX: Int)`. This updates may be quite often (tens/hundreds per sec) and may cause the `on point update` callback **recursion** and overloads the `layoutSubviews` method on the _short track_ because the ChartView doesnt have mechanism to skip excessive updates when the parameters the same.
This situation produces fail with internal error `(null) in -[NSISEngine _flushPendingRemovals] ().`

The fix include:
1. skip updates when the current point isn't changed
2. remove layoutSubviews overloading (this method should recalc the layout immediately and should not be called too frequent, the `setNeedsLayout` allows to batch the layout updates and redraw the view on the next runtime cycle)

Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
2025-08-22 11:58:01 +02:00
Kiryl Kaveryn
31970c87c4 [ios] Remove all activities on track recording start and stop
Closes https://github.com/organicmaps/organicmaps/issues/11045
1. Remove all activities on track recording start and stop
2. Store the latest activity id in the UD to retrieve on launch after the app termination
Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
2025-08-22 11:58:01 +02:00
Alexander Borsuk
8e9dbe0248 [ios] Removed unused variables
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-08-22 11:58:01 +02:00
Alexander Borsuk
3b1551be52 [ios] Fixed wrong ObjC function name that caused warnings
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-08-22 11:58:01 +02:00
Alexander Borsuk
9d8e84ae5a [mac][ios] Was: Silenced annoying deprecation warnings
pastk: removed silencing, left only minor style etc changes

Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-08-22 11:58:01 +02:00
Kiryl Kaveryn
c4d5109d5b [ios] Log the error when the exclude from icloud fails
Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
2025-08-22 11:58:01 +02:00
Kiryl Kaveryn
59499333ff [ios] Disable chartView user interaction for TR and when the chartData is nil
Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
2025-08-22 11:58:01 +02:00
Kiryl Kaveryn
b5e0d10cb1 [ios] Set track recrording elevation chart min points to draw to 2
Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
2025-08-22 11:58:01 +02:00
Kiryl Kaveryn
55b85183d5 [map] Limit the track recording length to 2 points min
Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
2025-08-22 11:58:01 +02:00
Kiryl Kaveryn
38406b149a [ios] Skip zoom/pinch gesture when the lower/upper is out of bounds
The previous check `if upper - lower < chartData.labels.count / 10 return` produces invalid state for drawing and fails when the upper == lower.

Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
2025-08-22 11:58:01 +02:00
Kiryl Kaveryn
ef2dea20fe [ios] Log error during the track editing instead of failing
The bug is quite rare and happens when the user taps on the edit (pencil) button on the PlacePage. It seems like the tap happens during the PP data object reloading the and the object type has changed. It is better to avoid failing in such cases because we cannot prevent user interaction during the pp reloading.

Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
2025-08-22 11:58:01 +02:00
Kiryl Kaveryn
aac80606f2 [ios] Disable user interaction on PP vc close
Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
2025-08-22 11:58:01 +02:00
Kiryl Kaveryn
7765d97cda [ios] Fix track recording indicator image
Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
2025-08-22 11:58:01 +02:00
Alexander Borsuk
3aa74bc427 [ios] Fixed ATM translation in the PlacePage
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-08-22 11:58:01 +02:00
Konstantin Pastbin
902e7f6453 Revert "[ios] Fixing ATM translation on place page"
This reverts commit 211e3fb4f0.
2025-08-22 11:58:01 +02:00
Kiryl Kaveryn
cecca729db [ios] Check that pp data exists before update the TR PP screen
Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
2025-08-22 11:58:01 +02:00
Kiryl Kaveryn
2b2518b0b4 [ios] Disable track recording live activity widget for apps running on macos
Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
2025-08-22 11:58:01 +02:00
x7z4w
3c34765595 [core] nits
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-08-22 11:02:44 +02:00
hb0nd
3f7815017e [docs] Use full url for license
it worked at the end of the file, but i guess it doesn't work in a href for some reason...

Signed-off-by: hb0nd <me@hbond.xyz>
2025-08-21 16:48:59 +02:00
Jean-Baptiste
0d4809c18e [doc] Update badge link to the license
Signed-off-by: jeanbaptisteC <jeanbaptiste.charron@outlook.fr>
2025-08-21 16:35:32 +02:00
Yannik Bloscheck
052a3123aa [styles] Adding animal shelter icon
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-08-21 15:57:15 +02:00
Konstantin Pastbin
f81bff512a [styles] Add amenity=animal_shelter
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-21 15:57:15 +02:00
Yannik Bloscheck
2587db91be [styles] Changed symbol for early entries to square
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-08-21 15:55:11 +02:00
Konstantin Pastbin
3b5d5e882b [styles] Make entrances visible earlier
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-21 15:55:11 +02:00
Konstantin Pastbin
3c4e0d05c5 [routing][tests] Comment changes on old maps after adding penalties code
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-21 17:26:46 +07:00
x7z4w
4be5b5dc45 [build] Add configure.sh
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-08-21 10:41:52 +02:00
x7z4w
9ff72366d5 [build] Check for generated files
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-08-21 10:41:52 +02:00
Yannik Bloscheck
7c354645b9 [xcode] Trying to force Xcode to add changed files
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-08-21 10:41:52 +02:00
map-per
00d3f9a370 Make address addable in the editor
Signed-off-by: map-per <map-per@gmx.de>
2025-08-20 14:02:12 +02:00
x7z4w
cd29eda949 [docs] nit
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-08-20 13:51:51 +02:00
gekeleda
1ed27f4052 Remove intermediate stops regardless of deactivateFollowing
Signed-off-by: gekeleda <git@davidgekeler.eu>
2025-08-20 13:07:20 +02:00
Michał Brzozowski
57ecf3848b [routing] Remove passed intermediate points when assembling a modified route mid-navigation
Fixes OM #9592

Signed-off-by: Michał Brzozowski <www.haxor@gmail.com>

# Conflicts:
#	libs/map/routing_manager.cpp
2025-08-20 13:07:20 +02:00
Konstantin Pastbin
697e871c1b [strings] Add barriers translations
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-20 12:39:48 +02:00
Konstantin Pastbin
d5966ff198 [tests] Add smoke tests for more barriers
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-20 12:39:48 +02:00
Konstantin Pastbin
3abd04426c [routing] Block cars going through barrier=yes
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-20 12:39:48 +02:00
Konstantin Pastbin
8237a7e417 [styles] Add barrier=wicket_gate
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-20 12:39:48 +02:00
Konstantin Pastbin
1607769551 [styles] Add generic barrier=yes points and lines
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-20 12:39:48 +02:00
Konstantin Pastbin
a189516736 [tools][styles] Output diffs in generate_drules.sh
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-20 10:40:40 +02:00
1242 changed files with 7871 additions and 4884 deletions

View File

@@ -21,12 +21,11 @@ jobs:
- name: Install appstream validator and flatpak Builder
shell: bash
run: |
apt-get update
apt-get install -y flatpak dbus --no-install-recommends
mkdir /run/dbus
dbus-daemon --system
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak install -y org.flatpak.Builder
sudo apt update -y
sudo apt install -y \
flatpak
sudo flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
sudo flatpak install -y org.flatpak.Builder
- name: Lint appstream data with flatpak Builder
shell: bash

View File

@@ -1,8 +1,9 @@
name: dco
name: DCO
on: [pull_request]
jobs:
check:
runs-on: codeberg-tiny
runs-on: ubuntu-latest
steps:
- uses: https://github.com/KineticCafe/actions-dco@v1
- name: Check for Developer Certificate of Origin (DCO) compliance
uses: https://github.com/KineticCafe/actions-dco@fb284c903a7673a3d4b0bdd104479a6f0d46dae7 # v1.3.6

View File

@@ -133,6 +133,14 @@ jobs:
with:
key: ${{ github.workflow }}-unity-${{ matrix.compiler.CC }}-${{ matrix.CMAKE_BUILD_TYPE }}
- name: Configure repository
shell: bash
env:
SKIP_MAP_DOWNLOAD: 1
SKIP_GENERATE_SYMBOLS: 1
SKIP_GENERATE_DRULES: 1
run: ./configure.sh
- name: CMake
shell: bash
env:

18
.gitignore vendored
View File

@@ -14,12 +14,10 @@ stxxl.errlog
stxxl.log
screenlog.0
data/symbols/*/design/
# symbols png/sdf are now generated at build
data/symbols/**/symbols.png
data/symbols/**/symbols.sdf
data/colors_design.txt
data/patterns_design.txt
data/bookmarks
data/edits.xml
data/World.mwm
@@ -27,11 +25,15 @@ data/WorldCoasts.mwm
data/world_mwm/*
data/*_hash
data/drules_proto*
data/classificator.txt
data/types.txt
data/visibility.txt
data/colors.txt
data/patterns.txt
data/classificator.txt*
data/types.txt*
data/visibility.txt*
data/colors.txt*
data/patterns.txt*
# TODO: designer is not used at the moment
# data/symbols/*/design/
# data/colors_design.txt
# data/patterns_design.txt
# Compiled Python
*.pyc

View File

@@ -49,8 +49,6 @@ if (APPLE AND NOT ("${CMAKE_SYSTEM_NAME}" STREQUAL Android))
set(CMAKE_OBJCXX_VISIBILITY_PRESET hidden)
endif()
execute_process(COMMAND "./configure.sh" WORKING_DIRECTORY ${OMIM_ROOT})
message(STATUS "Using compiler ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
if (CMAKE_UNITY_BUILD)

View File

@@ -19,7 +19,7 @@
</div>
<div align="center">
<p align="center">
<a href="https://codeberg.org/comaps/comaps/releases">
<a href="https://codeberg.org/comaps/comaps/src/branch/main/LICENSE">
<img src="https://img.shields.io/github/license/comaps/comaps?style=for-the-badge&logo=opensourceinitiative&logoColor=white&color=588157" alt="License"/>
</a>
<a href="https://github.com/comaps/comaps/actions/workflows/android-check.yaml">
@@ -41,8 +41,6 @@
A community-led free & open source maps app based on [OpenStreetMap](https://www.openstreetmap.org), built for transparency, privacy, and not-for-profit values. A fork of Organic Maps, originally based on Maps.ME.
**Available for:** Android, iOS, ARM macOS, and alpha Linux/macOS desktop builds (also usable on Linux phones).
<p align="center">
<a href="https://apps.apple.com/app/comaps/id6747180809">
<img src="docs/badges/apple-appstore.png" alt="App Store" width="160"/>
@@ -77,9 +75,10 @@ A community-led free & open source maps app based on [OpenStreetMap](https://www
## ⚡️ Highlights
- **Offline-first**: Navigate without a connection
- **Privacy-respecting**: No tracking, Ads or data collection
- **Privacy-respecting**: No tracking, ads or data collection
- **Lightweight**: Battery- and space-efficient
- **Simple**: Polished, user-focused interface
- **Cross-platform**: Available for Android, iOS, MacOS, and Linux.
- **Community-built**: Free, open source, and collaborative
- **Transparent**: Open finances and governance

View File

@@ -0,0 +1 @@
../../../../google/java/app/organicmaps/location

View File

@@ -1 +0,0 @@
../../../../../google/java/app/organicmaps/sdk/location

View File

@@ -0,0 +1,32 @@
A CoMaps egy közösség által létrehozott, ingyenes és nyílt forráskódú térképalkalmazás, amely az OpenStreetMap térképadatain alapul, és amelyet az átláthatóság, a magánélet védelme és a nonprofit jelleg iránti elkötelezettség erősít. A CoMaps az Organic Maps villája, amely viszont a Maps.ME villája.
A projekt előzményeiről és az irányáról a <b><i>codeberg.org/comaps</i></b> oldalon olvashatsz.
Csatlakozz ott a közösséghez, és segíts a legjobb térképalkalmazás elkészítésében.
• Használd az alkalmazást és terjeszd a hírét
• Adj visszajelzést és jelentsd a problémákat
• Frissítsd és javítsd a térképadatokat az alkalmazásban vagy az OpenStreetMap weboldalán.
‣ <b>Offline-fókuszú:</b> Tervezd meg és navigáld külföldi útad mobilszolgáltatás nélkül, keress útpontokat egy távoli túra során stb. Az alkalmazás minden funkcióját úgy terveztük, hogy internetkapcsolat nélkül is működjön.
‣ <b>A magánélet tiszteletben tartása:</b> Az alkalmazás az adatvédelem szem előtt tartásával készült, nem azonosítja az embereket, nem követi nyomon és nem gyűjt személyes adatokat, és reklámmentes.
‣ <b>Takarékosdik az akkumulátorral és a tárhellyel:</b> Nem meríti le az akkumulátort, mint más navigációs alkalmazások. A jól összeállítot kis méretű térképek értékes helyet takarítanak meg a telefonon.
‣ <b>Egyszerű és szép grafikus felület,</b> nagyszerű és könnyen használható funkciók, amelyek egyszerűen működnek.
‣ <b>Ingyenes és a közösség által készített:</b> A hozzád hasonló emberek segítettek az alkalmazás létrehozásában azáltal, hogy hozzáadtak helyeket az OpenStreetMap térképhez, tesztelték és visszajelzést adtak a funkciókról, valamint hozzájárultak a fejlesztői képességeikkel és a pénzükkel.
‣ <b>Nyílt és átlátható döntéshozatal és pénzügyek, nonprofit és teljesen nyílt forráskódú.</b>
<b>Főbb jellemzők:</b>
• Letölthető részletes térképek olyan helyekkel, amelyek sok kereskedelmi térképen nem állnak rendelkezésre.
• Szabadtéri üzemmód kiemelt túraútvonalakkal, táborhelyekkel, vízforrásokkal, csúcsokkal, szintvonalakkal stb.
• Sétaútvonalak és kerékpárutak
• Érdekes pontok, mint például éttermek, benzinkutak, szállodák, üzletek, látnivalók és még sok minden más
• Keresés név, cím vagy az érdekes pontok kategóriája alapján
• Navigáció hangutasításokkal gyalogláshoz, kerékpározáshoz vagy vezetéshez
• Kedvenc helyeid könyvjelzővel láthatod el egyetlen érintéssel
• Wikipedia szócikkek internetkapcsolat nélkül
• Metró tranzit réteg és irányok
• Útvonal mentése
• Könyvjelzők és nyomvonalak exportálása és importálása KML, KMZ, GPX formátumokban
• Sötét üzemmód az éjszakai használathoz
• Térképadatok javítása mindenki számára egy alapvető beépített szerkesztő segítségével
<b>Itt van a szabadság</b>
Fedezd fel az utadat, navigálj a világban úgy, hogy a magánélet és a közösség kerüljön előtérbe!

View File

@@ -1,4 +1,4 @@
Una app sviluppata dalla comunità, gratuita e open-source, basata su OpenStreetMap e sull'impegno alla trasparenza, al rispetto della Privacy senza scopo di lucro. CoMaps è uno spin-off di Organic Maps, che a sua volta deriva da Maps.ME.
Una app realizzata dalla community gratuita e open-source, basata su OpenStreetMap e sull'impegno alla trasparenza, al rispetto della Privacy e senza scopo di lucro. CoMaps è uno spin-off di Organic Maps, che a sua volta deriva da Maps.ME.
Leggi delle ragioni del progetto e della sua direzione futura su <b><i>codeberg.org/comaps</i></b>.
Unisciti alla nostra comunità e aiutaci a creare la migliore app di mappe.
@@ -15,7 +15,7 @@ Unisciti alla nostra comunità e aiutaci a creare la migliore app di mappe.
<b>Funzionalità principali</b>:
• Scarica mappe dettagliate di luoghi che non sono disponibili su Google Maps
• Modalità Outdoor con percorsi escursionistici, campeggi, sorgenti d'acqua, picchi, dislivelli ed altro evidenziati
• Modalità Outdoor con percorsi escursionistici, campeggi, sorgenti d'acqua, picchi, dislivelli ed altri punti d'interesse evidenziati
• Strade pedonali e piste ciclabili
• Punti d'interesse come ristoranti, stazioni di benzina, hotel, negozi, luoghi turistici e molto altro
• Cerca per nome, indirizzo o categoria

View File

@@ -1 +1 @@
Navigazione semplice - Immergiti nella tua avventura - Sviluppato dalla comunità
Navigazione semplice - Immergiti nella tua avventura - Realizzato dalla comunità

View File

@@ -1 +1 @@
CoMaps - Wandel, fiets, rijdt offline met privacy
CoMaps - Wandel, fiets, rijd offline met privacy

View File

@@ -1,4 +1,4 @@
package app.organicmaps.sdk.location;
package app.organicmaps.location;
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
@@ -10,6 +10,7 @@ import android.location.Location;
import android.os.Looper;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresPermission;
import app.organicmaps.sdk.location.BaseLocationProvider;
import app.organicmaps.sdk.util.LocationUtils;
import app.organicmaps.sdk.util.log.Logger;
import com.google.android.gms.common.api.ApiException;

View File

@@ -1,23 +1,25 @@
package app.organicmaps.sdk.location;
package app.organicmaps.location;
import android.content.Context;
import androidx.annotation.NonNull;
import app.organicmaps.sdk.location.AndroidNativeProvider;
import app.organicmaps.sdk.location.BaseLocationProvider;
import app.organicmaps.sdk.location.LocationProviderFactory;
import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.log.Logger;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
public class LocationProviderFactory
public class LocationProviderFactoryImpl implements LocationProviderFactory
{
private static final String TAG = LocationProviderFactory.class.getSimpleName();
private static final String TAG = LocationProviderFactoryImpl.class.getSimpleName();
public static boolean isGoogleLocationAvailable(@NonNull Context context)
public boolean isGoogleLocationAvailable(@NonNull Context context)
{
return GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS;
}
public static BaseLocationProvider getProvider(@NonNull Context context,
@NonNull BaseLocationProvider.Listener listener)
public BaseLocationProvider getProvider(@NonNull Context context, @NonNull BaseLocationProvider.Listener listener)
{
if (isGoogleLocationAvailable(context) && Config.useGoogleServices())
{

View File

@@ -0,0 +1 @@
../../../../google/java/app/organicmaps/location

View File

@@ -1 +0,0 @@
../../../../../google/java/app/organicmaps/sdk/location

View File

@@ -10,6 +10,8 @@ import androidx.core.content.ContextCompat;
import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.sdk.bookmarks.data.ElevationInfo;
import app.organicmaps.sdk.bookmarks.data.Track;
import app.organicmaps.sdk.bookmarks.data.TrackStatistics;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.widget.placepage.AxisValueFormatter;
@@ -31,17 +33,16 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class ChartController implements OnChartValueSelectedListener,
BookmarkManager.OnElevationActivePointChangedListener,
BookmarkManager.OnElevationCurrentPositionChangedListener
public class ChartController implements OnChartValueSelectedListener
{
private static final int CHART_Y_LABEL_COUNT = 3;
private static final int CHART_X_LABEL_COUNT = 6;
private static final int CHART_ANIMATION_DURATION = 1500;
private static final int CHART_ANIMATION_DURATION = 0;
private static final int CHART_FILL_ALPHA = (int) (0.12 * 255);
private static final int CHART_AXIS_GRANULARITY = 100;
private static final float CUBIC_INTENSITY = 0.2f;
private static final int CURRENT_POSITION_OUT_OF_TRACK = -1;
private static final String ELEVATION_PROFILE_POINTS = "ELEVATION_PROFILE_POINTS";
@SuppressWarnings("NullableProblems")
@NonNull
@@ -62,6 +63,7 @@ public class ChartController implements OnChartValueSelectedListener,
private final Context mContext;
private long mTrackId = Utils.INVALID_ID;
private boolean mCurrentPositionOutOfTrack = true;
private boolean mInformSelectedActivePointToCore = true;
public ChartController(@NonNull Context context)
{
@@ -70,8 +72,6 @@ public class ChartController implements OnChartValueSelectedListener,
public void initialize(@NonNull View view)
{
BookmarkManager.INSTANCE.setElevationActivePointChangedListener(this);
BookmarkManager.INSTANCE.setElevationCurrentPositionChangedListener(this);
final Resources resources = mContext.getResources();
mChart = view.findViewById(R.id.elevation_profile_chart);
@@ -101,13 +101,6 @@ public class ChartController implements OnChartValueSelectedListener,
initAxises();
}
@SuppressWarnings("unused")
public void destroy()
{
BookmarkManager.INSTANCE.setElevationActivePointChangedListener(null);
BookmarkManager.INSTANCE.setElevationCurrentPositionChangedListener(null);
}
private void highlightChartCurrentLocation()
{
mChart.highlightValues(Collections.singletonList(getCurrentPosHighlight()),
@@ -142,15 +135,17 @@ public class ChartController implements OnChartValueSelectedListener,
mChart.getAxisRight().setEnabled(false);
}
public void setData(@NonNull ElevationInfo info)
public void setData(Track track)
{
mTrackId = info.getId();
mTrackId = track.getTrackId();
ElevationInfo info = track.getElevationInfo();
TrackStatistics stats = track.getTrackStatistics();
List<Entry> values = new ArrayList<>();
for (ElevationInfo.Point point : info.getPoints())
values.add(new Entry((float) point.getDistance(), point.getAltitude()));
values.add(new Entry((float) point.getDistance(), point.getAltitude(), point));
LineDataSet set = new LineDataSet(values, "Elevation_profile_points");
LineDataSet set = new LineDataSet(values, ELEVATION_PROFILE_POINTS);
set.setMode(LineDataSet.Mode.CUBIC_BEZIER);
set.setCubicIntensity(CUBIC_INTENSITY);
set.setDrawFilled(true);
@@ -173,8 +168,8 @@ public class ChartController implements OnChartValueSelectedListener,
mChart.setData(data);
mChart.animateX(CHART_ANIMATION_DURATION);
mMinAltitude.setText(Framework.nativeFormatAltitude(info.getMinAltitude()));
mMaxAltitude.setText(Framework.nativeFormatAltitude(info.getMaxAltitude()));
mMinAltitude.setText(Framework.nativeFormatAltitude(stats.getMinElevation()));
mMaxAltitude.setText(Framework.nativeFormatAltitude(stats.getMaxElevation()));
highlightActivePointManually();
}
@@ -192,7 +187,9 @@ public class ChartController implements OnChartValueSelectedListener,
if (mTrackId == Utils.INVALID_ID)
return;
BookmarkManager.INSTANCE.setElevationActivePoint(mTrackId, e.getX());
if (mInformSelectedActivePointToCore)
BookmarkManager.INSTANCE.setElevationActivePoint(mTrackId, e.getX(), (ElevationInfo.Point) e.getData());
mInformSelectedActivePointToCore = true;
}
@NonNull
@@ -211,7 +208,6 @@ public class ChartController implements OnChartValueSelectedListener,
highlightChartCurrentLocation();
}
@Override
public void onCurrentPositionChanged()
{
if (mTrackId == Utils.INVALID_ID)
@@ -222,7 +218,6 @@ public class ChartController implements OnChartValueSelectedListener,
highlightActivePointManually();
}
@Override
public void onElevationActivePointChanged()
{
if (mTrackId == Utils.INVALID_ID)
@@ -234,6 +229,7 @@ public class ChartController implements OnChartValueSelectedListener,
private void highlightActivePointManually()
{
Highlight highlight = getActivePoint();
mInformSelectedActivePointToCore = false;
mChart.highlightValue(highlight, true);
}

View File

@@ -27,6 +27,7 @@ import androidx.annotation.StringRes;
import androidx.annotation.StyleRes;
import androidx.core.view.ViewCompat;
import app.organicmaps.base.BaseMwmFragmentActivity;
import app.organicmaps.downloader.MapManagerHelper;
import app.organicmaps.intent.Factory;
import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.downloader.CountryItem;
@@ -35,7 +36,7 @@ import app.organicmaps.sdk.location.LocationListener;
import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.ConnectionState;
import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener;
import com.google.android.material.button.MaterialButton;
@@ -116,10 +117,10 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
private final app.organicmaps.sdk.DownloadResourcesLegacyActivity.Listener mResourcesDownloadListener =
new app.organicmaps.sdk.DownloadResourcesLegacyActivity.Listener() {
@Override
public void onProgress(final int percent)
public void onProgress(final int bytesDownloaded)
{
if (!isFinishing())
mProgress.setProgressCompat(percent, true);
mProgress.setProgressCompat(bytesDownloaded, true);
}
@Override
@@ -155,7 +156,9 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
showMap();
return;
case CountryItem.STATUS_FAILED: MapManager.showError(DownloadResourcesLegacyActivity.this, item, null); return;
case CountryItem.STATUS_FAILED:
MapManagerHelper.showError(DownloadResourcesLegacyActivity.this, item, null);
return;
}
}
}
@@ -250,7 +253,8 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
setDownloadMessage(bytes);
mProgress.setMax(bytes);
mProgress.setProgressCompat(0, true);
// Start progress at 1% according to M3 guidelines
mProgress.setProgressCompat(bytes/100, true);
}
else
finishFilesDownload(bytes);
@@ -368,10 +372,11 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
String fileSizeString = StringUtils.getFileSizeString(this, item.totalSize);
mTvMessage.setText(getString(R.string.downloading_country_can_proceed, item.name, fileSizeString));
mProgress.setMax((int) item.totalSize);
mProgress.setProgressCompat(0, true);
// Start progress at 1% according to M3 guidelines
mProgress.setProgressCompat((int) (item.totalSize/100), true);
mCountryDownloadListenerSlot = MapManager.nativeSubscribe(mCountryDownloadListener);
MapManager.startDownload(mCurrentCountry);
MapManagerHelper.startDownload(mCurrentCountry);
setAction(PROCEED_TO_MAP);
}
else

View File

@@ -12,6 +12,7 @@ import static app.organicmaps.sdk.location.LocationState.FOLLOW;
import static app.organicmaps.sdk.location.LocationState.FOLLOW_AND_ROTATE;
import static app.organicmaps.sdk.location.LocationState.LOCATION_TAG;
import static app.organicmaps.sdk.util.PowerManagment.POWER_MANAGEMENT_TAG;
import static app.organicmaps.sdk.util.Utils.dimen;
import android.annotation.SuppressLint;
import android.app.Activity;
@@ -111,7 +112,6 @@ import app.organicmaps.sdk.settings.UnitLocale;
import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.LocationUtils;
import app.organicmaps.sdk.util.PowerManagment;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.sdk.util.log.Logger;
import app.organicmaps.sdk.widget.placepage.PlacePageData;
import app.organicmaps.search.FloatingSearchToolbarController;
@@ -122,6 +122,7 @@ import app.organicmaps.settings.SettingsActivity;
import app.organicmaps.util.SharingUtils;
import app.organicmaps.util.ThemeSwitcher;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment;
import app.organicmaps.util.bottomsheet.MenuBottomSheetItem;
@@ -457,12 +458,10 @@ public class MwmActivity extends BaseMwmFragmentActivity
@StyleRes
protected int getThemeResourceId(@NonNull String theme)
{
Context context = getApplicationContext();
if (ThemeUtils.isDefaultTheme(context, theme))
if (Config.UiTheme.isDefault(theme))
return R.style.MwmTheme_MainActivity;
if (ThemeUtils.isNightTheme(context, theme))
if (Config.UiTheme.isNight(theme))
return R.style.MwmTheme_Night_MainActivity;
return super.getThemeResourceId(theme);
@@ -584,7 +583,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
private void refreshLightStatusBar()
{
UiUtils.setLightStatusBar(this, !(ThemeUtils.isNightTheme(this) || RoutingController.get().isPlanning()
UiUtils.setLightStatusBar(this, !(ThemeUtils.isNightTheme() || RoutingController.get().isPlanning()
|| ChoosePositionMode.get() != ChoosePositionMode.None));
}
@@ -594,7 +593,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
UiUtils.setViewInsetsPaddingBottom(mPointChooser, windowInsets);
UiUtils.setViewInsetsPaddingNoBottom(mPointChooserToolbar, windowInsets);
final int trackRecorderOffset =
TrackRecorder.nativeIsTrackRecordingEnabled() ? UiUtils.dimen(this, R.dimen.map_button_size) : 0;
TrackRecorder.nativeIsTrackRecordingEnabled() ? dimen(this, R.dimen.map_button_size) : 0;
mNavBarHeight = isFullscreen() ? 0 : windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom;
// For the first loading, set compass top margin to status bar size
// The top inset will be then be updated by the routing controller
@@ -1648,17 +1647,17 @@ public class MwmActivity extends BaseMwmFragmentActivity
final int orientation = getResources().getConfiguration().orientation;
final boolean isTrackRecordingEnabled = TrackRecorder.nativeIsTrackRecordingEnabled();
if (isTrackRecordingEnabled && (orientation != Configuration.ORIENTATION_LANDSCAPE))
offsetY += UiUtils.dimen(this, R.dimen.map_button_size);
offsetY += dimen(this, R.dimen.map_button_size);
if (orientation == Configuration.ORIENTATION_LANDSCAPE)
{
if (show)
{
final boolean isSmallScreen = UiUtils.getDisplayTotalHeight(this) < UiUtils.dimen(this, R.dimen.dp_400);
final boolean isSmallScreen = UiUtils.getDisplayTotalHeight(this) < dimen(this, R.dimen.dp_400);
if (!isSmallScreen || TrackRecorder.nativeIsTrackRecordingEnabled())
offsetX += UiUtils.dimen(this, R.dimen.map_button_size);
offsetX += dimen(this, R.dimen.map_button_size);
}
else if (isTrackRecordingEnabled)
offsetY += UiUtils.dimen(this, R.dimen.map_button_size);
offsetY += dimen(this, R.dimen.map_button_size);
}
updateCompassOffset(offsetY, offsetX);
}
@@ -2457,7 +2456,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
if (mCurrentWindowInsets != null)
{
final int offset = mCurrentWindowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).top;
updateCompassOffset(offset + UiUtils.dimen(this, R.dimen.map_button_size));
updateCompassOffset(offset + dimen(this, R.dimen.map_button_size));
}
Toast.makeText(this, R.string.track_recording, Toast.LENGTH_SHORT).show();
TrackRecordingService.startForegroundService(getApplicationContext());
@@ -2550,7 +2549,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
items.add(new MenuBottomSheetItem(R.string.download_maps, R.drawable.ic_download, getDownloadMapsCounter(),
this::onDownloadMapsOptionSelected));
mDonatesUrl = Config.getDonateUrl(getApplicationContext());
mDonatesUrl = Utils.getDonateUrl(getApplicationContext());
if (!mDonatesUrl.isEmpty())
items.add(new MenuBottomSheetItem(R.string.donate, R.drawable.ic_donate, this::onDonateOptionSelected));

View File

@@ -14,8 +14,10 @@ import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.ProcessLifecycleOwner;
import androidx.preference.PreferenceManager;
import app.organicmaps.background.OsmUploadWork;
import app.organicmaps.downloader.DownloaderNotifier;
import app.organicmaps.location.LocationProviderFactoryImpl;
import app.organicmaps.location.TrackRecordingService;
import app.organicmaps.routing.NavigationService;
import app.organicmaps.sdk.Map;
@@ -41,6 +43,9 @@ public class MwmApplication extends Application implements Application.ActivityL
@NonNull
private static final String TAG = MwmApplication.class.getSimpleName();
@NonNull
private final LocationProviderFactoryImpl mLocationProviderFactory = new LocationProviderFactoryImpl();
@SuppressWarnings("NotNullFieldNotInitialized")
@NonNull
private OrganicMaps mOrganicMaps;
@@ -99,6 +104,12 @@ public class MwmApplication extends Application implements Application.ActivityL
return mOrganicMaps;
}
@NonNull
public LocationProviderFactoryImpl getLocationProviderFactory()
{
return mLocationProviderFactory;
}
@NonNull
public static MwmApplication from(@NonNull Context context)
{
@@ -119,7 +130,10 @@ public class MwmApplication extends Application implements Application.ActivityL
sInstance = this;
mOrganicMaps = new OrganicMaps(getApplicationContext());
PreferenceManager.setDefaultValues(this, R.xml.prefs_main, false);
mOrganicMaps = new OrganicMaps(getApplicationContext(), BuildConfig.FLAVOR, BuildConfig.APPLICATION_ID,
BuildConfig.VERSION_CODE, BuildConfig.VERSION_NAME,
BuildConfig.FILE_PROVIDER_AUTHORITY, mLocationProviderFactory);
ConnectionState.INSTANCE.initialize(this);

View File

@@ -9,7 +9,8 @@ import androidx.annotation.IntegerRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.sdk.util.Utils;
import app.organicmaps.util.UiUtils;
import org.chromium.base.ObserverList;
class PanelAnimator
@@ -26,7 +27,7 @@ class PanelAnimator
PanelAnimator(MwmActivity activity)
{
mActivity = activity;
mWidth = UiUtils.dimen(activity.getApplicationContext(), R.dimen.panel_width);
mWidth = Utils.dimen(activity.getApplicationContext(), R.dimen.panel_width);
mPanel = mActivity.findViewById(R.id.fragment_container);
mDuration = mActivity.getResources().getInteger(R.integer.anim_panel);
}

View File

@@ -60,11 +60,10 @@ public class SplashActivity extends AppCompatActivity
{
super.onCreate(savedInstanceState);
final Context context = getApplicationContext();
final String theme = Config.getCurrentUiTheme(context);
if (ThemeUtils.isDefaultTheme(context, theme))
final String theme = Config.UiTheme.getCurrent();
if (Config.UiTheme.isDefault(theme))
setTheme(R.style.MwmTheme_Splash);
else if (ThemeUtils.isNightTheme(context, theme))
else if (Config.UiTheme.isNight(theme))
setTheme(R.style.MwmTheme_Night_Splash);
else
throw new IllegalArgumentException("Attempt to apply unsupported theme: " + theme);

View File

@@ -9,7 +9,7 @@ import android.webkit.WebView;
import android.webkit.WebViewClient;
import androidx.annotation.NonNull;
import app.organicmaps.base.OnBackPressListener;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
public abstract class WebContainerDelegate implements OnBackPressListener
{

View File

@@ -1,6 +1,7 @@
package app.organicmaps.backup;
import static app.organicmaps.sdk.util.StorageUtils.isFolderWritable;
import static app.organicmaps.sdk.util.Utils.dimen;
import static app.organicmaps.settings.BackupSettingsFragment.MAX_BACKUPS_DEFAULT_COUNT;
import static app.organicmaps.settings.BackupSettingsFragment.MAX_BACKUPS_KEY;
@@ -15,8 +16,8 @@ import android.text.style.AbsoluteSizeSpan;
import androidx.annotation.NonNull;
import androidx.documentfile.provider.DocumentFile;
import app.organicmaps.R;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.sdk.util.log.Logger;
import app.organicmaps.util.UiUtils;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
@@ -50,14 +51,14 @@ public class BackupUtils
String volumeName;
if ("primary".equalsIgnoreCase(volumeId))
volumeName = context.getString(R.string.maps_storage_shared);
volumeName = context.getString(app.organicmaps.sdk.R.string.maps_storage_shared);
else
volumeName = context.getString(R.string.maps_storage_removable);
volumeName = context.getString(app.organicmaps.sdk.R.string.maps_storage_removable);
SpannableStringBuilder sb = new SpannableStringBuilder();
sb.append(volumeName + ": \n", new AbsoluteSizeSpan(UiUtils.dimen(context, R.dimen.text_size_body_3)),
sb.append(volumeName + ": \n", new AbsoluteSizeSpan(dimen(context, R.dimen.text_size_body_3)),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
sb.append("/" + subPath, new AbsoluteSizeSpan(UiUtils.dimen(context, R.dimen.text_size_body_4)),
sb.append("/" + subPath, new AbsoluteSizeSpan(dimen(context, R.dimen.text_size_body_4)),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return sb;
}

View File

@@ -15,7 +15,7 @@ public class BaseMwmDialogFragment extends DialogFragment
@StyleRes
protected final int getFullscreenTheme()
{
return ThemeUtils.isNightTheme(requireContext()) ? getFullscreenDarkTheme() : getFullscreenLightTheme();
return ThemeUtils.isNightTheme() ? getFullscreenDarkTheme() : getFullscreenLightTheme();
}
protected int getStyle()

View File

@@ -1,7 +1,6 @@
package app.organicmaps.base;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.media.AudioManager;
@@ -24,7 +23,6 @@ import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.concurrency.UiThread;
import app.organicmaps.sdk.util.log.Logger;
import app.organicmaps.util.RtlUtils;
import app.organicmaps.util.ThemeUtils;
import com.google.android.material.appbar.MaterialToolbar;
import java.util.Objects;
@@ -40,12 +38,10 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity
@StyleRes
protected int getThemeResourceId(@NonNull String theme)
{
Context context = getApplicationContext();
if (ThemeUtils.isDefaultTheme(context, theme))
if (Config.UiTheme.isDefault(theme))
return R.style.MwmTheme;
if (ThemeUtils.isNightTheme(context, theme))
if (Config.UiTheme.isNight(theme))
return R.style.MwmTheme_Night;
throw new IllegalArgumentException("Attempt to apply unsupported theme: " + theme);
@@ -62,7 +58,7 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity
protected final void onCreate(@Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mThemeName = Config.getCurrentUiTheme(getApplicationContext());
mThemeName = Config.UiTheme.getCurrent();
setTheme(getThemeResourceId(mThemeName));
EdgeToEdge.enable(this, SystemBarStyle.dark(Color.TRANSPARENT));
RtlUtils.manageRtl(this);
@@ -122,7 +118,7 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity
public void onPostResume()
{
super.onPostResume();
if (!mThemeName.equals(Config.getCurrentUiTheme(getApplicationContext())))
if (!mThemeName.equals(Config.UiTheme.getCurrent()))
{
// Workaround described in https://code.google.com/p/android/issues/detail?id=93731
UiThread.runLater(this::recreate);

View File

@@ -14,7 +14,7 @@ import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils.ScrollableContentInsetsListener;
import app.organicmaps.widget.PlaceholderView;

View File

@@ -10,7 +10,7 @@ import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentFactory;
import androidx.fragment.app.FragmentManager;
import app.organicmaps.R;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener;
import com.google.android.material.appbar.MaterialToolbar;

View File

@@ -42,7 +42,7 @@ public class BookmarkCategoriesActivity extends BaseToolbarActivity
@StyleRes
public int getThemeResourceId(@NonNull String theme)
{
return ThemeUtils.getWindowBgThemeResourceId(getApplicationContext(), theme);
return ThemeUtils.getWindowBgThemeResourceId(theme);
}
@Override

View File

@@ -11,7 +11,7 @@ import app.organicmaps.R;
import app.organicmaps.adapter.OnItemClickListener;
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;

View File

@@ -41,7 +41,7 @@ public class BookmarkListActivity extends BaseToolbarActivity
@StyleRes
public int getThemeResourceId(@NonNull String theme)
{
return ThemeUtils.getCardBgThemeResourceId(getApplicationContext(), theme);
return ThemeUtils.getCardBgThemeResourceId(theme);
}
@Override

View File

@@ -33,16 +33,15 @@ import app.organicmaps.sdk.bookmarks.data.BookmarkInfo;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.sdk.bookmarks.data.BookmarkSharingResult;
import app.organicmaps.sdk.bookmarks.data.CategoryDataSource;
import app.organicmaps.sdk.bookmarks.data.Icon;
import app.organicmaps.sdk.bookmarks.data.KmlFileType;
import app.organicmaps.sdk.bookmarks.data.PredefinedColors;
import app.organicmaps.sdk.bookmarks.data.SortedBlock;
import app.organicmaps.sdk.bookmarks.data.Track;
import app.organicmaps.sdk.search.BookmarkSearchListener;
import app.organicmaps.sdk.search.SearchEngine;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.Graphics;
import app.organicmaps.util.SharingUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils;
import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment;

View File

@@ -13,7 +13,7 @@ import androidx.fragment.app.FragmentManager;
import app.organicmaps.R;
import app.organicmaps.base.BaseMwmDialogFragment;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
public class ChooseBookmarksSortingTypeFragment
extends BaseMwmDialogFragment implements RadioGroup.OnCheckedChangeListener

View File

@@ -18,8 +18,8 @@ import app.organicmaps.sdk.bookmarks.data.BookmarkInfo;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.sdk.bookmarks.data.IconClickListener;
import app.organicmaps.sdk.bookmarks.data.Track;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.Graphics;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.widget.recycler.RecyclerClickListener;
import app.organicmaps.widget.recycler.RecyclerLongClickListener;

View File

@@ -73,8 +73,7 @@ public class NavigationScreen extends BaseMapScreen implements RoutingController
public Template onGetTemplate()
{
final NavigationTemplate.Builder builder = new NavigationTemplate.Builder();
builder.setBackgroundColor(ThemeUtils.isNightMode(getCarContext()) ? Colors.NAVIGATION_TEMPLATE_BACKGROUND_NIGHT
: Colors.NAVIGATION_TEMPLATE_BACKGROUND_DAY);
builder.setBackgroundColor(Colors.NAVIGATION_TEMPLATE_BACKGROUND);
builder.setActionStrip(createActionStrip());
builder.setMapActionStrip(UiHelpers.createMapActionStrip(getCarContext(), getSurfaceRenderer()));

View File

@@ -12,6 +12,7 @@ import androidx.lifecycle.LifecycleOwner;
import app.organicmaps.R;
import app.organicmaps.car.screens.ErrorScreen;
import app.organicmaps.car.screens.base.BaseScreen;
import app.organicmaps.downloader.MapManagerHelper;
import app.organicmaps.sdk.downloader.CountryItem;
import app.organicmaps.sdk.downloader.MapManager;
import app.organicmaps.sdk.util.StringUtils;
@@ -169,7 +170,7 @@ class DownloaderScreen extends BaseScreen
mIsDownloadFailed = true;
final ErrorScreen.Builder builder = new ErrorScreen.Builder(getCarContext())
.setTitle(R.string.country_status_download_failed)
.setErrorMessage(MapManager.getErrorCodeStrRes(data.errorCode))
.setErrorMessage(MapManagerHelper.getErrorCodeStrRes(data.errorCode))
.setPositiveButton(R.string.downloader_retry, null);
if (!mIsCancelActionDisabled)
builder.setNegativeButton(R.string.cancel, this::finish);

View File

@@ -11,8 +11,7 @@ public final class Colors
public static final CarColor OPENING_HOURS_CLOSES_SOON = CarColor.YELLOW;
public static final CarColor OPENING_HOURS_CLOSED = CarColor.RED;
public static final CarColor START_NAVIGATION = CarColor.GREEN;
public static final CarColor NAVIGATION_TEMPLATE_BACKGROUND_DAY = CarColor.GREEN;
public static final CarColor NAVIGATION_TEMPLATE_BACKGROUND_NIGHT = CarColor.DEFAULT;
public static final CarColor NAVIGATION_TEMPLATE_BACKGROUND = CarColor.GREEN;
public static final CarColor BUTTON_ACCEPT = CarColor.GREEN;
private Colors() {}

View File

@@ -10,19 +10,20 @@ import androidx.car.app.CarContext;
import app.organicmaps.R;
import app.organicmaps.sdk.MapStyle;
import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.util.Config;
public final class ThemeUtils
{
public enum ThemeMode
{
AUTO(R.string.auto, R.string.theme_auto),
LIGHT(R.string.off, R.string.theme_default),
NIGHT(R.string.on, R.string.theme_night);
AUTO(R.string.auto, Config.UiTheme.AUTO),
LIGHT(R.string.off, Config.UiTheme.DEFAULT),
NIGHT(R.string.on, Config.UiTheme.NIGHT);
ThemeMode(@StringRes int titleId, @StringRes int prefsKeyId)
ThemeMode(@StringRes int titleId, @NonNull String config)
{
mTitleId = titleId;
mPrefsKeyId = prefsKeyId;
mConfig = config;
}
@StringRes
@@ -31,16 +32,16 @@ public final class ThemeUtils
return mTitleId;
}
@StringRes
public int getPrefsKeyId()
@NonNull
public String getConfig()
{
return mPrefsKeyId;
return mConfig;
}
@StringRes
private final int mTitleId;
@StringRes
private final int mPrefsKeyId;
@NonNull
private final String mConfig;
}
private static final String ANDROID_AUTO_PREFERENCES_FILE_KEY = "ANDROID_AUTO_PREFERENCES_FILE_KEY";
@@ -79,23 +80,20 @@ public final class ThemeUtils
@UiThread
public static void setThemeMode(@NonNull CarContext context, @NonNull ThemeMode themeMode)
{
getSharedPreferences(context).edit().putString(THEME_KEY, context.getString(themeMode.getPrefsKeyId())).commit();
getSharedPreferences(context).edit().putString(THEME_KEY, themeMode.getConfig()).commit();
update(context, themeMode);
}
@NonNull
public static ThemeMode getThemeMode(@NonNull CarContext context)
{
final String autoTheme = context.getString(R.string.theme_auto);
final String lightTheme = context.getString(R.string.theme_default);
final String nightTheme = context.getString(R.string.theme_night);
final String themeMode = getSharedPreferences(context).getString(THEME_KEY, autoTheme);
final String themeMode = getSharedPreferences(context).getString(THEME_KEY, ThemeMode.AUTO.getConfig());
if (themeMode.equals(autoTheme))
if (themeMode.equals(ThemeMode.AUTO.getConfig()))
return ThemeMode.AUTO;
else if (themeMode.equals(lightTheme))
else if (themeMode.equals(ThemeMode.LIGHT.getConfig()))
return ThemeMode.LIGHT;
else if (themeMode.equals(nightTheme))
else if (themeMode.equals(ThemeMode.NIGHT.getConfig()))
return ThemeMode.NIGHT;
else
throw new IllegalArgumentException("Unsupported value");

View File

@@ -15,7 +15,7 @@ import app.organicmaps.sdk.downloader.CountryItem;
import app.organicmaps.sdk.downloader.MapManager;
import app.organicmaps.sdk.downloader.UpdateInfo;
import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
@@ -29,7 +29,7 @@ class BottomPanel
@Override
public void onClick(View v)
{
MapManager.warn3gAndDownload(mFragment.requireActivity(), mFragment.getCurrentRoot(), null);
MapManagerHelper.warn3gAndDownload(mFragment.requireActivity(), mFragment.getCurrentRoot(), null);
}
};
@@ -38,7 +38,10 @@ class BottomPanel
public void onClick(View v)
{
final String country = mFragment.getCurrentRoot();
MapManager.warnOn3gUpdate(mFragment.requireActivity(), country, () -> MapManager.startUpdate(country));
MapManagerHelper.warnOn3gUpdate(mFragment.requireActivity(), country, () -> {
DownloaderService.startForegroundService();
MapManagerHelper.startUpdate(country);
});
}
};
@@ -55,7 +58,7 @@ class BottomPanel
@Override
public void onClick(View v)
{
MapManager.warn3gAndRetry(mFragment.requireActivity(), mFragment.getCurrentRoot(), null);
MapManagerHelper.warn3gAndRetry(mFragment.requireActivity(), mFragment.getCurrentRoot(), null);
}
};

View File

@@ -16,7 +16,7 @@ import app.organicmaps.base.BaseMwmFragmentActivity;
import app.organicmaps.sdk.downloader.CountryItem;
import app.organicmaps.sdk.downloader.MapManager;
import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.widget.WheelProgressView;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.textview.MaterialTextView;
@@ -198,7 +198,8 @@ public class CountrySuggestFragment extends BaseMwmFragment implements View.OnCl
final int id = v.getId();
if (id == R.id.btn__download_map)
{
MapManager.warn3gAndDownload(requireActivity(), mCurrentCountry.id, () -> mDownloadingCountry = mCurrentCountry);
MapManagerHelper.warn3gAndDownload(requireActivity(), mCurrentCountry.id,
() -> mDownloadingCountry = mCurrentCountry);
}
else if (id == R.id.btn__select_map)
{

View File

@@ -24,7 +24,7 @@ import app.organicmaps.sdk.downloader.CountryItem;
import app.organicmaps.sdk.downloader.MapManager;
import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment;
import app.organicmaps.util.bottomsheet.MenuBottomSheetItem;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
@@ -93,7 +93,7 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
private void onDownloadActionSelected(final CountryItem item, DownloaderAdapter adapter)
{
MapManager.warn3gAndDownload(adapter.mActivity, item.id, null);
MapManagerHelper.warn3gAndDownload(adapter.mActivity, item.id, null);
}
private void onUpdateActionSelected(final CountryItem item, DownloaderAdapter adapter)
@@ -101,7 +101,7 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
item.update();
if (item.status != CountryItem.STATUS_UPDATABLE)
return;
MapManager.warnOn3gUpdate(adapter.mActivity, item.id, () -> MapManager.startUpdate(item.id));
MapManagerHelper.warnOn3gUpdate(adapter.mActivity, item.id, () -> MapManagerHelper.startUpdate(item.id));
}
private void onExploreActionSelected(CountryItem item, DownloaderAdapter adapter)
@@ -206,7 +206,7 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
{
if (item.isLeafNode && item.newStatus == CountryItem.STATUS_FAILED)
{
MapManager.showError(mActivity, item, null);
MapManagerHelper.showError(mActivity, item, null);
break;
}
}
@@ -382,9 +382,12 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
else
processLongClick();
}
case CountryItem.STATUS_FAILED -> MapManager.warn3gAndRetry(mActivity, mItem.id, null);
case CountryItem.STATUS_FAILED ->
{
MapManagerHelper.warn3gAndRetry(mActivity, mItem.id, null);
}
case CountryItem.STATUS_UPDATABLE ->
MapManager.warnOn3gUpdate(mActivity, mItem.id, () -> MapManager.startUpdate(mItem.id));
MapManagerHelper.warnOn3gUpdate(mActivity, mItem.id, () -> MapManagerHelper.startUpdate(mItem.id));
default -> throw new IllegalArgumentException("Inappropriate item status: " + mItem.status);
}
}

View File

@@ -9,7 +9,8 @@ import androidx.core.view.OnApplyWindowInsetsListener;
import androidx.core.view.WindowInsetsCompat;
import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.sdk.util.Utils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.WindowInsetUtils;
final class DownloaderInsetsListener implements OnApplyWindowInsetsListener
@@ -55,7 +56,7 @@ final class DownloaderInsetsListener implements OnApplyWindowInsetsListener
private void applyInsetsToButtons(Insets insets)
{
int baseMargin = UiUtils.dimen(mContext, R.dimen.margin_base);
int baseMargin = Utils.dimen(mContext, R.dimen.margin_base);
ViewGroup.MarginLayoutParams fabParams = (ViewGroup.MarginLayoutParams) mFab.getLayoutParams();
ViewGroup.MarginLayoutParams buttonParams = (ViewGroup.MarginLayoutParams) mButton.getLayoutParams();

View File

@@ -20,6 +20,7 @@ import app.organicmaps.R;
import app.organicmaps.sdk.downloader.MapManager;
import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.sdk.util.log.Logger;
import java.util.Objects;
public class DownloaderNotifier
{
@@ -29,7 +30,8 @@ public class DownloaderNotifier
public static final int NOTIFICATION_ID = 1;
private final Context mContext;
private NotificationCompat.Builder mProgressNotificationBuilder;
private NotificationCompat.Builder mProgressNotificationBuilder = null;
private String mNotificationCountryId = null;
public DownloaderNotifier(Context context)
{
@@ -45,6 +47,7 @@ public class DownloaderNotifier
.setShowBadge(true)
.setVibrationEnabled(false)
.setLightsEnabled(false)
.setSound(null, null)
.build();
notificationManager.createNotificationChannel(channel);
}
@@ -62,8 +65,6 @@ public class DownloaderNotifier
final String countryName = MapManager.nativeGetName(countryId);
final String content = mContext.getString(R.string.download_country_failed, countryName);
var contentPendingIntent = getNotificationPendingIntent(countryId);
final Notification notification = new NotificationCompat.Builder(mContext, CHANNEL_ID)
.setAutoCancel(true)
.setCategory(NotificationCompat.CATEGORY_ERROR)
@@ -74,7 +75,7 @@ public class DownloaderNotifier
.setContentText(content)
.setShowWhen(true)
.setTicker(getTicker(mContext, title, content))
.setContentIntent(contentPendingIntent)
.setContentIntent(getNotificationPendingIntent(countryId))
.setOnlyAlertOnce(true)
.build();
@@ -110,32 +111,41 @@ public class DownloaderNotifier
@NonNull
public Notification buildProgressNotification(@Nullable String countryId, int maxProgress, int progress)
{
var builder = startNotification(countryId);
builder.setProgress(maxProgress, progress, maxProgress == 0);
builder.setContentText("Download in progress");
var builder = getNotificationBuilder(countryId);
/// @todo Doesn't work properly .. Bad input sizes?
// builder.setProgress(maxProgress, progress, maxProgress == 0);
builder.setProgress(maxProgress, progress, true);
return builder.build();
}
@NonNull
private NotificationCompat.Builder startNotification(@Nullable String countryId)
private NotificationCompat.Builder getNotificationBuilder(@Nullable String countryId)
{
final String title = mContext.getString(R.string.app_name);
if (mProgressNotificationBuilder == null || !Objects.equals(countryId, mNotificationCountryId))
{
mNotificationCountryId = countryId;
final String countryName = countryId != null ? MapManager.nativeGetName(countryId) : "";
return new NotificationCompat.Builder(mContext, CHANNEL_ID)
.setAutoCancel(true)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setSmallIcon(R.drawable.ic_logo_small)
.setColor(ContextCompat.getColor(mContext, R.color.notification))
.setShowWhen(true)
.setContentTitle(title)
.setContentIntent(getNotificationPendingIntent(countryId));
mProgressNotificationBuilder =
new NotificationCompat.Builder(mContext, CHANNEL_ID)
.setAutoCancel(true)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setSmallIcon(R.drawable.ic_logo_small)
.setColor(ContextCompat.getColor(mContext, R.color.notification))
.setShowWhen(true)
.setContentTitle(mContext.getString(R.string.app_name))
.setContentIntent(getNotificationPendingIntent(countryId))
.setContentText(mContext.getString(R.string.downloader_downloading) + " " + countryName)
.setSound(null);
}
return mProgressNotificationBuilder;
}
@NonNull
private PendingIntent getNotificationPendingIntent(@Nullable String countryId)
{
/// @todo Zooming to the countryId when tapping on the notification?
/// Shows very low zoom level, need z=9/10, I suppose ...
final int FLAG_IMMUTABLE = Build.VERSION.SDK_INT < Build.VERSION_CODES.M ? 0 : PendingIntent.FLAG_IMMUTABLE;
final Intent contentIntent = MwmActivity.createShowMapIntent(mContext, countryId);
contentIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

View File

@@ -97,7 +97,7 @@ public class DownloaderService extends Service implements MapManager.StorageCall
}
@Override
public void onProgress(String countryId, long localSize, long remoteSize)
public void onProgress(String countryId, long bytesDownloaded, long bytesTotal)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
&& ContextCompat.checkSelfPermission(this, POST_NOTIFICATIONS) != PERMISSION_GRANTED)
@@ -106,8 +106,7 @@ public class DownloaderService extends Service implements MapManager.StorageCall
return;
}
// TODO: How to calculate progress?
mNotifier.notifyProgress();
mNotifier.notifyProgress(countryId, (int) bytesTotal, (int) bytesDownloaded);
}
@Override

View File

@@ -6,8 +6,8 @@ import androidx.annotation.AttrRes;
import androidx.annotation.DrawableRes;
import app.organicmaps.R;
import app.organicmaps.sdk.downloader.CountryItem;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.widget.WheelProgressView;
import com.google.android.material.imageview.ShapeableImageView;

View File

@@ -5,7 +5,7 @@ import android.content.Intent;
import android.text.TextUtils;
import android.view.View;
import app.organicmaps.R;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.widget.SearchToolbarController;
class DownloaderToolbarController extends SearchToolbarController

View File

@@ -0,0 +1,223 @@
package app.organicmaps.downloader;
import android.app.Activity;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AlertDialog;
import androidx.core.util.Consumer;
import app.organicmaps.R;
import app.organicmaps.sdk.downloader.CountryItem;
import app.organicmaps.sdk.downloader.ExpandRetryConfirmationListener;
import app.organicmaps.sdk.downloader.MapManager;
import app.organicmaps.sdk.util.ConnectionState;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.lang.ref.WeakReference;
public class MapManagerHelper
{
private static WeakReference<AlertDialog> sCurrentErrorDialog;
@StringRes
public static int getErrorCodeStrRes(final int errorCode)
{
return switch (errorCode)
{
case CountryItem.ERROR_NO_INTERNET -> R.string.common_check_internet_connection_dialog;
case CountryItem.ERROR_OOM -> R.string.downloader_no_space_title;
default -> throw new IllegalArgumentException("Given error can not be displayed: " + errorCode);
};
}
public static void showError(final Activity activity, final MapManager.StorageCallbackData errorData,
@Nullable final Consumer<Boolean> dialogClickListener)
{
if (!MapManager.nativeIsAutoretryFailed())
return;
showErrorDialog(activity, errorData, dialogClickListener);
}
public static void showErrorDialog(final Activity activity, final MapManager.StorageCallbackData errorData,
@Nullable final Consumer<Boolean> dialogClickListener)
{
if (sCurrentErrorDialog != null)
{
AlertDialog dlg = sCurrentErrorDialog.get();
if (dlg != null && dlg.isShowing())
return;
}
final AlertDialog dlg = new MaterialAlertDialogBuilder(activity, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.country_status_download_failed)
.setMessage(getErrorCodeStrRes(errorData.errorCode))
.setNegativeButton(R.string.cancel,
(dialog, which) -> {
sCurrentErrorDialog = null;
if (dialogClickListener != null)
dialogClickListener.accept(false);
})
.setPositiveButton(R.string.downloader_retry,
(dialog, which) -> {
ExpandRetryConfirmationListener listener =
new ExpandRetryConfirmationListener(dialogClickListener);
warn3gAndRetry(activity, errorData.countryId, listener);
})
.create();
dlg.setCanceledOnTouchOutside(false);
dlg.show();
sCurrentErrorDialog = new WeakReference<>(dlg);
}
private static void notifyNoSpaceInternal(Activity activity)
{
new MaterialAlertDialogBuilder(activity, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.downloader_no_space_title)
.setMessage(R.string.downloader_no_space_message)
.setPositiveButton(android.R.string.ok, null)
.show();
}
/**
* @return true if there is no space to update the given {@code root}, so the alert dialog will be shown.
*/
private static boolean notifyNoSpaceToUpdate(Activity activity, String root)
{
if (MapManager.nativeHasSpaceToUpdate(root))
return false;
notifyNoSpaceInternal(activity);
return true;
}
/**
* @return true if there is no space to download the given {@code root}, so the alert dialog will be shown.
*/
private static boolean notifyNoSpace(Activity activity, String root)
{
if (MapManager.nativeHasSpaceToDownloadCountry(root))
return false;
notifyNoSpaceInternal(activity);
return true;
}
/**
* @return true if there is no space to download {@code size} bytes, so the alert dialog will be shown.
*/
private static boolean notifyNoSpace(Activity activity, long size)
{
if (MapManager.nativeHasSpaceToDownloadAmount(size))
return false;
notifyNoSpaceInternal(activity);
return true;
}
private static boolean warnOn3gInternal(Activity activity, @NonNull final Runnable onAcceptListener)
{
if (MapManager.nativeIsDownloadOn3gEnabled() || !ConnectionState.INSTANCE.isMobileConnected())
{
onAcceptListener.run();
return false;
}
new MaterialAlertDialogBuilder(activity, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.download_over_mobile_header)
.setMessage(R.string.download_over_mobile_message)
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.ok,
(dlg, which) -> {
MapManager.nativeEnableDownloadOn3g();
onAcceptListener.run();
})
.show();
return true;
}
public static boolean warnOn3gUpdate(Activity activity, @Nullable String countryId,
@NonNull final Runnable onAcceptListener)
{
// noinspection SimplifiableIfStatement
if (TextUtils.isEmpty(countryId) || !notifyNoSpaceToUpdate(activity, countryId))
return warnOn3gInternal(activity, onAcceptListener);
return true;
}
public static boolean warnOn3g(Activity activity, @Nullable String countryId,
@NonNull final Runnable onAcceptListener)
{
// noinspection SimplifiableIfStatement
if (TextUtils.isEmpty(countryId) || !notifyNoSpace(activity, countryId))
return warnOn3gInternal(activity, onAcceptListener);
return true;
}
public static boolean warnOn3g(Activity activity, long size, @NonNull Runnable onAcceptListener)
{
return !notifyNoSpace(activity, size) && warnOn3gInternal(activity, onAcceptListener);
}
public static boolean warn3gAndDownload(Activity activity, final String countryId,
@Nullable final Runnable onAcceptListener)
{
return warnOn3g(activity, countryId, () -> {
if (onAcceptListener != null)
onAcceptListener.run();
startDownload(countryId);
});
}
public static boolean warn3gAndRetry(Activity activity, final String countryId,
@Nullable final Runnable onAcceptListener)
{
return warnOn3g(activity, countryId, () -> {
if (onAcceptListener != null)
onAcceptListener.run();
retryDownload(countryId);
});
}
/**
* Enqueues failed items under given {@code root} node in downloader.
*/
public static void retryDownload(@NonNull String countryId)
{
DownloaderService.startForegroundService();
MapManager.retryDownload(countryId);
}
/**
* Enqueues given {@code root} node with its children in downloader.
*/
public static void startUpdate(@NonNull String root)
{
DownloaderService.startForegroundService();
MapManager.startUpdate(root);
}
/**
* Enqueues the given list of nodes and its children in downloader.
*/
public static void startDownload(String... countries)
{
DownloaderService.startForegroundService();
for (var countryId : countries)
{
MapManager.startDownload(countryId);
}
}
/**
* Enqueues given {@code root} node and its children in downloader.
*/
public static void startDownload(@NonNull String countryId)
{
DownloaderService.startForegroundService();
MapManager.startDownload(countryId);
}
}

View File

@@ -15,7 +15,7 @@ import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.ConnectionState;
import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener;
import app.organicmaps.widget.WheelProgressView;
import com.google.android.material.button.MaterialButton;
@@ -52,7 +52,7 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
continue;
if (item.newStatus == CountryItem.STATUS_FAILED)
MapManager.showError(mActivity, item, null);
MapManagerHelper.showError(mActivity, item, null);
if (mCurrentCountry.id.equals(item.countryId))
{
@@ -163,7 +163,7 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
if (TextUtils.equals(mCurrentCountry.id, country)
&& MapManager.nativeHasSpaceToDownloadCountry(country))
{
MapManager.startDownload(mCurrentCountry.id);
MapManagerHelper.startDownload(mCurrentCountry.id);
}
}
}
@@ -199,18 +199,18 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
setAutodownloadLocked(true);
});
mButton.setOnClickListener(
v -> MapManager.warnOn3g(mActivity, mCurrentCountry == null ? null : mCurrentCountry.id, () -> {
v -> MapManagerHelper.warnOn3g(mActivity, mCurrentCountry == null ? null : mCurrentCountry.id, () -> {
if (mCurrentCountry == null)
return;
boolean retry = (mCurrentCountry.status == CountryItem.STATUS_FAILED);
if (retry)
{
MapManager.retryDownload(mCurrentCountry.id);
MapManagerHelper.retryDownload(mCurrentCountry.id);
}
else
{
MapManager.startDownload(mCurrentCountry.id);
MapManagerHelper.startDownload(mCurrentCountry.id);
mActivity.requestPostNotificationsPermission();
}
}));

View File

@@ -14,9 +14,9 @@ import app.organicmaps.R;
import app.organicmaps.base.BaseMwmFragment;
import app.organicmaps.sdk.editor.OpeningHours;
import app.organicmaps.sdk.util.Constants;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.Graphics;
import app.organicmaps.util.InputUtils;
import app.organicmaps.util.UiUtils;
import com.google.android.material.imageview.ShapeableImageView;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textview.MaterialTextView;

View File

@@ -29,10 +29,10 @@ import app.organicmaps.sdk.editor.data.LocalizedName;
import app.organicmaps.sdk.editor.data.LocalizedStreet;
import app.organicmaps.sdk.editor.data.Timetable;
import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.sdk.util.Utils;
import app.organicmaps.util.Graphics;
import app.organicmaps.util.InputUtils;
import app.organicmaps.util.UiUtils;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.imageview.ShapeableImageView;
import com.google.android.material.textfield.TextInputEditText;
@@ -236,6 +236,11 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
return true;
}
boolean saveEdits()
{
return setEdits() && beforeSavingValidation();
}
@NonNull
protected String getDescription()
{
@@ -282,6 +287,19 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
return validateNames();
}
private boolean beforeSavingValidation()
{
// Validation to make sure address features have a house number
if (!Editor.nativeCheckHouseNumberWhenIsAddress())
{
mHouseNumber.requestFocus();
UiUtils.setInputError(mInputHouseNumber, R.string.error_enter_correct_house_number);
InputUtils.showKeyboard(mHouseNumber);
return false;
}
return true;
}
private boolean validateNames()
{
for (int pos = 0; pos < mNamesAdapter.getItemCount(); pos++)

View File

@@ -1,6 +1,5 @@
package app.organicmaps.editor;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
@@ -25,7 +24,7 @@ import app.organicmaps.sdk.editor.data.Language;
import app.organicmaps.sdk.editor.data.LocalizedName;
import app.organicmaps.sdk.editor.data.LocalizedStreet;
import app.organicmaps.sdk.editor.data.NamesDataSource;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener;
import app.organicmaps.widget.SearchToolbarController;
@@ -276,6 +275,11 @@ public class EditorHostFragment
return ((EditorFragment) getChildFragmentManager().findFragmentByTag(EditorFragment.class.getName())).setEdits();
}
private boolean saveEdits()
{
return ((EditorFragment) getChildFragmentManager().findFragmentByTag(EditorFragment.class.getName())).saveEdits();
}
@Override
public void onClick(View v)
{
@@ -310,7 +314,7 @@ public class EditorHostFragment
case LANGUAGE -> editMapObject();
case MAP_OBJECT ->
{
if (!setEdits())
if (!saveEdits())
return;
// Save object edits

View File

@@ -10,7 +10,7 @@ import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R;
import app.organicmaps.sdk.editor.data.FeatureCategory;
import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textview.MaterialTextView;

View File

@@ -79,8 +79,8 @@ public class HoursMinutesPickerFragment extends BaseMwmDialogFragment
mTabs.getTabAt(mSelectedTab).select();
@StyleRes
final int theme = ThemeUtils.isNightTheme(requireContext()) ? R.style.MwmMain_DialogFragment_TimePicker_Night
: R.style.MwmMain_DialogFragment_TimePicker;
final int theme = ThemeUtils.isNightTheme() ? R.style.MwmMain_DialogFragment_TimePicker_Night
: R.style.MwmMain_DialogFragment_TimePicker;
final AlertDialog dialog = new MaterialAlertDialogBuilder(requireActivity(), theme)
.setView(root)
.setNegativeButton(R.string.cancel, null)
@@ -141,8 +141,8 @@ public class HoursMinutesPickerFragment extends BaseMwmDialogFragment
MaterialTextView tabView = (MaterialTextView) inflater.inflate(R.layout.tab_timepicker, mTabs, false);
tabView.setText(getResources().getString(R.string.editor_time_from));
final ColorStateList textColor = AppCompatResources.getColorStateList(
requireContext(), ThemeUtils.isNightTheme(requireContext()) ? R.color.accent_color_selector_night
: R.color.accent_color_selector);
requireContext(),
ThemeUtils.isNightTheme() ? R.color.accent_color_selector_night : R.color.accent_color_selector);
tabView.setTextColor(textColor);
mTabs.addTab(mTabs.newTab().setCustomView(tabView), true);
tabView = (MaterialTextView) inflater.inflate(R.layout.tab_timepicker, mTabs, false);

View File

@@ -10,7 +10,7 @@ import app.organicmaps.sdk.editor.Editor;
import app.organicmaps.sdk.editor.data.Language;
import app.organicmaps.sdk.editor.data.LocalizedName;
import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;

View File

@@ -15,10 +15,11 @@ import app.organicmaps.R;
import app.organicmaps.base.BaseMwmToolbarFragment;
import app.organicmaps.sdk.editor.OsmOAuth;
import app.organicmaps.sdk.util.Constants;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.sdk.util.DateUtils;
import app.organicmaps.sdk.util.concurrency.ThreadPool;
import app.organicmaps.sdk.util.concurrency.UiThread;
import app.organicmaps.util.InputUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils.ScrollableContentInsetsListener;
import com.google.android.material.button.MaterialButton;

View File

@@ -9,7 +9,7 @@ import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R;
import app.organicmaps.sdk.editor.Editor;
import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import com.google.android.material.imageview.ShapeableImageView;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;

View File

@@ -11,14 +11,17 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.fragment.app.FragmentManager;
import app.organicmaps.R;
import app.organicmaps.base.BaseMwmToolbarFragment;
import app.organicmaps.sdk.editor.OsmOAuth;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.sdk.util.NetworkPolicy;
import app.organicmaps.sdk.util.concurrency.ThreadPool;
import app.organicmaps.sdk.util.concurrency.UiThread;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils;
import app.organicmaps.widget.StackedButtonDialogFragment;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.imageview.ShapeableImageView;
import com.google.android.material.textview.MaterialTextView;
@@ -26,6 +29,24 @@ import java.text.NumberFormat;
public class ProfileFragment extends BaseMwmToolbarFragment
{
@NonNull
private static final NetworkPolicy.DialogPresenter mDialogPresenter = new NetworkPolicy.DialogPresenter() {
@Override
public void showDialogIfNeeded(@NonNull FragmentManager fragmentManager,
@NonNull NetworkPolicy.NetworkPolicyListener listener, @NonNull NetworkPolicy policy,
boolean isToday)
{
StackedButtonDialogFragment.showDialogIfNeeded(fragmentManager, listener, policy, isToday);
}
@Override
public void showDialog(@NonNull FragmentManager fragmentManager,
@NonNull NetworkPolicy.NetworkPolicyListener listener)
{
StackedButtonDialogFragment.showDialog(fragmentManager, listener);
}
};
private View mUserInfoBlock;
private MaterialTextView mEditsSent;
private MaterialTextView mProfileName;
@@ -84,7 +105,7 @@ public class ProfileFragment extends BaseMwmToolbarFragment
UiUtils.show(mProfileInfoLoading);
UiUtils.hide(mUserInfoBlock);
}
final int profileEditCount = OsmOAuth.getOsmChangesetsCount(getParentFragmentManager());
final int profileEditCount = OsmOAuth.getOsmChangesetsCount(mDialogPresenter, getParentFragmentManager());
final String profileUsername = OsmOAuth.getUsername();
final Bitmap profilePicture = OsmOAuth.getProfilePicture();

View File

@@ -11,7 +11,7 @@ import androidx.core.view.ViewCompat;
import app.organicmaps.R;
import app.organicmaps.base.BaseMwmToolbarFragment;
import app.organicmaps.sdk.editor.Editor;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.WindowInsetUtils.ScrollableContentInsetsListener;
import com.google.android.material.textfield.TextInputEditText;

View File

@@ -18,7 +18,8 @@ import app.organicmaps.sdk.editor.OpeningHours;
import app.organicmaps.sdk.editor.data.HoursMinutes;
import app.organicmaps.sdk.editor.data.Timespan;
import app.organicmaps.sdk.editor.data.Timetable;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.sdk.util.Utils;
import app.organicmaps.util.UiUtils;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.checkbox.MaterialCheckBox;
import com.google.android.material.textview.MaterialTextView;
@@ -224,7 +225,7 @@ class SimpleTimetableAdapter extends RecyclerView.Adapter<SimpleTimetableAdapter
LayoutInflater.from(itemView.getContext()).inflate(R.layout.item_timetable_closed_hours, closedHost, false);
closedHost.addView(
span, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
UiUtils.dimen(closedHost.getContext(), R.dimen.editor_height_closed)));
Utils.dimen(closedHost.getContext(), R.dimen.editor_height_closed)));
closedHours[i] = span;
final int finalI = i;
span.findViewById(R.id.iv__remove_closed)

View File

@@ -10,7 +10,7 @@ import app.organicmaps.MwmApplication;
import app.organicmaps.R;
import app.organicmaps.dialog.EditTextDialogFragment;
import app.organicmaps.sdk.editor.data.LocalizedStreet;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import com.google.android.material.radiobutton.MaterialRadioButton;
import com.google.android.material.textview.MaterialTextView;

View File

@@ -15,7 +15,7 @@ import androidx.fragment.app.FragmentActivity;
import app.organicmaps.R;
import app.organicmaps.base.BaseMwmFragment;
import app.organicmaps.sdk.editor.OpeningHours;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.textview.MaterialTextView;

View File

@@ -24,6 +24,8 @@ import app.organicmaps.util.Graphics;
import app.organicmaps.util.SharingUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils.ScrollableContentInsetsListener;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.textview.MaterialTextView;
public class HelpFragment extends BaseMwmFragment implements View.OnClickListener
{
@@ -41,15 +43,15 @@ public class HelpFragment extends BaseMwmFragment implements View.OnClickListene
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
{
mDonateUrl = Config.getDonateUrl(requireContext());
mDonateUrl = Utils.getDonateUrl(requireContext());
View root = inflater.inflate(R.layout.about, container, false);
((TextView) root.findViewById(R.id.version)).setText(BuildConfig.VERSION_NAME);
((MaterialTextView) root.findViewById(R.id.version)).setText(BuildConfig.VERSION_NAME);
final boolean isLandscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
final String dataVersion = DateUtils.getShortDateFormatter().format(Framework.getDataVersion());
final TextView osmPresentationView = root.findViewById(R.id.osm_presentation);
final MaterialTextView osmPresentationView = root.findViewById(R.id.osm_presentation);
if (osmPresentationView != null)
{
osmPresentationView.setText(getString(R.string.osm_presentation, dataVersion));
@@ -71,13 +73,13 @@ public class HelpFragment extends BaseMwmFragment implements View.OnClickListene
setupItem(R.id.report, isLandscape, root);
setupItem(R.id.copyright, false, root);
final TextView supportUsView = root.findViewById(R.id.support_us);
final MaterialTextView supportUsView = root.findViewById(R.id.support_us);
if (BuildConfig.FLAVOR.equals("google") && !TextUtils.isEmpty(mDonateUrl))
supportUsView.setVisibility(View.GONE);
else
setupItem(R.id.support_us, true, root);
final TextView donateView = root.findViewById(R.id.donate);
final MaterialButton donateView = root.findViewById(R.id.donate);
if (TextUtils.isEmpty(mDonateUrl))
donateView.setVisibility(View.GONE);
else

View File

@@ -8,7 +8,7 @@ import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R;
import app.organicmaps.sdk.util.SharedPropertiesUtils;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import java.util.List;
public class LayersAdapter extends RecyclerView.Adapter<LayerHolder>

View File

@@ -29,7 +29,7 @@ public class LayersButton extends FloatingActionButton
{
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (mAreLayersActive)
mergeDrawableStates(drawableState, new int[] {R.attr.state_layers_enabled});
mergeDrawableStates(drawableState, new int[] {R.attr.layers_enabled});
return drawableState;
}

View File

@@ -36,8 +36,9 @@ import app.organicmaps.sdk.maplayer.subway.SubwayManager;
import app.organicmaps.sdk.maplayer.traffic.TrafficManager;
import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils;
import app.organicmaps.widget.menu.MyPositionButton;
import app.organicmaps.widget.placepage.PlacePageViewModel;
@@ -214,7 +215,7 @@ public class MapButtonsController extends Fragment
// helpButton.setImageResource(R.drawable.ic_launcher);
// }
// // Keep this button colorful in normal theme.
// if (!ThemeUtils.isNightTheme(requireContext()))
// if (!ThemeUtils.isNightTheme())
// helpButton.getDrawable().setTintList(null);
}
else if (leftButtonView != null)

View File

@@ -16,9 +16,9 @@ import androidx.annotation.StringRes;
import app.organicmaps.R;
import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.search.SearchEngine;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.sdk.util.concurrency.UiThread;
import app.organicmaps.util.Graphics;
import app.organicmaps.util.UiUtils;
public class SearchWheel implements View.OnClickListener
{

View File

@@ -10,8 +10,8 @@ import android.widget.RelativeLayout;
import androidx.annotation.NonNull;
import androidx.core.content.res.ResourcesCompat;
import app.organicmaps.R;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.util.UiUtils;
import java.util.Objects;
@SuppressWarnings("unused")
@@ -43,22 +43,20 @@ public class TrafficButton
void turnOff()
{
stopWaitingAnimation();
mButton.setImageResource(ThemeUtils.isNightTheme(mButton.getContext()) ? R.drawable.ic_traffic_on_night
: R.drawable.ic_traffic_on);
mButton.setImageResource(ThemeUtils.isNightTheme() ? R.drawable.ic_traffic_on_night : R.drawable.ic_traffic_on);
}
void turnOn()
{
stopWaitingAnimation();
mButton.setImageResource(ThemeUtils.isNightTheme(mButton.getContext()) ? R.drawable.ic_traffic_on_night
: R.drawable.ic_traffic_on);
mButton.setImageResource(ThemeUtils.isNightTheme() ? R.drawable.ic_traffic_on_night : R.drawable.ic_traffic_on);
}
void markAsOutdated()
{
stopWaitingAnimation();
mButton.setImageResource(ThemeUtils.isNightTheme(mButton.getContext()) ? R.drawable.ic_traffic_outdated_night
: R.drawable.ic_traffic_outdated);
mButton.setImageResource(ThemeUtils.isNightTheme() ? R.drawable.ic_traffic_outdated_night
: R.drawable.ic_traffic_outdated);
}
void startWaitingAnimation()

View File

@@ -12,14 +12,14 @@ import android.widget.ExpandableListView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import app.organicmaps.R;
import app.organicmaps.adapter.DisabledChildSimpleExpandableListAdapter;
import app.organicmaps.base.BaseMwmDialogFragment;
import app.organicmaps.sdk.downloader.CountryItem;
import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.sdk.util.Utils;
import app.organicmaps.util.UiUtils;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.textview.MaterialTextView;
import java.util.ArrayList;
@@ -128,7 +128,7 @@ abstract class BaseRoutingErrorDialogFragment extends BaseMwmDialogFragment
UiUtils.waitLayout(listView, () -> {
final int width = listView.getWidth();
final int indicatorWidth = UiUtils.dimen(requireContext(), R.dimen.margin_quadruple);
final int indicatorWidth = Utils.dimen(requireContext(), R.dimen.margin_quadruple);
listView.setIndicatorBounds(width - indicatorWidth, width);
listView.setIndicatorBoundsRelative(width - indicatorWidth, width);
});

View File

@@ -16,7 +16,7 @@ import app.organicmaps.sdk.bookmarks.data.MapObject;
import app.organicmaps.sdk.routing.RouteMarkData;
import app.organicmaps.sdk.routing.RouteMarkType;
import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import com.google.android.material.imageview.ShapeableImageView;
import com.google.android.material.textview.MaterialTextView;
import java.util.ArrayList;
@@ -94,7 +94,7 @@ public class ManageRouteAdapter extends RecyclerView.Adapter<ManageRouteAdapter.
if (mRoutePoints.get(position).mIsMyPosition)
{
// My position point.
title = mContext.getString(R.string.core_my_position);
title = mContext.getString(app.organicmaps.sdk.R.string.core_my_position);
if (mRoutePoints.get(position).mPointType != RouteMarkType.Start)
subtitle = mRoutePoints.get(position).mTitle;

View File

@@ -23,7 +23,7 @@ import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.bookmarks.data.MapObject;
import app.organicmaps.sdk.routing.RouteMarkData;
import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;

View File

@@ -1,5 +1,7 @@
package app.organicmaps.routing;
import static app.organicmaps.sdk.util.Utils.dimen;
import android.location.Location;
import android.text.TextUtils;
import android.view.View;
@@ -21,7 +23,7 @@ import app.organicmaps.sdk.routing.CarDirection;
import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.routing.RoutingInfo;
import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils;
import app.organicmaps.widget.LanesView;
@@ -166,7 +168,7 @@ public class NavigationController implements TrafficManager.TrafficCallback, Nav
UiUtils.visibleIf(hasStreet, mStreetFrame);
if (!TextUtils.isEmpty(info.nextStreet))
mNextStreet.setText(info.nextStreet);
int margin = UiUtils.dimen(mFrame.getContext(), R.dimen.nav_frame_padding);
int margin = dimen(mFrame.getContext(), R.dimen.nav_frame_padding);
if (hasStreet)
margin += mStreetFrame.getHeight();
mMapButtonsViewModel.setTopButtonsMarginTop(margin);

View File

@@ -1,5 +1,7 @@
package app.organicmaps.routing;
import static app.organicmaps.sdk.util.Utils.dimen;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
@@ -37,12 +39,14 @@ import app.organicmaps.sdk.routing.RoutingInfo;
import app.organicmaps.sdk.routing.TransitRouteInfo;
import app.organicmaps.sdk.routing.TransitStepInfo;
import app.organicmaps.sdk.util.Distance;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.Graphics;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.widget.recycler.DotDividerItemDecoration;
import app.organicmaps.widget.recycler.MultilineLayoutManager;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.imageview.ShapeableImageView;
import com.google.android.material.textview.MaterialTextView;
import java.util.LinkedList;
@@ -151,10 +155,10 @@ final class RoutingBottomMenuController implements View.OnClickListener
mTransitViewDecorator =
new DotDividerItemDecoration(dividerDrawable, res.getDimensionPixelSize(R.dimen.margin_base),
res.getDimensionPixelSize(R.dimen.margin_half));
Button manageRouteButton = altitudeChartFrame.findViewById(R.id.btn__manage_route);
MaterialButton manageRouteButton = altitudeChartFrame.findViewById(R.id.btn__manage_route);
manageRouteButton.setOnClickListener(this);
Button saveButton = altitudeChartFrame.findViewById(R.id.btn__save);
MaterialButton saveButton = altitudeChartFrame.findViewById(R.id.btn__save);
saveButton.setOnClickListener(this);
}
@@ -166,7 +170,7 @@ final class RoutingBottomMenuController implements View.OnClickListener
showRouteAltitudeChart();
showRoutingDetails();
UiUtils.show(mAltitudeChartFrame);
Button saveButton = mAltitudeChartFrame.findViewById(R.id.btn__save);
MaterialButton saveButton = mAltitudeChartFrame.findViewById(R.id.btn__save);
saveButton.setText(R.string.save);
saveButton.setEnabled(true);
}
@@ -345,16 +349,17 @@ final class RoutingBottomMenuController implements View.OnClickListener
UiUtils.hide(mTimeVehicle);
int chartWidth = UiUtils.dimen(mContext, R.dimen.altitude_chart_image_width);
int chartHeight = UiUtils.dimen(mContext, R.dimen.altitude_chart_image_height);
int chartWidth = dimen(mContext, R.dimen.altitude_chart_image_width);
int chartHeight = dimen(mContext, R.dimen.altitude_chart_image_height);
Framework.RouteAltitudeLimits limits = new Framework.RouteAltitudeLimits();
Bitmap bm = Framework.generateRouteAltitudeChart(chartWidth, chartHeight, limits);
if (bm != null)
{
mAltitudeChart.setImageBitmap(bm);
UiUtils.show(mAltitudeChart);
final String unit = limits.isMetricUnits ? mAltitudeDifference.getResources().getString(R.string.m)
: mAltitudeDifference.getResources().getString(R.string.ft);
final String unit = limits.isMetricUnits
? mAltitudeDifference.getResources().getString(app.organicmaps.sdk.R.string.m)
: mAltitudeDifference.getResources().getString(app.organicmaps.sdk.R.string.ft);
mAltitudeDifference.setText("" + limits.totalAscentString + " " + unit + "" + limits.totalDescentString + " "
+ unit);
UiUtils.show(mAltitudeDifference);

View File

@@ -14,9 +14,10 @@ import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentFactory;
import androidx.fragment.app.FragmentManager;
import app.organicmaps.R;
import app.organicmaps.downloader.MapManagerHelper;
import app.organicmaps.sdk.downloader.CountryItem;
import app.organicmaps.sdk.downloader.MapManager;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import com.google.android.material.textview.MaterialTextView;
public class RoutingErrorDialogFragment extends BaseRoutingErrorDialogFragment
@@ -108,7 +109,7 @@ public class RoutingErrorDialogFragment extends BaseRoutingErrorDialogFragment
}
}
MapManager.warnOn3g(requireActivity(), size, () -> {
MapManagerHelper.warnOn3g(requireActivity(), size, () -> {
final FragmentManager manager = requireActivity().getSupportFragmentManager();
RoutingMapsDownloadFragment downloader =
RoutingMapsDownloadFragment.create(manager.getFragmentFactory(), getAppContextOrThrow(), mMapsArray);

View File

@@ -9,10 +9,11 @@ import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentFactory;
import app.organicmaps.R;
import app.organicmaps.downloader.MapManagerHelper;
import app.organicmaps.sdk.downloader.CountryItem;
import app.organicmaps.sdk.downloader.MapManager;
import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.widget.WheelProgressView;
import java.util.HashSet;
import java.util.List;
@@ -40,7 +41,7 @@ public class RoutingMapsDownloadFragment extends BaseRoutingErrorDialogFragment
mMapsArray[i] = item.id;
}
MapManager.startDownload(mMapsArray);
MapManagerHelper.startDownload(mMapsArray);
}
private View setupFrame(View frame)

View File

@@ -21,8 +21,8 @@ import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.routing.RoutingInfo;
import app.organicmaps.sdk.routing.RoutingOptions;
import app.organicmaps.sdk.routing.TransitRouteInfo;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.settings.DrivingOptionsActivity;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener;
import app.organicmaps.widget.RoutingToolbarButton;
import app.organicmaps.widget.ToolbarController;
@@ -141,7 +141,8 @@ public class RoutingPlanController extends ToolbarController
setupRouterButton(R.id.vehicle, R.drawable.ic_car, this::onVehicleModeSelected);
setupRouterButton(R.id.pedestrian, R.drawable.ic_pedestrian, this::onPedestrianModeSelected);
// setupRouterButton(R.id.taxi, R.drawable.ic_taxi, this::onTaxiModeSelected);
setupRouterButton(R.id.transit, R.drawable.ic_route_planning_metro_40px, this::onTransitModeSelected);
setupRouterButton(R.id.transit, app.organicmaps.sdk.R.drawable.ic_route_planning_metro_40px,
this::onTransitModeSelected);
setupRouterButton(R.id.bicycle, R.drawable.ic_bike, this::onBicycleModeSelected);
setupRouterButton(R.id.ruler, app.organicmaps.sdk.R.drawable.ic_ruler_route, this::onRulerModeSelected);
}

View File

@@ -9,7 +9,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import app.organicmaps.MwmActivity;
import app.organicmaps.R;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
public class RoutingPlanInplaceController extends RoutingPlanController
{

View File

@@ -90,7 +90,7 @@ public class TransitStepView extends View implements MultilineLayoutManager.Sque
{
mDrawable = null;
mText = info.getDistance() + " " + info.getDistanceUnits();
mTextPaint.setColor(ThemeUtils.isDefaultTheme(getContext()) ? Color.BLACK : Color.WHITE);
mTextPaint.setColor(ThemeUtils.isDefaultTheme() ? Color.BLACK : Color.WHITE);
}
else
{

View File

@@ -1,55 +0,0 @@
package app.organicmaps.sdk.bookmarks.data;
import androidx.annotation.Keep;
import app.organicmaps.sdk.util.Distance;
// Called from JNI.
@Keep
@SuppressWarnings("unused")
public class Track
{
private final long mTrackId;
private final long mCategoryId;
private final String mName;
private final Distance mLength;
private final int mColor;
Track(long trackId, long categoryId, String name, Distance length, int color)
{
mTrackId = trackId;
mCategoryId = categoryId;
mName = name;
mLength = length;
mColor = color;
}
public String getName()
{
return mName;
}
public Distance getLength()
{
return mLength;
}
public int getColor()
{
return mColor;
}
public long getTrackId()
{
return mTrackId;
}
public long getCategoryId()
{
return mCategoryId;
}
public String getTrackDescription()
{
return BookmarkManager.INSTANCE.getTrackDescription(mTrackId);
}
}

View File

@@ -1,26 +0,0 @@
package app.organicmaps.sdk.util;
import android.content.Context;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import java.text.DateFormat;
import java.util.Locale;
public final class DateUtils
{
private DateUtils() {}
@NonNull
public static DateFormat getShortDateFormatter()
{
return DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());
}
// Called from JNI.
@Keep
@SuppressWarnings("unused")
public static boolean is24HourFormat(@NonNull Context context)
{
return android.text.format.DateFormat.is24HourFormat(context);
}
}

View File

@@ -89,7 +89,7 @@ class CategoriesAdapter extends RecyclerView.Adapter<CategoriesAdapter.ViewHolde
@DrawableRes
private static int getDrawableResIdByKey(@NonNull Context context, @NonNull String packageName, @NonNull String key)
{
final boolean isNightTheme = ThemeUtils.isNightTheme(context);
final boolean isNightTheme = ThemeUtils.isNightTheme();
String iconId = "ic_" + key;
if (isNightTheme)
iconId = iconId + "_night";

View File

@@ -5,7 +5,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import app.organicmaps.sdk.search.SearchEngine;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener;
import app.organicmaps.widget.SearchToolbarController;

View File

@@ -37,7 +37,7 @@ public class SearchActivity extends BaseMwmFragmentActivity
@StyleRes
public int getThemeResourceId(@NonNull String theme)
{
return ThemeUtils.getCardBgThemeResourceId(getApplicationContext(), theme);
return ThemeUtils.getCardBgThemeResourceId(theme);
}
@Override

View File

@@ -13,9 +13,9 @@ import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R;
import app.organicmaps.sdk.search.SearchResult;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.Graphics;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.util.UiUtils;
class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.SearchDataViewHolder>
{

View File

@@ -39,7 +39,7 @@ import app.organicmaps.sdk.search.SearchResult;
import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.Language;
import app.organicmaps.sdk.util.SharedPropertiesUtils;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils;
import app.organicmaps.widget.PlaceholderView;

View File

@@ -11,7 +11,7 @@ import app.organicmaps.MwmApplication;
import app.organicmaps.R;
import app.organicmaps.base.BaseMwmRecyclerFragment;
import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.widget.PlaceholderView;
import app.organicmaps.widget.SearchToolbarController;

View File

@@ -47,7 +47,7 @@ abstract class BaseXmlSettingsFragment extends PreferenceFragmentCompat
super.onViewCreated(view, savedInstanceState);
int color;
if (ThemeUtils.isDefaultTheme(requireContext()))
if (ThemeUtils.isDefaultTheme())
color = ContextCompat.getColor(requireContext(), R.color.bg_cards);
else
color = ContextCompat.getColor(requireContext(), R.color.bg_cards_night);

View File

@@ -3,13 +3,11 @@ package app.organicmaps.settings;
import static app.organicmaps.leftbutton.LeftButtonsHolder.DISABLE_BUTTON_CODE;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
@@ -26,7 +24,6 @@ import app.organicmaps.sdk.downloader.MapManager;
import app.organicmaps.sdk.editor.OsmOAuth;
import app.organicmaps.sdk.editor.data.Language;
import app.organicmaps.sdk.location.LocationHelper;
import app.organicmaps.sdk.location.LocationProviderFactory;
import app.organicmaps.sdk.routing.RoutingOptions;
import app.organicmaps.sdk.search.SearchRecents;
import app.organicmaps.sdk.settings.MapLanguageCode;
@@ -309,7 +306,9 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment implements La
if (pref == null)
return;
if (!LocationProviderFactory.isGoogleLocationAvailable(requireActivity().getApplicationContext()))
if (!MwmApplication.from(requireContext())
.getLocationProviderFactory()
.isGoogleLocationAvailable(requireActivity().getApplicationContext()))
removePreference(getString(R.string.pref_privacy), pref);
else
{
@@ -441,19 +440,19 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment implements La
private void initMapStylePrefsCallbacks()
{
final ListPreference pref = getPreference(getString(R.string.pref_map_style));
String curTheme = Config.getUiThemeSettings(requireContext());
pref.setValue(curTheme);
pref.setEntryValues(new CharSequence[] {Config.UiTheme.DEFAULT, Config.UiTheme.NIGHT, Config.UiTheme.AUTO,
Config.UiTheme.NAV_AUTO});
pref.setValue(Config.UiTheme.getUiThemeSettings());
pref.setSummary(pref.getEntry());
pref.setOnPreferenceChangeListener((preference, newValue) -> {
final String themeName = (String) newValue;
if (!Config.setUiThemeSettings(requireContext(), themeName))
if (!Config.UiTheme.setUiThemeSettings(themeName))
return true;
ThemeSwitcher.INSTANCE.restart(false);
ThemeMode mode = ThemeMode.getInstance(requireContext().getApplicationContext(), themeName);
CharSequence summary = pref.getEntries()[mode.ordinal()];
final ThemeMode mode = ThemeMode.getInstance(themeName);
final CharSequence summary = pref.getEntries()[mode.ordinal()];
pref.setSummary(summary);
return true;
});
@@ -552,24 +551,25 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment implements La
enum ThemeMode
{
DEFAULT(R.string.theme_default),
NIGHT(R.string.theme_night),
AUTO(R.string.theme_auto),
NAV_AUTO(R.string.theme_nav_auto);
DEFAULT(Config.UiTheme.DEFAULT),
NIGHT(Config.UiTheme.NIGHT),
AUTO(Config.UiTheme.AUTO),
NAV_AUTO(Config.UiTheme.NAV_AUTO);
private final int mModeStringId;
@NonNull
private final String mMode;
ThemeMode(@StringRes int modeStringId)
ThemeMode(@NonNull String mode)
{
mModeStringId = modeStringId;
mMode = mode;
}
@NonNull
public static ThemeMode getInstance(@NonNull Context context, @NonNull String src)
public static ThemeMode getInstance(@NonNull String src)
{
for (ThemeMode each : values())
{
if (context.getResources().getString(each.mModeStringId).equals(src))
if (each.mMode.equals(src))
return each;
}
return AUTO;

View File

@@ -13,7 +13,7 @@ import android.widget.CheckedTextView;
import app.organicmaps.R;
import app.organicmaps.sdk.settings.StorageItem;
import app.organicmaps.sdk.settings.StoragePathManager;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.sdk.util.Utils;
import app.organicmaps.util.ThemeUtils;
class StoragePathAdapter extends BaseAdapter
@@ -65,14 +65,14 @@ class StoragePathAdapter extends BaseAdapter
SpannableStringBuilder sb = new SpannableStringBuilder(item.mLabel + "\n" + size);
sb.setSpan(new ForegroundColorSpan(ThemeUtils.getColor(mActivity, android.R.attr.textColorSecondary)),
sb.length() - size.length(), sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
sb.setSpan(new AbsoluteSizeSpan(UiUtils.dimen(mActivity, R.dimen.text_size_body_3)), sb.length() - size.length(),
sb.setSpan(new AbsoluteSizeSpan(Utils.dimen(mActivity, R.dimen.text_size_body_3)), sb.length() - size.length(),
sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
final String path = item.mPath + (item.mIsReadonly ? " (read-only)" : "");
sb.append("\n").append(path);
sb.setSpan(new ForegroundColorSpan(ThemeUtils.getColor(mActivity, android.R.attr.textColorSecondary)),
sb.length() - path.length(), sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
sb.setSpan(new AbsoluteSizeSpan(UiUtils.dimen(mActivity, R.dimen.text_size_body_4)), sb.length() - path.length(),
sb.setSpan(new AbsoluteSizeSpan(Utils.dimen(mActivity, R.dimen.text_size_body_4)), sb.length() - path.length(),
sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
checkedView.setText(sb);

View File

@@ -26,7 +26,7 @@ import app.organicmaps.sdk.settings.SpeedCameraMode;
import app.organicmaps.sdk.sound.LanguageData;
import app.organicmaps.sdk.sound.TtsPlayer;
import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils;
import java.util.Arrays;
import java.util.Collections;

View File

@@ -22,7 +22,6 @@ import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.bookmarks.data.BookmarkInfo;
import app.organicmaps.sdk.bookmarks.data.MapObject;
import app.organicmaps.sdk.util.StorageUtils;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.sdk.util.log.Logger;
import java.io.IOException;
import java.util.ArrayList;

View File

@@ -8,7 +8,6 @@ import android.os.Build;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatDelegate;
import app.organicmaps.MwmApplication;
import app.organicmaps.R;
import app.organicmaps.downloader.DownloaderStatusIcon;
import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.MapStyle;
@@ -28,17 +27,23 @@ public enum ThemeSwitcher
@Override
public void run()
{
boolean isNavAuto = RoutingController.get().isNavigating() && ThemeUtils.isNavAutoTheme(mContext);
boolean navAuto = RoutingController.get().isNavigating() && ThemeUtils.isNavAutoTheme();
// Cancel old checker
UiThread.cancelDelayedTasks(mAutoThemeChecker);
if (isNavAuto || ThemeUtils.isAutoTheme(mContext))
String theme;
if (navAuto || ThemeUtils.isAutoTheme())
{
UiThread.runLater(mAutoThemeChecker, CHECK_INTERVAL_MS);
setThemeAndMapStyle(calcAutoTheme());
theme = calcAutoTheme();
}
else // Only reached when an auto mode should be light
setThemeAndMapStyle(mContext.getResources().getString(R.string.theme_default));
else
{
// Happens when exiting the Navigation mode. Should restore the light.
theme = Config.UiTheme.DEFAULT;
}
setThemeAndMapStyle(theme);
}
};
@@ -64,8 +69,8 @@ public enum ThemeSwitcher
public void restart(boolean isRendererActive)
{
mRendererActive = isRendererActive;
String theme = Config.getUiThemeSettings(mContext);
if (ThemeUtils.isAutoTheme(mContext, theme) || ThemeUtils.isNavAutoTheme(mContext, theme))
String theme = Config.UiTheme.getUiThemeSettings();
if (ThemeUtils.isAutoTheme() || ThemeUtils.isNavAutoTheme())
{
mAutoThemeChecker.run();
return;
@@ -78,10 +83,10 @@ public enum ThemeSwitcher
private void setThemeAndMapStyle(@NonNull String theme)
{
UiModeManager uiModeManager = (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE);
String oldTheme = Config.getCurrentUiTheme(mContext);
String oldTheme = Config.UiTheme.getCurrent();
MapStyle style;
if (ThemeUtils.isNightTheme(mContext, theme))
if (ThemeUtils.isNightTheme())
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
uiModeManager.setApplicationNightMode(UiModeManager.MODE_NIGHT_YES);
@@ -112,7 +117,7 @@ public enum ThemeSwitcher
if (!theme.equals(oldTheme))
{
Config.setCurrentUiTheme(mContext, theme);
Config.UiTheme.setCurrent(theme);
DownloaderStatusIcon.clearCache();
final Activity a = MwmApplication.from(mContext).getTopActivity();
@@ -152,9 +157,7 @@ public enum ThemeSwitcher
@NonNull
private String calcAutoTheme()
{
String defaultTheme = mContext.getResources().getString(R.string.theme_default);
String nightTheme = mContext.getResources().getString(R.string.theme_night);
Location last = MwmApplication.from(mContext).getLocationHelper().getSavedLocation();
final Location last = MwmApplication.from(mContext).getLocationHelper().getSavedLocation();
boolean day;
if (last != null)
@@ -168,6 +171,6 @@ public enum ThemeSwitcher
day = (currentHour < 18 && currentHour > 6);
}
return (day ? defaultTheme : nightTheme);
return (day ? Config.UiTheme.DEFAULT : Config.UiTheme.NIGHT);
}
}

View File

@@ -16,7 +16,8 @@ public final class ThemeUtils
private ThemeUtils() {}
public static @ColorInt int getColor(@NonNull Context context, @AttrRes int attr)
@ColorInt
public static int getColor(@NonNull Context context, @AttrRes int attr)
{
if (!context.getTheme().resolveAttribute(attr, VALUE_BUFFER, true))
throw new IllegalArgumentException("Failed to resolve color theme attribute");
@@ -44,76 +45,45 @@ public final class ThemeUtils
return VALUE_BUFFER.resourceId;
}
public static boolean isDefaultTheme(@NonNull Context context)
public static boolean isDefaultTheme()
{
return isDefaultTheme(context, Config.getCurrentUiTheme(context));
return Config.UiTheme.isDefault(Config.UiTheme.getCurrent());
}
public static boolean isDefaultTheme(@NonNull Context context, String theme)
public static boolean isNightTheme()
{
String defaultTheme = context.getString(R.string.theme_default);
return defaultTheme.equals(theme);
return Config.UiTheme.isNight(Config.UiTheme.getCurrent());
}
public static boolean isNightTheme(@NonNull Context context)
public static boolean isAutoTheme()
{
return isNightTheme(context, Config.getCurrentUiTheme(context));
return Config.UiTheme.isAuto(Config.UiTheme.getUiThemeSettings());
}
public static boolean isNightTheme(@NonNull Context context, String theme)
public static boolean isNavAutoTheme()
{
String nightTheme = context.getString(R.string.theme_night);
return nightTheme.equals(theme);
}
public static boolean isAutoTheme(@NonNull Context context)
{
return isAutoTheme(context, Config.getUiThemeSettings(context));
}
public static boolean isAutoTheme(@NonNull Context context, String theme)
{
String autoTheme = context.getString(R.string.theme_auto);
return autoTheme.equals(theme);
}
public static boolean isNavAutoTheme(@NonNull Context context)
{
return isNavAutoTheme(context, Config.getUiThemeSettings(context));
}
public static boolean isNavAutoTheme(@NonNull Context context, String theme)
{
String navAutoTheme = context.getString(R.string.theme_nav_auto);
return navAutoTheme.equals(theme);
}
public static boolean isValidTheme(@NonNull Context context, String theme)
{
String defaultTheme = context.getString(R.string.theme_default);
String nightTheme = context.getString(R.string.theme_night);
return (defaultTheme.equals(theme) || nightTheme.equals(theme));
return Config.UiTheme.isNavAuto(Config.UiTheme.getUiThemeSettings());
}
@StyleRes
public static int getCardBgThemeResourceId(@NonNull Context context, @NonNull String theme)
public static int getCardBgThemeResourceId(@NonNull String theme)
{
if (isDefaultTheme(context, theme))
if (Config.UiTheme.isDefault(theme))
return R.style.MwmTheme_CardBg;
if (isNightTheme(context, theme))
if (Config.UiTheme.isNight(theme))
return R.style.MwmTheme_Night_CardBg;
throw new IllegalArgumentException("Attempt to apply unsupported theme: " + theme);
}
@StyleRes
public static int getWindowBgThemeResourceId(@NonNull Context context, @NonNull String theme)
public static int getWindowBgThemeResourceId(@NonNull String theme)
{
if (isDefaultTheme(context, theme))
if (Config.UiTheme.isDefault(theme))
return R.style.MwmTheme_WindowBg;
if (isNightTheme(context, theme))
if (Config.UiTheme.isNight(theme))
return R.style.MwmTheme_Night_WindowBg;
throw new IllegalArgumentException("Attempt to apply unsupported theme: " + theme);

View File

@@ -1,4 +1,4 @@
package app.organicmaps.sdk.util;
package app.organicmaps.util;
import android.animation.Animator;
import android.app.Activity;
@@ -16,13 +16,11 @@ import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.AnyRes;
import androidx.annotation.AttrRes;
import androidx.annotation.ColorInt;
import androidx.annotation.DimenRes;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
@@ -34,8 +32,6 @@ import androidx.core.view.WindowInsetsCompat;
import androidx.core.view.WindowInsetsControllerCompat;
import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.util.WindowInsetUtils;
import com.google.android.material.appbar.MaterialToolbar;
import com.google.android.material.textfield.TextInputLayout;
import java.util.Objects;
@@ -203,16 +199,6 @@ public final class UiUtils
ThemeUtils.getResource(toolbar.getContext(), androidx.appcompat.R.attr.homeAsUpIndicator));
}
public static boolean isTablet(@NonNull Context context)
{
return context.getResources().getBoolean(R.bool.tabletLayout);
}
public static int dimen(@NonNull Context context, @DimenRes int id)
{
return context.getResources().getDimensionPixelSize(id);
}
// this method returns the total height of the display (in pixels) including notch and other touchable areas
public static int getDisplayTotalHeight(Context context)
{
@@ -221,13 +207,6 @@ public final class UiUtils
windowManager.getDefaultDisplay().getRealMetrics(metrics);
return metrics.heightPixels;
}
public static void updateRedButton(Button button)
{
button.setTextColor(ThemeUtils.getColor(
button.getContext(), button.isEnabled() ? R.attr.redButtonTextColor : R.attr.redButtonTextColorDisabled));
}
public static void setInputError(@NonNull TextInputLayout layout, @StringRes int error)
{
setInputError(layout, error == 0 ? null : layout.getContext().getString(error));
@@ -241,6 +220,9 @@ public final class UiUtils
: ContextCompat.getColor(layout.getContext(), R.color.base_red));
}
/*
* Hide the Android UI elements
*/
public static void setFullscreen(@NonNull Activity activity, boolean fullscreen)
{
final Window window = activity.getWindow();

View File

@@ -1,5 +1,6 @@
package app.organicmaps.util;
import static app.organicmaps.sdk.util.Utils.dimen;
import static app.organicmaps.sdk.util.Utils.isIntentSupported;
import android.app.Activity;
@@ -7,7 +8,6 @@ import android.content.ActivityNotFoundException;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
@@ -39,10 +39,10 @@ import app.organicmaps.BuildConfig;
import app.organicmaps.MwmActivity;
import app.organicmaps.MwmApplication;
import app.organicmaps.R;
import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.Constants;
import app.organicmaps.sdk.util.Distance;
import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.sdk.util.concurrency.UiThread;
import app.organicmaps.sdk.util.log.Logger;
import app.organicmaps.sdk.util.log.LogsManager;
@@ -203,17 +203,33 @@ public class Utils
if (TextUtils.isEmpty(url))
return;
final Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri =
isHttpOrHttpsScheme(url) ? Uri.parse(url) : new Uri.Builder().scheme("http").appendEncodedPath(url).build();
Utils.openUri(context, uri, R.string.browser_not_available);
}
/**
* Attempts to open a URI in another app via the system app chooser.
* @param context the app context
* @param uri the URI to open.
* @param failMessage string id: message to show in a toast when the system can't find an app to open with.
*/
public static void openUri(@NonNull Context context, @NonNull Uri uri, @Nullable Integer failMessage)
{
final Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addCategory(Intent.CATEGORY_BROWSABLE);
try
{
context.startActivity(intent);
}
catch (ActivityNotFoundException e)
{
Toast.makeText(context, context.getString(R.string.browser_not_available), Toast.LENGTH_LONG).show();
if (failMessage != null)
Toast.makeText(context, context.getString(failMessage), Toast.LENGTH_LONG).show();
Logger.e(TAG, "ActivityNotFoundException", e);
}
catch (AndroidRuntimeException e)
@@ -224,28 +240,6 @@ public class Utils
}
}
/**
* Attempts to open a URI in another app via the system app chooser.
* @param context the app context
* @param uri the URI to open.
* @param failMessage string id: message to show in a toast when the system can't find an app to open with.
* @param action (optional) the Intent action to use. If none is provided, defaults to Intent.ACTION_VIEW.
*/
public static void openUri(@NonNull Context context, @NonNull Uri uri, Integer failMessage, @NonNull String... action)
{
final String act = (action != null && action.length > 0 && action[0] != null) ? action[0] : Intent.ACTION_VIEW;
final Intent intent = new Intent(act);
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// https://developer.android.com/guide/components/intents-common
// check that an app exists to open with, otherwise it'll crash
if (intent.resolveActivity(context.getPackageManager()) != null)
context.startActivity(intent);
else
Toast.makeText(context, failMessage, Toast.LENGTH_SHORT).show();
}
private static boolean isHttpOrHttpsScheme(@NonNull String url)
{
return url.startsWith("http://") || url.startsWith("https://");
@@ -286,9 +280,9 @@ public class Utils
String dimension, String unitText)
{
final SpannableStringBuilder res = new SpannableStringBuilder(dimension).append("\u00A0").append(unitText);
res.setSpan(new AbsoluteSizeSpan(UiUtils.dimen(context, size), false), 0, dimension.length(),
res.setSpan(new AbsoluteSizeSpan(dimen(context, size), false), 0, dimension.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
res.setSpan(new AbsoluteSizeSpan(UiUtils.dimen(context, units), false), dimension.length(), res.length(),
res.setSpan(new AbsoluteSizeSpan(dimen(context, units), false), dimension.length(), res.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return res;
}
@@ -297,9 +291,9 @@ public class Utils
public static Spannable formatDistance(Context context, @NonNull Distance distance)
{
final SpannableStringBuilder res = new SpannableStringBuilder(distance.toString(context));
res.setSpan(new AbsoluteSizeSpan(UiUtils.dimen(context, R.dimen.text_size_nav_number), false), 0,
res.setSpan(new AbsoluteSizeSpan(dimen(context, R.dimen.text_size_nav_number), false), 0,
distance.mDistanceStr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
res.setSpan(new AbsoluteSizeSpan(UiUtils.dimen(context, R.dimen.text_size_nav_dimension), false),
res.setSpan(new AbsoluteSizeSpan(dimen(context, R.dimen.text_size_nav_dimension), false),
distance.mDistanceStr.length(), res.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return res;
}
@@ -489,4 +483,15 @@ public class Utils
final LocalTime time = LocalTime.now().plusSeconds(seconds);
return StringUtils.formatUsingUsLocale("%d:%02d", time.getHour(), time.getMinute());
}
@NonNull
public static String getDonateUrl(@NonNull Context context)
{
final String url = Config.getDonateUrl();
// Enable donations by default if not Google or Huawei. Replace comaps.app/donate/ with localized page.
if ((url.isEmpty() && !BuildConfig.FLAVOR.equals("google") && !BuildConfig.FLAVOR.equals("huawei"))
|| url.endsWith("comaps.app/donate/"))
return context.getString(R.string.app_site_url) + "donate/";
return url;
}
}

View File

@@ -8,7 +8,7 @@ import androidx.core.graphics.Insets;
import androidx.core.view.OnApplyWindowInsetsListener;
import androidx.core.view.WindowInsetsCompat;
import app.organicmaps.R;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.sdk.util.Utils;
public final class WindowInsetUtils
{
@@ -79,7 +79,7 @@ public final class WindowInsetUtils
if (mFloatingActionButton != null)
{
int spacing = UiUtils.dimen(v.getContext(), R.dimen.margin_base);
int spacing = Utils.dimen(v.getContext(), R.dimen.margin_base);
int buttonMarginBottom = insets.bottom + spacing;
ViewGroup.MarginLayoutParams buttonLayoutParams =

View File

@@ -15,7 +15,7 @@ import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;

View File

@@ -14,7 +14,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import app.organicmaps.R;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.UiUtils;
public class PlaceholderView extends LinearLayout
{

View File

@@ -35,10 +35,9 @@ public class RoutingToolbarButton extends AppCompatRadioButton
private void initView()
{
setBackgroundResource(ThemeUtils.isNightTheme(getContext()) ? R.drawable.routing_toolbar_button_night
: R.drawable.routing_toolbar_button);
setButtonTintList(ThemeUtils.isNightTheme(getContext()) ? R.color.routing_toolbar_icon_tint_night
: R.color.routing_toolbar_icon_tint);
final boolean isNightTheme = ThemeUtils.isNightTheme();
setBackgroundResource(isNightTheme ? R.drawable.routing_toolbar_button_night : R.drawable.routing_toolbar_button);
setButtonTintList(isNightTheme ? R.color.routing_toolbar_icon_tint_night : R.color.routing_toolbar_icon_tint);
}
public void progress()

View File

@@ -16,8 +16,8 @@ import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import app.organicmaps.R;
import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.InputUtils;
import app.organicmaps.util.UiUtils;
import com.google.android.material.textfield.TextInputEditText;
public class SearchToolbarController extends ToolbarController implements View.OnClickListener

View File

@@ -13,6 +13,8 @@ import app.organicmaps.sdk.util.NetworkPolicy;
public class StackedButtonDialogFragment extends DialogFragment
{
private static final String TAG_NETWORK_POLICY = "network_policy";
@Nullable
private NetworkPolicy.NetworkPolicyListener mListener;
@@ -43,7 +45,7 @@ public class StackedButtonDialogFragment extends DialogFragment
{
Config.setUseMobileDataSettings(type);
if (mListener != null)
mListener.onResult(NetworkPolicy.newInstance(canUse));
mListener.onResult(new NetworkPolicy(canUse));
}
@Override
@@ -58,4 +60,29 @@ public class StackedButtonDialogFragment extends DialogFragment
{
mListener = listener;
}
public static void showDialogIfNeeded(@NonNull FragmentManager fragmentManager,
@NonNull NetworkPolicy.NetworkPolicyListener listener,
@NonNull NetworkPolicy policy, boolean isToday)
{
if (isToday)
{
listener.onResult(policy);
return;
}
showDialog(fragmentManager, listener);
}
public static void showDialog(@NonNull FragmentManager fragmentManager,
@NonNull NetworkPolicy.NetworkPolicyListener listener)
{
StackedButtonDialogFragment dialog =
(StackedButtonDialogFragment) fragmentManager.findFragmentByTag(TAG_NETWORK_POLICY);
if (dialog != null)
dialog.dismiss();
dialog = new StackedButtonDialogFragment();
dialog.setListener(listener);
dialog.show(fragmentManager, TAG_NETWORK_POLICY);
}
}

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