Compare commits

...

248 Commits

Author SHA1 Message Date
x7z4w
d36a0d8f0d [styles] Night mode bookmarks
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-08-24 20:59:28 +02:00
Yannik Bloscheck
68781adccb [ios] Stop overlap between last search results and home indicator
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-08-24 20:57:58 +02:00
Yannik Bloscheck
73cfd3a6dc [styles] Adjusting label colors to the new dark map style
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-08-24 20:57:34 +02:00
Yannik Bloscheck
439babe056 [styles] Improved dark map style
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-08-24 20:56:32 +02:00
Yannik Bloscheck
a69e68fb9f [styles] Improved dark map style icons
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-08-24 20:56:32 +02:00
x7z4w
c2bef3bd45 [styles] Colored labels
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-08-24 20:56:16 +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
Filip Czaplicki
9c0e1abd15 [styles] Deduplicate mapcss rules
Change done automatically using
``` zsh
for x in **/*.mapcss; do
    rg --passthru -UN --pcre2 '^node\|([^,]+),?\narea\|\1,?' --replace 'node|$1,' $x | sponge $x;
    rg --passthru -UN --pcre2 '^area\|([^,]+),?\nnode\|\1,?' --replace 'node|$1,' $x | sponge $x;
done
```

Follow up to #999

Signed-off-by: Filip Czaplicki <git@starsep.com>
2025-08-20 07:53:37 +02:00
Jean-Baptiste
ca9b3535a8 [android] Use Material 3 theme on linear progress bar
Signed-off-by: jeanbaptisteC <jeanbaptiste.charron@outlook.fr>
2025-08-20 06:51:55 +02:00
Jean-Baptiste
dddbfa315d [android] Drop OSM OAuth1 login
Signed-off-by: jeanbaptisteC <jeanbaptiste.charron@outlook.fr>
2025-08-20 06:35:21 +02:00
Jean-Baptiste
c30990ecda [android] Fix deprecation in HoursMinutesPickerFragment
Signed-off-by: jeanbaptisteC <jeanbaptiste.charron@outlook.fr>
2025-08-20 06:20:08 +02:00
x7z4w
fdb72c9d31 [android] Remove BOM
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-08-20 06:19:10 +02:00
Jean-Baptiste
139facfb00 [iOS] Remove old translations about osm re-auth
Signed-off-by: jeanbaptisteC <jeanbaptiste.charron@outlook.fr>
2025-08-19 19:39:11 +02:00
Konstantin Pastbin
7536591ca4 [routing] Make ladder and steps speed slower
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-19 23:34:00 +07:00
Viktor Govako
c7592276f7 [classifier] Added highway=ladder to the routing and other checkers.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-19 23:34:00 +07:00
Viktor Govako
8ef68a5559 [style] Set line rules for highway=ladder.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-19 23:34:00 +07:00
vikiawv
e46d3d9b65 [styles] Added Roadshieldcolors in Europe (Belgium-Portugal)
[styles] Added roadshield-color Romania

also some other, even though only highways there, as there are no letter markers inside the ref code
Spain and Turkey need to be checked by person with local knowledge.

[styles] corrected Ireland Motorway and Romania DS/DJ-Streets

Signed-off-by: vikiawv <vikiawv@noreply.codeberg.org>
2025-08-19 18:48:10 +07:00
Jean-Baptiste
62de63eda0 [android]Use ContextCompat API instead Resources API
Signed-off-by: Jean-Baptiste Charron <jeanbaptiste.charron@outlook.fr>
2025-08-19 07:45:03 +02:00
Codeberg Translate
e786dbe5f5 [strings] Update from Codeberg Translate
Co-authored-by: AnanasSux <ananassux@noreply.codeberg.org>
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: Laurent FAVOLE <lfavole@noreply.codeberg.org>
Co-authored-by: Lenny Angst <lenny@familie-angst.ch>
Co-authored-by: Mickael81 <mickael81@noreply.codeberg.org>
Co-authored-by: N4ta <codeberg@n4ta.anonaddy.me>
Co-authored-by: Outbreak2096 <outbreak2096@noreply.codeberg.org>
Co-authored-by: Prefill add-on <noreply-addon-prefill@weblate.org>
Co-authored-by: Priit Jõerüüt <jrtcdbrg@noreply.codeberg.org>
Co-authored-by: Stephan-P <stephan-p@noreply.codeberg.org>
Co-authored-by: alexgabi <alexgabi@noreply.codeberg.org>
Co-authored-by: and4po <and4po@noreply.codeberg.org>
Co-authored-by: aoxa <aoxa@noreply.codeberg.org>
Co-authored-by: concede2913 <concede2913@noreply.codeberg.org>
Co-authored-by: ghose <ghose@noreply.codeberg.org>
Co-authored-by: gimse <gimse@noreply.codeberg.org>
Co-authored-by: lazlo <lazlo@noreply.codeberg.org>
Co-authored-by: ldmpub <ldmpub@noreply.codeberg.org>
Co-authored-by: matheusgomesms <matheusgomesms@noreply.codeberg.org>
Co-authored-by: metehan <metehan@noreply.codeberg.org>
Co-authored-by: patepelo <patepelo@noreply.codeberg.org>
Co-authored-by: phama <phama@noreply.codeberg.org>
Translate-URL: https://translate.codeberg.org/projects/comaps/android-typestrings/
Translate-URL: https://translate.codeberg.org/projects/comaps/ios-typestrings/
Translation: CoMaps/Android - Map Feature Types
Translation: CoMaps/Android UI Strings
Translation: CoMaps/Apple AppStore description
Translation: CoMaps/Countries and regions names
Translation: CoMaps/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-19 04:38:04 +00:00
Harry Bond
d44f0ae7da [android] Display overlay layer state with icon
Fixes #1402

Signed-off-by: Harry Bond <me@hbond.xyz>
2025-08-19 06:37:50 +02:00
Jean-Baptiste
4232de04ac [android] Fix padding in bookmark category settings
Signed-off-by: JeanBaptisteC <jeanbaptiste.charron@outlook.fr>
2025-08-18 20:29:12 +02:00
map-per
bfacc2a98d Fix standalone notes not being saved when not logged in (#1433)
Signed-off-by: map-per <map-per@gmx.de>
2025-08-18 20:08:40 +02:00
Eivind Samseth
d04327082d [drape] Match iOS double tap to zoom behavior
Signed-off-by: eisa01 <eisa01@gmail.com>
2025-08-18 14:15:27 +02:00
Yannik Bloscheck
3097b54036 [ios] Import functional in MWMEditorHelper.mm
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-08-18 09:07:05 +02:00
Yannik Bloscheck
e2fa169832 [ios] Fix modulemap path in Xcode
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-08-18 09:07:05 +02:00
Viktor Govako
3d6d08e2a1 [kml] Factor out ParseXXXColor functions.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-18 09:07:05 +02:00
Interactiondesigner
5e8eeb1f20 Update categories_cuisines.txt
Changed translation of cuisine=barbecue in German from "Grill" to "Barbecue" since cuisine=Grill als uses "Grill". So when adding a restaurant, it can be better distinguished between more traditional European/Middle Eastern grill and the more American Barbecue cuisine.

Signed-off-by: Interactiondesigner <mr.funky@gmx.de>
2025-08-18 09:07:05 +02:00
Viktor Govako
8d61c7447b [routing][tests] Added "agricultural" roads test.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-18 09:07:05 +02:00
Osyotr
4117cca562 CMake fixes for Windows
Signed-off-by: Osyotr <Osyotr@users.noreply.github.com>
2025-08-18 09:07:05 +02:00
Osyotr
416b8ab95a Fix quoting in curl cmdline
Signed-off-by: Osyotr <Osyotr@users.noreply.github.com>
2025-08-18 09:07:05 +02:00
Osyotr
d8f9323705 Add missing lib on Windows (#11004)
* Add missing lib on Windows

Signed-off-by: Osyotr <Osyotr@users.noreply.github.com>

* Update libs/platform/CMakeLists.txt

Signed-off-by: Alexander Borsuk <170263+biodranik@users.noreply.github.com>

---------

Signed-off-by: Osyotr <Osyotr@users.noreply.github.com>
Signed-off-by: Alexander Borsuk <170263+biodranik@users.noreply.github.com>
Co-authored-by: Alexander Borsuk <170263+biodranik@users.noreply.github.com>
2025-08-18 09:07:05 +02:00
Alexander Borsuk
e3d47775fc [TTS] Clearer pronouncement of route recalculation in ru
> При уходе с тропы если язык подсказок русский, говорит - «преращик маршрута».

Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-08-18 09:07:05 +02:00
Andrei Shkrob
a580c19dc0 [android-auto] Fix null pointer exception
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-18 09:07:05 +02:00
Andrei Shkrob
8e0d4776af [style] Some improvements
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-18 09:07:05 +02:00
Alexander Borsuk
674abcf02e [linux] Fix zero file creation (birth) time
Observed in Ubuntu 24 via Orb on arm-based Mac

Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-08-18 09:07:05 +02:00
hemanggs
fbaa59ce3b [android] Refactoring regression fix
Signed-off-by: hemanggs <hemangmanhas@gmail.com>
2025-08-18 09:07:05 +02:00
Viktor Govako
72ff90defd [base] Added to_uint base for string_view.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-18 09:07:05 +02:00
Viktor Govako
1d29e7816a [coding] Rename non-empty string serialization.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-18 09:07:05 +02:00
Viktor Govako
7b4862b442 [base] Updated IsSortedAndUnique function.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-18 09:07:05 +02:00
Viktor Govako
b7b87f5530 [tracks] Safe GpsTrackCollection requests during recording.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-18 09:07:05 +02:00
Viktor Govako
fb62982000 [tracks] Set close distance threshold to 10m.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-18 09:07:05 +02:00
Viktor Govako
64f50d4e49 [tracks] Fixed ending points.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-18 09:07:05 +02:00
Viktor Govako
fda1da03c8 [tracks] Fixed starting points.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-18 09:07:05 +02:00
David Martinez
8477fff988 [strings] Add more Spanish categories translations
Signed-off-by: David Martinez <47610359+dvdmrtnz@users.noreply.github.com>
2025-08-18 09:07:05 +02:00
Osyotr
5158ceb311 Add windows support to vulkan_wrapper
Signed-off-by: Osyotr <Osyotr@users.noreply.github.com>
2025-08-18 09:07:05 +02:00
Ferenc Géczi
7e5e6ec78e [libs][linux] Fix incorrect include of fcntl.h
The POSIX standard says, that `fcntl.h` is to be included as `#include <fcntl.h>`.

This change fixes the compiler warnings that happen with `musl` libc :
```
/usr/include/sys/fcntl.h:1:2: warning: #warning redirecting incorrect #include <sys/fcntl.h> to <fcntl.h> [-Wcpp]
    1 | #warning redirecting incorrect #include <sys/fcntl.h> to <fcntl.h>
      |  ^~~~~~~
In file included from /home/ferenc/github.com/organicmaps/organicmaps/libs/coding/mmap_reader.cpp:18,
                 from /home/ferenc/github.com/organicmaps/organicmaps/build-alpine-3.21/build-alpine-3.21/libs/coding/CMakeFiles/coding.dir/Unity/unity_0_cxx.cxx:40:
/usr/include/sys/fcntl.h:1:2: warning: #warning redirecting incorrect #include <sys/fcntl.h> to <fcntl.h> [-Wcpp]
    1 | #warning redirecting incorrect #include <sys/fcntl.h> to <fcntl.h>
      |  ^~~~~~~
````

This happens because of the explicit [warning in the proxy header](
https://git.musl-libc.org/cgit/musl/tree/include/sys/fcntl.h)

Signed-off-by: Ferenc Géczi <ferenc.gm@gmail.com>
2025-08-18 09:07:05 +02:00
Osyotr
0ea0f2e49a Make UniformRandom standard-conforming
std::uniform_int_distribution<T> requires sizeof(T) >= sizeof(short)

Signed-off-by: Osyotr <Osyotr@users.noreply.github.com>
2025-08-18 09:07:05 +02:00
Viktor Govako
b1c2b204a1 gcc13 fix
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-18 09:07:05 +02:00
Alexander Borsuk
52a0c45083 Glaze smoke test
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-08-18 09:07:05 +02:00
Alexander Borsuk
4de9de38ad [3party] Add glaze submodule
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-08-18 09:07:05 +02:00
Alexander Borsuk
215c19dcc7 Fix unity build error by removing using namespace std;
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-08-18 09:07:05 +02:00
Osyotr
b5b333c832 Fix TokenizeIterator on Windows
Signed-off-by: Osyotr <Osyotr@users.noreply.github.com>
2025-08-18 09:07:05 +02:00
Osyotr
dfd7af92fa Remove usage of boost/iostreams from 3party/succint
Signed-off-by: Osyotr <Osyotr@users.noreply.github.com>
2025-08-18 09:07:05 +02:00
Osyotr
e00d5d33b2 Add missing include
Signed-off-by: Osyotr <Osyotr@users.noreply.github.com>
2025-08-18 09:07:05 +02:00
Osyotr
5ae8156fa3 Fix std::atomic_flag initialization
Signed-off-by: Osyotr <Osyotr@users.noreply.github.com>
2025-08-18 09:07:05 +02:00
Viktor Govako
b107638b8b [routing] SaveRoute minor fixes and CHECK.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-18 09:07:05 +02:00
Alexander Borsuk
c4599f4889 C++23
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-08-18 09:07:05 +02:00
Yannik Bloscheck
580209f7ea [ios] Ending search when switching over to routing
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-08-18 08:13:35 +02:00
Harry Bond
abc755c058 [styles] Don't show postbox labels
Fixes #1399
Signed-off-by: Harry Bond <me@hbond.xyz>


Signed-off-by: Harry Bond <me@hbond.xyz>
2025-08-18 08:07:14 +02:00
Yannik Bloscheck
035a8edebb [ios] Adding CarPlay entitlement
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-08-17 22:07:30 +02:00
Henry Sternberg
c59b63d784 [routing] OSM tag based time and turn penalties
Signed-off-by: Henry Sternberg <dev@bluelightmaps.com>
Co-Authored-By: eisa01 <eisa01@gmail.com>
Co-Authored-By: x7z4w <x7z4w@noreply.codeberg.org>
Co-Authored-By: Yannik Bloscheck <git@yannikbloscheck.com>
2025-08-17 19:40:00 +02:00
Jean-Baptiste
daf2a7d8e7 [android] Fix color issues for AppCompat components
Signed-off-by: Jean-Baptiste Charron <jeanbaptiste.charron@outlook.fr>
2025-08-17 18:43:47 +02:00
Jean-Baptiste
f549108e72 [docs] Remove custom styles badges to fix render on Github
Signed-off-by: Jean-Baptiste Charron <jeanbaptiste.charron@outlook.fr>
2025-08-17 18:24:37 +02:00
Codeberg Translate
90667e9fa1 [strings] Update from Codeberg Translate
Co-authored-by: Codeberg Translate <translate@codeberg.org>
Co-authored-by: Fjuro <fjuro@alius.cz>
Co-authored-by: Mickael81 <mickael81@noreply.codeberg.org>
Co-authored-by: N4ta <codeberg@n4ta.anonaddy.me>
Co-authored-by: Priit Jõerüüt <jrtcdbrg@noreply.codeberg.org>
Co-authored-by: Stephan-P <stephan-p@noreply.codeberg.org>
Co-authored-by: alexgabi <alexgabi@noreply.codeberg.org>
Co-authored-by: aoxa <aoxa@noreply.codeberg.org>
Co-authored-by: concede2913 <concede2913@noreply.codeberg.org>
Co-authored-by: metehan <metehan@noreply.codeberg.org>
Co-authored-by: patepelo <patepelo@noreply.codeberg.org>
Co-authored-by: phama <phama@noreply.codeberg.org>
Translate-URL: https://translate.codeberg.org/projects/comaps/ios-typestrings/
Translation: CoMaps/Android - Map Feature Types
Translation: CoMaps/Android UI Strings
Translation: CoMaps/Apple AppStore description
Translation: CoMaps/Countries and regions names
Translation: CoMaps/F-Droid app description
Translation: CoMaps/iOS - Map Feature Types
Translation: CoMaps/iOS Plist
Translation: CoMaps/iOS UI Strings
2025-08-17 17:38:15 +02:00
vikiawv
8bac8b7d37 [styles] Austria Reference Color
Signed-off-by: vikiawv <vikiawv@noreply.codeberg.org>
Co-authored-by: vikiawv <vikiawv@noreply.codeberg.org>
Co-committed-by: vikiawv <vikiawv@noreply.codeberg.org>
2025-08-17 15:54:03 +02:00
Konstantin Pastbin
bfffa1fff4 Format all C++ and Java code via clang-format
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-17 14:32:37 +07:00
Konstantin Pastbin
9f0290c0ec [ios] Disable clang-format temporary
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-17 14:28:44 +07:00
Andrei Shkrob
8a8a3c5a08 [ci] remove clang-format workflow
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-17 14:28:44 +07:00
Andrei Shkrob
518747d503 [ci] add code style check workflow
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-17 14:28:44 +07:00
Alexander Borsuk
5063b511ae tools/unix/clang-format.sh to format all necessary files in the repo
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-08-17 14:28:44 +07:00
Alexander Borsuk
fbe3f72fb1 .clang-format-ignore
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-08-17 14:28:44 +07:00
Alexander Borsuk
872c0d3e15 .clang-format rules
Signed-off-by: Alexander Borsuk <me@alex.bio>

.clang-format remove unnecessary semicolons

Signed-off-by: Alexander Borsuk <me@alex.bio>

[clang-format] Removed "AlignArrayOfStructures".

Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-17 14:28:44 +07:00
Andrei Shkrob
9833918aac [android][sdk] Refactoring
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-17 09:26:56 +02:00
renderexpert
0000ec149c Fix wrong texture setting for RouteMarker
Signed-off-by: renderexpert <expert@renderconsulting.co.uk>
2025-08-17 08:30:56 +02:00
renderexpert
da3053f5fc Make check more strict in ApplyTextures
Signed-off-by: renderexpert <expert@renderconsulting.co.uk>
2025-08-17 08:30:56 +02:00
renderexpert
5a0ff536a7 Regenerate Vulkan shaders
Signed-off-by: renderexpert <expert@renderconsulting.co.uk>
2025-08-17 08:30:56 +02:00
renderexpert
36f123ef25 Fix crash in CreateDescriptorSetGroup
Signed-off-by: renderexpert <expert@renderconsulting.co.uk>
2025-08-17 08:30:56 +02:00
renderexpert
01c2f02c86 Remove OpenGL ES2 leftovers that caused crash in Vulkan
Signed-off-by: renderexpert <expert@renderconsulting.co.uk>
2025-08-17 08:30:56 +02:00
renderexpert
4d702ec541 Set OpenGLES 3.0 as minimal version in Android manifest
Signed-off-by: renderexpert <expert@renderconsulting.co.uk>
2025-08-17 08:30:56 +02:00
renderexpert
344cf6d709 Fix OpenGL glUniform mismatch
Signed-off-by: renderexpert <expert@renderconsulting.co.uk>
2025-08-17 08:30:56 +02:00
renderexpert
14b3e8fc8f Fix shader tests on Linux
Signed-off-by: renderexpert <expert@renderconsulting.co.uk>
2025-08-17 08:30:56 +02:00
renderexpert
6d0daf6fe7 Rewrite shaders to use OpenGL ES3 syntax
Signed-off-by: renderexpert <expert@renderconsulting.co.uk>
2025-08-17 08:30:56 +02:00
renderexpert
9b3507211f Remove Tegra support hacks
Signed-off-by: renderexpert <expert@renderconsulting.co.uk>
2025-08-17 08:30:56 +02:00
renderexpert
a406462549 Remove Adreno 200 support hacks
Signed-off-by: renderexpert <expert@renderconsulting.co.uk>
2025-08-17 08:30:56 +02:00
renderexpert
897d7a253d Refactor shaders to use GLES3 syntax
Signed-off-by: renderexpert <expert@renderconsulting.co.uk>
2025-08-17 08:30:56 +02:00
renderexpert
b23c2ba3e3 [Drape] Remove GLES2-related code
Signed-off-by: renderexpert <expert@renderconsulting.co.uk>
2025-08-17 08:30:56 +02:00
hb0nd
705c715356 [docs] Make funding section sound less threatening
Currently, it sounds like a threat to make it paid etc unless people donate 😅

Signed-off-by: hb0nd <me@hbond.xyz>
2025-08-16 19:48:29 +02:00
Jean-Baptiste
826ddba26f [android] Use material properties in styles and themes
Signed-off-by: Jean-Baptiste Charron <jeanbaptiste.charron@outlook.fr>
2025-08-16 11:04:30 +02:00
hemanggs
2492e8bda4 [Android] Standalone Note UI in Category select screen
Signed-off-by: hemanggs <hemangmanhas@gmail.com>
2025-08-16 07:04:33 +02:00
hemanggs
9e494ed8a5 [core] Create Standalone Note core
Signed-off-by: hemanggs <hemangmanhas@gmail.com>
2025-08-16 07:04:33 +02:00
Andrei Shkrob
1c8ac1f32a [android] Show bookmark icon in color selector
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-16 07:04:33 +02:00
Andrei Shkrob
d0bb8c1c49 [android] Fix colors order
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-16 07:04:33 +02:00
Jean-Baptiste
6c4503b0db [android] Improve size of bookmark icons
Signed-off-by: Jean-Baptiste Charron <jeanbaptiste.charron@outlook.fr>
2025-08-16 07:04:33 +02:00
Viktor Govako
a39b3a9921 [android] Fixed getting drawable icons.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-08-16 07:04:33 +02:00
Andrei Shkrob
8493ed369a [android] Fix collor selector issue
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-16 07:04:33 +02:00
Andrei Shkrob
2ded7e5e2b [android] Load icon types from core
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-16 07:04:33 +02:00
Andrei Shkrob
d9335c0b6c [android] Load predefined colors from core
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-16 07:04:33 +02:00
Andrei Shkrob
ebc5370052 [android] Load TTS languages from core
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-16 07:04:33 +02:00
Konstantin Pastbin
0a96a23ca0 [desktop] Fix Mac icon file location
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-16 01:43:47 +07:00
Konstantin Pastbin
5b05a7ac71 [3party] Protobuf MSVC and C++23 fixes
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-16 01:15:07 +07:00
Kiryl Kaveryn
31104eed4d [ios] Remove fileCoordinator wrapping from downloading starting
And add check `isUbiquitousItem` before downloading start. This method returns false when the file doesn't exist.

Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
2025-08-16 00:33:06 +07:00
Kiryl Kaveryn
0f2353aae6 [ios] Track the percentDownloaded for the downloaded from the cloud files
Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
2025-08-16 00:32:58 +07:00
Kiryl Kaveryn
d01b8aaab4 [map] Remove zooming back on track deselection
Closes https://github.com/organicmaps/organicmaps/issues/10941

Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
2025-08-16 00:27:55 +07:00
Alexander Borsuk
33f8e20f1b [Linux] Vulkan build fixes
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-08-16 00:23:24 +07:00
Alexander Borsuk
76d8396cb1 [3party] Updated Vulkan headers to v1.4.322
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-08-16 00:19:01 +07:00
Andrei Shkrob
0f744e7cf2 [desktop] Organize desktop resources
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-08-16 00:12:24 +07:00
Konstantin Pastbin
5d990bdc19 [docs] Add ninja to MacOS deps
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-08-15 11:47:53 +07:00
Yannik Bloscheck
1f2d70c720 [xcode] Updated upgrade check version to latest value
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-08-14 18:22:40 +02:00
Alexander Borsuk
76ffc99abd New cpp folder structure
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-08-14 20:52:04 +07:00
x7z4w
c9cbb64f12 [search] Follow-up fix for synonyms
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-08-14 11:07:33 +02:00
x7z4w
c4722f7025 [ci] Fix Github CI
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-08-14 10:57:30 +02:00
4476 changed files with 77222 additions and 81090 deletions

View File

@@ -3,7 +3,6 @@ BasedOnStyle: Google
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignArrayOfStructures: Right
AlignConsecutiveMacros: AcrossEmptyLinesAndComments
AlignEscapedNewlines: LeftWithLastLine
AlignOperands: AlignAfterOperator
@@ -40,8 +39,10 @@ ColumnLimit: 120
ConstructorInitializerIndentWidth: 2
ContinuationIndentWidth: 4
DerivePointerAlignment: false
EmptyLineBeforeAccessModifier: Always
IncludeBlocks: Preserve
IndentAccessModifiers: false
IndentCaseLabels: false
IndentExternBlock: NoIndent
InsertBraces: false
InsertNewlineAtEOF: true
@@ -49,6 +50,7 @@ LambdaBodyIndentation: OuterScope
PackConstructorInitializers: CurrentLine
PointerAlignment: Middle
RemoveBracesLLVM: true
RemoveSemicolon: true
QualifierAlignment: Right
SpacesInContainerLiterals: false
Standard: Latest

8
.clang-format-ignore Normal file
View File

@@ -0,0 +1,8 @@
# Files that should not be formatted.
./3party
# A patched copy of the https://registry.khronos.org/OpenGL/api/GLES3/gl3.h
./android/sdk/src/main/cpp/app/organicmaps/sdk/opengl/gl3stub.h
# Formatting it leads to crashes in runtime. Newer protobuf may fix it.
./libs/indexer/drules_struct.pb.cc
# No need to format this 3party tool.
tools/osmctools/*.c

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

@@ -3,7 +3,7 @@ on:
workflow_dispatch: # Manual trigger
pull_request:
paths:
- qt/res/app.comaps.comaps.desktop
- qt/res/linux/app.comaps.comaps.desktop
- .forgejo/workflows/desktop-file-check.yaml # Run check on self change
jobs:
@@ -16,7 +16,7 @@ jobs:
with:
fetch-depth: 1
sparse-checkout: |
qt/res/app.comaps.comaps.desktop
qt/res/linux/app.comaps.comaps.desktop
- name: Install desktop-file-validate tool
shell: bash
@@ -27,4 +27,4 @@ jobs:
- name: Validate desktop file
shell: bash
run: desktop-file-validate qt/res/app.comaps.comaps.desktop && echo "Successfully validated .desktop file"
run: desktop-file-validate qt/res/linux/app.comaps.comaps.desktop && echo "Successfully validated .desktop file"

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:

View File

@@ -23,6 +23,10 @@ jobs:
shell: bash
run: git submodule update --depth 1 --init --recursive --jobs=$(($(nproc) * 20))
- name: Configure repository
shell: bash
run: SKIP_GENERATE_SYMBOLS=1 ./configure.sh
- name: Lint
shell: bash
working-directory: android
@@ -62,6 +66,7 @@ jobs:
libxinerama-dev \
libxcursor-dev \
libxi-dev \
python3-protobuf \
zlib1g-dev
- name: Checkout sources

View File

@@ -1,43 +0,0 @@
name: clang-format
on:
push:
branches: [ master ]
paths:
- 'android/app/src/**.java'
- '.clang-format'
- '.github/workflows/clang-format.yml'
pull_request:
branches: [ master ]
paths:
- 'android/app/src/**.java'
- '.clang-format'
- '.github/workflows/clang-format.yml'
jobs:
check-formatting:
runs-on: ubuntu-latest
continue-on-error: true # TODO(AB): Remove this line when ready to enforce formatting.
steps:
- uses: actions/checkout@v4
- name: Install clang-format
run: |
sudo apt-get update
sudo apt-get install -y clang-format-19
clang-format-19 --version
- name: Check Java formatting
run: |
JAVA_FILES=($(find android/app/src -name '*.java'))
FORMATTING_ISSUES=$(clang-format-19 --dry-run --Werror $JAVA_FILES 2>&1 || true)
if [ -n "$FORMATTING_ISSUES" ]; then
echo "$FORMATTING_ISSUES"
echo ""
echo "To fix formatting, please run:"
echo " clang-format -i <file>"
exit 1
fi

51
.github/workflows/code-style-check.yaml vendored Normal file
View File

@@ -0,0 +1,51 @@
name: Code style check
on:
pull_request:
branches: [ master ]
paths: # Should stay in sync with tools/unix/clang-format.sh
- '.github/workflows/code-style-check.yaml'
- 'android/app/src/**.java'
- 'android/sdk/src/**.java'
- 'android/sdk/src/main/cpp/**.[ch]pp'
- 'dev_sandbox/**.[ch]pp'
- 'generator/**.[ch]pp'
- 'iphone/**.[ch]pp'
- 'iphone/**.[hm]'
- 'iphone/**.mm'
- 'libs/**.[ch]pp'
- 'libs/**.[hm]'
- '!libs/indexer/drules_struct.pb.h'
- 'libs/**.mm'
- 'qt/**.[ch]pp'
- 'qt/**.h'
- 'tools/**.[ch]pp'
- '.clang-format'
- '.clang-format-ignore'
jobs:
code-style-check:
runs-on: ubuntu-latest
steps:
- name: Install clang-format
run: |
sudo apt purge -y clang-format-18 # Remove default old version of clang-format
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
echo 'deb http://apt.llvm.org/noble/ llvm-toolchain-noble-20 main' | sudo tee /etc/apt/sources.list.d/llvm-toolchain-noble-20.list
sudo apt-get update
sudo apt-get install -y clang-format-20
sudo update-alternatives --force --install /usr/bin/clang-format clang-format /usr/bin/clang-format-20 10
sudo update-alternatives --force --install /usr/bin/git-clang-format git-clang-format /usr/bin/git-clang-format-20 10
clang-format --version
- name: Checkout sources
uses: actions/checkout@v4
- name: Check code style
run: tools/unix/clang-format.sh
- name: Post clang-format comments
if: failure()
uses: reviewdog/action-suggester@v1.21.0
with:
tool_name: clang-format
fail_level: error

View File

@@ -30,6 +30,7 @@ jobs:
run: |
brew install qt \
optipng
pip3 install "protobuf<3.21" --break-system-packages
- name: Checkout sources
uses: actions/checkout@v4

20
.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
@@ -50,7 +52,7 @@ omim.sdf
*.suo
*.aps
*.rc
!qt/res/windows.rc
!qt/res/windows/windows.rc
*.pdb
out/

4
.gitmodules vendored
View File

@@ -65,3 +65,7 @@
[submodule "3party/imgui/imgui"]
path = 3party/imgui/imgui
url = https://github.com/ocornut/imgui
[submodule "3party/glaze"]
path = 3party/glaze
url = https://github.com/stephenberry/glaze
branch = main

View File

@@ -57,6 +57,7 @@ endif()
add_subdirectory(agg)
add_subdirectory(bsdiff-courgette)
add_subdirectory(glaze)
add_subdirectory(minizip)
add_subdirectory(open-location-code)
add_subdirectory(opening_hours)

View File

@@ -4,7 +4,9 @@ set(FT_DISABLE_HARFBUZZ ON)
add_subdirectory(freetype)
# Fix warning with ONE_PIXEL macro clash.
target_compile_options(freetype PRIVATE -Wno-macro-redefined)
if(NOT MSVC)
target_compile_options(freetype PRIVATE -Wno-macro-redefined)
endif()
# Use ft2build.h from the current directory instead of the default.
target_include_directories(freetype

1
3party/glaze Submodule

Submodule 3party/glaze added at 5a58d7936e

View File

@@ -11,14 +11,23 @@ target_include_directories(${PROJECT_NAME}
harfbuzz/src
)
# Keep these settigns in sync with xcode/harfbuzz project.
target_compile_options(${PROJECT_NAME}
PRIVATE
-fno-rtti
-fno-exceptions
-fno-threadsafe-statics
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:-Wno-format-pedantic>
)
if (MSVC)
target_compile_options(${PROJECT_NAME}
PRIVATE
/GR-
/EHsc-
/Zc:threadSafeInit-
)
else()
# Keep these settings in sync with xcode/harfbuzz project.
target_compile_options(${PROJECT_NAME}
PRIVATE
-fno-rtti
-fno-exceptions
-fno-threadsafe-statics
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:-Wno-format-pedantic>
)
endif()
target_compile_definitions(${PROJECT_NAME}
PRIVATE
@@ -28,14 +37,20 @@ target_compile_definitions(${PROJECT_NAME}
#$<$<BOOL:${APPLE}>:HAVE_CORETEXT>
HAVE_ATEXIT
HAVE_GETPAGESIZE
HAVE_MMAP
HAVE_MPROTECT
HAVE_PTHREAD
HAVE_SYSCONF
HAVE_SYS_MMAN_H
HAVE_UNISTD_H
)
if (NOT MSVC)
target_compile_definitions(${PROJECT_NAME}
PRIVATE
HAVE_MMAP
HAVE_PTHREAD
HAVE_SYS_MMAN_H
HAVE_UNISTD_H
)
endif()
target_link_libraries(${PROJECT_NAME} Freetype::Freetype)
add_library(harfbuzz::harfbuzz ALIAS harfbuzz)

View File

@@ -172,6 +172,7 @@ add_library(icuuc
icu/icu4c/source/common/uvector.cpp
icu/icu4c/source/common/uvectr32.cpp
icu/icu4c/source/common/uvectr64.h
icu/icu4c/source/common/wintz.cpp
icu/icu4c/source/common/wintz.h
)

View File

@@ -11,6 +11,7 @@ set(SRC
protobuf/src/google/protobuf/message_lite.cc
protobuf/src/google/protobuf/repeated_field.cc
protobuf/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc
protobuf/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc
protobuf/src/google/protobuf/stubs/bytestream.cc
protobuf/src/google/protobuf/stubs/common.cc
protobuf/src/google/protobuf/stubs/int128.cc

View File

@@ -7,7 +7,6 @@
#include <boost/utility/enable_if.hpp>
#include <boost/utility.hpp>
#include <boost/type_traits/is_pod.hpp>
#include <boost/iostreams/device/mapped_file.hpp>
#include "mappable_vector.hpp"
@@ -283,12 +282,6 @@ namespace succinct { namespace mapper {
return mapper.bytes_read();
}
template <typename T>
size_t map(T& val, boost::iostreams::mapped_file_source const& m, uint64_t flags = 0, const char* friendly_name = "<TOP>")
{
return map(val, m.data(), flags, friendly_name);
}
template <typename T>
uint64_t size_of(T& val)
{

View File

@@ -8,7 +8,6 @@
#include <stdint.h>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/iostreams/device/mapped_file.hpp>
namespace succinct { namespace util {
@@ -205,29 +204,6 @@ namespace succinct { namespace util {
std::string m_cur_value;
};
struct mmap_lines
{
typedef buffer_line_iterator iterator;
typedef buffer_line_iterator const_iterator;
mmap_lines(std::string filename)
: m_map(filename)
{}
const_iterator begin() const
{
return const_iterator(m_map.data(), m_map.size());
}
const_iterator end() const
{
return const_iterator();
}
private:
boost::iostreams::mapped_file_source m_map;
};
struct input_error : std::invalid_argument
{
input_error(std::string const& what)

View File

@@ -19,7 +19,18 @@ extern "C" {
#endif
#include "vulkan_wrapper.h"
#if defined(_WIN32)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#else
#include <dlfcn.h>
#endif
int InitVulkan(void) {
#if defined(__APPLE__)
@@ -30,6 +41,9 @@ int InitVulkan(void) {
if (!libvulkan) {
libvulkan = dlopen("libMoltenVK.dylib", RTLD_NOW | RTLD_LOCAL);
}
#elif defined( _WIN32 )
HMODULE libvulkan = LoadLibraryA("vulkan-1.dll");
auto dlsym = [](HMODULE h, char const * name) { return GetProcAddress(h, name); };
#else
void* libvulkan = dlopen("libvulkan.so.1", RTLD_NOW | RTLD_LOCAL);
if (!libvulkan) {

View File

@@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.22.1)
project(omim C CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_C_STANDARD 17)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_C_STANDARD 23)
# Our code does not rely on gnu extensions.
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_C_EXTENSIONS OFF)
@@ -39,18 +39,16 @@ if (APPLE AND NOT ("${CMAKE_SYSTEM_NAME}" STREQUAL Android))
# https://gitlab.kitware.com/cmake/cmake/-/issues/21963
enable_language(OBJC)
set(CMAKE_OBJC_EXTENSIONS OFF)
set(CMAKE_OBJC_STANDARD 11)
set(CMAKE_OBJC_STANDARD 23)
set(CMAKE_OBJC_FLAGS -fobjc-arc)
set(CMAKE_OBJC_VISIBILITY_PRESET hidden)
enable_language(OBJCXX)
set(CMAKE_OBJCXX_EXTENSIONS OFF)
set(CMAKE_OBJCXX_STANDARD 20)
set(CMAKE_OBJCXX_STANDARD 23)
set(CMAKE_OBJCXX_FLAGS -fobjc-arc)
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)
@@ -87,7 +85,7 @@ if (MSVC)
add_compile_options(/utf-8)
add_link_options(/INCREMENTAL:NO)
else()
add_compile_options(-ffast-math)
add_compile_options(-ffast-math $<$<CXX_COMPILER_ID:GNU>:-Wno-psabi>)
endif()
if (PLATFORM_WIN)
@@ -185,7 +183,7 @@ if (NOT PLATFORM_IPHONE AND NOT PLATFORM_ANDROID)
endif()
# To allow #include "base/file_name.hpp" in all sources.
include_directories(${CMAKE_HOME_DIRECTORY})
include_directories("${CMAKE_HOME_DIRECTORY}" "${CMAKE_HOME_DIRECTORY}/libs" "${CMAKE_HOME_DIRECTORY}/tools")
if (USE_PCH)
message(STATUS "Precompiled headers are ON")
@@ -197,7 +195,7 @@ if (USE_PCH)
endif()
# Should be on the root level, not in 3party, so tests can get these dependencies.
if (PLATFORM_LINUX OR PLATFORM_WIN)
if (PLATFORM_LINUX)
find_package(ICU COMPONENTS uc i18n data REQUIRED)
find_package(Freetype REQUIRED)
find_package(harfbuzz REQUIRED)
@@ -227,49 +225,22 @@ endif()
# Used in qt/ and shaders/
find_package(Python3 REQUIRED COMPONENTS Interpreter)
add_subdirectory(base)
add_subdirectory(coding)
add_subdirectory(descriptions)
add_subdirectory(drape)
add_subdirectory(drape_frontend)
add_subdirectory(editor)
add_subdirectory(ge0)
add_subdirectory(generator/mwm_diff)
add_subdirectory(geometry)
add_subdirectory(indexer)
add_subdirectory(kml)
add_subdirectory(map)
add_subdirectory(cppjansson)
add_subdirectory(platform)
add_subdirectory(routing)
add_subdirectory(routing_common)
add_subdirectory(search)
add_subdirectory(shaders)
add_subdirectory(storage)
add_subdirectory(tracking)
add_subdirectory(traffic)
add_subdirectory(transit)
add_subdirectory(libs)
if (PLATFORM_DESKTOP)
omim_add_tool_subdirectory(feature_list)
add_subdirectory(dev_sandbox)
add_subdirectory(generator)
add_subdirectory(openlr)
add_subdirectory(poly_borders)
omim_add_tool_subdirectory(topography_generator)
add_subdirectory(track_analyzing)
omim_add_tool_subdirectory(track_generator)
add_subdirectory(tools)
if (NOT SKIP_QT_GUI)
add_subdirectory(qt)
omim_add_tool_subdirectory(skin_generator)
endif()
if (GENERATOR_TOOL)
add_compile_options(-march=native -mtune=native)
message(STATUS "target CPU optimizations enabled, produced binaries will NOT work on a different CPU")
endif()
add_subdirectory(dev_sandbox)
endif()
omim_add_test_subdirectory(qt_tstfrm)
omim_add_test_subdirectory(libs/qt_tstfrm)
if (PLATFORM_ANDROID)
add_subdirectory(android/sdk/src/main/cpp)

View File

@@ -19,20 +19,20 @@
</div>
<div align="center">
<p align="center">
<a href="https://codeberg.org/comaps/comaps/releases">
<img src="https://img.shields.io/github/license/comaps/comaps?style=for-the-badge&logo=opensourceinitiative&logoColor=white&color=588157" alt="License" style="width: 90%; max-width: 150px;"/>
<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">
<img src="https://img.shields.io/github/actions/workflow/status/comaps/comaps/.github/workflows/android-check.yaml?label=Android%20Build&logo=android&logoColor=white&style=for-the-badge&color=588157" alt="Android Build Status" style="width: 90%; max-width: 170px;"/>
<img src="https://img.shields.io/github/actions/workflow/status/comaps/comaps/.github/workflows/android-check.yaml?label=Android%20Build&logo=android&logoColor=white&style=for-the-badge&color=588157" alt="Android Build Status"/>
</a>
<a href="https://github.com/comaps/comaps/actions/workflows/ios-check.yaml">
<img src="https://img.shields.io/github/actions/workflow/status/comaps/comaps/.github/workflows/ios-check.yaml?label=iOS%20Build&logo=apple&logoColor=white&style=for-the-badge&color=588157" alt="iOS Build Status" style="width: 90%; max-width: 145px;"/>
<img src="https://img.shields.io/github/actions/workflow/status/comaps/comaps/.github/workflows/ios-check.yaml?label=iOS%20Build&logo=apple&logoColor=white&style=for-the-badge&color=588157" alt="iOS Build Status"/>
</a>
<a href="https://opencollective.com/comaps">
<img src="https://img.shields.io/opencollective/all/comaps?label=Open%20Collective%20Donors&logo=opencollective&logoColor=white&style=for-the-badge&color=588157" alt="Open Collective Donors" style="width: 90%; max-width: 191px;"/>
<img src="https://img.shields.io/opencollective/all/comaps?label=Open%20Collective%20Donors&logo=opencollective&logoColor=white&style=for-the-badge&color=588157" alt="Open Collective Donors"/>
</a>
<a href="https://liberapay.com/CoMaps">
<img src="https://img.shields.io/liberapay/patrons/CoMaps.svg?label=Liberapay%20Patrons&logo=liberapay&logoColor=white&style=for-the-badge&color=588157" alt="Liberapay Patrons" style="width: 90%; max-width: 160px;"/>
<img src="https://img.shields.io/liberapay/patrons/CoMaps.svg?label=Liberapay%20Patrons&logo=liberapay&logoColor=white&style=for-the-badge&color=588157" alt="Liberapay Patrons"/>
</a>
</p>
</div>
@@ -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
@@ -140,7 +139,7 @@ There is a dedicated [Zulip](https://codeberg.org/comaps/Governance/src/branch/m
## 💸 Funding
CoMaps is free. To stay that way, it relies on your support.
CoMaps is free. To fund development, we rely on your voluntary support ♥️
Donate via [OpenCollective](https://opencollective.com/comaps/donate) or [Liberapay](https://liberapay.com/CoMaps).
The project's financial information is completely open and transparent at [our Open Collective](https://opencollective.com/comaps).

View File

@@ -138,8 +138,6 @@ android {
disable 'MissingTranslation'
// https://github.com/organicmaps/organicmaps/issues/3551
disable 'MissingQuantity', 'UnusedQuantity'
// https://github.com/organicmaps/organicmaps/issues/3550
disable 'ByteOrderMark'
// https://github.com/organicmaps/organicmaps/issues/1077
disable 'CustomSplashScreen'
// https://github.com/organicmaps/organicmaps/issues/3610

View File

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

View File

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

View File

@@ -24,7 +24,7 @@ Sartu komunitatean eta lagundu maparik onena aplikatzen
• Lineaz kanpoko Wikipedia artikuluak
• Metroaren garraio geruza eta jarraibideak
• Arrastoen grabazioa
Laster-markak eta ibilbideak esportatu eta inportatu KML, KMZ, GPX formatuetan
Markagailuak eta arrastoak esportatu eta inportatu KML, KMZ, GPX formatuetan
• Gauean erabiltzeko modu iluna
• Hobetu mapako datuak guztiontzat oinarrizko editore integratua erabiliz

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

@@ -0,0 +1 @@
Lett kart navigasjon - Opplev mere på din reise - Drevet av felleskapet

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

@@ -6,7 +6,7 @@
<!-- Requiring "android.hardware.touchscreen" here breaks DeX mode -->
<uses-feature
android:glEsVersion="0x00020000"
android:glEsVersion="0x00030000"
android:required="true"/>
<uses-feature
android:name="android.hardware.wifi"

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
@@ -150,14 +151,14 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
switch (item.newStatus)
{
case CountryItem.STATUS_DONE:
mAreResourcesDownloaded = true;
showMap();
return;
case CountryItem.STATUS_DONE:
mAreResourcesDownloaded = true;
showMap();
return;
case CountryItem.STATUS_FAILED:
MapManager.showError(DownloadResourcesLegacyActivity.this, item, null);
return;
case CountryItem.STATUS_FAILED:
MapManagerHelper.showError(DownloadResourcesLegacyActivity.this, item, null);
return;
}
}
}
@@ -252,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);
@@ -370,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

@@ -23,6 +23,8 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
public class MapFragment extends BaseMwmFragment implements View.OnTouchListener, SurfaceHolder.Callback
{
private static final String TAG = MapFragment.class.getSimpleName();
@NonNull
private final Map mMap = new Map(DisplayType.Device);
public void updateCompassOffset(int offsetX, int offsetY)
@@ -84,6 +86,8 @@ public class MapFragment extends BaseMwmFragment implements View.OnTouchListener
{
Logger.d(TAG);
super.onAttach(context);
mMap.setLocationHelper(MwmApplication.from(requireContext()).getLocationHelper());
mMap.setMapRenderingListener((MapRenderingListener) context);
mMap.setCallbackUnsupported(this::reportUnsupported);
}
@@ -159,24 +163,24 @@ public class MapFragment extends BaseMwmFragment implements View.OnTouchListener
int pointerIndex = event.getActionIndex();
switch (action)
{
case MotionEvent.ACTION_POINTER_UP -> action = Map.NATIVE_ACTION_UP;
case MotionEvent.ACTION_UP ->
{
action = Map.NATIVE_ACTION_UP;
pointerIndex = 0;
}
case MotionEvent.ACTION_POINTER_DOWN -> action = Map.NATIVE_ACTION_DOWN;
case MotionEvent.ACTION_DOWN ->
{
action = Map.NATIVE_ACTION_DOWN;
pointerIndex = 0;
}
case MotionEvent.ACTION_MOVE ->
{
action = Map.NATIVE_ACTION_MOVE;
pointerIndex = Map.INVALID_POINTER_MASK;
}
case MotionEvent.ACTION_CANCEL -> action = Map.NATIVE_ACTION_CANCEL;
case MotionEvent.ACTION_POINTER_UP -> action = Map.NATIVE_ACTION_UP;
case MotionEvent.ACTION_UP ->
{
action = Map.NATIVE_ACTION_UP;
pointerIndex = 0;
}
case MotionEvent.ACTION_POINTER_DOWN -> action = Map.NATIVE_ACTION_DOWN;
case MotionEvent.ACTION_DOWN ->
{
action = Map.NATIVE_ACTION_DOWN;
pointerIndex = 0;
}
case MotionEvent.ACTION_MOVE ->
{
action = Map.NATIVE_ACTION_MOVE;
pointerIndex = Map.INVALID_POINTER_MASK;
}
case MotionEvent.ACTION_CANCEL -> action = Map.NATIVE_ACTION_CANCEL;
}
Map.onTouch(action, event, pointerIndex);
return true;

View File

@@ -12,13 +12,13 @@ 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;
import android.app.Dialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
@@ -28,7 +28,6 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
@@ -66,7 +65,6 @@ import app.organicmaps.downloader.OnmapDownloader;
import app.organicmaps.editor.EditorActivity;
import app.organicmaps.editor.EditorHostFragment;
import app.organicmaps.editor.FeatureCategoryActivity;
import app.organicmaps.editor.OsmLoginActivity;
import app.organicmaps.editor.ReportFragment;
import app.organicmaps.help.HelpActivity;
import app.organicmaps.intent.Factory;
@@ -82,7 +80,6 @@ import app.organicmaps.routing.ManageRouteBottomSheet;
import app.organicmaps.routing.NavigationController;
import app.organicmaps.routing.NavigationService;
import app.organicmaps.routing.RoutingBottomMenuListener;
import app.organicmaps.routing.RoutingController;
import app.organicmaps.routing.RoutingErrorDialogFragment;
import app.organicmaps.routing.RoutingPlanFragment;
import app.organicmaps.routing.RoutingPlanInplaceController;
@@ -100,7 +97,6 @@ import app.organicmaps.sdk.display.DisplayType;
import app.organicmaps.sdk.downloader.MapManager;
import app.organicmaps.sdk.downloader.UpdateInfo;
import app.organicmaps.sdk.editor.Editor;
import app.organicmaps.sdk.editor.OsmOAuth;
import app.organicmaps.sdk.location.LocationHelper;
import app.organicmaps.sdk.location.LocationListener;
import app.organicmaps.sdk.location.LocationState;
@@ -108,6 +104,7 @@ import app.organicmaps.sdk.location.SensorListener;
import app.organicmaps.sdk.location.TrackRecorder;
import app.organicmaps.sdk.maplayer.isolines.IsolinesState;
import app.organicmaps.sdk.routing.RouteMarkType;
import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.routing.RoutingOptions;
import app.organicmaps.sdk.search.SearchEngine;
import app.organicmaps.sdk.settings.RoadType;
@@ -115,8 +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.ThemeSwitcher;
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;
@@ -125,7 +120,9 @@ import app.organicmaps.search.SearchFragment;
import app.organicmaps.settings.DrivingOptionsActivity;
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;
@@ -290,7 +287,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
}
processIntent();
migrateOAuthCredentials();
}
/**
@@ -345,36 +341,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
}
}
private void migrateOAuthCredentials()
{
if (OsmOAuth.containsOAuth1Credentials())
{
// Remove old OAuth v1 secrets
OsmOAuth.clearOAuth1Credentials();
// Notify user to re-login
dismissAlertDialog();
final DialogInterface.OnClickListener navigateToLoginHandler =
(dialog, which) -> startActivity(new Intent(MwmActivity.this, OsmLoginActivity.class));
final int marginBase = getResources().getDimensionPixelSize(R.dimen.margin_base);
final float textSize = getResources().getDimension(R.dimen.line_spacing_extra_1);
final TextView text = new TextView(this);
text.setText(getText(R.string.alert_reauth_message));
text.setPadding(marginBase, marginBase, marginBase, marginBase);
text.setTextSize(textSize);
text.setMovementMethod(LinkMovementMethod.getInstance());
mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.login_osm)
.setView(text)
.setPositiveButton(R.string.login, navigateToLoginHandler)
.setNegativeButton(R.string.cancel, null)
.setOnDismissListener(dialog -> mAlertDialog = null)
.show();
}
}
private static void checkMeasurementSystem()
{
UnitLocale.initializeCurrentUnits();
@@ -492,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);
@@ -619,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));
}
@@ -629,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
@@ -683,29 +647,29 @@ public class MwmActivity extends BaseMwmFragmentActivity
mPointChooser.findViewById(R.id.done).setOnClickListener(v -> {
switch (ChoosePositionMode.get())
{
case Api:
final Intent apiResult = new Intent();
final double[] center = Framework.nativeGetScreenRectCenter();
apiResult.putExtra(Const.EXTRA_POINT_LAT, center[0]);
apiResult.putExtra(Const.EXTRA_POINT_LON, center[1]);
apiResult.putExtra(Const.EXTRA_ZOOM_LEVEL, Framework.nativeGetDrawScale());
setResult(Activity.RESULT_OK, apiResult);
finish();
break;
case Editor:
if (Framework.nativeIsDownloadedMapAtScreenCenter())
startActivity(new Intent(MwmActivity.this, FeatureCategoryActivity.class));
else
{
dismissAlertDialog();
mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.message_invalid_feature_position)
.setPositiveButton(R.string.ok, null)
.setOnDismissListener(dialog -> mAlertDialog = null)
.show();
}
break;
case None: throw new IllegalStateException("Unexpected Framework.nativeGetChoosePositionMode()");
case Api:
final Intent apiResult = new Intent();
final double[] center = Framework.nativeGetScreenRectCenter();
apiResult.putExtra(Const.EXTRA_POINT_LAT, center[0]);
apiResult.putExtra(Const.EXTRA_POINT_LON, center[1]);
apiResult.putExtra(Const.EXTRA_ZOOM_LEVEL, Framework.nativeGetDrawScale());
setResult(Activity.RESULT_OK, apiResult);
finish();
break;
case Editor:
if (Framework.nativeIsDownloadedMapAtScreenCenter())
startActivity(new Intent(MwmActivity.this, FeatureCategoryActivity.class));
else
{
dismissAlertDialog();
mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.message_invalid_feature_position)
.setPositiveButton(R.string.ok, null)
.setOnDismissListener(dialog -> mAlertDialog = null)
.show();
}
break;
case None: throw new IllegalStateException("Unexpected Framework.nativeGetChoosePositionMode()");
}
closePositionChooser();
});
@@ -772,9 +736,9 @@ public class MwmActivity extends BaseMwmFragmentActivity
final View mapView = mMapFragment.getView();
if (mapView != null)
{
int width = mapView.getWidth();
int height = mapView.getHeight();
Framework.nativeSetVisibleRect(0, 0, width, height);
int width = mapView.getWidth();
int height = mapView.getHeight();
Framework.nativeSetVisibleRect(0, 0, width, height);
}
}
UiUtils.show(mPointChooser);
@@ -972,24 +936,24 @@ public class MwmActivity extends BaseMwmFragmentActivity
{
switch (button)
{
case zoomIn -> Map.zoomIn();
case zoomOut -> Map.zoomOut();
case myPosition ->
{
Logger.i(LOCATION_TAG, "The location button pressed");
// Calls onMyPositionModeChanged(mode + 1).
LocationState.nativeSwitchToNextMode();
}
case toggleMapLayer -> toggleMapLayerBottomSheet();
case bookmarks -> showBookmarks();
case search -> showSearch("");
case menu ->
{
closeFloatingPanels();
showBottomSheet(MAIN_MENU_ID);
}
case help -> showHelp();
case trackRecordingStatus -> showTrackSaveDialog();
case zoomIn -> Map.zoomIn();
case zoomOut -> Map.zoomOut();
case myPosition ->
{
Logger.i(LOCATION_TAG, "The location button pressed");
// Calls onMyPositionModeChanged(mode + 1).
LocationState.nativeSwitchToNextMode();
}
case toggleMapLayer -> toggleMapLayerBottomSheet();
case bookmarks -> showBookmarks();
case search -> showSearch("");
case menu ->
{
closeFloatingPanels();
showBottomSheet(MAIN_MENU_ID);
}
case help -> showHelp();
case trackRecordingStatus -> showTrackSaveDialog();
}
}
@@ -1223,21 +1187,22 @@ public class MwmActivity extends BaseMwmFragmentActivity
private void onIsolinesStateChanged(@NonNull IsolinesState type)
{
if (type != IsolinesState.EXPIREDDATA)
if (type == IsolinesState.NODATA)
{
type.activate(this, findViewById(R.id.coordinator), findViewById(R.id.menu_frame));
return;
Toast.makeText(this, R.string.isolines_location_error_dialog, Toast.LENGTH_SHORT).show();
}
dismissAlertDialog();
mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.downloader_update_maps)
.setMessage(R.string.isolines_activation_error_dialog)
.setPositiveButton(R.string.ok,
(dialog, which) -> startActivity(new Intent(this, DownloaderActivity.class)))
.setNegativeButton(R.string.cancel, null)
.setOnDismissListener(dialog -> mAlertDialog = null)
.show();
if (type == IsolinesState.EXPIREDDATA)
{
mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.downloader_update_maps)
.setMessage(R.string.isolines_activation_error_dialog)
.setPositiveButton(
R.string.ok, (dialog, which) -> startActivity(new Intent(this, DownloaderActivity.class)))
.setNegativeButton(R.string.cancel, null)
.setOnDismissListener(dialog -> mAlertDialog = null)
.show();
}
}
@Override
@@ -1682,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);
}
@@ -2428,18 +2393,18 @@ public class MwmActivity extends BaseMwmFragmentActivity
{
switch (keyCode)
{
case KeyEvent.KEYCODE_DPAD_DOWN: Map.zoomOut(); return true;
case KeyEvent.KEYCODE_DPAD_UP: Map.zoomIn(); return true;
case KeyEvent.KEYCODE_ESCAPE:
final Intent currIntent = getIntent();
final String backUrl = Framework.nativeGetParsedBackUrl();
if (TextUtils.isEmpty(backUrl) || (currIntent != null && Factory.isStartedForApiResult(currIntent)))
{
finish();
return true;
}
return super.onKeyUp(keyCode, event);
default: return super.onKeyUp(keyCode, event);
case KeyEvent.KEYCODE_DPAD_DOWN: Map.zoomOut(); return true;
case KeyEvent.KEYCODE_DPAD_UP: Map.zoomIn(); return true;
case KeyEvent.KEYCODE_ESCAPE:
final Intent currIntent = getIntent();
final String backUrl = Framework.nativeGetParsedBackUrl();
if (TextUtils.isEmpty(backUrl) || (currIntent != null && Factory.isStartedForApiResult(currIntent)))
{
finish();
return true;
}
return super.onKeyUp(keyCode, event);
default: return super.onKeyUp(keyCode, event);
}
}
@@ -2491,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());
@@ -2584,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,11 +14,12 @@ 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.routing.RoutingController;
import app.organicmaps.sdk.Map;
import app.organicmaps.sdk.OrganicMaps;
import app.organicmaps.sdk.display.DisplayManager;
@@ -28,9 +29,11 @@ import app.organicmaps.sdk.location.SensorHelper;
import app.organicmaps.sdk.location.TrackRecorder;
import app.organicmaps.sdk.maplayer.isolines.IsolinesManager;
import app.organicmaps.sdk.maplayer.subway.SubwayManager;
import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.ConnectionState;
import app.organicmaps.sdk.util.log.Logger;
import app.organicmaps.util.ThemeSwitcher;
import app.organicmaps.util.Utils;
import java.io.IOException;
import java.lang.ref.WeakReference;
@@ -40,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;
@@ -98,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)
{
@@ -118,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);
@@ -133,6 +148,8 @@ public class MwmApplication extends Application implements Application.ActivityL
public boolean initOrganicMaps(@NonNull Runnable onComplete) throws IOException
{
return mOrganicMaps.init(() -> {
ThemeSwitcher.INSTANCE.initialize(this);
ThemeSwitcher.INSTANCE.restart(false);
ProcessLifecycleOwner.get().getLifecycle().addObserver(mProcessLifecycleObserver);
onComplete.run();
});

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

@@ -62,39 +62,39 @@ public class LocalBackupManager implements BookmarkManager.BookmarksSharingListe
ErrorCode errorCode = null;
switch (result.getCode())
{
case BookmarkSharingResult.SUCCESS ->
{
if (!saveBackup(result))
{
Logger.e(TAG, "Failed to save backup. See system log above");
errorCode = ErrorCode.FILE_ERROR;
}
else
{
Logger.i(TAG, "Backup was created and saved successfully");
}
}
case BookmarkSharingResult.EMPTY_CATEGORY ->
{
errorCode = ErrorCode.EMPTY_CATEGORY;
Logger.e(TAG, "Failed to create backup. Category is empty");
}
case BookmarkSharingResult.ARCHIVE_ERROR ->
{
errorCode = ErrorCode.ARCHIVE_ERROR;
Logger.e(TAG, "Failed to create archive of bookmarks");
}
case BookmarkSharingResult.FILE_ERROR ->
case BookmarkSharingResult.SUCCESS ->
{
if (!saveBackup(result))
{
Logger.e(TAG, "Failed to save backup. See system log above");
errorCode = ErrorCode.FILE_ERROR;
Logger.e(TAG, "Failed create file for archive");
}
default ->
else
{
errorCode = ErrorCode.UNSUPPORTED;
Logger.e(TAG, "Failed to create backup. Unknown error");
Logger.i(TAG, "Backup was created and saved successfully");
}
}
case BookmarkSharingResult.EMPTY_CATEGORY ->
{
errorCode = ErrorCode.EMPTY_CATEGORY;
Logger.e(TAG, "Failed to create backup. Category is empty");
}
case BookmarkSharingResult.ARCHIVE_ERROR ->
{
errorCode = ErrorCode.ARCHIVE_ERROR;
Logger.e(TAG, "Failed to create archive of bookmarks");
}
case BookmarkSharingResult.FILE_ERROR ->
{
errorCode = ErrorCode.FILE_ERROR;
Logger.e(TAG, "Failed create file for archive");
}
default ->
{
errorCode = ErrorCode.UNSUPPORTED;
Logger.e(TAG, "Failed to create backup. Unknown error");
}
}
ErrorCode finalErrorCode = errorCode;
UiThread.run(() -> {

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

@@ -66,47 +66,47 @@ public class BookmarkCategoriesAdapter extends BaseBookmarkCategoryAdapter<Recyc
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch (viewType)
{
case TYPE_ACTION_HEADER ->
{
View header = inflater.inflate(R.layout.item_bookmark_group_list_header, parent, false);
return new HeaderViewHolder(header);
}
case TYPE_CATEGORY_ITEM ->
{
View view = inflater.inflate(R.layout.item_bookmark_category, parent, false);
final CategoryViewHolder holder = new CategoryViewHolder(view);
view.setOnClickListener(new CategoryItemClickListener(holder));
view.setOnLongClickListener(new LongClickListener(holder));
return holder;
}
case TYPE_ACTION_ADD ->
{
View item = inflater.inflate(R.layout.item_bookmark_button, parent, false);
item.setOnClickListener(v -> {
if (mCategoryListCallback != null)
mCategoryListCallback.onAddButtonClick();
});
return new Holders.GeneralViewHolder(item);
}
case TYPE_ACTION_IMPORT ->
{
View item = inflater.inflate(R.layout.item_bookmark_button, parent, false);
item.setOnClickListener(v -> {
if (mCategoryListCallback != null)
mCategoryListCallback.onImportButtonClick();
});
return new Holders.GeneralViewHolder(item);
}
case TYPE_ACTION_EXPORT_ALL_AS_KMZ ->
{
View item = inflater.inflate(R.layout.item_bookmark_button, parent, false);
item.setOnClickListener(v -> {
if (mCategoryListCallback != null)
mCategoryListCallback.onExportButtonClick();
});
return new Holders.GeneralViewHolder(item);
}
default -> throw new AssertionError("Invalid item type: " + viewType);
case TYPE_ACTION_HEADER ->
{
View header = inflater.inflate(R.layout.item_bookmark_group_list_header, parent, false);
return new HeaderViewHolder(header);
}
case TYPE_CATEGORY_ITEM ->
{
View view = inflater.inflate(R.layout.item_bookmark_category, parent, false);
final CategoryViewHolder holder = new CategoryViewHolder(view);
view.setOnClickListener(new CategoryItemClickListener(holder));
view.setOnLongClickListener(new LongClickListener(holder));
return holder;
}
case TYPE_ACTION_ADD ->
{
View item = inflater.inflate(R.layout.item_bookmark_button, parent, false);
item.setOnClickListener(v -> {
if (mCategoryListCallback != null)
mCategoryListCallback.onAddButtonClick();
});
return new Holders.GeneralViewHolder(item);
}
case TYPE_ACTION_IMPORT ->
{
View item = inflater.inflate(R.layout.item_bookmark_button, parent, false);
item.setOnClickListener(v -> {
if (mCategoryListCallback != null)
mCategoryListCallback.onImportButtonClick();
});
return new Holders.GeneralViewHolder(item);
}
case TYPE_ACTION_EXPORT_ALL_AS_KMZ ->
{
View item = inflater.inflate(R.layout.item_bookmark_button, parent, false);
item.setOnClickListener(v -> {
if (mCategoryListCallback != null)
mCategoryListCallback.onExportButtonClick();
});
return new Holders.GeneralViewHolder(item);
}
default -> throw new AssertionError("Invalid item type: " + viewType);
}
}
@@ -116,44 +116,44 @@ public class BookmarkCategoriesAdapter extends BaseBookmarkCategoryAdapter<Recyc
int type = getItemViewType(position);
switch (type)
{
case TYPE_ACTION_HEADER ->
{
HeaderViewHolder headerViewHolder = (HeaderViewHolder) holder;
headerViewHolder.setAction(mMassOperationAction, BookmarkManager.INSTANCE.areAllCategoriesInvisible());
headerViewHolder.getText().setText(R.string.bookmark_lists);
}
case TYPE_CATEGORY_ITEM ->
{
final BookmarkCategory category = getCategoryByPosition(toCategoryPosition(position));
CategoryViewHolder categoryHolder = (CategoryViewHolder) holder;
categoryHolder.setEntity(category);
categoryHolder.setName(category.getName());
categoryHolder.setSize();
categoryHolder.setVisibilityState(category.isVisible());
ToggleVisibilityClickListener visibilityListener = new ToggleVisibilityClickListener(categoryHolder);
categoryHolder.setVisibilityListener(visibilityListener);
CategoryItemMoreClickListener moreClickListener = new CategoryItemMoreClickListener(categoryHolder);
categoryHolder.setMoreButtonClickListener(moreClickListener);
}
case TYPE_ACTION_ADD ->
{
Holders.GeneralViewHolder generalViewHolder = (Holders.GeneralViewHolder) holder;
generalViewHolder.getImage().setImageResource(R.drawable.ic_add_list);
generalViewHolder.getText().setText(R.string.bookmarks_create_new_group);
}
case TYPE_ACTION_IMPORT ->
{
Holders.GeneralViewHolder generalViewHolder = (Holders.GeneralViewHolder) holder;
generalViewHolder.getImage().setImageResource(R.drawable.ic_import);
generalViewHolder.getText().setText(R.string.bookmarks_import);
}
case TYPE_ACTION_EXPORT_ALL_AS_KMZ ->
{
Holders.GeneralViewHolder generalViewHolder = (Holders.GeneralViewHolder) holder;
generalViewHolder.getImage().setImageResource(R.drawable.ic_export);
generalViewHolder.getText().setText(R.string.bookmarks_export);
}
default -> throw new AssertionError("Invalid item type: " + type);
case TYPE_ACTION_HEADER ->
{
HeaderViewHolder headerViewHolder = (HeaderViewHolder) holder;
headerViewHolder.setAction(mMassOperationAction, BookmarkManager.INSTANCE.areAllCategoriesInvisible());
headerViewHolder.getText().setText(R.string.bookmark_lists);
}
case TYPE_CATEGORY_ITEM ->
{
final BookmarkCategory category = getCategoryByPosition(toCategoryPosition(position));
CategoryViewHolder categoryHolder = (CategoryViewHolder) holder;
categoryHolder.setEntity(category);
categoryHolder.setName(category.getName());
categoryHolder.setSize();
categoryHolder.setVisibilityState(category.isVisible());
ToggleVisibilityClickListener visibilityListener = new ToggleVisibilityClickListener(categoryHolder);
categoryHolder.setVisibilityListener(visibilityListener);
CategoryItemMoreClickListener moreClickListener = new CategoryItemMoreClickListener(categoryHolder);
categoryHolder.setMoreButtonClickListener(moreClickListener);
}
case TYPE_ACTION_ADD ->
{
Holders.GeneralViewHolder generalViewHolder = (Holders.GeneralViewHolder) holder;
generalViewHolder.getImage().setImageResource(R.drawable.ic_add_list);
generalViewHolder.getText().setText(R.string.bookmarks_create_new_group);
}
case TYPE_ACTION_IMPORT ->
{
Holders.GeneralViewHolder generalViewHolder = (Holders.GeneralViewHolder) holder;
generalViewHolder.getImage().setImageResource(R.drawable.ic_import);
generalViewHolder.getText().setText(R.string.bookmarks_import);
}
case TYPE_ACTION_EXPORT_ALL_AS_KMZ ->
{
Holders.GeneralViewHolder generalViewHolder = (Holders.GeneralViewHolder) holder;
generalViewHolder.getImage().setImageResource(R.drawable.ic_export);
generalViewHolder.getText().setText(R.string.bookmarks_export);
}
default -> throw new AssertionError("Invalid item type: " + type);
}
}

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

@@ -442,37 +442,37 @@ public class BookmarkListAdapter extends RecyclerView.Adapter<Holders.BaseBookma
Holders.BaseBookmarkHolder holder = null;
switch (viewType)
{
case TYPE_TRACK:
Holders.TrackViewHolder trackHolder =
new Holders.TrackViewHolder(inflater.inflate(R.layout.item_track, parent, false));
trackHolder.setOnClickListener(mClickListener);
trackHolder.setOnLongClickListener(mLongClickListener);
trackHolder.setTrackIconClickListener(mIconClickListener);
trackHolder.setMoreButtonClickListener(mMoreClickListener);
holder = trackHolder;
break;
case TYPE_BOOKMARK:
Holders.BookmarkViewHolder bookmarkHolder =
new Holders.BookmarkViewHolder(inflater.inflate(R.layout.item_bookmark, parent, false));
bookmarkHolder.setOnClickListener(mClickListener);
bookmarkHolder.setOnLongClickListener(mLongClickListener);
holder = bookmarkHolder;
break;
case TYPE_SECTION:
MaterialTextView tv = (MaterialTextView) inflater.inflate(R.layout.item_category_title, parent, false);
holder = new Holders.SectionViewHolder(tv);
break;
case TYPE_DESC:
View desc = inflater.inflate(R.layout.item_category_description, parent, false);
MaterialTextView moreBtn = desc.findViewById(R.id.more_btn);
MaterialTextView text = desc.findViewById(R.id.text);
MaterialTextView title = desc.findViewById(R.id.title);
setMoreButtonVisibility(text, moreBtn);
holder = new Holders.DescriptionViewHolder(desc, mSectionsDataSource.getCategory());
text.setOnClickListener(v -> onMoreButtonClicked(text, moreBtn));
moreBtn.setOnClickListener(v -> onMoreButtonClicked(text, moreBtn));
title.setOnClickListener(v -> onMoreButtonClicked(text, moreBtn));
break;
case TYPE_TRACK:
Holders.TrackViewHolder trackHolder =
new Holders.TrackViewHolder(inflater.inflate(R.layout.item_track, parent, false));
trackHolder.setOnClickListener(mClickListener);
trackHolder.setOnLongClickListener(mLongClickListener);
trackHolder.setTrackIconClickListener(mIconClickListener);
trackHolder.setMoreButtonClickListener(mMoreClickListener);
holder = trackHolder;
break;
case TYPE_BOOKMARK:
Holders.BookmarkViewHolder bookmarkHolder =
new Holders.BookmarkViewHolder(inflater.inflate(R.layout.item_bookmark, parent, false));
bookmarkHolder.setOnClickListener(mClickListener);
bookmarkHolder.setOnLongClickListener(mLongClickListener);
holder = bookmarkHolder;
break;
case TYPE_SECTION:
MaterialTextView tv = (MaterialTextView) inflater.inflate(R.layout.item_category_title, parent, false);
holder = new Holders.SectionViewHolder(tv);
break;
case TYPE_DESC:
View desc = inflater.inflate(R.layout.item_category_description, parent, false);
MaterialTextView moreBtn = desc.findViewById(R.id.more_btn);
MaterialTextView text = desc.findViewById(R.id.text);
MaterialTextView title = desc.findViewById(R.id.title);
setMoreButtonVisibility(text, moreBtn);
holder = new Holders.DescriptionViewHolder(desc, mSectionsDataSource.getCategory());
text.setOnClickListener(v -> onMoreButtonClicked(text, moreBtn));
moreBtn.setOnClickListener(v -> onMoreButtonClicked(text, moreBtn));
title.setOnClickListener(v -> onMoreButtonClicked(text, moreBtn));
break;
}
if (holder == null)

View File

@@ -33,15 +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;
@@ -551,12 +551,12 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
switch (adapter.getItemViewType(position))
{
case BookmarkListAdapter.TYPE_SECTION, BookmarkListAdapter.TYPE_DESC ->
{
return;
}
case BookmarkListAdapter.TYPE_BOOKMARK -> onBookmarkClicked(position, intent, adapter);
case BookmarkListAdapter.TYPE_TRACK -> onTrackClicked(position, intent, adapter);
case BookmarkListAdapter.TYPE_SECTION, BookmarkListAdapter.TYPE_DESC ->
{
return;
}
case BookmarkListAdapter.TYPE_BOOKMARK -> onBookmarkClicked(position, intent, adapter);
case BookmarkListAdapter.TYPE_TRACK -> onTrackClicked(position, intent, adapter);
}
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
@@ -592,7 +592,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
if (mTrack == null)
return;
final Bundle args = new Bundle();
args.putInt(BookmarkColorDialogFragment.ICON_TYPE, Icon.getColorPosition(mTrack.getColor()));
args.putInt(BookmarkColorDialogFragment.ICON_COLOR, PredefinedColors.getPredefinedColorIndex(mTrack.getColor()));
final FragmentManager manager = getChildFragmentManager();
String className = BookmarkColorDialogFragment.class.getName();
final FragmentFactory factory = manager.getFragmentFactory();
@@ -601,7 +601,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
dialogFragment.setArguments(args);
dialogFragment.setOnColorSetListener((colorPos) -> {
int from = mTrack.getColor();
int to = BookmarkManager.ICONS.get(colorPos).argb();
int to = PredefinedColors.getColor(colorPos);
if (from == to)
return;
BookmarkManager.INSTANCE.changeTrackColor(mTrack.getTrackId(), to);
@@ -621,22 +621,22 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
switch (type)
{
case BookmarkListAdapter.TYPE_SECTION:
case BookmarkListAdapter.TYPE_DESC:
// Do nothing here?
break;
case BookmarkListAdapter.TYPE_SECTION:
case BookmarkListAdapter.TYPE_DESC:
// Do nothing here?
break;
case BookmarkListAdapter.TYPE_BOOKMARK:
final BookmarkInfo bookmark = (BookmarkInfo) adapter.getItem(mSelectedPosition);
MenuBottomSheetFragment.newInstance(BOOKMARKS_MENU_ID, bookmark.getName())
.show(getChildFragmentManager(), BOOKMARKS_MENU_ID);
break;
case BookmarkListAdapter.TYPE_BOOKMARK:
final BookmarkInfo bookmark = (BookmarkInfo) adapter.getItem(mSelectedPosition);
MenuBottomSheetFragment.newInstance(BOOKMARKS_MENU_ID, bookmark.getName())
.show(getChildFragmentManager(), BOOKMARKS_MENU_ID);
break;
case BookmarkListAdapter.TYPE_TRACK:
final Track track = (Track) adapter.getItem(mSelectedPosition);
MenuBottomSheetFragment.newInstance(TRACK_MENU_ID, track.getName())
.show(getChildFragmentManager(), TRACK_MENU_ID);
break;
case BookmarkListAdapter.TYPE_TRACK:
final Track track = (Track) adapter.getItem(mSelectedPosition);
MenuBottomSheetFragment.newInstance(TRACK_MENU_ID, track.getName())
.show(getChildFragmentManager(), TRACK_MENU_ID);
break;
}
}
@@ -843,19 +843,19 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
{
switch (id)
{
case BOOKMARKS_MENU_ID ->
{
return getBookmarkMenuItems();
}
case TRACK_MENU_ID ->
{
final Track track = (Track) getBookmarkListAdapter().getItem(mSelectedPosition);
return getTrackMenuItems(track);
}
case OPTIONS_MENU_ID ->
{
return getOptionsMenuItems();
}
case BOOKMARKS_MENU_ID ->
{
return getBookmarkMenuItems();
}
case TRACK_MENU_ID ->
{
final Track track = (Track) getBookmarkListAdapter().getItem(mSelectedPosition);
return getTrackMenuItems(track);
}
case OPTIONS_MENU_ID ->
{
return getOptionsMenuItems();
}
}
return null;
}

View File

@@ -57,27 +57,27 @@ public enum BookmarksSharingHelper
switch (result.getCode())
{
case BookmarkSharingResult.SUCCESS ->
SharingUtils.shareBookmarkFile(context, launcher, result.getSharingPath(), result.getMimeType());
case BookmarkSharingResult.EMPTY_CATEGORY ->
new MaterialAlertDialogBuilder(context, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.bookmarks_error_title_share_empty)
.setMessage(R.string.bookmarks_error_message_share_empty)
.setPositiveButton(R.string.ok, null)
.show();
case BookmarkSharingResult.ARCHIVE_ERROR, BookmarkSharingResult.FILE_ERROR ->
{
new MaterialAlertDialogBuilder(context, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.dialog_routing_system_error)
.setMessage(R.string.bookmarks_error_message_share_general)
.setPositiveButton(R.string.ok, null)
.show();
List<String> names = new ArrayList<>();
for (long categoryId : result.getCategoriesIds())
names.add(BookmarkManager.INSTANCE.getCategoryById(categoryId).getName());
Logger.e(TAG, "Failed to share bookmark categories " + names + ", error code: " + result.getCode());
}
default -> throw new AssertionError("Unsupported bookmark sharing code: " + result.getCode());
case BookmarkSharingResult.SUCCESS ->
SharingUtils.shareBookmarkFile(context, launcher, result.getSharingPath(), result.getMimeType());
case BookmarkSharingResult.EMPTY_CATEGORY ->
new MaterialAlertDialogBuilder(context, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.bookmarks_error_title_share_empty)
.setMessage(R.string.bookmarks_error_message_share_empty)
.setPositiveButton(R.string.ok, null)
.show();
case BookmarkSharingResult.ARCHIVE_ERROR, BookmarkSharingResult.FILE_ERROR ->
{
new MaterialAlertDialogBuilder(context, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.dialog_routing_system_error)
.setMessage(R.string.bookmarks_error_message_share_general)
.setPositiveButton(R.string.ok, null)
.show();
List<String> names = new ArrayList<>();
for (long categoryId : result.getCategoriesIds())
names.add(BookmarkManager.INSTANCE.getCategoryById(categoryId).getName());
Logger.e(TAG, "Failed to share bookmark categories " + names + ", error code: " + result.getCode());
}
default -> throw new AssertionError("Unsupported bookmark sharing code: " + result.getCode());
}
}

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
@@ -64,10 +64,10 @@ public class ChooseBookmarksSortingTypeFragment
{
switch (sortingType)
{
case BookmarkManager.SORT_BY_TYPE: return R.id.sort_by_type;
case BookmarkManager.SORT_BY_DISTANCE: return R.id.sort_by_distance;
case BookmarkManager.SORT_BY_TIME: return R.id.sort_by_time;
case BookmarkManager.SORT_BY_NAME: return R.id.sort_by_name;
case BookmarkManager.SORT_BY_TYPE: return R.id.sort_by_type;
case BookmarkManager.SORT_BY_DISTANCE: return R.id.sort_by_distance;
case BookmarkManager.SORT_BY_TIME: return R.id.sort_by_time;
case BookmarkManager.SORT_BY_NAME: return R.id.sort_by_name;
}
}
return R.id.sort_by_default;

View File

@@ -6,19 +6,26 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import androidx.annotation.DrawableRes;
import app.organicmaps.R;
import app.organicmaps.sdk.bookmarks.data.Icon;
import app.organicmaps.sdk.bookmarks.data.PredefinedColors;
import app.organicmaps.util.Graphics;
import com.google.android.material.imageview.ShapeableImageView;
import java.util.List;
import java.util.Objects;
public class IconsAdapter extends ArrayAdapter<Icon>
public class ColorsAdapter extends ArrayAdapter<Integer>
{
@PredefinedColors.Color
private int mCheckedIconColor;
public IconsAdapter(Context context, List<Icon> list)
@DrawableRes
private final int mIconResId;
public ColorsAdapter(Context context, List<Integer> list, @DrawableRes int iconResId)
{
super(context, 0, 0, list);
mIconResId = iconResId;
}
@Override
@@ -35,19 +42,19 @@ public class IconsAdapter extends ArrayAdapter<Icon>
else
holder = (SpinnerViewHolder) convertView.getTag();
final Icon icon = getItem(position);
@PredefinedColors.Color
final int color = Objects.requireNonNull(getItem(position));
Drawable circle;
if (icon.getColor() == mCheckedIconColor)
if (color == mCheckedIconColor)
{
circle = Graphics.drawCircleAndImage(getItem(position).argb(), R.dimen.track_circle_size,
app.organicmaps.sdk.R.drawable.ic_bookmark_none, R.dimen.bookmark_icon_size,
getContext());
circle = Graphics.drawCircleAndImage(PredefinedColors.getColor(mCheckedIconColor), R.dimen.track_circle_size,
mIconResId, R.dimen.bookmark_icon_size, getContext());
}
else
{
circle =
Graphics.drawCircle(getItem(position).argb(), R.dimen.select_color_circle_size, getContext().getResources());
circle = Graphics.drawCircle(PredefinedColors.getColor(color), R.dimen.select_color_circle_size,
getContext().getResources());
}
holder.icon.setImageDrawable(circle);
return convertView;

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

@@ -26,7 +26,6 @@ import app.organicmaps.car.util.CurrentCountryChangedListener;
import app.organicmaps.car.util.IntentUtils;
import app.organicmaps.car.util.ThemeUtils;
import app.organicmaps.car.util.UserActionRequired;
import app.organicmaps.routing.RoutingController;
import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.PlacePageActivationListener;
import app.organicmaps.sdk.bookmarks.data.MapObject;
@@ -34,6 +33,7 @@ import app.organicmaps.sdk.display.DisplayChangedListener;
import app.organicmaps.sdk.display.DisplayManager;
import app.organicmaps.sdk.display.DisplayType;
import app.organicmaps.sdk.location.LocationState;
import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.LocationUtils;
import app.organicmaps.sdk.util.log.Logger;

View File

@@ -27,7 +27,10 @@ public class SurfaceRenderer implements DefaultLifecycleObserver, SurfaceCallbac
{
private static final String TAG = SurfaceRenderer.class.getSimpleName();
@NonNull
private final CarContext mCarContext;
@NonNull
private final Map mMap = new Map(Car);
@NonNull
@@ -56,6 +59,7 @@ public class SurfaceRenderer implements DefaultLifecycleObserver, SurfaceCallbac
mSurface.release();
mSurface = surfaceContainer.getSurface();
mMap.setLocationHelper(MwmApplication.from(mCarContext).getLocationHelper());
mMap.onSurfaceCreated(mCarContext, mSurface,
new Rect(0, 0, surfaceContainer.getWidth(), surfaceContainer.getHeight()),
surfaceContainer.getDpi());

View File

@@ -28,11 +28,11 @@ import app.organicmaps.car.util.RoutingUtils;
import app.organicmaps.car.util.ThemeUtils;
import app.organicmaps.car.util.UiHelpers;
import app.organicmaps.routing.NavigationService;
import app.organicmaps.routing.RoutingController;
import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.location.LocationHelper;
import app.organicmaps.sdk.location.LocationListener;
import app.organicmaps.sdk.routing.JunctionInfo;
import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.routing.RoutingInfo;
import app.organicmaps.sdk.sound.TtsPlayer;
import app.organicmaps.sdk.util.LocationUtils;

View File

@@ -35,11 +35,11 @@ import app.organicmaps.car.util.OnBackPressedCallback;
import app.organicmaps.car.util.RoutingHelpers;
import app.organicmaps.car.util.UiHelpers;
import app.organicmaps.routing.ResultCodesHelper;
import app.organicmaps.routing.RoutingController;
import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.Router;
import app.organicmaps.sdk.bookmarks.data.MapObject;
import app.organicmaps.sdk.bookmarks.data.Metadata;
import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.routing.RoutingInfo;
import app.organicmaps.sdk.util.Config;
import java.util.Objects;

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

@@ -62,29 +62,29 @@ public final class SearchUiHelpers
CarColor color = Colors.DEFAULT;
switch (searchResult.description.openNow)
{
case SearchResult.OPEN_NOW_YES:
if (searchResult.description.minutesUntilClosed < 60) // less than 1 hour
{
final String time = searchResult.description.minutesUntilClosed + " " + carContext.getString(R.string.minute);
text = carContext.getString(R.string.closes_in, time);
color = Colors.OPENING_HOURS_CLOSES_SOON;
}
else
{
text = carContext.getString(R.string.editor_time_open);
color = Colors.OPENING_HOURS_OPEN;
}
break;
case SearchResult.OPEN_NOW_NO:
if (searchResult.description.minutesUntilOpen < 60) // less than 1 hour
{
final String time = searchResult.description.minutesUntilOpen + " " + carContext.getString(R.string.minute);
text = carContext.getString(R.string.opens_in, time);
}
else
text = carContext.getString(R.string.closed);
color = Colors.OPENING_HOURS_CLOSED;
break;
case SearchResult.OPEN_NOW_YES:
if (searchResult.description.minutesUntilClosed < 60) // less than 1 hour
{
final String time = searchResult.description.minutesUntilClosed + " " + carContext.getString(R.string.minute);
text = carContext.getString(R.string.closes_in, time);
color = Colors.OPENING_HOURS_CLOSES_SOON;
}
else
{
text = carContext.getString(R.string.editor_time_open);
color = Colors.OPENING_HOURS_OPEN;
}
break;
case SearchResult.OPEN_NOW_NO:
if (searchResult.description.minutesUntilOpen < 60) // less than 1 hour
{
final String time = searchResult.description.minutesUntilOpen + " " + carContext.getString(R.string.minute);
text = carContext.getString(R.string.opens_in, time);
}
else
text = carContext.getString(R.string.closed);
color = Colors.OPENING_HOURS_CLOSED;
break;
}
result.append(text);

View File

@@ -7,9 +7,9 @@ import androidx.car.app.CarContext;
import androidx.car.app.ScreenManager;
import app.organicmaps.car.screens.download.DownloadMapsScreen;
import app.organicmaps.car.screens.download.DownloadMapsScreenBuilder;
import app.organicmaps.routing.RoutingController;
import app.organicmaps.sdk.downloader.CountryItem;
import app.organicmaps.sdk.downloader.MapManager;
import app.organicmaps.sdk.routing.RoutingController;
public class CurrentCountryChangedListener implements MapManager.CurrentCountryChangedListener
{

View File

@@ -15,13 +15,13 @@ import app.organicmaps.car.CarAppService;
import app.organicmaps.car.SurfaceRenderer;
import app.organicmaps.car.screens.NavigationScreen;
import app.organicmaps.car.screens.search.SearchScreen;
import app.organicmaps.routing.RoutingController;
import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.Map;
import app.organicmaps.sdk.api.ParsedSearchRequest;
import app.organicmaps.sdk.api.RequestType;
import app.organicmaps.sdk.display.DisplayManager;
import app.organicmaps.sdk.display.DisplayType;
import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.util.log.Logger;
public final class IntentUtils
@@ -65,36 +65,36 @@ public final class IntentUtils
final ScreenManager screenManager = carContext.getCarService(ScreenManager.class);
switch (Framework.nativeParseAndSetApiUrl(uri.toString()))
{
case RequestType.INCORRECT: return;
case RequestType.MAP:
screenManager.popToRoot();
Map.executeMapApiRequest();
return;
case RequestType.SEARCH:
screenManager.popToRoot();
final ParsedSearchRequest request = Framework.nativeGetParsedSearchRequest();
final double[] latlon = Framework.nativeGetParsedCenterLatLon();
if (latlon != null)
{
Framework.nativeStopLocationFollow();
Framework.nativeSetViewportCenter(latlon[0], latlon[1], SEARCH_IN_VIEWPORT_ZOOM);
// We need to update viewport for search api manually because of drape engine
// will not notify subscribers when search activity is shown.
if (!request.mIsSearchOnMap)
Framework.nativeSetSearchViewport(latlon[0], latlon[1], SEARCH_IN_VIEWPORT_ZOOM);
}
final SearchScreen.Builder builder = new SearchScreen.Builder(carContext, surfaceRenderer);
builder.setQuery(request.mQuery);
if (request.mLocale != null)
builder.setLocale(request.mLocale);
case RequestType.INCORRECT: return;
case RequestType.MAP:
screenManager.popToRoot();
Map.executeMapApiRequest();
return;
case RequestType.SEARCH:
screenManager.popToRoot();
final ParsedSearchRequest request = Framework.nativeGetParsedSearchRequest();
final double[] latlon = Framework.nativeGetParsedCenterLatLon();
if (latlon != null)
{
Framework.nativeStopLocationFollow();
Framework.nativeSetViewportCenter(latlon[0], latlon[1], SEARCH_IN_VIEWPORT_ZOOM);
// We need to update viewport for search api manually because of drape engine
// will not notify subscribers when search activity is shown.
if (!request.mIsSearchOnMap)
Framework.nativeSetSearchViewport(latlon[0], latlon[1], SEARCH_IN_VIEWPORT_ZOOM);
}
final SearchScreen.Builder builder = new SearchScreen.Builder(carContext, surfaceRenderer);
builder.setQuery(request.mQuery);
if (request.mLocale != null)
builder.setLocale(request.mLocale);
screenManager.popToRoot();
screenManager.push(builder.build());
return;
case RequestType.ROUTE: Logger.e(TAG, "Route API is not supported by Android Auto: " + uri); return;
case RequestType.CROSSHAIR: Logger.e(TAG, "Crosshair API is not supported by Android Auto: " + uri); return;
case RequestType.MENU: Logger.e(TAG, "Menu API is not supported by Android Auto: " + uri); return;
case RequestType.SETTINGS: Logger.e(TAG, "Settings API is not supported by Android Auto: " + uri);
screenManager.popToRoot();
screenManager.push(builder.build());
return;
case RequestType.ROUTE: Logger.e(TAG, "Route API is not supported by Android Auto: " + uri); return;
case RequestType.CROSSHAIR: Logger.e(TAG, "Crosshair API is not supported by Android Auto: " + uri); return;
case RequestType.MENU: Logger.e(TAG, "Menu API is not supported by Android Auto: " + uri); return;
case RequestType.SETTINGS: Logger.e(TAG, "Settings API is not supported by Android Auto: " + uri);
}
}

View File

@@ -8,21 +8,22 @@ import androidx.annotation.StringRes;
import androidx.annotation.UiThread;
import androidx.car.app.CarContext;
import app.organicmaps.R;
import app.organicmaps.routing.RoutingController;
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

@@ -171,20 +171,20 @@ public final class UiHelpers
int drawableRes;
switch (locationMode)
{
case LocationState.PENDING_POSITION, LocationState.NOT_FOLLOW_NO_POSITION ->
drawableRes = R.drawable.ic_location_off;
case LocationState.NOT_FOLLOW -> drawableRes = R.drawable.ic_not_follow;
case LocationState.FOLLOW ->
{
drawableRes = R.drawable.ic_follow;
tintColor = Colors.LOCATION_TINT;
}
case LocationState.FOLLOW_AND_ROTATE ->
{
drawableRes = R.drawable.ic_follow_and_rotate;
tintColor = Colors.LOCATION_TINT;
}
default -> throw new IllegalArgumentException("Invalid button mode: " + locationMode);
case LocationState.PENDING_POSITION, LocationState.NOT_FOLLOW_NO_POSITION ->
drawableRes = R.drawable.ic_location_off;
case LocationState.NOT_FOLLOW -> drawableRes = R.drawable.ic_not_follow;
case LocationState.FOLLOW ->
{
drawableRes = R.drawable.ic_follow;
tintColor = Colors.LOCATION_TINT;
}
case LocationState.FOLLOW_AND_ROTATE ->
{
drawableRes = R.drawable.ic_follow_and_rotate;
tintColor = Colors.LOCATION_TINT;
}
default -> throw new IllegalArgumentException("Invalid button mode: " + locationMode);
}
final CarIcon icon =

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);
}
};
@@ -115,15 +118,15 @@ class BottomPanel
{
switch (status)
{
case STATUS_UPDATABLE ->
{
UpdateInfo info = MapManager.nativeGetUpdateInfo(root);
setUpdateAllState(info);
} // Special case for "Countries" node when no maps currently downloaded.
case STATUS_DOWNLOADABLE, STATUS_DONE, STATUS_PARTLY -> show = false;
case STATUS_PROGRESS, STATUS_APPLYING, STATUS_ENQUEUED -> setCancelState();
case STATUS_FAILED -> setRetryFailedStates();
default -> throw new IllegalArgumentException("Inappropriate status for \"" + root + "\": " + status);
case STATUS_UPDATABLE ->
{
UpdateInfo info = MapManager.nativeGetUpdateInfo(root);
setUpdateAllState(info);
} // Special case for "Countries" node when no maps currently downloaded.
case STATUS_DOWNLOADABLE, STATUS_DONE, STATUS_PARTLY -> show = false;
case STATUS_PROGRESS, STATUS_APPLYING, STATUS_ENQUEUED -> setCancelState();
case STATUS_FAILED -> setRetryFailedStates();
default -> throw new IllegalArgumentException("Inappropriate status for \"" + root + "\": " + status);
}
}
else
@@ -133,15 +136,15 @@ class BottomPanel
{
switch (status)
{
case STATUS_UPDATABLE ->
{
UpdateInfo info = MapManager.nativeGetUpdateInfo(root);
setUpdateAllState(info);
}
case STATUS_DONE -> show = false;
case STATUS_PROGRESS, STATUS_APPLYING, STATUS_ENQUEUED -> setCancelState();
case STATUS_FAILED -> setRetryFailedStates();
default -> setDownloadAllState();
case STATUS_UPDATABLE ->
{
UpdateInfo info = MapManager.nativeGetUpdateInfo(root);
setUpdateAllState(info);
}
case STATUS_DONE -> show = false;
case STATUS_PROGRESS, STATUS_APPLYING, STATUS_ENQUEUED -> setCancelState();
case STATUS_FAILED -> setRetryFailedStates();
default -> setDownloadAllState();
}
}
}

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;
@@ -70,9 +70,9 @@ public class CountrySuggestFragment extends BaseMwmFragment implements View.OnCl
switch (item.newStatus)
{
case CountryItem.STATUS_FAILED: updateViews(); return;
case CountryItem.STATUS_FAILED: updateViews(); return;
case CountryItem.STATUS_DONE: exitFragment(); return;
case CountryItem.STATUS_DONE: exitFragment(); return;
}
break;
@@ -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

@@ -20,11 +20,11 @@ import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.MwmActivity;
import app.organicmaps.MwmApplication;
import app.organicmaps.R;
import app.organicmaps.routing.RoutingController;
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;
}
}
@@ -287,41 +287,41 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
ArrayList<MenuBottomSheetItem> items = new ArrayList<>();
switch (mSelectedItem.status)
{
case CountryItem.STATUS_DOWNLOADABLE: items.add(getDownloadMenuItem()); break;
case CountryItem.STATUS_DOWNLOADABLE: items.add(getDownloadMenuItem()); break;
case CountryItem.STATUS_UPDATABLE:
items.add(getUpdateMenuItem());
// Fallthrough
case CountryItem.STATUS_UPDATABLE:
items.add(getUpdateMenuItem());
// Fallthrough
case CountryItem.STATUS_DONE:
if (!mSelectedItem.isExpandable())
items.add(getExploreMenuItem());
case CountryItem.STATUS_DONE:
if (!mSelectedItem.isExpandable())
items.add(getExploreMenuItem());
appendDeleteMenuItem(items);
break;
case CountryItem.STATUS_FAILED:
items.add(getCancelMenuItem());
if (mSelectedItem.present)
{
appendDeleteMenuItem(items);
break;
items.add(getExploreMenuItem());
}
break;
case CountryItem.STATUS_FAILED:
items.add(getCancelMenuItem());
case CountryItem.STATUS_PROGRESS:
case CountryItem.STATUS_APPLYING:
case CountryItem.STATUS_ENQUEUED:
items.add(getCancelMenuItem());
if (mSelectedItem.present)
{
appendDeleteMenuItem(items);
items.add(getExploreMenuItem());
}
break;
if (mSelectedItem.present)
items.add(getExploreMenuItem());
break;
case CountryItem.STATUS_PROGRESS:
case CountryItem.STATUS_APPLYING:
case CountryItem.STATUS_ENQUEUED:
items.add(getCancelMenuItem());
if (mSelectedItem.present)
items.add(getExploreMenuItem());
break;
case CountryItem.STATUS_PARTLY:
items.add(getDownloadMenuItem());
appendDeleteMenuItem(items);
break;
case CountryItem.STATUS_PARTLY:
items.add(getDownloadMenuItem());
appendDeleteMenuItem(items);
break;
}
return items;
}
@@ -372,20 +372,23 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
{
switch (mItem.status)
{
case CountryItem.STATUS_DONE, CountryItem.STATUS_PROGRESS, CountryItem.STATUS_APPLYING,
CountryItem.STATUS_ENQUEUED ->
case CountryItem.STATUS_DONE, CountryItem.STATUS_PROGRESS, CountryItem.STATUS_APPLYING,
CountryItem.STATUS_ENQUEUED ->
processLongClick();
case CountryItem.STATUS_DOWNLOADABLE, CountryItem.STATUS_PARTLY ->
{
if (clickOnStatus)
onDownloadActionSelected(mItem, DownloaderAdapter.this);
else
processLongClick();
case CountryItem.STATUS_DOWNLOADABLE, CountryItem.STATUS_PARTLY ->
{
if (clickOnStatus)
onDownloadActionSelected(mItem, DownloaderAdapter.this);
else
processLongClick();
}
case CountryItem.STATUS_FAILED -> MapManager.warn3gAndRetry(mActivity, mItem.id, null);
case CountryItem.STATUS_UPDATABLE ->
MapManager.warnOn3gUpdate(mActivity, mItem.id, () -> MapManager.startUpdate(mItem.id));
default -> throw new IllegalArgumentException("Inappropriate item status: " + mItem.status);
}
case CountryItem.STATUS_FAILED ->
{
MapManagerHelper.warn3gAndRetry(mActivity, mItem.id, null);
}
case CountryItem.STATUS_UPDATABLE ->
MapManagerHelper.warnOn3gUpdate(mActivity, mItem.id, () -> MapManagerHelper.startUpdate(mItem.id));
default -> throw new IllegalArgumentException("Inappropriate item status: " + mItem.status);
}
}
@@ -535,33 +538,33 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
{
switch (ci.category)
{
case CountryItem.CATEGORY_NEAR_ME ->
case CountryItem.CATEGORY_NEAR_ME ->
{
if (ci.category != prev)
{
if (ci.category != prev)
{
headerId = CountryItem.CATEGORY_NEAR_ME;
mItemsAndHeader.add(new GenericItem(mActivity.getString(R.string.downloader_near_me_subtitle)));
prev = ci.category;
}
}
case CountryItem.CATEGORY_DOWNLOADED ->
{
if (ci.category != prev)
{
headerId = CountryItem.CATEGORY_DOWNLOADED;
mItemsAndHeader.add(new GenericItem(mActivity.getString(R.string.downloader_downloaded_subtitle)));
prev = ci.category;
}
}
default ->
{
int prevHeader = headerId;
headerId = CountryItem.CATEGORY_AVAILABLE + ci.name.charAt(0);
if (headerId != prevHeader)
mItemsAndHeader.add(new GenericItem(StringUtils.toUpperCase(ci.name.substring(0, 1))));
headerId = CountryItem.CATEGORY_NEAR_ME;
mItemsAndHeader.add(new GenericItem(mActivity.getString(R.string.downloader_near_me_subtitle)));
prev = ci.category;
}
}
case CountryItem.CATEGORY_DOWNLOADED ->
{
if (ci.category != prev)
{
headerId = CountryItem.CATEGORY_DOWNLOADED;
mItemsAndHeader.add(new GenericItem(mActivity.getString(R.string.downloader_downloaded_subtitle)));
prev = ci.category;
}
}
default ->
{
int prevHeader = headerId;
headerId = CountryItem.CATEGORY_AVAILABLE + ci.name.charAt(0);
if (headerId != prevHeader)
mItemsAndHeader.add(new GenericItem(StringUtils.toUpperCase(ci.name.substring(0, 1))));
prev = ci.category;
}
}
ci.headerId = headerId;
}
mItemsAndHeader.add(new GenericItem(ci));

View File

@@ -24,8 +24,8 @@ import app.organicmaps.widget.PlaceholderView;
import java.util.ArrayList;
import java.util.List;
public class DownloaderFragment extends BaseMwmRecyclerFragment<DownloaderAdapter>
implements MenuBottomSheetFragment.MenuBottomSheetInterface
public class DownloaderFragment
extends BaseMwmRecyclerFragment<DownloaderAdapter> implements MenuBottomSheetFragment.MenuBottomSheetInterface
{
private DownloaderToolbarController mToolbarController;
@@ -153,7 +153,8 @@ public class DownloaderFragment extends BaseMwmRecyclerFragment<DownloaderAdapte
mBottomPanel = new BottomPanel(this, view);
mToolbarController = new DownloaderToolbarController(view, requireActivity(), this);
requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), mToolbarController.getBackPressedCallback());
requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(),
mToolbarController.getBackPressedCallback());
update();
}
@@ -195,7 +196,8 @@ public class DownloaderFragment extends BaseMwmRecyclerFragment<DownloaderAdapte
{
if (mAdapter == null)
mAdapter = new DownloaderAdapter(this);
requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), mAdapter.getBackPressedCallback());
requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(),
mAdapter.getBackPressedCallback());
return mAdapter;
}

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

@@ -9,13 +9,13 @@ import androidx.core.view.ViewCompat;
import app.organicmaps.MwmActivity;
import app.organicmaps.MwmApplication;
import app.organicmaps.R;
import app.organicmaps.routing.RoutingController;
import app.organicmaps.sdk.downloader.CountryItem;
import app.organicmaps.sdk.downloader.MapManager;
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;
@@ -87,8 +87,8 @@ public class AdvancedTimetableFragment extends BaseMwmFragment implements View.O
private void setExampleDrawables(@DrawableRes int left, @DrawableRes int right)
{
mExamplesTitle.setCompoundDrawablesRelativeWithIntrinsicBounds(
Graphics.tint(requireActivity(), left, androidx.appcompat.R.attr.colorAccent), null,
Graphics.tint(requireActivity(), right, androidx.appcompat.R.attr.colorAccent), null);
Graphics.tint(requireActivity(), left, com.google.android.material.R.attr.colorSecondary), null,
Graphics.tint(requireActivity(), right, com.google.android.material.R.attr.colorSecondary), null);
}
@Override

View File

@@ -20,19 +20,19 @@ import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R;
import app.organicmaps.base.BaseMwmFragment;
import app.organicmaps.dialog.EditTextDialogFragment;
import app.organicmaps.editor.data.TimeFormatUtils;
import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.bookmarks.data.Metadata;
import app.organicmaps.sdk.editor.Editor;
import app.organicmaps.sdk.editor.OpeningHours;
import app.organicmaps.sdk.editor.data.LocalizedName;
import app.organicmaps.sdk.editor.data.LocalizedStreet;
import app.organicmaps.editor.data.TimeFormatUtils;
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++)
@@ -623,11 +641,11 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
switch (Editor.nativeGetMapObjectStatus())
{
case Editor.CREATED -> mReset.setText(R.string.editor_remove_place_button);
case Editor.MODIFIED -> mReset.setText(R.string.editor_reset_edits_button);
case Editor.UNTOUCHED -> mReset.setText(R.string.editor_place_doesnt_exist);
case Editor.DELETED -> throw new IllegalStateException("Can't delete already deleted feature.");
case Editor.OBSOLETE -> throw new IllegalStateException("Obsolete objects cannot be reverted.");
case Editor.CREATED -> mReset.setText(R.string.editor_remove_place_button);
case Editor.MODIFIED -> mReset.setText(R.string.editor_reset_edits_button);
case Editor.UNTOUCHED -> mReset.setText(R.string.editor_place_doesnt_exist);
case Editor.DELETED -> throw new IllegalStateException("Can't delete already deleted feature.");
case Editor.OBSOLETE -> throw new IllegalStateException("Obsolete objects cannot be reverted.");
}
}
@@ -641,11 +659,11 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
switch (Editor.nativeGetMapObjectStatus())
{
case Editor.CREATED -> rollback(Editor.CREATED);
case Editor.MODIFIED -> rollback(Editor.MODIFIED);
case Editor.UNTOUCHED -> placeDoesntExist();
case Editor.DELETED -> throw new IllegalStateException("Can't delete already deleted feature.");
case Editor.OBSOLETE -> throw new IllegalStateException("Obsolete objects cannot be reverted.");
case Editor.CREATED -> rollback(Editor.CREATED);
case Editor.MODIFIED -> rollback(Editor.MODIFIED);
case Editor.UNTOUCHED -> placeDoesntExist();
case Editor.DELETED -> throw new IllegalStateException("Can't delete already deleted feature.");
case Editor.OBSOLETE -> throw new IllegalStateException("Obsolete objects cannot be reverted.");
}
}

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;
@@ -173,8 +172,8 @@ public class EditorHostFragment
{
switch (mMode)
{
case OPENING_HOURS, STREET, CUISINE, LANGUAGE, PHONE, SELF_SERVICE -> editMapObject();
default -> Utils.navigateToParent(requireActivity());
case OPENING_HOURS, STREET, CUISINE, LANGUAGE, PHONE, SELF_SERVICE -> editMapObject();
default -> Utils.navigateToParent(requireActivity());
}
return true;
}
@@ -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)
{
@@ -283,57 +287,57 @@ public class EditorHostFragment
{
switch (mMode)
{
case OPENING_HOURS ->
{
final String timetables = ((TimetableContainerFragment) getChildFragmentManager().findFragmentByTag(
TimetableContainerFragment.class.getName()))
.getTimetable();
Editor.nativeSetOpeningHours(timetables);
editMapObject();
}
case STREET ->
setStreet(((StreetFragment) getChildFragmentManager().findFragmentByTag(StreetFragment.class.getName()))
.getStreet());
case CUISINE ->
{
String[] cuisines =
((CuisineFragment) getChildFragmentManager().findFragmentByTag(CuisineFragment.class.getName()))
.getCuisines();
Editor.nativeSetSelectedCuisines(cuisines);
editMapObject();
}
case SELF_SERVICE ->
setSelection(
Metadata.MetadataType.FMD_SELF_SERVICE,
((SelfServiceFragment) getChildFragmentManager().findFragmentByTag(SelfServiceFragment.class.getName()))
.getSelection());
case LANGUAGE -> editMapObject();
case MAP_OBJECT ->
{
if (!setEdits())
return;
case OPENING_HOURS ->
{
final String timetables = ((TimetableContainerFragment) getChildFragmentManager().findFragmentByTag(
TimetableContainerFragment.class.getName()))
.getTimetable();
Editor.nativeSetOpeningHours(timetables);
editMapObject();
}
case STREET ->
setStreet(
((StreetFragment) getChildFragmentManager().findFragmentByTag(StreetFragment.class.getName())).getStreet());
case CUISINE ->
{
String[] cuisines =
((CuisineFragment) getChildFragmentManager().findFragmentByTag(CuisineFragment.class.getName()))
.getCuisines();
Editor.nativeSetSelectedCuisines(cuisines);
editMapObject();
}
case SELF_SERVICE ->
setSelection(
Metadata.MetadataType.FMD_SELF_SERVICE,
((SelfServiceFragment) getChildFragmentManager().findFragmentByTag(SelfServiceFragment.class.getName()))
.getSelection());
case LANGUAGE -> editMapObject();
case MAP_OBJECT ->
{
if (!saveEdits())
return;
// Save object edits
if (!MwmApplication.prefs(requireContext()).contains(NOOB_ALERT_SHOWN))
{
showNoobDialog();
}
else
{
saveNote();
saveMapObjectEdits();
}
}
case PHONE ->
// Save object edits
if (!MwmApplication.prefs(requireContext()).contains(NOOB_ALERT_SHOWN))
{
final String phone =
((PhoneFragment) getChildFragmentManager().findFragmentByTag(PhoneFragment.class.getName())).getPhone();
if (Editor.nativeIsPhoneValid(phone))
{
Editor.nativeSetPhone(phone);
editMapObject();
}
showNoobDialog();
}
else
{
saveNote();
saveMapObjectEdits();
}
}
case PHONE ->
{
final String phone =
((PhoneFragment) getChildFragmentManager().findFragmentByTag(PhoneFragment.class.getName())).getPhone();
if (Editor.nativeIsPhoneValid(phone))
{
Editor.nativeSetPhone(phone);
editMapObject();
}
}
}
}
}

View File

@@ -9,7 +9,9 @@ import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R;
import app.organicmaps.sdk.editor.data.FeatureCategory;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.util.UiUtils;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textview.MaterialTextView;
public class FeatureCategoryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
@@ -21,6 +23,12 @@ public class FeatureCategoryAdapter extends RecyclerView.Adapter<RecyclerView.Vi
private final FeatureCategoryFragment mFragment;
private final FeatureCategory mSelectedCategory;
public interface FooterListener
{
void onNoteTextChanged(String newText);
void onSendNoteClicked();
}
public FeatureCategoryAdapter(@NonNull FeatureCategoryFragment host, @NonNull FeatureCategory[] categories,
@Nullable FeatureCategory category)
{
@@ -47,19 +55,23 @@ public class FeatureCategoryAdapter extends RecyclerView.Adapter<RecyclerView.Vi
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch (viewType)
{
case TYPE_CATEGORY ->
{
return new FeatureViewHolder(
LayoutInflater.from(parent.getContext()).inflate(R.layout.item_feature_category, parent, false));
}
case TYPE_FOOTER ->
{
return new FooterViewHolder(
LayoutInflater.from(parent.getContext()).inflate(R.layout.item_feature_category_footer, parent, false));
}
default -> throw new IllegalArgumentException("Unsupported");
case TYPE_CATEGORY ->
{
return new FeatureViewHolder(inflater.inflate(R.layout.item_feature_category, parent, false));
}
case TYPE_FOOTER ->
{
return new FooterViewHolder(inflater.inflate(R.layout.item_feature_category_footer, parent, false),
(FooterListener) mFragment);
}
default ->
{
throw new IllegalArgumentException("Unsupported viewType: " + viewType);
}
}
}
@@ -70,6 +82,10 @@ public class FeatureCategoryAdapter extends RecyclerView.Adapter<RecyclerView.Vi
{
((FeatureViewHolder) holder).bind(position);
}
else if (holder instanceof FooterViewHolder)
{
((FooterViewHolder) holder).bind(mFragment.getPendingNoteText());
}
}
@Override
@@ -105,11 +121,36 @@ public class FeatureCategoryAdapter extends RecyclerView.Adapter<RecyclerView.Vi
protected static class FooterViewHolder extends RecyclerView.ViewHolder
{
FooterViewHolder(@NonNull View itemView)
private final TextInputEditText mNoteEditText;
private final View mSendNoteButton;
FooterViewHolder(@NonNull View itemView, @NonNull FooterListener listener)
{
super(itemView);
MaterialTextView categoryUnsuitableText = itemView.findViewById(R.id.editor_category_unsuitable_text);
categoryUnsuitableText.setMovementMethod(LinkMovementMethod.getInstance());
mNoteEditText = itemView.findViewById(R.id.note_edit_text);
mSendNoteButton = itemView.findViewById(R.id.send_note_button);
mSendNoteButton.setOnClickListener(v -> listener.onSendNoteClicked());
mNoteEditText.addTextChangedListener(new StringUtils.SimpleTextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
final String str = s.toString();
listener.onNoteTextChanged(str);
mSendNoteButton.setEnabled(!str.trim().isEmpty());
}
});
}
public void bind(String pendingNoteText)
{
if (!mNoteEditText.getText().toString().equals(pendingNoteText))
{
mNoteEditText.setText(pendingNoteText);
if (pendingNoteText != null)
mNoteEditText.setSelection(pendingNoteText.length());
}
mSendNoteButton.setEnabled(pendingNoteText != null && !pendingNoteText.trim().isEmpty());
}
}

View File

@@ -2,28 +2,39 @@ package app.organicmaps.editor;
import static app.organicmaps.sdk.util.Utils.getLocalizedFeatureType;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.CallSuper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import app.organicmaps.MwmApplication;
import app.organicmaps.R;
import app.organicmaps.base.BaseMwmRecyclerFragment;
import app.organicmaps.dialog.EditTextDialogFragment;
import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.editor.Editor;
import app.organicmaps.sdk.editor.OsmOAuth;
import app.organicmaps.sdk.editor.data.FeatureCategory;
import app.organicmaps.sdk.util.Language;
import app.organicmaps.util.Utils;
import app.organicmaps.widget.SearchToolbarController;
import app.organicmaps.widget.ToolbarController;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.util.Arrays;
import java.util.Comparator;
public class FeatureCategoryFragment extends BaseMwmRecyclerFragment<FeatureCategoryAdapter>
public class FeatureCategoryFragment
extends BaseMwmRecyclerFragment<FeatureCategoryAdapter> implements FeatureCategoryAdapter.FooterListener
{
private FeatureCategory mSelectedCategory;
protected ToolbarController mToolbarController;
private static final String NOTE_CONFIRMATION_SHOWN = "NoteConfirmationAlertWasShown";
private static String mPendingNoteText = "";
public interface FeatureCategoryListener
{
@@ -104,4 +115,71 @@ public class FeatureCategoryFragment extends BaseMwmRecyclerFragment<FeatureCate
else if (getParentFragment() instanceof FeatureCategoryListener)
((FeatureCategoryListener) getParentFragment()).onFeatureCategorySelected(category);
}
public String getPendingNoteText()
{
return mPendingNoteText;
}
@Override
public void onNoteTextChanged(String newText)
{
mPendingNoteText = newText;
}
@Override
public void onSendNoteClicked()
{
final double[] center = Framework.nativeGetScreenRectCenter();
final double lat = center[0];
final double lon = center[1];
if (!MwmApplication.prefs(requireContext().getApplicationContext()).contains(NOTE_CONFIRMATION_SHOWN))
{
showNoteConfirmationDialog(lat, lon, mPendingNoteText);
}
else
{
Editor.nativeCreateStandaloneNote(lat, lon, mPendingNoteText);
mPendingNoteText = "";
Toast.makeText(requireContext(), R.string.osm_note_toast, Toast.LENGTH_SHORT).show();
if (!OsmOAuth.isAuthorized())
{
final Intent intent = new Intent(requireActivity(), OsmLoginActivity.class);
startActivity(intent);
}
requireActivity().finish();
}
}
// Duplicate of showNoobDialog()
private void showNoteConfirmationDialog(double lat, double lon, String noteText)
{
new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setTitle(R.string.editor_share_to_all_dialog_title)
.setMessage(getString(R.string.editor_share_to_all_dialog_message_1) + " "
+ getString(R.string.editor_share_to_all_dialog_message_2))
.setPositiveButton(android.R.string.ok,
(dlg, which) -> {
MwmApplication.prefs(requireContext().getApplicationContext())
.edit()
.putBoolean(NOTE_CONFIRMATION_SHOWN, true)
.apply();
Editor.nativeCreateStandaloneNote(lat, lon, noteText);
mPendingNoteText = "";
Toast.makeText(requireContext(), R.string.osm_note_toast, Toast.LENGTH_SHORT).show();
if (!OsmOAuth.isAuthorized())
{
final Intent intent = new Intent(requireActivity(), OsmLoginActivity.class);
startActivity(intent);
}
requireActivity().finish();
})
.setNegativeButton(R.string.cancel, null)
.show();
}
}

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,15 +141,15 @@ 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);
tabView.setText(getResources().getString(R.string.editor_time_to));
tabView.setTextColor(textColor);
mTabs.addTab(mTabs.newTab().setCustomView(tabView), true);
mTabs.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
mTabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab)
{

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

@@ -13,12 +13,13 @@ import androidx.appcompat.widget.SwitchCompat;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R;
import app.organicmaps.editor.data.TimeFormatUtils;
import app.organicmaps.sdk.editor.OpeningHours;
import app.organicmaps.sdk.editor.data.HoursMinutes;
import app.organicmaps.editor.data.TimeFormatUtils;
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;
@@ -162,8 +162,8 @@ public class TimetableContainerFragment extends BaseMwmFragment implements Timet
switch (mMode)
{
case SIMPLE -> setMode(Mode.ADVANCED, filledTimetables);
case ADVANCED -> setMode(Mode.SIMPLE, filledTimetables);
case SIMPLE -> setMode(Mode.ADVANCED, filledTimetables);
case ADVANCED -> setMode(Mode.SIMPLE, filledTimetables);
}
}

View File

@@ -42,8 +42,8 @@ public class FaqFragment extends BaseMwmFragment
{
switch (which)
{
case 0 -> sendGeneralFeedback();
case 1 -> reportBug();
case 0 -> sendGeneralFeedback();
case 1 -> reportBug();
}
}
};

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

@@ -10,7 +10,6 @@ import androidx.core.content.IntentCompat;
import app.organicmaps.MwmActivity;
import app.organicmaps.MwmApplication;
import app.organicmaps.editor.OsmLoginActivity;
import app.organicmaps.routing.RoutingController;
import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.Map;
import app.organicmaps.sdk.api.ParsedRoutingData;
@@ -20,6 +19,7 @@ import app.organicmaps.sdk.api.RoutePoint;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.sdk.bookmarks.data.FeatureId;
import app.organicmaps.sdk.bookmarks.data.MapObject;
import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.search.SearchEngine;
import app.organicmaps.sdk.util.StorageUtils;
import app.organicmaps.sdk.util.concurrency.ThreadPool;
@@ -78,67 +78,67 @@ public class Factory
switch (Framework.nativeParseAndSetApiUrl(uri.toString()))
{
case RequestType.INCORRECT: return false;
case RequestType.INCORRECT: return false;
case RequestType.MAP:
SearchEngine.INSTANCE.cancelInteractiveSearch();
Map.executeMapApiRequest();
return true;
case RequestType.MAP:
SearchEngine.INSTANCE.cancelInteractiveSearch();
Map.executeMapApiRequest();
return true;
case RequestType.ROUTE:
SearchEngine.INSTANCE.cancelInteractiveSearch();
final ParsedRoutingData data = Framework.nativeGetParsedRoutingData();
RoutingController.get().setRouterType(data.mRouterType);
final RoutePoint from = data.mPoints[0];
final RoutePoint to = data.mPoints[1];
RoutingController.get().prepare(
MapObject.createMapObject(FeatureId.EMPTY, MapObject.API_POINT, from.mName, "", from.mLat, from.mLon),
MapObject.createMapObject(FeatureId.EMPTY, MapObject.API_POINT, to.mName, "", to.mLat, to.mLon));
return true;
case RequestType.SEARCH:
case RequestType.ROUTE:
SearchEngine.INSTANCE.cancelInteractiveSearch();
final ParsedRoutingData data = Framework.nativeGetParsedRoutingData();
RoutingController.get().setRouterType(data.mRouterType);
final RoutePoint from = data.mPoints[0];
final RoutePoint to = data.mPoints[1];
RoutingController.get().prepare(
MapObject.createMapObject(FeatureId.EMPTY, MapObject.API_POINT, from.mName, "", from.mLat, from.mLon),
MapObject.createMapObject(FeatureId.EMPTY, MapObject.API_POINT, to.mName, "", to.mLat, to.mLon));
return true;
case RequestType.SEARCH:
{
SearchEngine.INSTANCE.cancelInteractiveSearch();
final ParsedSearchRequest request = Framework.nativeGetParsedSearchRequest();
final double[] latlon = Framework.nativeGetParsedCenterLatLon();
if (latlon != null)
{
SearchEngine.INSTANCE.cancelInteractiveSearch();
final ParsedSearchRequest request = Framework.nativeGetParsedSearchRequest();
final double[] latlon = Framework.nativeGetParsedCenterLatLon();
if (latlon != null)
{
Framework.nativeStopLocationFollow();
Framework.nativeSetViewportCenter(latlon[0], latlon[1], SEARCH_IN_VIEWPORT_ZOOM);
// We need to update viewport for search api manually because of drape engine
// will not notify subscribers when search activity is shown.
if (!request.mIsSearchOnMap)
Framework.nativeSetSearchViewport(latlon[0], latlon[1], SEARCH_IN_VIEWPORT_ZOOM);
}
SearchActivity.start(target, request.mQuery, request.mLocale, request.mIsSearchOnMap);
return true;
Framework.nativeStopLocationFollow();
Framework.nativeSetViewportCenter(latlon[0], latlon[1], SEARCH_IN_VIEWPORT_ZOOM);
// We need to update viewport for search api manually because of drape engine
// will not notify subscribers when search activity is shown.
if (!request.mIsSearchOnMap)
Framework.nativeSetSearchViewport(latlon[0], latlon[1], SEARCH_IN_VIEWPORT_ZOOM);
}
case RequestType.CROSSHAIR:
SearchActivity.start(target, request.mQuery, request.mLocale, request.mIsSearchOnMap);
return true;
}
case RequestType.CROSSHAIR:
{
SearchEngine.INSTANCE.cancelInteractiveSearch();
target.showPositionChooserForAPI(Framework.nativeGetParsedAppName());
final double[] latlon = Framework.nativeGetParsedCenterLatLon();
if (latlon != null)
{
SearchEngine.INSTANCE.cancelInteractiveSearch();
target.showPositionChooserForAPI(Framework.nativeGetParsedAppName());
final double[] latlon = Framework.nativeGetParsedCenterLatLon();
if (latlon != null)
{
Framework.nativeStopLocationFollow();
Framework.nativeSetViewportCenter(latlon[0], latlon[1], SEARCH_IN_VIEWPORT_ZOOM);
}
return true;
}
case RequestType.OAUTH2:
{
SearchEngine.INSTANCE.cancelInteractiveSearch();
final String oauth2code = Framework.nativeGetParsedOAuth2Code();
OsmLoginActivity.OAuth2Callback(target, oauth2code);
return true;
Framework.nativeStopLocationFollow();
Framework.nativeSetViewportCenter(latlon[0], latlon[1], SEARCH_IN_VIEWPORT_ZOOM);
}
// Menu and Settings url types should be implemented to support deeplinking.
case RequestType.MENU:
case RequestType.SETTINGS:
return true;
}
case RequestType.OAUTH2:
{
SearchEngine.INSTANCE.cancelInteractiveSearch();
final String oauth2code = Framework.nativeGetParsedOAuth2Code();
OsmLoginActivity.OAuth2Callback(target, oauth2code);
return true;
}
// Menu and Settings url types should be implemented to support deeplinking.
case RequestType.MENU:
case RequestType.SETTINGS:
}
return false;

View File

@@ -42,26 +42,26 @@ public class LayerBottomSheetItem
int buttonTextResource = R.string.layers_title;
switch (mode)
{
case OUTDOORS:
disabledResource = R.attr.outdoorsMenuDisabled;
enabledResource = R.attr.outdoorsMenuEnabled;
buttonTextResource = R.string.button_layer_outdoor;
break;
case SUBWAY:
disabledResource = R.attr.subwayMenuDisabled;
enabledResource = R.attr.subwayMenuEnabled;
buttonTextResource = R.string.subway;
break;
case ISOLINES:
disabledResource = R.attr.isoLinesMenuDisabled;
enabledResource = R.attr.isoLinesMenuEnabled;
buttonTextResource = R.string.button_layer_isolines;
break;
case TRAFFIC:
disabledResource = R.attr.trafficMenuDisabled;
enabledResource = R.attr.trafficMenuEnabled;
buttonTextResource = R.string.button_layer_traffic;
break;
case OUTDOORS:
disabledResource = R.attr.outdoorsMenuDisabled;
enabledResource = R.attr.outdoorsMenuEnabled;
buttonTextResource = R.string.button_layer_outdoor;
break;
case SUBWAY:
disabledResource = R.attr.subwayMenuDisabled;
enabledResource = R.attr.subwayMenuEnabled;
buttonTextResource = R.string.subway;
break;
case ISOLINES:
disabledResource = R.attr.isoLinesMenuDisabled;
enabledResource = R.attr.isoLinesMenuEnabled;
buttonTextResource = R.string.button_layer_isolines;
break;
case TRAFFIC:
disabledResource = R.attr.trafficMenuDisabled;
enabledResource = R.attr.trafficMenuEnabled;
buttonTextResource = R.string.button_layer_traffic;
break;
}
int disabled = ThemeUtils.getResource(mContext, disabledResource);
int enabled = ThemeUtils.getResource(mContext, enabledResource);

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