Compare commits

..

84 Commits

Author SHA1 Message Date
Harry Bond
00e77cd745 [android] Add Map Layers button to custom left button options
Signed-off-by: Harry Bond <me@hbond.xyz>

Signed-off-by: Harry Bond <me@hbond.xyz>
2025-08-06 09:49:44 +01:00
x7z4w
ae0ef4d3f8 [ios] Run configure.sh for clean builds
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-08-05 10:16:31 +00:00
Jean-Baptiste
68d1ead44c [doc] Improve doc and updates codeberg teams
Signed-off-by: Jean-Baptiste Charron <jeanbaptiste.charron@outlook.fr>
2025-08-04 19:10:52 +02:00
x7z4w
09de87fd29 [ci] Use container with Android SDK
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-08-03 17:44:59 +02:00
Yannik Bloscheck
1a241121c4 [ios] Fix configure.sh at build for Xcode
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-08-03 13:14:58 +02:00
Eivind Samseth
fdeeb1ae34 [routing] Add faux oneways for motor_vehicle and vehicle forward/backward
Signed-off-by: Eivind Samseth <eisa01@gmail.com>
Co-authored-by: Eivind Samseth <eisa01@gmail.com>
Co-committed-by: Eivind Samseth <eisa01@gmail.com>
2025-08-02 22:57:41 +02:00
Codeberg Translate
c2bd2b897a [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: Lenny Angst <lenny@familie-angst.ch>
Co-authored-by: N4ta <codeberg@n4ta.anonaddy.me>
Co-authored-by: NLBRT <nlbrt@noreply.codeberg.org>
Co-authored-by: Outbreak2096 <outbreak2096@noreply.codeberg.org>
Co-authored-by: Priit Jõerüüt <jrtcdbrg@noreply.codeberg.org>
Co-authored-by: Weblate <noreply-mt-weblate@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: cramoe <cramoe@noreply.codeberg.org>
Co-authored-by: joysriramsarkar <joysriramsarkar@noreply.codeberg.org>
Co-authored-by: matheusgomesms <matheusgomesms@noreply.codeberg.org>
Co-authored-by: patepelo <patepelo@noreply.codeberg.org>
Co-authored-by: sunsand <sunsand@noreply.codeberg.org>
Co-authored-by: x7z4w <x7z4w@noreply.codeberg.org>
Co-authored-by: yannikbloscheck <yannikbloscheck@noreply.codeberg.org>
Translate-URL: https://translate.codeberg.org/projects/comaps/appstore-description/
Translate-URL: https://translate.codeberg.org/projects/comaps/countries/
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/Google Play and Huawei AppGallery descriptions
Translation: CoMaps/iOS - Map Feature Types
Translation: CoMaps/iOS Plist
Translation: CoMaps/iOS Plurals
Translation: CoMaps/iOS UI Strings
2025-08-02 18:46:36 +00:00
matkoniecz
e39b5eb507 [strings] Add key cutter synonyms
Signed-off-by: matkoniecz <matkoniecz@noreply.codeberg.org>
Co-authored-by: matkoniecz <matkoniecz@noreply.codeberg.org>
Co-committed-by: matkoniecz <matkoniecz@noreply.codeberg.org>
2025-08-02 15:52:04 +02:00
x7z4w
96ef33a401 [cmake] Run configure.sh at build
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-08-02 06:25:56 +00:00
Yannik Bloscheck
c6dcfc71bf [build] Changed to hash based comparing and adjustments to make it work on macOS
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-08-01 23:03:41 +02:00
x7z4w
053fe3c143 [build] Cache World maps and symbols version
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-08-01 23:03:41 +02:00
x7z4w
c6439aaa82 [3party] Do not recompile boost
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-08-01 23:03:41 +02:00
x7z4w
e50a668feb [strings] Fix weblate merge
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-08-01 15:51:07 +00:00
Harry Bond
5ce753bd5c [android] Don't use inset for ic_launcher
hardcoding the drawable inset is the only option, as it's not supported on android 5-7
fixes #1175


Signed-off-by: Harry Bond <me@hbond.xyz>
2025-07-31 21:00:05 +01:00
Harry Bond
8058183f72 [android] Remove old debug icons
Signed-off-by: Harry Bond <me@hbond.xyz>
2025-07-31 20:44:00 +01:00
Harry Bond
07f745411f [android] fix drawables not found
caused due to the big sdk refactoring - i'm not sure why we're storing some drawables in the sdk package, but this fixes build for now.

Signed-off-by: Harry Bond <me@hbond.xyz>
2025-07-31 19:52:33 +01:00
Jean-Baptiste
2004c9bfc1 [iOS]Drop last parts of NY features
Signed-off-by: Jean-Baptiste Charron <jeanbaptiste.charron@outlook.fr>
2025-07-31 20:10:42 +02:00
bowie
1e7715d10f [strings] Removed minor errors countries-strings
Removed minor errors (Points 2, 5 and 6) as noted in https://codeberg.org/comaps/comaps/issues/986
Line 225: changed "p" to upper case "P" in "Península"

Signed-off-by: bowie <bowie@noreply.codeberg.org>
2025-07-31 17:07:46 +02:00
Yannik Bloscheck
e884e32bb6 [ios] Prevent unnecessary log messages because of empty image
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-07-31 13:28:11 +02:00
Yannik Bloscheck
660694aee0 [ios] Fixed merge error after removing method
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-07-31 13:26:46 +02:00
Jean-Baptiste
99fa3ec551 [android] Migrate Webp assets to SVG
Signed-off-by: Jean-Baptiste Charron <jeanbaptiste.charron@outlook.fr>
2025-07-31 13:04:37 +02:00
Alexander Borsuk
f26db1a79b [android] Increase gradle heap to 2Gb to fix linter OOM
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-07-31 13:03:12 +02:00
Viktor Govako
1151f0fb75 [android] Expected "Show on map" search button behaviour.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-07-31 13:03:12 +02:00
Alexander Borsuk
bbb28107b8 [android][editor] Keep the last background unique osm upload work to avoid duplicates
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-07-31 13:03:12 +02:00
Andrei Shkrob
9c7b39fd5b [android] Migrate DownloaderActivity to OnBackPressedCallback
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-07-31 13:03:12 +02:00
Andrei Shkrob
0d9514bee9 [android] Hot fix for broken OnBackPressed
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-07-31 13:03:12 +02:00
Alexander Borsuk
a036edc9c5 [android] Use OpenGL on Emulator API 30 and 36 (Android 11 and 16)
OM crashes likely due to some bugs in Vulkan driver

Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-07-31 13:03:12 +02:00
hemanggs
90492e95e6 [drape] Allow controlling viewport restoration on DeactivateMapSelection
Signed-off-by: hemanggs <hemangmanhas@gmail.com>
2025-07-31 13:03:12 +02:00
hemanggs
fc199252eb [android] Fixes crosshair jump when adding POI
Signed-off-by: hemanggs <hemangmanhas@gmail.com>
2025-07-31 13:03:12 +02:00
Yannik Bloscheck
327d302aae [ios] Change how authorization check after editing is handled
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-07-31 12:31:46 +02:00
Yannik Bloscheck
0b8bd42cb0 [ios] Remove celebratory alert after editing
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-07-31 12:17:58 +02:00
x7z4w
962ee67833 [docs] Add Zulip and governance doc
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-07-31 11:58:00 +02:00
Codeberg Translate
69e3fdca90 [strings] Update from Codeberg Translate
Co-authored-by: Anonymous <anonymous@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: Outbreak2096 <outbreak2096@noreply.codeberg.org>
Co-authored-by: Prefill add-on <noreply-addon-prefill@weblate.org>
Co-authored-by: ghose <ghose@noreply.codeberg.org>
Co-authored-by: loscati <loscati@noreply.codeberg.org>
Co-authored-by: matheusgomesms <matheusgomesms@noreply.codeberg.org>
Co-authored-by: paulb <paulb@noreply.codeberg.org>
Co-authored-by: x7z4w <x7z4w@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/F-Droid app description
Translation: CoMaps/Google Play and Huawei AppGallery descriptions
Translation: CoMaps/iOS - Map Feature Types
Translation: CoMaps/iOS Plist
Translation: CoMaps/iOS Plurals
Translation: CoMaps/iOS UI Strings
2025-07-31 09:30:15 +02:00
Codeberg Translate
ac8f945455 [strings] Update from Codeberg Translate
Co-authored-by: Anonymous <anonymous@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: 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: ghose <ghose@noreply.codeberg.org>
Co-authored-by: loscati <loscati@noreply.codeberg.org>
Co-authored-by: matheusgomesms <matheusgomesms@noreply.codeberg.org>
Co-authored-by: patepelo <patepelo@noreply.codeberg.org>
Co-authored-by: paulb <paulb@noreply.codeberg.org>
Co-authored-by: phama <phama@noreply.codeberg.org>
Co-authored-by: x7z4w <x7z4w@noreply.codeberg.org>
Co-authored-by: yannikbloscheck <yannikbloscheck@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/Google Play and Huawei AppGallery descriptions
Translation: CoMaps/iOS - Map Feature Types
Translation: CoMaps/iOS Plist
Translation: CoMaps/iOS Plurals
Translation: CoMaps/iOS UI Strings
2025-07-31 05:20:25 +00:00
S. Kozyr
c8a4726500 Changed priority of Gradle repos
Signed-off-by: S. Kozyr <s.trump@gmail.com>
2025-07-31 07:19:55 +02:00
Andrei Shkrob
40adb0f860 [android][sdk] Refactor shared preferences
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-07-31 07:19:55 +02:00
Andrei Shkrob
c600a4fd5d [android][sdk] Move drawables into sdk lib
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-07-31 07:19:55 +02:00
Andrei Shkrob
07420a3f19 [android][sdk] Move Android7RootCertificateWorkaround into sdk package
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-07-31 07:19:55 +02:00
Andrei Shkrob
3920988ef4 [android][sdk] Fix dependecies in sdk package
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-07-31 07:19:55 +02:00
matheusgomesms
6136abb33a [strings] Shortened test TTS button title
Signed-off-by: matheusgomesms <matheusgomesms@noreply.codeberg.org>

Reviewed-on: https://codeberg.org/comaps/comaps/pulls/1186
Reviewed-by: Yannik Bloscheck <yannikbloscheck@noreply.codeberg.org>
Reviewed-by: jeanbaptisteC <jeanbaptistec@noreply.codeberg.org>
Co-authored-by: matheusgomesms <matheusgomesms@noreply.codeberg.org>
Co-committed-by: matheusgomesms <matheusgomesms@noreply.codeberg.org>
2025-07-30 18:22:40 +02:00
matheusgomesms
a0e40c98d7 [editor] Fix Irish post codes format
Signed-off-by: matheusgomesms <matheusgomesms@noreply.codeberg.org>
2025-07-30 14:03:09 +02:00
matheusgomesms
3bdaa44c3a [editor] Adding support for Irish post codes
Signed-off-by: matheusgomesms <matheusgomesms@noreply.codeberg.org>
2025-07-30 11:08:49 +02:00
Yannik Bloscheck
945c6205a0 [styles] Refreshed aerialway station icon
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-07-30 11:08:38 +02:00
IXVG47QZ
ef4fd85883 [strings] Change zip to postal
Signed-off-by: IXVG47QZ <jako_accomm@simplelogin.com>
2025-07-30 11:03:29 +02:00
Yannik Bloscheck
83db427c40 [styles] Regenerated files for green color for dog park
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-07-30 10:43:31 +02:00
Yannik Bloscheck
946fea1e07 [styles] Green color for dog park
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-07-30 10:43:31 +02:00
Yannik Bloscheck
bd80e9160d [ios] Respect system language order for map with mutiple regional languages
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-07-30 10:03:21 +02:00
Konstantin Pastbin
5333ad3597 [android] Re-format java code by clang-format
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-07-30 14:59:53 +07:00
Alexander Borsuk
65b5234396 [github] clang-format check on CI
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-07-30 14:58:54 +07:00
Alexander Borsuk
969c805182 Update clang-format for Java
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-07-30 14:58:54 +07:00
David Martinez
8b03e99035 [styles] Add fast_food search result icons & bookmark icons
Signed-off-by: David Martinez <47610359+dvdmrtnz@users.noreply.github.com>
2025-07-29 21:49:45 +07:00
David Martinez
3aabde338a [styles] Add bicycle search result icons & bookmark icons
Signed-off-by: David Martinez <47610359+dvdmrtnz@users.noreply.github.com>
2025-07-29 21:41:20 +07:00
David Martinez
d5d86ffd36 [styles] Add charging_station search result icon & bookmark icon
Signed-off-by: David Martinez <47610359+dvdmrtnz@users.noreply.github.com>
2025-07-29 21:38:49 +07:00
David Martinez
d4cef9385b [styles] Update fuel search result icon & bookmark icon
Signed-off-by: David Martinez <47610359+dvdmrtnz@users.noreply.github.com>
2025-07-29 21:35:15 +07:00
Jean-Baptiste
9c495ca616 [android] Migrate preferences screens to Material
Signed-off-by: Jean-Baptiste Charron <jeanbaptiste.charron@outlook.fr>
2025-07-29 13:52:29 +02:00
matheusgomesms
a08f3df3e6 [ios] Fix long strings in search (#1146)
Fixes #1145

Reviewed-on: https://codeberg.org/comaps/comaps/pulls/1146
Reviewed-by: Yannik Bloscheck <yannikbloscheck@noreply.codeberg.org>

Signed-off-by: matheusgomesms <matheusgomesms@noreply.codeberg.org>
Co-authored-by: matheusgomesms <matheusgomesms@noreply.codeberg.org>
Co-committed-by: matheusgomesms <matheusgomesms@noreply.codeberg.org>
2025-07-29 12:46:24 +02:00
x7z4w
bb5da20fec [strings] Cell -> Mobile
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-07-29 11:21:54 +02:00
Codeberg Translate
e112dc2ac4 [strings] Update from Codeberg Translate
Co-authored-by: Alexey Ladygin <nitrodox@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: Dimitar5555 <dimitar5555@noreply.codeberg.org>
Co-authored-by: ERYpTION <eryption@noreply.codeberg.org>
Co-authored-by: Laurent FAVOLE <lfavole@noreply.codeberg.org>
Co-authored-by: Lenny Angst <lenny@familie-angst.ch>
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: Supaplextw <supaplextw@noreply.codeberg.org>
Co-authored-by: Weblate <noreply-mt-weblate@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: ZeljkoBG <zeljkobg@noreply.codeberg.org>
Co-authored-by: alexgabi <alexgabi@noreply.codeberg.org>
Co-authored-by: ceirios <ceirios@noreply.codeberg.org>
Co-authored-by: hb0nd <hb0nd@noreply.codeberg.org>
Co-authored-by: hosara <hosara@noreply.codeberg.org>
Co-authored-by: marcosm <marcosm@noreply.codeberg.org>
Co-authored-by: matheusgomesms <matheusgomesms@noreply.codeberg.org>
Co-authored-by: patepelo <patepelo@noreply.codeberg.org>
Co-authored-by: pestanzul <pestanzul@posteo.me>
Co-authored-by: phama <phama@noreply.codeberg.org>
Co-authored-by: sunsand <sunsand@noreply.codeberg.org>
Co-authored-by: x7z4w <x7z4w@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/Countries and regions names
Translation: CoMaps/F-Droid app description
Translation: CoMaps/Google Play and Huawei AppGallery descriptions
Translation: CoMaps/Voice announcements for navigation (TTS)
Translation: CoMaps/iOS - Map Feature Types
Translation: CoMaps/iOS Plurals
Translation: CoMaps/iOS UI Strings
2025-07-29 09:18:33 +00:00
Alexander Borsuk
3e2e6cb487 [android] Fix gradle deprecations
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-07-28 21:45:00 +02:00
Alexander Borsuk
21020429cb [android] Remove unnecessary sdk library variables that are already defined in the app
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-07-28 21:45:00 +02:00
Andrei Shkrob
07025ff696 [android] Export all debug symbols
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-07-28 21:45:00 +02:00
Andrei Shkrob
c13da0f0a2 [android] add ndkVersion to app/build.gradle
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-07-28 21:45:00 +02:00
Andrei Shkrob
dd023b65c7 [android][sdk] Move cpp code into sdk lib
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-07-28 21:45:00 +02:00
Codeberg Translate
0c8648d1e3 [strings] Update from Codeberg Translate
Co-authored-by: Alexey Ladygin <nitrodox@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: Dimitar5555 <dimitar5555@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: Supaplextw <supaplextw@noreply.codeberg.org>
Co-authored-by: Weblate <noreply-mt-weblate@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: ZeljkoBG <zeljkobg@noreply.codeberg.org>
Co-authored-by: alexgabi <alexgabi@noreply.codeberg.org>
Co-authored-by: ceirios <ceirios@noreply.codeberg.org>
Co-authored-by: hb0nd <hb0nd@noreply.codeberg.org>
Co-authored-by: hosara <hosara@noreply.codeberg.org>
Co-authored-by: patepelo <patepelo@noreply.codeberg.org>
Co-authored-by: sunsand <sunsand@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/Countries and regions names
Translation: CoMaps/F-Droid app description
Translation: CoMaps/Google Play and Huawei AppGallery descriptions
Translation: CoMaps/Voice announcements for navigation (TTS)
Translation: CoMaps/iOS - Map Feature Types
Translation: CoMaps/iOS Plurals
Translation: CoMaps/iOS UI Strings
2025-07-28 18:42:45 +02:00
matheusgomesms
760e050110 Update MWMObjectsCategorySelectorController.mm
Fixes https://github.com/organicmaps/organicmaps/issues/10223
2025-07-28 18:00:47 +02:00
x7z4w
db4b46f8ad [forgejo] Remove "feat:" and "bug:" from issue templates
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-07-28 17:48:18 +02:00
matkoniecz
29ebd8b725 [strings] new search terms for battery recycling
Signed-off-by: Mateusz Konieczny <matkoniecz@tutanota.com>
Co-authored-by: matkoniecz <matkoniecz@noreply.codeberg.org>
Co-committed-by: matkoniecz <matkoniecz@noreply.codeberg.org>
2025-07-28 16:43:10 +02:00
Stzyxh
6b53d1fb91 [Docs] add obtainium badge to readme
Signed-off-by: Stzyxh <stzyxh@tutamail.com>
2025-07-28 11:11:42 +02:00
gekeleda
d1da6c197e [android] Round map download percentage
Reviewed-on: https://codeberg.org/comaps/comaps/pulls/1110
Reviewed-by: x7z4w <x7z4w@noreply.codeberg.org>
Co-authored-by: gekeleda <git@davidgekeler.eu>
Co-committed-by: gekeleda <git@davidgekeler.eu>
2025-07-28 08:41:11 +02:00
Konstantin Pastbin
0dc8d69375 [isolines] Upgrade some popular hiking regions to 20m step
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-07-28 08:41:02 +02:00
Andrei Shkrob
3352279d9d [android][sdk] Create empty SDK library
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-07-27 19:31:30 +02:00
Harry Bond
6da8b69a1b [android] Fix donate button not opening in hamburger menu
oops - fixes #1099

Signed-off-by: Harry Bond <me@hbond.xyz>
2025-07-27 18:07:31 +02:00
x7z4w
fe1c371b5f [android-auto] Fix SearchRecents.add
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-07-27 17:34:38 +02:00
Jean-Baptiste
309eed2365 [android] Use SVG assets for download status icons
Signed-off-by: Jean-Baptiste Charron <jeanbaptiste.charron@outlook.fr>
2025-07-27 17:18:29 +02:00
Jean-Baptiste
979c713436 [android] Fix logo missing in about layout
Signed-off-by: Jean-Baptiste Charron <jeanbaptiste.charron@outlook.fr>
2025-07-27 14:15:50 +02:00
x7z4w
5e8a8de646 [docs] Allow pseudonyms
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-07-27 13:37:18 +02:00
Yannik Bloscheck
b0bdd2c665 [core] Respect system language order
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-07-27 12:22:45 +02:00
Yannik Bloscheck
dd949925f6 [core] Respect system language order
Signed-off-by: Yannik Bloscheck <git@yannikbloscheck.com>
2025-07-27 12:22:11 +02:00
Codeberg Translate
b37572000f [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: ERYpTION <eryption@noreply.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: Weblate <noreply-mt-weblate@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: patepelo <patepelo@noreply.codeberg.org>
Translation: CoMaps/Android - Map Feature Types
Translation: CoMaps/Android UI Strings
Translation: CoMaps/Apple AppStore description
Translation: CoMaps/Countries and regions names
Translation: CoMaps/Google Play and Huawei AppGallery descriptions
Translation: CoMaps/iOS - Map Feature Types
Translation: CoMaps/iOS Plurals
Translation: CoMaps/iOS UI Strings
2025-07-27 12:13:17 +02:00
Jean-Baptiste
332ab819b2 [android] Remove somes Android warnings
Signed-off-by: Jean-Baptiste Charron <jeanbaptiste.charron@outlook.fr>
2025-07-27 12:10:10 +02:00
sunsand
860f58e60e [strings] Fixed and squashed - Translated using Codeberg Translate
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-07-27 09:16:54 +02:00
Jean-Baptiste
0e7d8a65cc [android] Improve layouts in RTL mode with LTR texts
Signed-off-by: Jean-Baptiste Charron <jeanbaptiste.charron@outlook.fr>
2025-07-27 09:12:52 +02:00
jeanbaptisteC
4c6207a8ce Translated using Weblate (French)
Currently translated at 100.0% (631 of 631 strings)

Translation: CoMaps/Android UI Strings
2025-07-27 08:49:10 +02:00
Jean-Baptiste
b96afc6fbb [android] Enable animateLayoutChanges in a layout
Signed-off-by: Jean-Baptiste Charron <jeanbaptiste.charron@outlook.fr>
2025-07-27 07:35:22 +02:00
1062 changed files with 11096 additions and 8343 deletions

View File

@@ -1,48 +1,59 @@
# Configuration file for clang-format, based on docs/CPP_STYLE.md. # Configuration file for clang-format, based on docs/CPP_STYLE.md.
---
BasedOnStyle: Google BasedOnStyle: Google
AccessModifierOffset: -2 AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignArrayOfStructures: Right
AlignConsecutiveMacros: AcrossEmptyLinesAndComments
AlignEscapedNewlines: LeftWithLastLine
AlignOperands: AlignAfterOperator AlignOperands: AlignAfterOperator
AllowShortBlocksOnASingleLine: Empty AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: Never AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false AllowShortLoopsOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: true
BraceWrapping: BraceWrapping:
AfterCaseLabel: true AfterCaseLabel: true
AfterClass: true AfterClass: true
AfterControlStatement: Always AfterControlStatement: Always
AfterEnum: true AfterEnum: true
AfterExternBlock: true
AfterFunction: true AfterFunction: true
AfterNamespace: true AfterNamespace: true
AfterObjCDeclaration: true AfterObjCDeclaration: true
AfterStruct: true AfterStruct: true
AfterUnion: true AfterUnion: true
AfterExternBlock: true
BeforeCatch: true BeforeCatch: true
BeforeElse: true BeforeElse: true
BeforeLambdaBody: true BeforeLambdaBody: true
BeforeWhile: true BeforeWhile: true
IndentBraces: false
SplitEmptyFunction: false SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false SplitEmptyNamespace: false
SplitEmptyRecord: false
BinPackArguments: true
BinPackParameters: true
BreakAfterJavaFieldAnnotations: true
BreakBeforeBraces: Custom BreakBeforeBraces: Custom
BreakConstructorInitializers: BeforeComma BreakConstructorInitializers: BeforeComma
BreakInheritanceList: BeforeComma BreakInheritanceList: BeforeComma
ColumnLimit: 120 ColumnLimit: 120
ConstructorInitializerIndentWidth: 2 ConstructorInitializerIndentWidth: 2
ContinuationIndentWidth: 2 ContinuationIndentWidth: 4
DerivePointerAlignment: false DerivePointerAlignment: false
IncludeBlocks: Preserve IncludeBlocks: Preserve
IndentCaseLabels: false IndentAccessModifiers: false
IndentExternBlock: NoIndent IndentExternBlock: NoIndent
InsertBraces: false
InsertNewlineAtEOF: true InsertNewlineAtEOF: true
PackConstructorInitializers: Never LambdaBodyIndentation: OuterScope
PackConstructorInitializers: CurrentLine
PointerAlignment: Middle PointerAlignment: Middle
RemoveBracesLLVM: true
QualifierAlignment: Right QualifierAlignment: Right
SpacesInContainerLiterals: false SpacesInContainerLiterals: false
Standard: Latest Standard: Latest
TabWidth: 2 TabWidth: 2
UseTab: Never
---
Language: Java
AllowShortFunctionsOnASingleLine: Empty

View File

@@ -1,6 +1,5 @@
name: 🐞 Bug Report name: 🐞 Bug Report
description: Report a problem you've encountered description: Report a problem you've encountered
title: "bug: "
labels: labels:
- bug - bug
body: body:

View File

@@ -1,6 +1,5 @@
name: "💡 Feature Request" name: "💡 Feature Request"
description: "Suggest an idea or improvement for CoMaps" description: "Suggest an idea or improvement for CoMaps"
title: "feat: "
labels: labels:
- "enhancement" - "enhancement"
body: body:

View File

@@ -32,13 +32,12 @@ on:
- track_generator/** - track_generator/**
- xcode/** - xcode/**
env:
JAVA_HOME: /usr/lib/jvm/temurin-17-jdk-amd64 # Java 17 is required for Android Gradle 8 plugin
jobs: jobs:
android-google-beta: android-google-beta:
name: Android Google Beta name: Android Google Beta
runs-on: ubuntu-latest runs-on: ubuntu-latest
container:
image: runmymind/docker-android-sdk:latest
environment: beta environment: beta
steps: steps:
- name: Install build tools and dependencies - name: Install build tools and dependencies
@@ -71,10 +70,6 @@ jobs:
SECURE_PROPERTIES: ${{ secrets.SECURE_PROPERTIES }} SECURE_PROPERTIES: ${{ secrets.SECURE_PROPERTIES }}
RELEASE_KEYSTORE: ${{ secrets.RELEASE_KEYSTORE }} RELEASE_KEYSTORE: ${{ secrets.RELEASE_KEYSTORE }}
- name: Configure repository
shell: bash
run: ./configure.sh
- name: Compile - name: Compile
shell: bash shell: bash
working-directory: android working-directory: android

View File

@@ -11,7 +11,7 @@ on:
jobs: jobs:
android-check-metadata: android-check-metadata:
name: Check app metadata name: Check app metadata
runs-on: ubuntu-latest runs-on: codeberg-tiny
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4

View File

@@ -34,13 +34,12 @@ on:
- track_generator/** - track_generator/**
- xcode/** - xcode/**
env:
JAVA_HOME: /usr/lib/jvm/temurin-17-jdk-amd64 # Java 17 is required for Android Gradle 8 plugin
jobs: jobs:
lint: lint:
name: Android Lint name: Android Lint
runs-on: ubuntu-latest runs-on: codeberg-tiny
container:
image: runmymind/docker-android-sdk:latest
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -51,10 +50,6 @@ jobs:
shell: bash shell: bash
run: git submodule update --depth 1 --init --recursive --jobs=$(($(nproc) * 20)) run: git submodule update --depth 1 --init --recursive --jobs=$(($(nproc) * 20))
- name: Configure repository
shell: bash
run: ./configure.sh
- name: Lint - name: Lint
shell: bash shell: bash
working-directory: android working-directory: android
@@ -63,6 +58,8 @@ jobs:
android-check: android-check:
name: Build Android Debug name: Build Android Debug
runs-on: ubuntu-latest runs-on: ubuntu-latest
container:
image: runmymind/docker-android-sdk:latest
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@@ -93,10 +90,6 @@ jobs:
shell: bash shell: bash
run: git submodule update --depth 1 --init --recursive --jobs=$(($(nproc) * 20)) run: git submodule update --depth 1 --init --recursive --jobs=$(($(nproc) * 20))
- name: Configure repository
shell: bash
run: ./configure.sh
- name: Configure ccache - name: Configure ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2
with: with:

View File

@@ -4,12 +4,9 @@ on:
schedule: schedule:
- cron: '0 5 * * 0' # Once per week at 05:00 UTC - cron: '0 5 * * 0' # Once per week at 05:00 UTC
env:
JAVA_HOME: /usr/lib/jvm/temurin-17-jdk-amd64 # Java 17 is required for Android Gradle 8 plugin
jobs: jobs:
precondition: precondition:
runs-on: ubuntu-latest runs-on: codeberg-tiny
name: Check preconditions name: Check preconditions
steps: steps:
- name: Checkout sources - name: Checkout sources
@@ -34,6 +31,8 @@ jobs:
android-google-beta: android-google-beta:
name: Android Google Beta name: Android Google Beta
runs-on: ubuntu-latest runs-on: ubuntu-latest
container:
image: runmymind/docker-android-sdk:latest
needs: precondition needs: precondition
if: ${{ needs.precondition.outputs.updated != '' }} if: ${{ needs.precondition.outputs.updated != '' }}
environment: beta environment: beta
@@ -73,10 +72,6 @@ jobs:
SECURE_PROPERTIES: ${{ secrets.SECURE_PROPERTIES }} SECURE_PROPERTIES: ${{ secrets.SECURE_PROPERTIES }}
RELEASE_KEYSTORE: ${{ secrets.RELEASE_KEYSTORE }} RELEASE_KEYSTORE: ${{ secrets.RELEASE_KEYSTORE }}
- name: Configure repository
shell: bash
run: ./configure.sh
- name: Compile - name: Compile
shell: bash shell: bash
working-directory: android working-directory: android

View File

@@ -2,13 +2,12 @@ name: Android Release Metadata
on: on:
workflow_dispatch: # Manual trigger workflow_dispatch: # Manual trigger
env:
JAVA_HOME: /usr/lib/jvm/temurin-17-jdk-amd64 # Java 17 is required for Android Gradle 8 plugin
jobs: jobs:
android-release-metadata: android-release-metadata:
name: Upload Google Play metadata name: Upload Google Play metadata
runs-on: ubuntu-latest runs-on: codeberg-tiny
container:
image: runmymind/docker-android-sdk:latest
environment: production environment: production
steps: steps:
- name: Checkout sources - name: Checkout sources

View File

@@ -5,12 +5,13 @@ on:
env: env:
RELEASE_NOTES: android/app/src/google/play/release-notes/en-US/default.txt RELEASE_NOTES: android/app/src/google/play/release-notes/en-US/default.txt
FDROID_VERSION: android/app/src/fdroid/play/version.yaml FDROID_VERSION: android/app/src/fdroid/play/version.yaml
JAVA_HOME: /usr/lib/jvm/temurin-17-jdk-amd64 # Java 17 is required for Android Gradle 8 plugin
jobs: jobs:
tag: tag:
name: Tag name: Tag
runs-on: ubuntu-latest runs-on: ubuntu-latest
container:
image: runmymind/docker-android-sdk:latest
environment: production environment: production
steps: steps:
- name: Checkout sources - name: Checkout sources
@@ -117,10 +118,6 @@ jobs:
SECURE_PROPERTIES: ${{ secrets.SECURE_PROPERTIES }} SECURE_PROPERTIES: ${{ secrets.SECURE_PROPERTIES }}
RELEASE_KEYSTORE: ${{ secrets.RELEASE_KEYSTORE }} RELEASE_KEYSTORE: ${{ secrets.RELEASE_KEYSTORE }}
- name: Configure repository
shell: bash
run: ./configure.sh
- name: Set up SDK - name: Set up SDK
shell: bash shell: bash
run: echo "sdk.dir=$ANDROID_SDK_ROOT" > android/local.properties run: echo "sdk.dir=$ANDROID_SDK_ROOT" > android/local.properties

View File

@@ -3,20 +3,20 @@ on:
workflow_dispatch: # Manual trigger workflow_dispatch: # Manual trigger
pull_request: pull_request:
paths: paths:
- packaging/app.organicmaps.desktop.metainfo.xml - packaging/app.comaps.desktop.metainfo.xml
- .forgejo/workflows/appstream-check.yaml # Run check on self change - .forgejo/workflows/appstream-check.yaml # Run check on self change
jobs: jobs:
validate-appstream: validate-appstream:
name: Validate appstream metadata xml name: Validate appstream metadata xml
runs-on: ubuntu-24.04 runs-on: codeberg-tiny
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
fetch-depth: 1 fetch-depth: 1
sparse-checkout: | sparse-checkout: |
packaging/app.organicmaps.desktop.metainfo.xml packaging/app.comaps.desktop.metainfo.xml
- name: Install appstream validator and flatpak Builder - name: Install appstream validator and flatpak Builder
shell: bash shell: bash
@@ -29,8 +29,8 @@ jobs:
- name: Lint appstream data with flatpak Builder - name: Lint appstream data with flatpak Builder
shell: bash shell: bash
run: flatpak run --command=flatpak-builder-lint org.flatpak.Builder appstream packaging/app.organicmaps.desktop.metainfo.xml run: flatpak run --command=flatpak-builder-lint org.flatpak.Builder appstream packaging/app.comaps.desktop.metainfo.xml
- name: Run appstreamcli in pedantic mode - name: Run appstreamcli in pedantic mode
shell: bash shell: bash
run: flatpak run --command=appstreamcli org.flatpak.Builder validate --pedantic packaging/app.organicmaps.desktop.metainfo.xml run: flatpak run --command=appstreamcli org.flatpak.Builder validate --pedantic packaging/app.comaps.desktop.metainfo.xml

View File

@@ -33,7 +33,7 @@ concurrency:
jobs: jobs:
should-run-check: should-run-check:
name: Should run coverage name: Should run coverage
runs-on: ubuntu-24.04 runs-on: codeberg-tiny
outputs: outputs:
run-from-pr: ${{ steps.run-from-pr.outputs.run-from-pr }} run-from-pr: ${{ steps.run-from-pr.outputs.run-from-pr }}
manually-triggered: ${{ steps.manually-triggered.outputs.manually-triggered }} manually-triggered: ${{ steps.manually-triggered.outputs.manually-triggered }}
@@ -59,14 +59,9 @@ jobs:
coverage: coverage:
needs: should-run-check needs: should-run-check
name: Generate coverage report name: Generate coverage report
runs-on: ubuntu-24.04 runs-on: ubuntu-latest
if: ${{ needs.should-run-check.outputs.run-from-pr == 'true' || needs.should-run-check.outputs.manually-triggered == 'true'}} if: ${{ needs.should-run-check.outputs.run-from-pr == 'true' || needs.should-run-check.outputs.manually-triggered == 'true'}}
steps: steps:
- name: Free disk space by removing .NET, Android and Haskell
shell: bash
run: |
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
@@ -94,10 +89,6 @@ jobs:
llvm \ llvm \
gcovr gcovr
- name: Configure repository
shell: bash
run: ./configure.sh
- name: Configure ccache - name: Configure ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2
with: with:

View File

@@ -3,20 +3,20 @@ on:
workflow_dispatch: # Manual trigger workflow_dispatch: # Manual trigger
pull_request: pull_request:
paths: paths:
- qt/res/app.organicmaps.desktop.desktop - qt/res/app.comaps.desktop.desktop
- .forgejo/workflows/desktop-file-check.yaml # Run check on self change - .forgejo/workflows/desktop-file-check.yaml # Run check on self change
jobs: jobs:
validate-desktop-file: validate-desktop-file:
name: Validate .desktop file name: Validate .desktop file
runs-on: ubuntu-24.04 runs-on: codeberg-tiny
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
fetch-depth: 1 fetch-depth: 1
sparse-checkout: | sparse-checkout: |
qt/res/app.organicmaps.desktop.desktop qt/res/app.comaps.desktop.desktop
- name: Install desktop-file-validate tool - name: Install desktop-file-validate tool
shell: bash shell: bash
@@ -27,4 +27,4 @@ jobs:
- name: Validate desktop file - name: Validate desktop file
shell: bash shell: bash
run: desktop-file-validate qt/res/app.organicmaps.desktop.desktop && echo "Successfully validated .desktop file" run: desktop-file-validate qt/res/app.comaps.desktop.desktop && echo "Successfully validated .desktop file"

View File

@@ -10,7 +10,7 @@ on:
jobs: jobs:
ios-check-metadata: ios-check-metadata:
name: Check app metadata name: Check app metadata
runs-on: ubuntu-latest runs-on: codeberg-tiny
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4

View File

@@ -31,18 +31,13 @@ on:
jobs: jobs:
linux-no-unity: linux-no-unity:
name: Linux no unity build name: Linux no unity build
runs-on: ubuntu-24.04 runs-on: ubuntu-latest
# Cancels previous jobs if the same branch or PR was updated again. # Cancels previous jobs if the same branch or PR was updated again.
concurrency: concurrency:
group: ${{ github.workflow }}-no-unity-${{ github.event.pull_request.number || github.ref }} group: ${{ github.workflow }}-no-unity-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true cancel-in-progress: true
steps: steps:
- name: Free disk space by removing .NET, Android and Haskell
shell: bash
run: |
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
@@ -71,10 +66,6 @@ jobs:
libqt6positioning6-plugins \ libqt6positioning6-plugins \
libqt6positioning6 libqt6positioning6
- name: Configure repository
shell: bash
run: ./configure.sh
- name: Configure ccache - name: Configure ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2
with: with:
@@ -99,7 +90,7 @@ jobs:
linux-matrix: linux-matrix:
name: Linux builds and tests name: Linux builds and tests
runs-on: ubuntu-24.04 runs-on: ubuntu-latest
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@@ -111,11 +102,6 @@ jobs:
cancel-in-progress: true cancel-in-progress: true
steps: steps:
- name: Free disk space by removing .NET, Android and Haskell
shell: bash
run: |
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -142,10 +128,6 @@ jobs:
libqt6positioning6-plugins \ libqt6positioning6-plugins \
libqt6positioning6 libqt6positioning6
- name: Configure repository
shell: bash
run: ./configure.sh
- name: Configure ccache - name: Configure ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2
with: with:

View File

@@ -57,10 +57,6 @@ jobs:
run: | run: |
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install ninja qt@6 HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install ninja qt@6
- name: Configure repository
shell: bash
run: ./configure.sh
- name: Configure ccache - name: Configure ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2
with: with:

View File

@@ -7,6 +7,7 @@ on:
env: env:
JAVA_HOME: /usr/lib/jvm/temurin-17-jdk-amd64 # Java 17 is required for Android Gradle 8 plugin JAVA_HOME: /usr/lib/jvm/temurin-17-jdk-amd64 # Java 17 is required for Android Gradle 8 plugin
SKIP_MAP_DOWNLOAD: true
jobs: jobs:
lint: lint:
@@ -22,10 +23,6 @@ jobs:
shell: bash shell: bash
run: git submodule update --depth 1 --init --recursive --jobs=$(($(nproc) * 20)) run: git submodule update --depth 1 --init --recursive --jobs=$(($(nproc) * 20))
- name: Init boost, generate textures
shell: bash
run: ./configure.sh --skip-map-download
- name: Lint - name: Lint
shell: bash shell: bash
working-directory: android working-directory: android
@@ -76,10 +73,6 @@ jobs:
shell: bash shell: bash
run: git submodule update --depth 1 --init --recursive --jobs=$(($(nproc) * 20)) run: git submodule update --depth 1 --init --recursive --jobs=$(($(nproc) * 20))
- name: Init boost, generate textures
shell: bash
run: ./configure.sh --skip-map-download
- name: Configure ccache - name: Configure ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2
with: with:

43
.github/workflows/clang-format.yaml vendored Normal file
View File

@@ -0,0 +1,43 @@
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

View File

@@ -37,7 +37,7 @@ jobs:
shell: bash shell: bash
run: git submodule update --depth 1 --init --recursive --jobs=$(($(sysctl -n hw.logicalcpu) * 20)) run: git submodule update --depth 1 --init --recursive --jobs=$(($(sysctl -n hw.logicalcpu) * 20))
- name: Init boost, download World map, generate textures - name: Configure repository
shell: bash shell: bash
run: ./configure.sh run: ./configure.sh

6
.gitignore vendored
View File

@@ -26,10 +26,8 @@ data/bookmarks
data/edits.xml data/edits.xml
data/World.mwm data/World.mwm
data/WorldCoasts.mwm data/WorldCoasts.mwm
data/world_mwm/*
# generated when running tests. NOT the lowercase 'testing' which should be kept. data/*_hash
Testing
!testing
# Compiled Python # Compiled Python
*.pyc *.pyc

View File

@@ -48,6 +48,8 @@ if (APPLE AND NOT ("${CMAKE_SYSTEM_NAME}" STREQUAL Android))
set(CMAKE_OBJCXX_VISIBILITY_PRESET hidden) set(CMAKE_OBJCXX_VISIBILITY_PRESET hidden)
endif() endif()
execute_process(COMMAND "./configure.sh" WORKING_DIRECTORY ${OMIM_ROOT})
message(STATUS "Using compiler ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}") message(STATUS "Using compiler ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
if (CMAKE_UNITY_BUILD) if (CMAKE_UNITY_BUILD)
@@ -269,5 +271,5 @@ endif()
omim_add_test_subdirectory(qt_tstfrm) omim_add_test_subdirectory(qt_tstfrm)
if (PLATFORM_ANDROID) if (PLATFORM_ANDROID)
add_subdirectory(android/app/src/main/cpp) add_subdirectory(android/sdk/src/main/cpp)
endif() endif()

View File

@@ -53,6 +53,9 @@ A community-led free & open source maps app based on [OpenStreetMap](https://www
<a href="https://f-droid.org/en/packages/app.comaps.fdroid/"> <a href="https://f-droid.org/en/packages/app.comaps.fdroid/">
<img src="docs/badges/fdroid.png" alt="F-Droid" width="160"/> <img src="docs/badges/fdroid.png" alt="F-Droid" width="160"/>
</a> </a>
<a href="https://apps.obtainium.imranr.dev/redirect?r=obtainium://add/https://codeberg.org/comaps/comaps">
<img src="docs/badges/obtainium.png" alt="Obtainium" width="160"/>
</a>
<a href="https://codeberg.org/comaps/comaps/releases"> <a href="https://codeberg.org/comaps/comaps/releases">
<img src="docs/badges/codeberg.png" alt="Codeberg" width="160"/> <img src="docs/badges/codeberg.png" alt="Codeberg" width="160"/>
</a> </a>

View File

@@ -18,5 +18,4 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
libxi-dev \ libxi-dev \
optipng optipng
WORKDIR /root/comaps WORKDIR /root/comaps
RUN ./configure.sh
CMD ./gradlew -Parm64 assembleFdroidDebug CMD ./gradlew -Parm64 assembleFdroidDebug

View File

@@ -15,43 +15,17 @@ buildscript {
} }
} }
repositories {
google()
mavenCentral()
maven { url 'https://www.jitpack.io' } // MPAndroidChart
}
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'com.github.triplet.play' apply plugin: 'com.github.triplet.play'
apply plugin: 'ru.cian.huawei-publish-gradle-plugin' apply plugin: 'ru.cian.huawei-publish-gradle-plugin'
def run(cmd) {
def stdout = new ByteArrayOutputStream()
exec {
commandLine = cmd
standardOutput = stdout
}
return stdout.toString()
}
import com.github.triplet.gradle.androidpublisher.ReleaseStatus import com.github.triplet.gradle.androidpublisher.ReleaseStatus
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
def getVersion() {
def isWindows = DefaultNativePlatform.getCurrentOperatingSystem().isWindows()
def bash = isWindows ? 'C:\\Program Files\\Git\\bin\\bash.exe' : 'bash'
def versionCode = Integer.parseInt(run([bash, '../../tools/unix/version.sh', 'android_code']).trim())
def versionName = run([bash, '../../tools/unix/version.sh', 'android_name']).trim()
return new Tuple2(versionCode, versionName)
}
def getCommitMessage() { def getCommitMessage() {
return run(['git', '--no-pager', 'show', '-s', '--format=%s%n%n%b', 'HEAD']).trim() return run(['git', '--no-pager', 'show', '-s', '--format=%s%n%n%b', 'HEAD']).trim()
} }
def osName = System.properties['os.name'].toLowerCase()
project.ext.appId = 'app.comaps' project.ext.appId = 'app.comaps'
project.ext.appName = 'CoMaps' project.ext.appName = 'CoMaps'
@@ -63,7 +37,10 @@ project.ext.appName = 'CoMaps'
//} //}
android { android {
namespace 'app.organicmaps' namespace = 'app.organicmaps'
// TODO: it should not be here, but in sdk/build.gradle. But for some reason it should be specified here as well.
ndkVersion = '28.2.13676358'
dependenciesInfo { dependenciesInfo {
// Disables dependency metadata when building APKs (for IzzyOnDroid/F-Droid) // Disables dependency metadata when building APKs (for IzzyOnDroid/F-Droid)
@@ -85,79 +62,23 @@ android {
} }
// All properties are read from gradle.properties file // All properties are read from gradle.properties file
compileSdk propCompileSdkVersion.toInteger() compileSdk = propCompileSdkVersion.toInteger()
ndkVersion '28.2.13676358'
defaultConfig { defaultConfig {
// Default package name is taken from the manifest and should be app.comaps versionCode = rootProject.ext.versionCode
def ver = getVersion() versionName = rootProject.ext.versionName
versionCode = ver.V1
versionName = ver.V2
println('Version: ' + versionName) println('Version: ' + versionName)
println('VersionCode: ' + versionCode) println('VersionCode: ' + versionCode)
minSdk propMinSdkVersion.toInteger() minSdk = propMinSdkVersion.toInteger()
targetSdk propTargetSdkVersion.toInteger() targetSdk = propTargetSdkVersion.toInteger()
applicationId project.ext.appId applicationId project.ext.appId
buildConfigField 'String', 'SUPPORT_MAIL', '"android@comaps.app"' buildConfigField 'String', 'SUPPORT_MAIL', '"android@comaps.app"'
// Should be customized in flavors. // Should be customized in flavors.
buildConfigField 'String', 'REVIEW_URL', '""' buildConfigField 'String', 'REVIEW_URL', '""'
externalNativeBuild { base.archivesName = appName.replaceAll('\\s','') + '-' + defaultConfig.versionCode
def pchFlag = 'OFF'
if (project.hasProperty('pch')) pchFlag = 'ON'
def njobs = '' ndk.debugSymbolLevel = 'full'
if (project.hasProperty('njobs')) njobs = project.getProperty('njobs')
def enableVulkanDiagnostics = 'OFF'
if (project.hasProperty('enableVulkanDiagnostics')) {
enableVulkanDiagnostics = project.getProperty('enableVulkanDiagnostics')
}
def enableTrace = 'OFF'
if (project.hasProperty('enableTrace')) {
enableTrace = project.getProperty('enableTrace')
}
cmake {
cppFlags '-fexceptions', '-frtti'
// There is no sense to enable sections without gcc's --gc-sections flag.
cFlags '-fno-function-sections', '-fno-data-sections',
'-Wno-extern-c-compat'
arguments '-DANDROID_TOOLCHAIN=clang', '-DANDROID_STL=c++_static',
"-DOS=$osName", '-DSKIP_TESTS=ON', '-DSKIP_TOOLS=ON', "-DUSE_PCH=$pchFlag",
"-DNJOBS=$njobs", "-DENABLE_VULKAN_DIAGNOSTICS=$enableVulkanDiagnostics",
"-DENABLE_TRACE=$enableTrace"
targets 'organicmaps'
}
}
// Use, for example, -Parm32 gradle parameter to build only for armeabi-v7a.
ndk {
abiFilters = new HashSet<>()
if (project.hasProperty('arm32') || project.hasProperty('armeabi-v7a')) {
abiFilters.add('armeabi-v7a')
}
if (project.hasProperty('arm64') || project.hasProperty('arm64-v8a')) {
abiFilters.add('arm64-v8a')
}
if (project.hasProperty('x86')) {
abiFilters.add('x86')
}
if (project.hasProperty('x86_64') || project.hasProperty('x64')) {
abiFilters.add('x86_64')
}
if (abiFilters.isEmpty()) {
abiFilters.add('armeabi-v7a')
abiFilters.add('arm64-v8a')
// For the emulator, chromebooks and some Intel Atom devices.
abiFilters.add('x86_64')
}
println('Building for ' + abiFilters + ' archs.')
}
setProperty('archivesBaseName', appName.replaceAll('\\s','') + '-' + defaultConfig.versionCode)
} }
flavorDimensions += 'default' flavorDimensions += 'default'
@@ -207,10 +128,10 @@ android {
splits.abi { splits.abi {
boolean enabled = project.hasProperty('splitApk') boolean enabled = project.hasProperty('splitApk')
println ('Create separate apks: ' + enabled) println ('Create separate apks: ' + enabled)
enable enabled enable = enabled
reset() reset()
include 'x86', 'armeabi-v7a', 'arm64-v8a', 'x86_64' include 'x86', 'armeabi-v7a', 'arm64-v8a', 'x86_64'
universalApk true universalApk = true
} }
lint { lint {
@@ -223,7 +144,7 @@ android {
disable 'CustomSplashScreen' disable 'CustomSplashScreen'
// https://github.com/organicmaps/organicmaps/issues/3610 // https://github.com/organicmaps/organicmaps/issues/3610
disable 'InsecureBaseConfiguration' disable 'InsecureBaseConfiguration'
abortOnError true abortOnError = true
} }
gradle.projectsEvaluated { gradle.projectsEvaluated {
@@ -282,33 +203,29 @@ android {
debug { debug {
applicationIdSuffix '.debug' // Allows to install debug and release builds together applicationIdSuffix '.debug' // Allows to install debug and release builds together
versionNameSuffix '-debug' versionNameSuffix '-debug'
jniDebuggable true // Enable jni debug build
zipAlignEnabled true zipAlignEnabled true
signingConfig signingConfigs.debug signingConfig = signingConfigs.debug
resValue 'string', 'app_name', 'CoMaps Debug' resValue 'string', 'app_name', 'CoMaps Debug'
// Do not generate separate debug symbols for debug apps, because we don't distribute them.
ndk.debugSymbolLevel = 'none'
} }
release { release {
if (taskName.contains('release')) { if (taskName.contains('release')) {
if (secureReleasePropertiesFileExists) { if (secureReleasePropertiesFileExists) {
println('Using RELEASE signing keys from secure.properties.release') println('Using RELEASE signing keys from secure.properties.release')
signingConfig signingConfigs.release signingConfig = signingConfigs.release
} else { } else {
println('NO RELEASE signing keys found') println('NO RELEASE signing keys found')
println('Using DEBUG signing keys') println('Using DEBUG signing keys')
signingConfig signingConfigs.debug signingConfig = signingConfigs.debug
} }
} }
minifyEnabled true minifyEnabled true
shrinkResources true shrinkResources = true
// Includes the default ProGuard rules files that are packaged with the Android Gradle plugin. // Includes the default ProGuard rules files that are packaged with the Android Gradle plugin.
// To learn more, go to the documentation section about R8 configuration files. // To learn more, go to the documentation section about R8 configuration files.
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
resValue 'string', 'app_name', project.ext.appName resValue 'string', 'app_name', project.ext.appName
// Full size symbols are too big for Google, 217mb aab vs 95mb.
ndk.debugSymbolLevel = 'symbol_table'
} }
beta { beta {
@@ -317,37 +234,27 @@ android {
if (taskName.contains('beta')) { if (taskName.contains('beta')) {
if (secureTestPropertiesFileExists) { if (secureTestPropertiesFileExists) {
println('Using TEST signing keys from secure.properties.test') println('Using TEST signing keys from secure.properties.test')
signingConfig signingConfigs.test signingConfig = signingConfigs.test
} else { } else {
println('NO TEST signing keys found') println('NO TEST signing keys found')
println('Using DEBUG signing keys') println('Using DEBUG signing keys')
signingConfig signingConfigs.debug signingConfig = signingConfigs.debug
} }
} }
minifyEnabled true minifyEnabled true
shrinkResources true shrinkResources = true
// Includes the default ProGuard rules files that are packaged with the Android Gradle plugin. // Includes the default ProGuard rules files that are packaged with the Android Gradle plugin.
// To learn more, go to the documentation section about R8 configuration files. // To learn more, go to the documentation section about R8 configuration files.
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
matchingFallbacks = ['release'] // use dependencies of "release" build type matchingFallbacks = ['release'] // use dependencies of "release" build type
resValue 'string', 'app_name', 'CoMaps Test' resValue 'string', 'app_name', 'CoMaps Test'
// Full size symbols are too big for Google, 217mb aab vs 95mb.
ndk.debugSymbolLevel = 'symbol_table'
}
}
externalNativeBuild {
cmake {
version '3.22.1+'
buildStagingDirectory './nativeOutputs'
path '../../CMakeLists.txt'
} }
} }
// We don't compress these extensions in assets/ because our random FileReader can't read zip-compressed files from apk. // We don't compress these extensions in assets/ because our random FileReader can't read zip-compressed files from apk.
// TODO: Load all minor files via separate call to ReadAsString which can correctly handle compressed files in zip containers. // TODO: Load all minor files via separate call to ReadAsString which can correctly handle compressed files in zip containers.
androidResources { androidResources {
ignoreAssetsPattern '!.svn:!.git:!.DS_Store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~' ignoreAssetsPattern = '!.svn:!.git:!.DS_Store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~'
noCompress = ['txt', 'bin', 'html', 'png', 'json', 'mwm', 'ttf', 'sdf', 'ui', 'config', 'csv', 'spv', 'obj'] noCompress = ['txt', 'bin', 'html', 'png', 'json', 'mwm', 'ttf', 'sdf', 'ui', 'config', 'csv', 'spv', 'obj']
localeFilters += [ localeFilters += [
"af", "af",
@@ -404,7 +311,7 @@ android {
} }
compileOptions { compileOptions {
coreLibraryDesugaringEnabled true coreLibraryDesugaringEnabled = true
sourceCompatibility JavaVersion.VERSION_17 sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17
@@ -412,6 +319,8 @@ android {
} }
dependencies { dependencies {
implementation project(':sdk')
coreLibraryDesugaring libs.android.tools.desugar coreLibraryDesugaring libs.android.tools.desugar
// Google Play Location Services // Google Play Location Services
@@ -457,10 +366,6 @@ dependencies {
testImplementation libs.mockito.core testImplementation libs.mockito.core
} }
tasks.withType(JavaCompile) {
options.compilerArgs << '-Xlint:unchecked' << '-Xlint:deprecation'
}
android.applicationVariants.all { variant -> android.applicationVariants.all { variant ->
def authorityValue = variant.applicationId + ".provider" def authorityValue = variant.applicationId + ".provider"
def authority = "\"" + authorityValue + "\"" def authority = "\"" + authorityValue + "\""
@@ -508,3 +413,7 @@ huaweiPublish {
} }
} }
} }
tasks.withType(JavaCompile).configureEach {
options.compilerArgs << '-Xlint:unchecked' << '-Xlint:deprecation'
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

View File

@@ -0,0 +1 @@
সহজ মানচিত্র নেভিগেশন - আপনার যাত্রা সম্পর্কে আরও জানুন - সম্প্রদায় কর্তৃক পরিচালিত

View File

@@ -0,0 +1 @@
কোম্যাপস - অফলাইনে হাইকিং, সাইকেলিং এবং ড্রাইভিং করুন গোপনীয়তা সহ

View File

@@ -0,0 +1 @@
Navegació intuïtiva - Descobreix el teu camí - El poder de la comunitat

View File

@@ -0,0 +1,65 @@
Una aplicación de mapas gratuita y de código abierto liderada por la comunidad, basada en los datos de OpenStreetMap y reforzada con un compromiso con la transparencia, la privacidad y la ausencia de fines de lucro. CoMaps es un fork o derivado de Organic Maps, que a su vez es un fork de Maps.ME.
<br><br>
Lee más sobre los motivos del proyecto y su dirección en <b><i>codeberg.org/comaps</i></b>.
<br><br>
Únete allí a la comunidad y ayuda a crear la mejor app de mapas
• Usa la aplicación y corre la voz sobre ella
• Envía comentarios y reporta problemas
• Actualiza los datos del mapa en la app o en el sitio web de OpenStreetMap
<br><br>
‣ <b>Enfocada en el uso sin conexión</b>: Planifica y navega tus viajes sin necesidad de conexión móvil, busca puntos de paso en rutas remotas, etc. Todas las funciones están diseñadas para funcionar sin conexión.
‣ <b>Respeta tu Privacidad</b>: La app está diseñada pensando en tu privacidad: no identifica personas, no rastrea y no recoge datos personales. Sin publicidad.
‣ <b>Sencilla y Pulida</b>: funciones esenciales fáciles de usar que simplemente funcionan.
‣ <b>Ahorra Batería y Espacio</b>: No consume la batería como otras apps de navegación. Los mapas compactos ahorran espacio valioso en tu teléfono.
‣ <b>Gratuita y Creada por la Comunidad</b>: Personas como tú ayudaron a construir la app añadiendo lugares a OpenStreetMap, probando funciones, dando opiniones y contribuyendo con desarrollo o financiación.
‣ <b>Toma de decisiones y finanzas abiertas y transparentes, sin ánimo de lucro y completamente de código abierto.</b>
<br><br>
<b>Funciones Principales</b>:
• Mapas detallados descargables con lugares que no aparecen en Google Maps
• Modo exterior con rutas de senderismo destacadas, campings, fuentes de agua, picos, curvas de nivel, etc.
• Caminos peatonales y carriles bici
• Puntos de interés como restaurantes, gasolineras, hoteles, tiendas, lugares turísticos y muchos más
• Búsqueda por nombre, dirección o categoría de punto de interés
• Navegación con indicaciones por voz para caminar, ir en bici o conducir
• Guarda tus lugares favoritos con un solo toque
• Artículos de Wikipedia sin conexión
• Capa de transporte subterráneo y rutas
• Grabación de rutas
• Exporta e importa favoritos y rutas en formatos KML, KMZ y GPX
• Modo oscuro para usar de noche
• Mejora los datos del mapa para todos usando un editor básico integrado
<br><br>
<b>La Libertad Está Aquí</b>
Descubre tu camino, navega el mundo con privacidad y con la comunidad como prioridad.

View File

@@ -0,0 +1 @@
Navegación de mapa fácil - Descubre más en tu camino - Creado por la comunidad

View File

@@ -0,0 +1 @@
CoMaps - Senderismo, ciclismo y conducción offline

View File

@@ -0,0 +1 @@
Navigation facile del mappa Discoperi tu viage Alimentate per le communitate

View File

@@ -1 +1 @@
CoMaps - Mapas com Privacidade CoMaps - Mapas e Navegação Offline com Privacidade

View File

@@ -8,10 +8,10 @@ import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.location.Location; import android.location.Location;
import android.os.Looper; import android.os.Looper;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.RequiresPermission; import androidx.annotation.RequiresPermission;
import app.organicmaps.sdk.util.LocationUtils;
import app.organicmaps.sdk.util.log.Logger;
import com.google.android.gms.common.api.ApiException; import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.ResolvableApiException; import com.google.android.gms.common.api.ResolvableApiException;
import com.google.android.gms.location.FusedLocationProviderClient; import com.google.android.gms.location.FusedLocationProviderClient;
@@ -26,9 +26,6 @@ import com.google.android.gms.location.LocationSettingsStatusCodes;
import com.google.android.gms.location.Priority; import com.google.android.gms.location.Priority;
import com.google.android.gms.location.SettingsClient; import com.google.android.gms.location.SettingsClient;
import app.organicmaps.sdk.util.LocationUtils;
import app.organicmaps.sdk.util.log.Logger;
class GoogleFusedLocationProvider extends BaseLocationProvider class GoogleFusedLocationProvider extends BaseLocationProvider
{ {
private static final String TAG = GoogleFusedLocationProvider.class.getSimpleName(); private static final String TAG = GoogleFusedLocationProvider.class.getSimpleName();
@@ -72,9 +69,11 @@ class GoogleFusedLocationProvider extends BaseLocationProvider
{ {
Logger.d(TAG); Logger.d(TAG);
final LocationRequest locationRequest = new LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, interval) final LocationRequest locationRequest =
// Wait a few seconds for accurate locations initially, when accurate locations could not be computed on the device immediately. new LocationRequest
// https://github.com/organicmaps/organicmaps/issues/2149 .Builder(Priority.PRIORITY_HIGH_ACCURACY, interval)
// Wait a few seconds for accurate locations initially, when accurate locations could not be computed on the
// device immediately. https://github.com/organicmaps/organicmaps/issues/2149
.setWaitForAccurateLocation(true) .setWaitForAccurateLocation(true)
// The desired location granularity should correspond to the client permission level. The client will be // The desired location granularity should correspond to the client permission level. The client will be
// delivered fine locations while it has the Manifest.permission.ACCESS_FINE_LOCATION permission, coarse // delivered fine locations while it has the Manifest.permission.ACCESS_FINE_LOCATION permission, coarse
@@ -90,10 +89,12 @@ class GoogleFusedLocationProvider extends BaseLocationProvider
builder.setAlwaysShow(true); // improves the wording/appearance of the dialog builder.setAlwaysShow(true); // improves the wording/appearance of the dialog
final LocationSettingsRequest locationSettingsRequest = builder.build(); final LocationSettingsRequest locationSettingsRequest = builder.build();
mSettingsClient.checkLocationSettings(locationSettingsRequest).addOnSuccessListener(locationSettingsResponse -> { mSettingsClient.checkLocationSettings(locationSettingsRequest)
.addOnSuccessListener(locationSettingsResponse -> {
Logger.d(TAG, "Service is available"); Logger.d(TAG, "Service is available");
mFusedLocationClient.requestLocationUpdates(locationRequest, mCallback, Looper.myLooper()); mFusedLocationClient.requestLocationUpdates(locationRequest, mCallback, Looper.myLooper());
}).addOnFailureListener(e -> { })
.addOnFailureListener(e -> {
try try
{ {
int statusCode = ((ApiException) e).getStatusCode(); int statusCode = ((ApiException) e).getStatusCode();
@@ -104,10 +105,10 @@ class GoogleFusedLocationProvider extends BaseLocationProvider
// 2. Google Location Accuracy a.k.a High Accuracy; // 2. Google Location Accuracy a.k.a High Accuracy;
// 3. Both Wi-Fi && Mobile Data together (needed for 2). // 3. Both Wi-Fi && Mobile Data together (needed for 2).
// //
// PendingIntent below will show a special Google "For better experience... enable (1) and/or (2) and/or (3)" // PendingIntent below will show a special Google "For better experience... enable (1) and/or (2) and/or
// dialog. This system dialog can change system settings if "Yes" is pressed. We can't do it from our app. // (3)" dialog. This system dialog can change system settings if "Yes" is pressed. We can't do it from our
// However, we don't want to annoy a user who disabled (2) or (3) intentionally. GPS (1) is mandatory to // app. However, we don't want to annoy a user who disabled (2) or (3) intentionally. GPS (1) is mandatory
// continue, while (2) and (3) are not dealbreakers here. // to continue, while (2) and (3) are not dealbreakers here.
// //
// See https://github.com/organicmaps/organicmaps/issues/3846 // See https://github.com/organicmaps/organicmaps/issues/3846
// //

View File

@@ -1,13 +1,11 @@
package app.organicmaps.sdk.location; package app.organicmaps.sdk.location;
import android.content.Context; import android.content.Context;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import app.organicmaps.sdk.util.Config; import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.log.Logger; 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 LocationProviderFactory
{ {
@@ -18,7 +16,8 @@ public class LocationProviderFactory
return GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS; return GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS;
} }
public static BaseLocationProvider getProvider(@NonNull Context context, @NonNull BaseLocationProvider.Listener listener) public static BaseLocationProvider getProvider(@NonNull Context context,
@NonNull BaseLocationProvider.Listener listener)
{ {
if (isGoogleLocationAvailable(context) && Config.useGoogleServices()) if (isGoogleLocationAvailable(context) && Config.useGoogleServices())
{ {

View File

@@ -0,0 +1 @@
সহজ মানচিত্র নেভিগেশন - আপনার যাত্রা সম্পর্কে আরও জানুন - সম্প্রদায় কর্তৃক পরিচালিত

View File

@@ -0,0 +1 @@
CoMaps - গোপনীয়তা সহ যাতায়াত

View File

@@ -0,0 +1,36 @@
CoMaps és una aplicació de mapes lliure i de codi obert a càrrec de la comunitat que es basa en les dades OpenStreetMap i es fonamenta en el compromís amb la transparència i la privadesa sense ànim de lucre.
Uneix-te a la comunitat i ajuda a crear la millor aplicació de mapes.
• Fes servir l'aplicació i recomana-la.
• Dona la teva opinió i comunica qualsevol problema.
• Actualitza les dades de mapes a l'aplicació o al web d'OpenStreetMap.
<i>Els teus comentaris i les valoracions de 5 estrelles són el que més ens ajuda.</i>
‣ <b>Disseny senzill i polit</b>: funcions bàsiques i fàcils de fer servir que funcionen i punt.
‣ <b>Centrada en l'ús sense connexió</b>: planifica viatges a l'estranger i navega sense haver d'accedir a les dades mòbils o cerca punts d'interès durant rutes d'excursionisme llargues. Totes les funcions de l'aplicació s'han dissenyat perquè funcionin sense connexió.
‣ <b>Respecte per la privadesa</b>: el disseny de l'aplicació prioritza la privadesa. No t'identifica, no fa cap seguiment i no recull dades personals. A més, no té anuncis.
‣ <b>Ús eficient de la bateria i l'espai</b>: consumeix menys bateria que altres aplicacions de navegació. Els mapes compactes ocupen molt poc espai al telèfon.
‣ <b>Lliure gràcies a la comunitat</b>: aquesta aplicació s'ha desenvolupat gràcies a persones com tu que han afegit llocs a OpenStreetMap, han provat funcions, n'han aportat comentaris i hi han contribuït amb diners i esforç.
‣ <b>És un projecte obert i transparent en les seves decisions i finances. No té cap ànim de lucre i és completament de codi obert.</b>
<b>Funcions principals</b>:
• Mapes detallats que es poden baixar i inclouen llocs que no apareixen a Google Maps
• Mode exterior en què es ressalten les rutes d'excursionisme, els llocs d'acampada, les fonts d'aigua, els pics i les línies de contorn, entre altres coses
• Zones per a vianants i carrils bici
• Punts d'interès, com ara restaurants, benzineres, hotels, botigues, atraccions turístiques i molt més
• Cerques per nom, adreça o categoria de punt d'interès
• Navegació amb indicacions per veu mentre camines, vas amb bicicleta o condueixes
• Adreces d'interès perquè desis els teus llocs preferits amb un toc
• Articles de Wikipedia sense connexió
• Capa de línies de metro amb direccions
• Enregistrament d'itineraris
• Exportació i importació d'adreces d'interès i itineraris en els formats KML, KMZ i GPX
• Mode fosc per fer servir l'aplicació a la nit
• Millora de les dades de mapes per a tothom amb un editor integrat bàsic
• Compatibilitat amb Android Auto
Pots informar de problemes a l'aplicació, suggerir idees i unir-te a la comunitat al web <b><i>comaps.app</i></b>.
<b>La llibertat ha arribat</b>
Descobreix el teu camí i explora el món amb la privadesa i la comunitat com a eix central!

View File

@@ -0,0 +1 @@
Navegació intuïtiva - Descobreix el teu camí - El poder de la comunitat

View File

@@ -0,0 +1 @@
CoMaps Navega amb privadesa

View File

@@ -0,0 +1,36 @@
En fællesskabsdrevet gratis og open source-kortapp baseret på OpenStreetMap-data og forstærket med en forpligtelse til gennemsigtighed, privatliv og non-profit.
Bliv en del af fællesskabet og vær med til at skabe den bedste kortapp
• Brug appen og fortæl andre om den
• Giv feedback og rapporter problemer
• Opdater kortdata i appen eller på OpenStreetMap-webstedet
<i>Din feedback og 5-stjernede anmeldelser er den bedste støtte for os!</i>
‣ <b>Enkel og poleret</b>: væsentlige, brugervenlige funktioner, der bare virker.
‣ <b>Offline-focused</b>: Planlæg og naviger på din rejse i udlandet uden behov for mobilfordbindelse, søg efter rutepunkter, mens du er på en lang vandretur osv. Alle app-funktioner er designet til at fungere offline..
‣ <b>Respekt for privatlivets fred</b>: Appen er designet med fokus på privatlivets fred den identificerer ikke personer, sporer ikke og indsamler ikke personlige oplysninger. Annoncefri.
‣ <b>Sparer på batteriet og plads</b>: Dræner ikke dit batteri som andre navigationsapps. Kompakte kort sparer værdifuld plads på din telefon.
‣ <b>Gratis og udviklet af fællesskabet</b>: Folk som dig har været med til at udvikle appen ved at tilføje steder til OpenStreetMap, teste og give feedback på funktioner samt bidrage med deres udviklingskompetencer og penge.
‣ <b>Åben og gennemsigtig beslutningstagning og økonomi, non-profit og fuldstændig open source.</b>
<b>Vigtigste funktioner</b>:
• Detaljerede kort med steder, der ikke er tilgængelige på Google Maps, kan downloades.
• Udendørstilstand med fremhævede vandreruter, campingpladser, vandkilder, bjergtoppe, højdekurver osv.
• Gang- og cykelstier
• Interessepunkter som restauranter, tankstationer, hoteller, butikker, seværdigheder og meget mere
• Søg efter navn, adresse eller efter interessepunkt-kategori
• Navigation med stemmevejledning til gående, cyklende eller kørende
• Bogmærk dine yndlingssteder med ét enkelt tryk
• Offline Wikipedia-artikler
• Lag med metrolinjer og rutevejledning
• Sporoptagelse
• Eksportér og importér bogmærker og ruter i KML, KMZ, GPX-formater
• En mørk tilstand til brug om natten
• Forbedr kortdata for alle ved hjælp af en simpel, indbygget redigeringsfunktion
• Android Auto-understøttelse
Rapportér app-problemer, kom med forslag og bliv en del af vores fællesskab på <b><i>comaps.app</i></b> webstedet.
<b>Nu med frihed</b>
Udforsk din rejse, og navigér i verden med fokus på privatliv og fællesskab!

View File

@@ -0,0 +1 @@
CoMaps - Naviger med privatliv

View File

@@ -0,0 +1,71 @@
Una aplicación de mapas gratuita y de código abierto liderada por la comunidad, basada en los datos de OpenStreetMap y reforzada con un compromiso con la transparencia, la privacidad y la ausencia de fines de lucro.
<br><br>
Únete a la comunidad y ayuda a crear la mejor app de mapas
• Usa la aplicación y corre la voz sobre ella
• Envía comentarios y reporta problemas
• Actualiza los datos del mapa en la app o en el sitio web de OpenStreetMap
<br><br>
<i>¡Tus comentarios y valoraciones de 5 estrellas son el mejor apoyo para nosotros!</i>
<br><br>
‣ <b>Sencilla y Pulida</b>: funciones esenciales fáciles de usar que simplemente funcionan.
‣ <b>Enfocada en el uso sin conexión</b>: Planifica y navega tus viajes sin necesidad de conexión móvil, busca puntos de paso en rutas remotas, etc. Todas las funciones están diseñadas para funcionar sin conexión.
‣ <b>Respeta tu Privacidad</b>: La app está diseñada pensando en tu privacidad: no identifica personas, no rastrea y no recoge datos personales. Sin publicidad.
‣ <b>Ahorra Batería y Espacio</b>: No consume la batería como otras apps de navegación. Los mapas compactos ahorran espacio valioso en tu teléfono.
‣ <b>Gratuita y Creada por la Comunidad</b>: Personas como tú ayudaron a construir la app añadiendo lugares a OpenStreetMap, probando funciones, dando opiniones y contribuyendo con desarrollo o financiación.
‣ <b>Toma de decisiones y finanzas abiertas y transparentes, sin ánimo de lucro y completamente de código abierto.</b>
<br><br>
<b>Funciones Principales</b>:
• Mapas detallados descargables con lugares que no aparecen en Google Maps
• Modo exterior con rutas de senderismo destacadas, campings, fuentes de agua, picos, curvas de nivel, etc.
• Caminos peatonales y carriles bici
• Puntos de interés como restaurantes, gasolineras, hoteles, tiendas, lugares turísticos y muchos más
• Búsqueda por nombre, dirección o categoría de punto de interés
• Navegación con indicaciones por voz para caminar, ir en bici o conducir
• Guarda tus lugares favoritos con un solo toque
• Artículos de Wikipedia sin conexión
• Capa de transporte subterráneo y rutas
• Grabación de rutas
• Exporta e importa favoritos y rutas en formatos KML, KMZ y GPX
• Modo oscuro para usar de noche
• Mejora los datos del mapa para todos usando un editor básico integrado
• Compatibilidad con Android Auto
<br><br>
Por favor, informa de errores, sugiere ideas y únete a nuestra comunidad en el sitio web <b><i>comaps.app</i></b>.
<br><br>
<b>La Libertad Está Aquí</b>
Descubre tu camino, navega el mundo con privacidad y con la comunidad como prioridad.

View File

@@ -0,0 +1 @@
Navegación de mapa fácil - Descubre más en tu camino - Creado por la comunidad

View File

@@ -0,0 +1 @@
CoMaps - Navega con Privacidad

View File

@@ -1 +1 @@
Navigation cartographique facile - Propulsé par la communauté Navigation cartographique facile - Découvrez davantage de votre voyage - Propulsé par la communauté

View File

@@ -0,0 +1 @@
Navigation facile del mappa Discoperi tu viage Alimentate per le communitate

View File

@@ -0,0 +1 @@
CoMaps Naviga private

View File

@@ -1 +1 @@
CoMaps - Navegue privadamente CoMaps - Navegue Privadamente

View File

@@ -1 +1 @@
CoMaps - Оффлайн навигация CoMaps - Приватная навигация

View File

@@ -75,6 +75,7 @@
android:backupInForeground="true" android:backupInForeground="true"
android:fullBackupContent="@xml/backup_content" android:fullBackupContent="@xml/backup_content"
android:dataExtractionRules="@xml/backup_content_v31" android:dataExtractionRules="@xml/backup_content_v31"
android:enableOnBackInvokedCallback="false"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:localeConfig="@xml/locales_config" android:localeConfig="@xml/locales_config"
@@ -376,6 +377,7 @@
<activity <activity
android:name="app.organicmaps.downloader.DownloaderActivity" android:name="app.organicmaps.downloader.DownloaderActivity"
android:enableOnBackInvokedCallback="true"
android:configChanges="orientation|screenLayout|screenSize" android:configChanges="orientation|screenLayout|screenSize"
android:screenOrientation="fullUser" android:screenOrientation="fullUser"
android:label="@string/download_maps" android:label="@string/download_maps"

View File

@@ -5,10 +5,16 @@ import android.content.res.Resources;
import android.graphics.Color; import android.graphics.Color;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat; 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.util.ThemeUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.widget.placepage.AxisValueFormatter;
import app.organicmaps.widget.placepage.CurrentLocationMarkerView;
import app.organicmaps.widget.placepage.FloatingMarkerView;
import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.components.MarkerView;
@@ -20,16 +26,6 @@ import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.formatter.ValueFormatter;
import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.sdk.bookmarks.data.ElevationInfo;
import app.organicmaps.widget.placepage.AxisValueFormatter;
import app.organicmaps.widget.placepage.CurrentLocationMarkerView;
import app.organicmaps.widget.placepage.FloatingMarkerView;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.util.Utils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@@ -184,15 +180,15 @@ public class ChartController implements OnChartValueSelectedListener,
} }
@Override @Override
public void onValueSelected(Entry e, Highlight h) { public void onValueSelected(Entry e, Highlight h)
{
mFloatingMarkerView.updateOffsets(e, h); mFloatingMarkerView.updateOffsets(e, h);
Highlight curPos = getCurrentPosHighlight(); Highlight curPos = getCurrentPosHighlight();
if (mCurrentPositionOutOfTrack) if (mCurrentPositionOutOfTrack)
mChart.highlightValues(Collections.singletonList(h), Collections.singletonList(mFloatingMarkerView)); mChart.highlightValues(Collections.singletonList(h), Collections.singletonList(mFloatingMarkerView));
else else
mChart.highlightValues(Arrays.asList(curPos, h), Arrays.asList(mCurrentLocationMarkerView, mChart.highlightValues(Arrays.asList(curPos, h), Arrays.asList(mCurrentLocationMarkerView, mFloatingMarkerView));
mFloatingMarkerView));
if (mTrackId == Utils.INVALID_ID) if (mTrackId == Utils.INVALID_ID)
return; return;

View File

@@ -18,7 +18,6 @@ import android.location.Location;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
@@ -28,10 +27,10 @@ import androidx.annotation.StringRes;
import androidx.annotation.StyleRes; import androidx.annotation.StyleRes;
import androidx.core.view.ViewCompat; import androidx.core.view.ViewCompat;
import app.organicmaps.base.BaseMwmFragmentActivity; import app.organicmaps.base.BaseMwmFragmentActivity;
import app.organicmaps.intent.Factory;
import app.organicmaps.sdk.Framework; import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.downloader.CountryItem; import app.organicmaps.sdk.downloader.CountryItem;
import app.organicmaps.sdk.downloader.MapManager; import app.organicmaps.sdk.downloader.MapManager;
import app.organicmaps.intent.Factory;
import app.organicmaps.sdk.location.LocationListener; import app.organicmaps.sdk.location.LocationListener;
import app.organicmaps.sdk.util.Config; import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.ConnectionState; import app.organicmaps.sdk.util.ConnectionState;
@@ -39,13 +38,11 @@ import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.sdk.util.UiUtils; import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener; import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener;
import com.google.android.material.button.MaterialButton; import com.google.android.material.button.MaterialButton;
import com.google.android.material.checkbox.MaterialCheckBox; import com.google.android.material.checkbox.MaterialCheckBox;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.progressindicator.LinearProgressIndicator; import com.google.android.material.progressindicator.LinearProgressIndicator;
import com.google.android.material.textview.MaterialTextView; import com.google.android.material.textview.MaterialTextView;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@@ -81,10 +78,9 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
private int mCountryDownloadListenerSlot; private int mCountryDownloadListenerSlot;
private final LocationListener mLocationListener = new LocationListener() private final LocationListener mLocationListener = new LocationListener() {
{
@Override @Override
public void onLocationUpdated(Location location) public void onLocationUpdated(@NonNull Location location)
{ {
if (mCurrentCountry != null) if (mCurrentCountry != null)
return; return;
@@ -117,8 +113,8 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
} }
}; };
private final app.organicmaps.sdk.DownloadResourcesLegacyActivity.Listener mResourcesDownloadListener = new app.organicmaps.sdk.DownloadResourcesLegacyActivity.Listener() private final app.organicmaps.sdk.DownloadResourcesLegacyActivity.Listener mResourcesDownloadListener =
{ new app.organicmaps.sdk.DownloadResourcesLegacyActivity.Listener() {
@Override @Override
public void onProgress(final int percent) public void onProgress(final int percent)
{ {
@@ -143,8 +139,7 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
} }
}; };
private final MapManager.StorageCallback mCountryDownloadListener = new MapManager.StorageCallback() private final MapManager.StorageCallback mCountryDownloadListener = new MapManager.StorageCallback() {
{
@Override @Override
public void onStatusChanged(List<MapManager.StorageCallbackData> data) public void onStatusChanged(List<MapManager.StorageCallbackData> data)
{ {
@@ -237,8 +232,7 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
private void setDownloadMessage(int bytesToDownload) private void setDownloadMessage(int bytesToDownload)
{ {
mTvMessage.setText(getString(R.string.download_resources, mTvMessage.setText(getString(R.string.download_resources, StringUtils.getFileSizeString(this, bytesToDownload)));
StringUtils.getFileSizeString(this, bytesToDownload)));
} }
private boolean prepareFilesDownload(boolean showMap) private boolean prepareFilesDownload(boolean showMap)
@@ -399,8 +393,10 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
if (mAlertDialog != null && mAlertDialog.isShowing()) if (mAlertDialog != null && mAlertDialog.isShowing())
return; return;
@StringRes final int titleId; @StringRes
@StringRes final int messageId = switch (result) final int titleId;
@StringRes
final int messageId = switch (result)
{ {
case ERR_NOT_ENOUGH_FREE_SPACE -> case ERR_NOT_ENOUGH_FREE_SPACE ->
{ {
@@ -431,7 +427,8 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
.setMessage(messageId) .setMessage(messageId)
.setCancelable(true) .setCancelable(true)
.setOnCancelListener((dialog) -> setAction(PAUSE)) .setOnCancelListener((dialog) -> setAction(PAUSE))
.setPositiveButton(R.string.try_again, (dialog, which) -> { .setPositiveButton(R.string.try_again,
(dialog, which) -> {
setAction(TRY_AGAIN); setAction(TRY_AGAIN);
onTryAgainClicked(); onTryAgainClicked();
}) })

View File

@@ -10,17 +10,14 @@ import android.view.SurfaceHolder;
import android.view.SurfaceView; import android.view.SurfaceView;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.content.res.ConfigurationHelper; import androidx.core.content.res.ConfigurationHelper;
import app.organicmaps.base.BaseMwmFragment; import app.organicmaps.base.BaseMwmFragment;
import app.organicmaps.sdk.display.DisplayType;
import app.organicmaps.sdk.Map; import app.organicmaps.sdk.Map;
import app.organicmaps.sdk.MapRenderingListener; import app.organicmaps.sdk.MapRenderingListener;
import app.organicmaps.sdk.display.DisplayType;
import app.organicmaps.sdk.util.log.Logger; import app.organicmaps.sdk.util.log.Logger;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
public class MapFragment extends BaseMwmFragment implements View.OnTouchListener, SurfaceHolder.Callback public class MapFragment extends BaseMwmFragment implements View.OnTouchListener, SurfaceHolder.Callback
@@ -71,7 +68,8 @@ public class MapFragment extends BaseMwmFragment implements View.OnTouchListener
public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height)
{ {
Logger.d(TAG); Logger.d(TAG);
mMap.onSurfaceChanged(requireContext(), surfaceHolder.getSurface(), surfaceHolder.getSurfaceFrame(), surfaceHolder.isCreating()); mMap.onSurfaceChanged(requireContext(), surfaceHolder.getSurface(), surfaceHolder.getSurfaceFrame(),
surfaceHolder.isCreating());
} }
@Override @Override

View File

@@ -2,10 +2,8 @@ package app.organicmaps;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import app.organicmaps.base.BaseMwmFragmentActivity; import app.organicmaps.base.BaseMwmFragmentActivity;
import app.organicmaps.sdk.display.DisplayChangedListener; import app.organicmaps.sdk.display.DisplayChangedListener;
import app.organicmaps.sdk.display.DisplayManager; import app.organicmaps.sdk.display.DisplayManager;
@@ -24,7 +22,7 @@ public class MapPlaceholderActivity extends BaseMwmFragmentActivity implements D
super.onSafeCreate(savedInstanceState); super.onSafeCreate(savedInstanceState);
setContentView(R.layout.activity_map_placeholder); setContentView(R.layout.activity_map_placeholder);
mDisplayManager = DisplayManager.from(this); mDisplayManager = MwmApplication.from(this).getDisplayManager();
mDisplayManager.addListener(DisplayType.Device, this); mDisplayManager.addListener(DisplayType.Device, this);
findViewById(R.id.btn_continue).setOnClickListener((unused) -> mDisplayManager.changeDisplay(DisplayType.Device)); findViewById(R.id.btn_continue).setOnClickListener((unused) -> mDisplayManager.changeDisplay(DisplayType.Device));
@@ -34,8 +32,7 @@ public class MapPlaceholderActivity extends BaseMwmFragmentActivity implements D
public void onDisplayChangedToDevice(@NonNull Runnable onTaskFinishedCallback) public void onDisplayChangedToDevice(@NonNull Runnable onTaskFinishedCallback)
{ {
mRemoveDisplayListener = false; mRemoveDisplayListener = false;
startActivity(new Intent(this, MwmActivity.class) startActivity(new Intent(this, MwmActivity.class).putExtra(MwmActivity.EXTRA_UPDATE_THEME, true));
.putExtra(MwmActivity.EXTRA_UPDATE_THEME, true));
finish(); finish();
onTaskFinishedCallback.run(); onTaskFinishedCallback.run();
} }

View File

@@ -1,5 +1,19 @@
package app.organicmaps; package app.organicmaps;
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.Manifest.permission.POST_NOTIFICATIONS;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static app.organicmaps.leftbutton.LeftButtonsHolder.BUTTON_ADD_PLACE_CODE;
import static app.organicmaps.leftbutton.LeftButtonsHolder.BUTTON_HELP_CODE;
import static app.organicmaps.leftbutton.LeftButtonsHolder.BUTTON_MAP_LAYER_CODE;
import static app.organicmaps.leftbutton.LeftButtonsHolder.BUTTON_RECORD_TRACK_CODE;
import static app.organicmaps.leftbutton.LeftButtonsHolder.BUTTON_SETTINGS_CODE;
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 android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.app.Dialog; import android.app.Dialog;
@@ -23,7 +37,6 @@ import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.activity.result.ActivityResult; import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.IntentSenderRequest; import androidx.activity.result.IntentSenderRequest;
@@ -48,117 +61,92 @@ import app.organicmaps.backup.PeriodicBackupRunner;
import app.organicmaps.base.BaseMwmFragmentActivity; import app.organicmaps.base.BaseMwmFragmentActivity;
import app.organicmaps.base.OnBackPressListener; import app.organicmaps.base.OnBackPressListener;
import app.organicmaps.bookmarks.BookmarkCategoriesActivity; import app.organicmaps.bookmarks.BookmarkCategoriesActivity;
import app.organicmaps.downloader.DownloaderActivity;
import app.organicmaps.downloader.DownloaderFragment;
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;
import app.organicmaps.intent.IntentProcessor;
import app.organicmaps.leftbutton.LeftButton;
import app.organicmaps.leftbutton.LeftButtonsHolder;
import app.organicmaps.leftbutton.LeftToggleButton;
import app.organicmaps.location.TrackRecordingService;
import app.organicmaps.maplayer.MapButtonsController;
import app.organicmaps.maplayer.MapButtonsViewModel;
import app.organicmaps.maplayer.ToggleMapLayerFragment;
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;
import app.organicmaps.sdk.ChoosePositionMode;
import app.organicmaps.sdk.Framework; import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.Map; import app.organicmaps.sdk.Map;
import app.organicmaps.sdk.MapRenderingListener; import app.organicmaps.sdk.MapRenderingListener;
import app.organicmaps.sdk.PlacePageActivationListener;
import app.organicmaps.sdk.Router;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager; import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.sdk.bookmarks.data.MapObject; import app.organicmaps.sdk.bookmarks.data.MapObject;
import app.organicmaps.sdk.display.DisplayChangedListener; import app.organicmaps.sdk.display.DisplayChangedListener;
import app.organicmaps.sdk.display.DisplayManager; import app.organicmaps.sdk.display.DisplayManager;
import app.organicmaps.sdk.display.DisplayType; import app.organicmaps.sdk.display.DisplayType;
import app.organicmaps.downloader.DownloaderActivity;
import app.organicmaps.downloader.DownloaderFragment;
import app.organicmaps.sdk.downloader.MapManager; import app.organicmaps.sdk.downloader.MapManager;
import app.organicmaps.downloader.OnmapDownloader;
import app.organicmaps.sdk.downloader.UpdateInfo; import app.organicmaps.sdk.downloader.UpdateInfo;
import app.organicmaps.sdk.editor.Editor; import app.organicmaps.sdk.editor.Editor;
import app.organicmaps.editor.EditorActivity;
import app.organicmaps.editor.EditorHostFragment;
import app.organicmaps.editor.FeatureCategoryActivity;
import app.organicmaps.editor.OsmLoginActivity;
import app.organicmaps.sdk.editor.OsmOAuth; import app.organicmaps.sdk.editor.OsmOAuth;
import app.organicmaps.editor.ReportFragment;
import app.organicmaps.help.HelpActivity;
import app.organicmaps.intent.Factory;
import app.organicmaps.intent.IntentProcessor;
import app.organicmaps.sdk.location.LocationHelper; import app.organicmaps.sdk.location.LocationHelper;
import app.organicmaps.sdk.location.LocationListener; import app.organicmaps.sdk.location.LocationListener;
import app.organicmaps.sdk.location.LocationState; import app.organicmaps.sdk.location.LocationState;
import app.organicmaps.sdk.location.SensorListener; import app.organicmaps.sdk.location.SensorListener;
import app.organicmaps.sdk.location.TrackRecorder; import app.organicmaps.sdk.location.TrackRecorder;
import app.organicmaps.location.TrackRecordingService;
import app.organicmaps.maplayer.MapButtonsController;
import app.organicmaps.maplayer.MapButtonsViewModel;
import app.organicmaps.maplayer.ToggleMapLayerFragment;
import app.organicmaps.sdk.maplayer.isolines.IsolinesState; import app.organicmaps.sdk.maplayer.isolines.IsolinesState;
import app.organicmaps.routing.ManageRouteBottomSheet;
import app.organicmaps.routing.NavigationController;
import app.organicmaps.routing.NavigationService;
import app.organicmaps.sdk.routing.RouteMarkType; import app.organicmaps.sdk.routing.RouteMarkType;
import app.organicmaps.routing.RoutingBottomMenuListener;
import app.organicmaps.routing.RoutingController;
import app.organicmaps.routing.RoutingErrorDialogFragment;
import app.organicmaps.sdk.routing.RoutingOptions; import app.organicmaps.sdk.routing.RoutingOptions;
import app.organicmaps.routing.RoutingPlanFragment;
import app.organicmaps.routing.RoutingPlanInplaceController;
import app.organicmaps.sdk.ChoosePositionMode;
import app.organicmaps.sdk.PlacePageActivationListener;
import app.organicmaps.sdk.Router;
import app.organicmaps.search.FloatingSearchToolbarController;
import app.organicmaps.search.SearchActivity;
import app.organicmaps.sdk.search.SearchEngine; import app.organicmaps.sdk.search.SearchEngine;
import app.organicmaps.search.SearchFragment;
import app.organicmaps.settings.DrivingOptionsActivity;
import app.organicmaps.sdk.settings.RoadType; import app.organicmaps.sdk.settings.RoadType;
import app.organicmaps.settings.SettingsActivity;
import app.organicmaps.sdk.settings.UnitLocale; import app.organicmaps.sdk.settings.UnitLocale;
import app.organicmaps.leftbutton.LeftButton;
import app.organicmaps.leftbutton.LeftButtonsHolder;
import app.organicmaps.leftbutton.LeftToggleButton;
import app.organicmaps.sdk.util.Config; import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.LocationUtils; import app.organicmaps.sdk.util.LocationUtils;
import app.organicmaps.sdk.util.PowerManagment; import app.organicmaps.sdk.util.PowerManagment;
import app.organicmaps.util.SharingUtils;
import app.organicmaps.sdk.util.ThemeSwitcher; import app.organicmaps.sdk.util.ThemeSwitcher;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.sdk.util.UiUtils; 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;
import app.organicmaps.search.SearchActivity;
import app.organicmaps.search.SearchFragment;
import app.organicmaps.settings.DrivingOptionsActivity;
import app.organicmaps.settings.SettingsActivity;
import app.organicmaps.util.SharingUtils;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment; import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment;
import app.organicmaps.util.bottomsheet.MenuBottomSheetItem; import app.organicmaps.util.bottomsheet.MenuBottomSheetItem;
import app.organicmaps.sdk.util.log.Logger;
import app.organicmaps.widget.StackedButtonsDialog; import app.organicmaps.widget.StackedButtonsDialog;
import app.organicmaps.widget.menu.MainMenu; import app.organicmaps.widget.menu.MainMenu;
import app.organicmaps.widget.placepage.PlacePageController; import app.organicmaps.widget.placepage.PlacePageController;
import app.organicmaps.sdk.widget.placepage.PlacePageData;
import app.organicmaps.widget.placepage.PlacePageViewModel; import app.organicmaps.widget.placepage.PlacePageViewModel;
import com.google.android.material.appbar.MaterialToolbar; import com.google.android.material.appbar.MaterialToolbar;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Objects; import java.util.Objects;
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.Manifest.permission.POST_NOTIFICATIONS;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
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.leftbutton.LeftButtonsHolder.BUTTON_ADD_PLACE_CODE;
import static app.organicmaps.leftbutton.LeftButtonsHolder.BUTTON_HELP_CODE;
import static app.organicmaps.leftbutton.LeftButtonsHolder.BUTTON_RECORD_TRACK_CODE;
import static app.organicmaps.leftbutton.LeftButtonsHolder.BUTTON_SETTINGS_CODE;
import static app.organicmaps.sdk.util.PowerManagment.POWER_MANAGEMENT_TAG;
import static app.organicmaps.sdk.util.concurrency.UiThread.runLater;
public class MwmActivity extends BaseMwmFragmentActivity public class MwmActivity extends BaseMwmFragmentActivity
implements PlacePageActivationListener, implements PlacePageActivationListener, View.OnTouchListener, MapRenderingListener, RoutingController.Container,
View.OnTouchListener, LocationListener, SensorListener, LocationState.ModeChangeListener,
MapRenderingListener, RoutingPlanInplaceController.RoutingPlanListener, RoutingBottomMenuListener,
RoutingController.Container, BookmarkManager.BookmarksLoadingListener, FloatingSearchToolbarController.SearchToolbarListener,
LocationListener,
SensorListener,
LocationState.ModeChangeListener,
RoutingPlanInplaceController.RoutingPlanListener,
RoutingBottomMenuListener,
BookmarkManager.BookmarksLoadingListener,
FloatingSearchToolbarController.SearchToolbarListener,
MenuBottomSheetFragment.MenuBottomSheetInterfaceWithHeader, MenuBottomSheetFragment.MenuBottomSheetInterfaceWithHeader,
PlacePageController.PlacePageRouteSettingsListener, PlacePageController.PlacePageRouteSettingsListener, MapButtonsController.MapButtonClickListener,
MapButtonsController.MapButtonClickListener,
DisplayChangedListener DisplayChangedListener
{ {
private static final String TAG = MwmActivity.class.getSimpleName(); private static final String TAG = MwmActivity.class.getSimpleName();
@@ -171,14 +159,12 @@ public class MwmActivity extends BaseMwmFragmentActivity
private static final String EXTRA_CONSUMED = "mwm.extra.intent.processed"; private static final String EXTRA_CONSUMED = "mwm.extra.intent.processed";
private boolean mPreciseLocationDialogShown = false; private boolean mPreciseLocationDialogShown = false;
private static final String[] DOCKED_FRAGMENTS = { SearchFragment.class.getName(), private static final String[] DOCKED_FRAGMENTS = {SearchFragment.class.getName(), DownloaderFragment.class.getName(),
DownloaderFragment.class.getName(),
RoutingPlanFragment.class.getName(), RoutingPlanFragment.class.getName(),
EditorHostFragment.class.getName(), EditorHostFragment.class.getName(), ReportFragment.class.getName()};
ReportFragment.class.getName() };
public final ActivityResultLauncher<Intent> startDrivingOptionsForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> public final ActivityResultLauncher<Intent> startDrivingOptionsForResult =
{ registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> {
if (activityResult.getResultCode() == Activity.RESULT_OK) if (activityResult.getResultCode() == Activity.RESULT_OK)
rebuildLastRoute(); rebuildLastRoute();
}); });
@@ -275,8 +261,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
public static Intent createShowMapIntent(@NonNull Context context, @Nullable String countryId) public static Intent createShowMapIntent(@NonNull Context context, @Nullable String countryId)
{ {
return new Intent(context, DownloadResourcesLegacyActivity.class) return new Intent(context, DownloadResourcesLegacyActivity.class).putExtra(EXTRA_COUNTRY_ID, countryId);
.putExtra(EXTRA_COUNTRY_ID, countryId);
} }
@Override @Override
@@ -363,14 +348,15 @@ public class MwmActivity extends BaseMwmFragmentActivity
private void migrateOAuthCredentials() private void migrateOAuthCredentials()
{ {
if (OsmOAuth.containsOAuth1Credentials(this)) if (OsmOAuth.containsOAuth1Credentials())
{ {
// Remove old OAuth v1 secrets // Remove old OAuth v1 secrets
OsmOAuth.clearOAuth1Credentials(this); OsmOAuth.clearOAuth1Credentials();
// Notify user to re-login // Notify user to re-login
dismissAlertDialog(); dismissAlertDialog();
final DialogInterface.OnClickListener navigateToLoginHandler = (dialog, which) -> startActivity(new Intent(MwmActivity.this, OsmLoginActivity.class)); final DialogInterface.OnClickListener navigateToLoginHandler =
(dialog, which) -> startActivity(new Intent(MwmActivity.this, OsmLoginActivity.class));
final int marginBase = getResources().getDimensionPixelSize(R.dimen.margin_base); final int marginBase = getResources().getDimensionPixelSize(R.dimen.margin_base);
final float textSize = getResources().getDimension(R.dimen.line_spacing_extra_1); final float textSize = getResources().getDimension(R.dimen.line_spacing_extra_1);
@@ -398,8 +384,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
@Override @Override
protected int getFragmentContentResId() protected int getFragmentContentResId()
{ {
return (mIsTabletLayout ? R.id.fragment_container return (mIsTabletLayout ? R.id.fragment_container : super.getFragmentContentResId());
: super.getFragmentContentResId());
} }
@Nullable @Nullable
@@ -417,7 +402,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
} }
@Override @Override
public void replaceFragment(@NonNull Class<? extends Fragment> fragmentClass, @Nullable Bundle args, @Nullable Runnable completionListener) public void replaceFragment(@NonNull Class<? extends Fragment> fragmentClass, @Nullable Bundle args,
@Nullable Runnable completionListener)
{ {
if (mPanelAnimator.isVisible() && getFragment(fragmentClass) != null) if (mPanelAnimator.isVisible() && getFragment(fragmentClass) != null)
{ {
@@ -534,7 +520,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
final int newUiMode = newConfig.uiMode & Configuration.UI_MODE_TYPE_MASK; final int newUiMode = newConfig.uiMode & Configuration.UI_MODE_TYPE_MASK;
final boolean newUiModeIsCarConnected = newUiMode == Configuration.UI_MODE_TYPE_CAR; final boolean newUiModeIsCarConnected = newUiMode == Configuration.UI_MODE_TYPE_CAR;
final boolean newUiModeIsCarDisconnected = mLastUiMode == Configuration.UI_MODE_TYPE_CAR && newUiMode == Configuration.UI_MODE_TYPE_NORMAL; final boolean newUiModeIsCarDisconnected =
mLastUiMode == Configuration.UI_MODE_TYPE_CAR && newUiMode == Configuration.UI_MODE_TYPE_NORMAL;
mLastUiMode = newUiMode; mLastUiMode = newUiMode;
if (newUiModeIsCarConnected || newUiModeIsCarDisconnected) if (newUiModeIsCarConnected || newUiModeIsCarDisconnected)
@@ -566,8 +553,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
mMapButtonsViewModel.getLayoutMode().observe(this, this::initNavigationButtons); mMapButtonsViewModel.getLayoutMode().observe(this, this::initNavigationButtons);
mSearchController = new FloatingSearchToolbarController(this, this); mSearchController = new FloatingSearchToolbarController(this, this);
mSearchController.getToolbar() mSearchController.getToolbar().getViewTreeObserver();
.getViewTreeObserver();
// Note: You must call registerForActivityResult() before the fragment or activity is created. // Note: You must call registerForActivityResult() before the fragment or activity is created.
mLocationPermissionRequest = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), mLocationPermissionRequest = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(),
@@ -576,15 +562,15 @@ public class MwmActivity extends BaseMwmFragmentActivity
this::onLocationResolutionResult); this::onLocationResolutionResult);
mPostNotificationPermissionRequest = registerForActivityResult(new ActivityResultContracts.RequestPermission(), mPostNotificationPermissionRequest = registerForActivityResult(new ActivityResultContracts.RequestPermission(),
this::onPostNotificationPermissionResult); this::onPostNotificationPermissionResult);
mPowerSaveSettings = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), mPowerSaveSettings =
this::onPowerSaveResult); registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), this::onPowerSaveResult);
mSettingsLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), mSettingsLauncher =
this::onSettingsResult); registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), this::onSettingsResult);
mShareLauncher = SharingUtils.RegisterLauncher(this); mShareLauncher = SharingUtils.RegisterLauncher(this);
mDisplayManager = DisplayManager.from(this); mDisplayManager = MwmApplication.from(this).getDisplayManager();
if (mDisplayManager.isCarDisplayUsed()) if (mDisplayManager.isCarDisplayUsed())
{ {
mRemoveDisplayListener = false; mRemoveDisplayListener = false;
@@ -622,7 +608,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
Intent data = activityResult.getData(); Intent data = activityResult.getData();
if (data != null && data.hasExtra(MwmActivity.this.getString(R.string.pref_left_button))) if (data != null && data.hasExtra(MwmActivity.this.getString(R.string.pref_left_button)))
{ {
MapButtonsController mMapButtonsController = (MapButtonsController) getSupportFragmentManager().findFragmentById(R.id.map_buttons); MapButtonsController mMapButtonsController =
(MapButtonsController) getSupportFragmentManager().findFragmentById(R.id.map_buttons);
if (mMapButtonsController != null) if (mMapButtonsController != null)
{ {
mMapButtonsController.reloadLeftButton(buttonsHolder.getActiveButton()); mMapButtonsController.reloadLeftButton(buttonsHolder.getActiveButton());
@@ -633,11 +620,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
private void refreshLightStatusBar() private void refreshLightStatusBar()
{ {
UiUtils.setLightStatusBar(this, !( UiUtils.setLightStatusBar(this, !(ThemeUtils.isNightTheme(this) || RoutingController.get().isPlanning()
ThemeUtils.isNightTheme(this) || ChoosePositionMode.get() != ChoosePositionMode.None));
|| RoutingController.get().isPlanning()
|| ChoosePositionMode.get() != ChoosePositionMode.None
));
} }
private void updateViewsInsets() private void updateViewsInsets()
@@ -645,13 +629,15 @@ public class MwmActivity extends BaseMwmFragmentActivity
ViewCompat.setOnApplyWindowInsetsListener(mPointChooser, (view, windowInsets) -> { ViewCompat.setOnApplyWindowInsetsListener(mPointChooser, (view, windowInsets) -> {
UiUtils.setViewInsetsPaddingBottom(mPointChooser, windowInsets); UiUtils.setViewInsetsPaddingBottom(mPointChooser, windowInsets);
UiUtils.setViewInsetsPaddingNoBottom(mPointChooserToolbar, windowInsets); UiUtils.setViewInsetsPaddingNoBottom(mPointChooserToolbar, windowInsets);
final int trackRecorderOffset = TrackRecorder.nativeIsTrackRecordingEnabled() ? UiUtils.dimen(this, R.dimen.map_button_size) : 0; final int trackRecorderOffset =
TrackRecorder.nativeIsTrackRecordingEnabled() ? UiUtils.dimen(this, R.dimen.map_button_size) : 0;
mNavBarHeight = isFullscreen() ? 0 : windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom; mNavBarHeight = isFullscreen() ? 0 : windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).bottom;
// For the first loading, set compass top margin to status bar size // For the first loading, set compass top margin to status bar size
// The top inset will be then be updated by the routing controller // The top inset will be then be updated by the routing controller
if (mCurrentWindowInsets == null) if (mCurrentWindowInsets == null)
{ {
updateCompassOffset(trackRecorderOffset + windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).top, windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).right); updateCompassOffset(trackRecorderOffset + windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).top,
windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).right);
} }
refreshLightStatusBar(); refreshLightStatusBar();
updateBottomWidgetsOffset(windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).left); updateBottomWidgetsOffset(windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).left);
@@ -677,7 +663,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
removeCurrentFragment(false); removeCurrentFragment(false);
} }
mNavigationController = new NavigationController(this, v -> onSettingsOptionSelected(), this::updateBottomWidgetsOffset); mNavigationController =
new NavigationController(this, v -> onSettingsOptionSelected(), this::updateBottomWidgetsOffset);
// TrafficManager.INSTANCE.attach(mNavigationController); // TrafficManager.INSTANCE.attach(mNavigationController);
initMainMenu(); initMainMenu();
@@ -694,9 +681,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
mPointChooserToolbar = mPointChooser.findViewById(R.id.toolbar_point_chooser); mPointChooserToolbar = mPointChooser.findViewById(R.id.toolbar_point_chooser);
UiUtils.showHomeUpButton(mPointChooserToolbar); UiUtils.showHomeUpButton(mPointChooserToolbar);
mPointChooserToolbar.setNavigationOnClickListener(v -> closePositionChooser()); mPointChooserToolbar.setNavigationOnClickListener(v -> closePositionChooser());
mPointChooser.findViewById(R.id.done).setOnClickListener( mPointChooser.findViewById(R.id.done).setOnClickListener(v -> {
v ->
{
switch (ChoosePositionMode.get()) switch (ChoosePositionMode.get())
{ {
case Api: case Api:
@@ -721,8 +706,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
.show(); .show();
} }
break; break;
case None: case None: throw new IllegalStateException("Unexpected Framework.nativeGetChoosePositionMode()");
throw new IllegalStateException("Unexpected Framework.nativeGetChoosePositionMode()");
} }
closePositionChooser(); closePositionChooser();
}); });
@@ -750,7 +734,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
} }
} }
/** Hides/shows UI while keeping state /**
*Hides/shows UI while keeping state
* @param isUiHidden True to hide the UI * @param isUiHidden True to hide the UI
**/ **/
public void hideOrShowUIWithoutClosingPlacePage(boolean isUiHidden) public void hideOrShowUIWithoutClosingPlacePage(boolean isUiHidden)
@@ -783,6 +768,16 @@ public class MwmActivity extends BaseMwmFragmentActivity
private void showPositionChooser(ChoosePositionMode mode, boolean isBusiness, boolean applyPosition) private void showPositionChooser(ChoosePositionMode mode, boolean isBusiness, boolean applyPosition)
{ {
closeFloatingToolbarsAndPanels(false); closeFloatingToolbarsAndPanels(false);
if (mMapFragment != null)
{
final View mapView = mMapFragment.getView();
if (mapView != null)
{
int width = mapView.getWidth();
int height = mapView.getHeight();
Framework.nativeSetVisibleRect(0, 0, width, height);
}
}
UiUtils.show(mPointChooser); UiUtils.show(mPointChooser);
mMapButtonsViewModel.setButtonsHidden(true); mMapButtonsViewModel.setButtonsHidden(true);
ChoosePositionMode.set(mode, isBusiness, applyPosition); ChoosePositionMode.set(mode, isBusiness, applyPosition);
@@ -795,6 +790,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
ChoosePositionMode mode = ChoosePositionMode.get(); ChoosePositionMode mode = ChoosePositionMode.get();
ChoosePositionMode.set(ChoosePositionMode.None, false, false); ChoosePositionMode.set(ChoosePositionMode.None, false, false);
mMapButtonsViewModel.setButtonsHidden(false); mMapButtonsViewModel.setButtonsHidden(false);
Framework.nativeDeactivatePopup();
refreshLightStatusBar(); refreshLightStatusBar();
if (mode == ChoosePositionMode.Api) if (mode == ChoosePositionMode.Api)
finish(); finish();
@@ -811,8 +807,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
final FragmentFactory factory = manager.getFragmentFactory(); final FragmentFactory factory = manager.getFragmentFactory();
mMapFragment = (MapFragment) factory.instantiate(getClassLoader(), MapFragment.class.getName()); mMapFragment = (MapFragment) factory.instantiate(getClassLoader(), MapFragment.class.getName());
mMapFragment.setArguments(args); mMapFragment.setArguments(args);
manager manager.beginTransaction()
.beginTransaction()
.replace(R.id.map_fragment_container, mMapFragment, MapFragment.class.getName()) .replace(R.id.map_fragment_container, mMapFragment, MapFragment.class.getName())
.commit(); .commit();
} }
@@ -833,8 +828,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
private void prepareNavigationButtons() private void prepareNavigationButtons()
{ {
buttonsHolder = LeftButtonsHolder.getInstance(this); buttonsHolder = LeftButtonsHolder.getInstance(this);
buttonsHolder.registerButton(new LeftButton() buttonsHolder.registerButton(new LeftButton() {
{
@Override @Override
public String getCode() public String getCode()
{ {
@@ -860,8 +854,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
MwmActivity.this.startActivity(intent); MwmActivity.this.startActivity(intent);
} }
}); });
buttonsHolder.registerButton(new LeftButton() buttonsHolder.registerButton(new LeftButton() {
{
@Override @Override
public String getCode() public String getCode()
{ {
@@ -886,8 +879,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
onAddPlace(); onAddPlace();
} }
}); });
buttonsHolder.registerButton(new LeftButton() buttonsHolder.registerButton(new LeftButton() {
{
@Override @Override
public String getCode() public String getCode()
{ {
@@ -913,8 +905,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
} }
}); });
buttonsHolder.registerButton(new LeftToggleButton() buttonsHolder.registerButton(new LeftToggleButton() {
{
private boolean isRecording = TrackRecorder.nativeIsTrackRecordingEnabled(); private boolean isRecording = TrackRecorder.nativeIsTrackRecordingEnabled();
@Override @Override
@@ -940,8 +931,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
{ {
imageView.setImageResource(R.drawable.ic_track_recording_off); imageView.setImageResource(R.drawable.ic_track_recording_off);
int color = isRecording int color = isRecording ? ContextCompat.getColor(MwmActivity.this, R.color.active_track_recording)
? ContextCompat.getColor(MwmActivity.this, R.color.active_track_recording)
: ThemeUtils.getColor(MwmActivity.this, R.attr.iconTint); : ThemeUtils.getColor(MwmActivity.this, R.attr.iconTint);
ColorStateList colorStateList = ColorStateList.valueOf(color); ColorStateList colorStateList = ColorStateList.valueOf(color);
@@ -955,6 +945,42 @@ public class MwmActivity extends BaseMwmFragmentActivity
drawIcon(left); drawIcon(left);
} }
}); });
buttonsHolder.registerButton(new LeftToggleButton() {
//TODO: hide layers button
private boolean isLayerActive = false; //TODO: hook up
@Override
public void setChecked(boolean checked)
{
isLayerActive = checked;
}
@Override
public String getCode()
{
return BUTTON_MAP_LAYER_CODE;
}
@Override
public String getPrefsName()
{
return getString(R.string.layers_title);
}
@Override
public void drawIcon(FloatingActionButton imageView)
{
imageView.setImageResource(isLayerActive ? R.drawable.ic_layers : R.drawable.ic_layers_clear);
}
@Override
public void onClick(FloatingActionButton left)
{
toggleMapLayerBottomSheet();
drawIcon(left);
}
});
} }
private void initNavigationButtons(MapButtonsController.LayoutMode layoutMode) private void initNavigationButtons(MapButtonsController.LayoutMode layoutMode)
@@ -965,8 +991,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
MapButtonsController mapButtonsController = new MapButtonsController(); MapButtonsController mapButtonsController = new MapButtonsController();
mapButtonsController.setLeftButton(buttonsHolder.getActiveButton()); mapButtonsController.setLeftButton(buttonsHolder.getActiveButton());
FragmentTransaction transaction = getSupportFragmentManager() FragmentTransaction transaction =
.beginTransaction().replace(R.id.map_buttons, mapButtonsController); getSupportFragmentManager().beginTransaction().replace(R.id.map_buttons, mapButtonsController);
transaction.commit(); transaction.commit();
mPreviousMapLayoutMode = layoutMode; mPreviousMapLayoutMode = layoutMode;
} }
@@ -1004,11 +1030,9 @@ public class MwmActivity extends BaseMwmFragmentActivity
} }
} }
private boolean closeBottomSheet(String id) private boolean closeBottomSheet(String id)
{ {
MenuBottomSheetFragment bottomSheet = MenuBottomSheetFragment bottomSheet = (MenuBottomSheetFragment) getSupportFragmentManager().findFragmentByTag(id);
(MenuBottomSheetFragment) getSupportFragmentManager().findFragmentByTag(id);
if (bottomSheet == null || !bottomSheet.isAdded()) if (bottomSheet == null || !bottomSheet.isAdded())
return false; return false;
bottomSheet.dismiss(); bottomSheet.dismiss();
@@ -1246,7 +1270,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog) mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.downloader_update_maps) .setTitle(R.string.downloader_update_maps)
.setMessage(R.string.isolines_activation_error_dialog) .setMessage(R.string.isolines_activation_error_dialog)
.setPositiveButton(R.string.ok, (dialog, which) -> startActivity(new Intent(this, DownloaderActivity.class))) .setPositiveButton(R.string.ok,
(dialog, which) -> startActivity(new Intent(this, DownloaderActivity.class)))
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)
.setOnDismissListener(dialog -> mAlertDialog = null) .setOnDismissListener(dialog -> mAlertDialog = null)
.show(); .show();
@@ -1259,8 +1284,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
super.onNewIntent(intent); super.onNewIntent(intent);
if (isMapRendererActive()) if (isMapRendererActive())
processIntent(); processIntent();
if (intent.getAction() != null && intent.getAction() if (intent.getAction() != null && intent.getAction().equals(TrackRecordingService.STOP_TRACK_RECORDING))
.equals(TrackRecordingService.STOP_TRACK_RECORDING))
{ {
// closes the bottom sheet in case it is opened to deal with updation of track recording status in bottom sheet. // closes the bottom sheet in case it is opened to deal with updation of track recording status in bottom sheet.
closeBottomSheet(MAIN_MENU_ID); closeBottomSheet(MAIN_MENU_ID);
@@ -1268,11 +1292,9 @@ public class MwmActivity extends BaseMwmFragmentActivity
} }
} }
private boolean isMapRendererActive() private boolean isMapRendererActive()
{ {
return mMapFragment != null && Map.isEngineCreated() return mMapFragment != null && Map.isEngineCreated() && mMapFragment.isContextCreated();
&& mMapFragment.isContextCreated();
} }
@CallSuper @CallSuper
@@ -1386,10 +1408,9 @@ public class MwmActivity extends BaseMwmFragmentActivity
public void onBackPressed() public void onBackPressed()
{ {
final RoutingController routingController = RoutingController.get(); final RoutingController routingController = RoutingController.get();
if (!closeBottomSheet(MAIN_MENU_ID) && !closeBottomSheet(LAYERS_MENU_ID) && if (!closeBottomSheet(MAIN_MENU_ID) && !closeBottomSheet(LAYERS_MENU_ID) && !collapseNavMenu() && !closePlacePage()
!collapseNavMenu() && !closePlacePage() && !closeSearchToolbar(true, true) && && !closeSearchToolbar(true, true) && !closeSidePanel() && !closePositionChooser()
!closeSidePanel() && !closePositionChooser() && && !routingController.resetToPlanningStateIfNavigating() && !routingController.cancel())
!routingController.resetToPlanningStateIfNavigating() && !routingController.cancel())
{ {
try try
{ {
@@ -1421,9 +1442,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
if (fm.isDestroyed()) if (fm.isDestroyed())
return; return;
fm.beginTransaction() fm.beginTransaction().remove(fragment).commitAllowingStateLoss();
.remove(fragment)
.commitAllowingStateLoss();
fm.executePendingTransactions(); fm.executePendingTransactions();
} }
@@ -1484,8 +1503,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
private void setFullscreen(boolean isFullscreen) private void setFullscreen(boolean isFullscreen)
{ {
if (RoutingController.get().isNavigating() if (RoutingController.get().isNavigating() || RoutingController.get().isBuilding()
|| RoutingController.get().isBuilding()
|| RoutingController.get().isPlanning()) || RoutingController.get().isPlanning())
return; return;
@@ -1496,13 +1514,15 @@ public class MwmActivity extends BaseMwmFragmentActivity
private boolean isFullscreen() private boolean isFullscreen()
{ {
// Buttons are hidden in position chooser mode but we are not in fullscreen // Buttons are hidden in position chooser mode but we are not in fullscreen
return Boolean.TRUE.equals(mMapButtonsViewModel.getButtonsHidden().getValue()) && return Boolean.TRUE.equals(mMapButtonsViewModel.getButtonsHidden().getValue())
ChoosePositionMode.get() == ChoosePositionMode.None; && ChoosePositionMode.get() == ChoosePositionMode.None;
} }
@Override @Override
public boolean dispatchGenericMotionEvent(MotionEvent event) { public boolean dispatchGenericMotionEvent(MotionEvent event)
if (event.getActionMasked() == MotionEvent.ACTION_SCROLL) { {
if (event.getActionMasked() == MotionEvent.ACTION_SCROLL)
{
int exponent = event.getAxisValue(MotionEvent.AXIS_VSCROLL) < 0 ? -1 : 1; int exponent = event.getAxisValue(MotionEvent.AXIS_VSCROLL) < 0 ? -1 : 1;
Map.onScale(Math.pow(1.7f, exponent), event.getX(), event.getY(), true); Map.onScale(Math.pow(1.7f, exponent), event.getX(), event.getY(), true);
return true; return true;
@@ -1541,7 +1561,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
Map.onCompassUpdated(north, true); Map.onCompassUpdated(north, true);
} }
public void onMapBottomButtonsHeightChange(float height) { public void onMapBottomButtonsHeightChange(float height)
{
updateBottomWidgetsOffset(); updateBottomWidgetsOffset();
} }
@@ -1608,8 +1629,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
mMainMenu.setState(MainMenu.State.MENU, isFullscreen()); mMainMenu.setState(MainMenu.State.MENU, isFullscreen());
} }
private boolean showAddStartOrFinishFrame(@NonNull RoutingController controller, private boolean showAddStartOrFinishFrame(@NonNull RoutingController controller, boolean showFrame)
boolean showFrame)
{ {
// S - start, F - finish, L - my position // S - start, F - finish, L - my position
// -S-F-L -> Start // -S-F-L -> Start
@@ -1684,7 +1704,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
{ {
// TODO This code section may be called when insets are not yet initialized // TODO This code section may be called when insets are not yet initialized
// This is only a workaround to prevent crashes but a proper fix should be implemented // This is only a workaround to prevent crashes but a proper fix should be implemented
if (mCurrentWindowInsets == null) { if (mCurrentWindowInsets == null)
{
return; return;
} }
int offsetY = mCurrentWindowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).top; int offsetY = mCurrentWindowInsets.getInsets(WindowInsetsCompat.Type.systemBars()).top;
@@ -1880,8 +1901,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
@Override @Override
public void onCommonBuildError(int lastResultCode, @NonNull String[] lastMissingMaps) public void onCommonBuildError(int lastResultCode, @NonNull String[] lastMissingMaps)
{ {
RoutingErrorDialogFragment fragment = RoutingErrorDialogFragment.create(getSupportFragmentManager().getFragmentFactory(), RoutingErrorDialogFragment fragment = RoutingErrorDialogFragment.create(
getApplicationContext(), lastResultCode, lastMissingMaps); getSupportFragmentManager().getFragmentFactory(), getApplicationContext(), lastResultCode, lastMissingMaps);
fragment.show(getSupportFragmentManager(), RoutingErrorDialogFragment.class.getSimpleName()); fragment.show(getSupportFragmentManager(), RoutingErrorDialogFragment.class.getSimpleName());
} }
@@ -1889,10 +1910,12 @@ public class MwmActivity extends BaseMwmFragmentActivity
public void onDrivingOptionsBuildError() public void onDrivingOptionsBuildError()
{ {
dismissAlertDialog(); dismissAlertDialog();
mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog) mAlertDialog =
new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.unable_to_calc_alert_title) .setTitle(R.string.unable_to_calc_alert_title)
.setMessage(R.string.unable_to_calc_alert_subtitle) .setMessage(R.string.unable_to_calc_alert_subtitle)
.setPositiveButton(R.string.settings, (dialog, which) -> DrivingOptionsActivity.start(this, startDrivingOptionsForResult)) .setPositiveButton(R.string.settings,
(dialog, which) -> DrivingOptionsActivity.start(this, startDrivingOptionsForResult))
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)
.setOnDismissListener(dialog -> mAlertDialog = null) .setOnDismissListener(dialog -> mAlertDialog = null)
.show(); .show();
@@ -1904,7 +1927,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
return true; return true;
final StringBuilder builder = new StringBuilder(); final StringBuilder builder = new StringBuilder();
for (int resId : new int[]{R.string.dialog_routing_disclaimer_priority, R.string.dialog_routing_disclaimer_precision, for (int resId :
new int[] {R.string.dialog_routing_disclaimer_priority, R.string.dialog_routing_disclaimer_precision,
R.string.dialog_routing_disclaimer_recommendations, R.string.dialog_routing_disclaimer_borders, R.string.dialog_routing_disclaimer_recommendations, R.string.dialog_routing_disclaimer_borders,
R.string.dialog_routing_disclaimer_beware}) R.string.dialog_routing_disclaimer_beware})
builder.append(getString(resId)).append("\n\n"); builder.append(getString(resId)).append("\n\n");
@@ -1915,7 +1939,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
.setMessage(builder.toString()) .setMessage(builder.toString())
.setCancelable(false) .setCancelable(false)
.setNegativeButton(R.string.decline, null) .setNegativeButton(R.string.decline, null)
.setPositiveButton(R.string.accept, (dlg, which) -> { .setPositiveButton(R.string.accept,
(dlg, which) -> {
Config.acceptRoutingDisclaimer(); Config.acceptRoutingDisclaimer();
onRoutingStart(); onRoutingStart();
}) })
@@ -1986,10 +2011,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
Logger.i(LOCATION_TAG, "Requesting ACCESS_FINE_LOCATION + ACCESS_FINE_LOCATION permissions"); Logger.i(LOCATION_TAG, "Requesting ACCESS_FINE_LOCATION + ACCESS_FINE_LOCATION permissions");
dismissLocationErrorDialog(); dismissLocationErrorDialog();
mLocationPermissionRequest.launch(new String[]{ mLocationPermissionRequest.launch(new String[] {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION});
ACCESS_COARSE_LOCATION,
ACCESS_FINE_LOCATION
});
return; return;
} }
@@ -2000,10 +2022,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
// Try to optimistically request FINE permission for FOLLOW and FOLLOW_AND_ROTATE modes. // Try to optimistically request FINE permission for FOLLOW and FOLLOW_AND_ROTATE modes.
Logger.i(LOCATION_TAG, "Requesting ACCESS_FINE_LOCATION permission for " + LocationState.nameOf(newMode)); Logger.i(LOCATION_TAG, "Requesting ACCESS_FINE_LOCATION permission for " + LocationState.nameOf(newMode));
dismissLocationErrorDialog(); dismissLocationErrorDialog();
mLocationPermissionRequest.launch(new String[]{ mLocationPermissionRequest.launch(new String[] {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION});
ACCESS_COARSE_LOCATION,
ACCESS_FINE_LOCATION
});
} }
} }
@@ -2067,16 +2086,14 @@ public class MwmActivity extends BaseMwmFragmentActivity
@UiThread @UiThread
public void onCompassCalibrationRecommended() public void onCompassCalibrationRecommended()
{ {
Toast.makeText(this, getString(R.string.compass_calibration_recommended), Toast.makeText(this, getString(R.string.compass_calibration_recommended), Toast.LENGTH_LONG).show();
Toast.LENGTH_LONG).show();
} }
@Override @Override
@UiThread @UiThread
public void onCompassCalibrationRequired() public void onCompassCalibrationRequired()
{ {
Toast.makeText(this, getString(R.string.compass_calibration_required), Toast.makeText(this, getString(R.string.compass_calibration_required), Toast.LENGTH_LONG).show();
Toast.LENGTH_LONG).show();
} }
/** /**
@@ -2084,8 +2101,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
*/ */
public void requestPostNotificationsPermission() public void requestPostNotificationsPermission()
{ {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU || if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU
ActivityCompat.checkSelfPermission(this, POST_NOTIFICATIONS) == PERMISSION_GRANTED) || ActivityCompat.checkSelfPermission(this, POST_NOTIFICATIONS) == PERMISSION_GRANTED)
{ {
Logger.i(TAG, "Permissions POST_NOTIFICATIONS is granted"); Logger.i(TAG, "Permissions POST_NOTIFICATIONS is granted");
return; return;
@@ -2139,7 +2156,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
if (!mPreciseLocationDialogShown) if (!mPreciseLocationDialogShown)
{ {
mPreciseLocationDialogShown = true; mPreciseLocationDialogShown = true;
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog) final MaterialAlertDialogBuilder builder =
new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle("" + getString(R.string.limited_accuracy)) .setTitle("" + getString(R.string.limited_accuracy))
.setMessage(R.string.precise_location_is_disabled_long_text) .setMessage(R.string.precise_location_is_disabled_long_text)
.setNegativeButton(R.string.close, (dialog, which) -> dialog.dismiss()) .setNegativeButton(R.string.close, (dialog, which) -> dialog.dismiss())
@@ -2349,11 +2367,13 @@ public class MwmActivity extends BaseMwmFragmentActivity
} }
dismissAlertDialog(); dismissAlertDialog();
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog) final MaterialAlertDialogBuilder builder =
new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.current_location_unknown_error_title) .setTitle(R.string.current_location_unknown_error_title)
.setCancelable(true) .setCancelable(true)
.setMessage(R.string.power_save_dialog_summary) .setMessage(R.string.power_save_dialog_summary)
.setNegativeButton(R.string.not_now, (dialog, which) -> { .setNegativeButton(R.string.not_now,
(dialog, which) -> {
Logger.d(POWER_MANAGEMENT_TAG, "The Power Save disclaimer was ignored"); Logger.d(POWER_MANAGEMENT_TAG, "The Power Save disclaimer was ignored");
mPowerSaveDisclaimerShown = true; mPowerSaveDisclaimerShown = true;
}) })
@@ -2372,12 +2392,15 @@ public class MwmActivity extends BaseMwmFragmentActivity
public void onBookmarksFileUnsupported(@NonNull Uri uri) public void onBookmarksFileUnsupported(@NonNull Uri uri)
{ {
dismissAlertDialog(); dismissAlertDialog();
mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog) mAlertDialog =
new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.load_kmz_title) .setTitle(R.string.load_kmz_title)
.setMessage(getString(R.string.unknown_file_type, uri)) .setMessage(getString(R.string.unknown_file_type, uri))
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
.setNegativeButton(R.string.report_a_bug, (dialog, which) -> Utils.sendBugReport(mShareLauncher, this, .setNegativeButton(R.string.report_a_bug,
getString(R.string.load_kmz_title), getString(R.string.unknown_file_type, uri))) (dialog, which)
-> Utils.sendBugReport(mShareLauncher, this, getString(R.string.load_kmz_title),
getString(R.string.unknown_file_type, uri)))
.setOnDismissListener(dialog -> mAlertDialog = null) .setOnDismissListener(dialog -> mAlertDialog = null)
.show(); .show();
} }
@@ -2386,12 +2409,15 @@ public class MwmActivity extends BaseMwmFragmentActivity
public void onBookmarksFileDownloadFailed(@NonNull Uri uri, @NonNull String error) public void onBookmarksFileDownloadFailed(@NonNull Uri uri, @NonNull String error)
{ {
dismissAlertDialog(); dismissAlertDialog();
mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog) mAlertDialog =
new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.load_kmz_title) .setTitle(R.string.load_kmz_title)
.setMessage(getString(R.string.failed_to_open_file, uri, error)) .setMessage(getString(R.string.failed_to_open_file, uri, error))
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
.setNegativeButton(R.string.report_a_bug, (dialog, which) -> Utils.sendBugReport(mShareLauncher, this, .setNegativeButton(R.string.report_a_bug,
getString(R.string.load_kmz_title), getString(R.string.failed_to_open_file, uri, error))) (dialog, which)
-> Utils.sendBugReport(mShareLauncher, this, getString(R.string.load_kmz_title),
getString(R.string.failed_to_open_file, uri, error)))
.setOnDismissListener(dialog -> mAlertDialog = null) .setOnDismissListener(dialog -> mAlertDialog = null)
.show(); .show();
} }
@@ -2439,12 +2465,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
{ {
switch (keyCode) switch (keyCode)
{ {
case KeyEvent.KEYCODE_DPAD_DOWN: case KeyEvent.KEYCODE_DPAD_DOWN: Map.zoomOut(); return true;
Map.zoomOut(); case KeyEvent.KEYCODE_DPAD_UP: Map.zoomIn(); return true;
return true;
case KeyEvent.KEYCODE_DPAD_UP:
Map.zoomIn();
return true;
case KeyEvent.KEYCODE_ESCAPE: case KeyEvent.KEYCODE_ESCAPE:
final Intent currIntent = getIntent(); final Intent currIntent = getIntent();
final String backUrl = Framework.nativeGetParsedBackUrl(); final String backUrl = Framework.nativeGetParsedBackUrl();
@@ -2454,8 +2476,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
return true; return true;
} }
return super.onKeyUp(keyCode, event); return super.onKeyUp(keyCode, event);
default: default: return super.onKeyUp(keyCode, event);
return super.onKeyUp(keyCode, event);
} }
} }
@@ -2553,8 +2574,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
{ {
if (TrackRecorder.nativeIsTrackRecordingEmpty()) if (TrackRecorder.nativeIsTrackRecordingEmpty())
{ {
Toast.makeText(this, R.string.track_recording_toast_nothing_to_save, Toast.LENGTH_SHORT) Toast.makeText(this, R.string.track_recording_toast_nothing_to_save, Toast.LENGTH_SHORT).show();
.show();
stopTrackRecording(); stopTrackRecording();
return; return;
} }
@@ -2565,11 +2585,13 @@ public class MwmActivity extends BaseMwmFragmentActivity
.setCancelable(false) .setCancelable(false)
// Negative/Positive/Neutral do not have their usual meaning here. // Negative/Positive/Neutral do not have their usual meaning here.
.setNegativeButton(R.string.continue_recording, (dialog, which) -> mAlertDialog = null) .setNegativeButton(R.string.continue_recording, (dialog, which) -> mAlertDialog = null)
.setNeutralButton(R.string.stop_without_saving, (dialog, which) -> { .setNeutralButton(R.string.stop_without_saving,
(dialog, which) -> {
stopTrackRecording(); stopTrackRecording();
mAlertDialog = null; mAlertDialog = null;
}) })
.setPositiveButton(R.string.save, (dialog, which) -> { .setPositiveButton(R.string.save,
(dialog, which) -> {
saveAndStopTrackRecording(); saveAndStopTrackRecording();
mAlertDialog = null; mAlertDialog = null;
}) })
@@ -2593,20 +2615,25 @@ public class MwmActivity extends BaseMwmFragmentActivity
ArrayList<MenuBottomSheetItem> items = new ArrayList<>(); ArrayList<MenuBottomSheetItem> items = new ArrayList<>();
if (!BUTTON_ADD_PLACE_CODE.equals(activeLeftButton)) if (!BUTTON_ADD_PLACE_CODE.equals(activeLeftButton))
items.add(new MenuBottomSheetItem(R.string.placepage_add_place_button, R.drawable.ic_plus, this::onAddPlaceOptionSelected)); items.add(new MenuBottomSheetItem(R.string.placepage_add_place_button, R.drawable.ic_plus,
this::onAddPlaceOptionSelected));
items.add(new MenuBottomSheetItem(R.string.download_maps, R.drawable.ic_download, getDownloadMapsCounter(), this::onDownloadMapsOptionSelected)); items.add(new MenuBottomSheetItem(R.string.download_maps, R.drawable.ic_download, getDownloadMapsCounter(),
this::onDownloadMapsOptionSelected));
if (!Config.getDonateUrl(getApplicationContext()).isEmpty()) mDonatesUrl = Config.getDonateUrl(getApplicationContext());
if (!mDonatesUrl.isEmpty())
items.add(new MenuBottomSheetItem(R.string.donate, R.drawable.ic_donate, this::onDonateOptionSelected)); items.add(new MenuBottomSheetItem(R.string.donate, R.drawable.ic_donate, this::onDonateOptionSelected));
if (!BUTTON_SETTINGS_CODE.equals(activeLeftButton)) if (!BUTTON_SETTINGS_CODE.equals(activeLeftButton))
items.add(new MenuBottomSheetItem(R.string.settings, R.drawable.ic_settings, this::onSettingsOptionSelected)); items.add(new MenuBottomSheetItem(R.string.settings, R.drawable.ic_settings, this::onSettingsOptionSelected));
if (!BUTTON_RECORD_TRACK_CODE.equals(activeLeftButton)) if (!BUTTON_RECORD_TRACK_CODE.equals(activeLeftButton))
items.add(new MenuBottomSheetItem(R.string.start_track_recording, R.drawable.ic_track_recording_off, -1, this::onTrackRecordingOptionSelected)); items.add(new MenuBottomSheetItem(R.string.start_track_recording, R.drawable.ic_track_recording_off, -1,
this::onTrackRecordingOptionSelected));
items.add(new MenuBottomSheetItem(R.string.share_my_location, R.drawable.ic_share, this::onShareLocationOptionSelected)); items.add(new MenuBottomSheetItem(R.string.share_my_location, R.drawable.ic_share,
this::onShareLocationOptionSelected));
if (!BUTTON_HELP_CODE.equals(activeLeftButton)) if (!BUTTON_HELP_CODE.equals(activeLeftButton))
items.add(new MenuBottomSheetItem(R.string.about_help, R.drawable.ic_logo_monochrome, this::showHelp)); items.add(new MenuBottomSheetItem(R.string.about_help, R.drawable.ic_logo_monochrome, this::showHelp));

View File

@@ -7,7 +7,6 @@ import android.app.Application;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.UiThread; import androidx.annotation.UiThread;
@@ -15,30 +14,26 @@ import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleObserver; import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.ProcessLifecycleOwner; import androidx.lifecycle.ProcessLifecycleOwner;
import java.io.IOException;
import java.lang.ref.WeakReference;
import app.organicmaps.background.OsmUploadWork; import app.organicmaps.background.OsmUploadWork;
import app.organicmaps.downloader.Android7RootCertificateWorkaround;
import app.organicmaps.downloader.DownloaderNotifier; import app.organicmaps.downloader.DownloaderNotifier;
import app.organicmaps.sdk.display.DisplayManager; import app.organicmaps.location.TrackRecordingService;
import app.organicmaps.routing.NavigationService;
import app.organicmaps.routing.RoutingController;
import app.organicmaps.sdk.Map; import app.organicmaps.sdk.Map;
import app.organicmaps.sdk.OrganicMaps;
import app.organicmaps.sdk.display.DisplayManager;
import app.organicmaps.sdk.location.LocationHelper; import app.organicmaps.sdk.location.LocationHelper;
import app.organicmaps.sdk.location.LocationState; import app.organicmaps.sdk.location.LocationState;
import app.organicmaps.sdk.location.SensorHelper; import app.organicmaps.sdk.location.SensorHelper;
import app.organicmaps.sdk.location.TrackRecorder; import app.organicmaps.sdk.location.TrackRecorder;
import app.organicmaps.location.TrackRecordingService;
import app.organicmaps.sdk.maplayer.isolines.IsolinesManager; import app.organicmaps.sdk.maplayer.isolines.IsolinesManager;
import app.organicmaps.sdk.maplayer.subway.SubwayManager; import app.organicmaps.sdk.maplayer.subway.SubwayManager;
import app.organicmaps.routing.NavigationService;
import app.organicmaps.routing.RoutingController;
import app.organicmaps.sdk.OrganicMaps;
import app.organicmaps.sdk.util.Config; import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.ConnectionState; import app.organicmaps.sdk.util.ConnectionState;
import app.organicmaps.util.Utils;
import app.organicmaps.sdk.util.log.Logger; import app.organicmaps.sdk.util.log.Logger;
import app.organicmaps.sdk.util.log.LogsManager; import app.organicmaps.util.Utils;
import java.io.IOException;
import java.lang.ref.WeakReference;
public class MwmApplication extends Application implements Application.ActivityLifecycleCallbacks public class MwmApplication extends Application implements Application.ActivityLifecycleCallbacks
{ {
@@ -56,6 +51,10 @@ public class MwmApplication extends Application implements Application.ActivityL
@Nullable @Nullable
private WeakReference<Activity> mTopActivity; private WeakReference<Activity> mTopActivity;
@SuppressWarnings("NotNullFieldNotInitialized")
@NonNull
public static MwmApplication sInstance;
@UiThread @UiThread
@Nullable @Nullable
public Activity getTopActivity() public Activity getTopActivity()
@@ -105,13 +104,10 @@ public class MwmApplication extends Application implements Application.ActivityL
return (MwmApplication) context.getApplicationContext(); return (MwmApplication) context.getApplicationContext();
} }
@NonNull
public static MwmApplication sInstance;
@NonNull @NonNull
public static SharedPreferences prefs(@NonNull Context context) public static SharedPreferences prefs(@NonNull Context context)
{ {
return context.getSharedPreferences(context.getString(R.string.pref_file_name), MODE_PRIVATE); return from(context).getOrganicMaps().getPreferences();
} }
@Override @Override
@@ -124,10 +120,6 @@ public class MwmApplication extends Application implements Application.ActivityL
mOrganicMaps = new OrganicMaps(getApplicationContext()); mOrganicMaps = new OrganicMaps(getApplicationContext());
LogsManager.INSTANCE.initFileLogging(this);
Android7RootCertificateWorkaround.initializeIfNeeded(this);
ConnectionState.INSTANCE.initialize(this); ConnectionState.INSTANCE.initialize(this);
DownloaderNotifier.createNotificationChannel(this); DownloaderNotifier.createNotificationChannel(this);
@@ -146,8 +138,7 @@ public class MwmApplication extends Application implements Application.ActivityL
}); });
} }
private final LifecycleObserver mProcessLifecycleObserver = new DefaultLifecycleObserver() private final LifecycleObserver mProcessLifecycleObserver = new DefaultLifecycleObserver() {
{
@Override @Override
public void onStart(@NonNull LifecycleOwner owner) public void onStart(@NonNull LifecycleOwner owner)
{ {

View File

@@ -5,21 +5,19 @@ import android.animation.ValueAnimator;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import android.view.animation.AccelerateInterpolator; import android.view.animation.AccelerateInterpolator;
import androidx.annotation.IntegerRes; import androidx.annotation.IntegerRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import org.chromium.base.ObserverList;
import app.organicmaps.sdk.util.UiUtils; import app.organicmaps.sdk.util.UiUtils;
import org.chromium.base.ObserverList;
class PanelAnimator class PanelAnimator
{ {
private final MwmActivity mActivity; private final MwmActivity mActivity;
private final ObserverList<MwmActivity.LeftAnimationTrackListener> mAnimationTrackListeners = new ObserverList<>(); private final ObserverList<MwmActivity.LeftAnimationTrackListener> mAnimationTrackListeners = new ObserverList<>();
private final ObserverList.RewindableIterator<MwmActivity.LeftAnimationTrackListener> mAnimationTrackIterator = mAnimationTrackListeners.rewindableIterator(); private final ObserverList.RewindableIterator<MwmActivity.LeftAnimationTrackListener> mAnimationTrackIterator =
mAnimationTrackListeners.rewindableIterator();
private final View mPanel; private final View mPanel;
private final int mWidth; private final int mWidth;
@IntegerRes @IntegerRes
@@ -50,7 +48,8 @@ class PanelAnimator
} }
/** @param completionListener will be called before the fragment becomes actually visible */ /** @param completionListener will be called before the fragment becomes actually visible */
public void show(final Class<? extends Fragment> clazz, final Bundle args, @Nullable final Runnable completionListener) public void show(final Class<? extends Fragment> clazz, final Bundle args,
@Nullable final Runnable completionListener)
{ {
if (isVisible()) if (isVisible())
{ {
@@ -78,8 +77,7 @@ class PanelAnimator
ValueAnimator animator = ValueAnimator.ofFloat(-mWidth, 0.0f); ValueAnimator animator = ValueAnimator.ofFloat(-mWidth, 0.0f);
animator.addUpdateListener(this::track); animator.addUpdateListener(this::track);
animator.addListener(new UiUtils.SimpleAnimatorListener() animator.addListener(new UiUtils.SimpleAnimatorListener() {
{
@Override @Override
public void onAnimationEnd(Animator animation) public void onAnimationEnd(Animator animation)
{ {
@@ -109,8 +107,7 @@ class PanelAnimator
ValueAnimator animator = ValueAnimator.ofFloat(0.0f, -mWidth); ValueAnimator animator = ValueAnimator.ofFloat(0.0f, -mWidth);
animator.addUpdateListener(this::track); animator.addUpdateListener(this::track);
animator.addListener(new UiUtils.SimpleAnimatorListener() animator.addListener(new UiUtils.SimpleAnimatorListener() {
{
@Override @Override
public void onAnimationEnd(Animator animation) public void onAnimationEnd(Animator animation)
{ {

View File

@@ -9,7 +9,6 @@ import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.Keep; import androidx.annotation.Keep;
@@ -21,20 +20,18 @@ import androidx.core.graphics.Insets;
import androidx.core.view.OnApplyWindowInsetsListener; import androidx.core.view.OnApplyWindowInsetsListener;
import androidx.core.view.ViewCompat; import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat; import androidx.core.view.WindowInsetsCompat;
import app.organicmaps.sdk.display.DisplayManager;
import app.organicmaps.downloader.DownloaderActivity; import app.organicmaps.downloader.DownloaderActivity;
import app.organicmaps.intent.Factory; import app.organicmaps.intent.Factory;
import app.organicmaps.sdk.display.DisplayManager;
import app.organicmaps.sdk.location.LocationHelper; import app.organicmaps.sdk.location.LocationHelper;
import app.organicmaps.sdk.util.Config; import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.LocationUtils; import app.organicmaps.sdk.util.LocationUtils;
import app.organicmaps.sdk.util.concurrency.UiThread;
import app.organicmaps.sdk.util.log.Logger;
import app.organicmaps.util.SharingUtils; import app.organicmaps.util.SharingUtils;
import app.organicmaps.util.ThemeUtils; import app.organicmaps.util.ThemeUtils;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import app.organicmaps.sdk.util.concurrency.UiThread;
import app.organicmaps.sdk.util.log.Logger;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.io.IOException; import java.io.IOException;
import java.util.Objects; import java.util.Objects;
@@ -93,7 +90,7 @@ public class SplashActivity extends AppCompatActivity
}); });
mShareLauncher = SharingUtils.RegisterLauncher(this); mShareLauncher = SharingUtils.RegisterLauncher(this);
if (DisplayManager.from(this).isCarDisplayUsed()) if (MwmApplication.from(this).getDisplayManager().isCarDisplayUsed())
{ {
startActivity(new Intent(this, MapPlaceholderActivity.class)); startActivity(new Intent(this, MapPlaceholderActivity.class));
finish(); finish();
@@ -109,10 +106,7 @@ public class SplashActivity extends AppCompatActivity
if (!Config.isLocationRequested() && !LocationUtils.checkLocationPermission(this)) if (!Config.isLocationRequested() && !LocationUtils.checkLocationPermission(this))
{ {
Logger.d(TAG, "Requesting location permissions"); Logger.d(TAG, "Requesting location permissions");
mPermissionRequest.launch(new String[]{ mPermissionRequest.launch(new String[] {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION});
ACCESS_COARSE_LOCATION,
ACCESS_FINE_LOCATION
});
return; return;
} }
@@ -144,13 +138,7 @@ public class SplashActivity extends AppCompatActivity
.setMessage(messageId) .setMessage(messageId)
.setPositiveButton( .setPositiveButton(
R.string.report_a_bug, R.string.report_a_bug,
(dialog, which) -> Utils.sendBugReport( (dialog, which) -> Utils.sendBugReport(mShareLauncher, this, "Fatal Error", Log.getStackTraceString(error)))
mShareLauncher,
this,
"Fatal Error",
Log.getStackTraceString(error)
)
)
.setCancelable(false) .setCancelable(false)
.show(); .show();
} }
@@ -162,7 +150,8 @@ public class SplashActivity extends AppCompatActivity
try try
{ {
asyncContinue = app.initOrganicMaps(this::processNavigation); asyncContinue = app.initOrganicMaps(this::processNavigation);
} catch (IOException error) }
catch (IOException error)
{ {
showFatalErrorDialog(R.string.dialog_error_storage_title, R.string.dialog_error_storage_message, error); showFatalErrorDialog(R.string.dialog_error_storage_title, R.string.dialog_error_storage_message, error);
return; return;
@@ -195,9 +184,12 @@ public class SplashActivity extends AppCompatActivity
// https://github.com/organicmaps/organicmaps/issues/6944 // https://github.com/organicmaps/organicmaps/issues/6944
final Intent intent = Objects.requireNonNull(getIntent()); final Intent intent = Objects.requireNonNull(getIntent());
if (isManageSpaceActivity(intent)) { if (isManageSpaceActivity(intent))
{
intent.setComponent(new ComponentName(this, DownloaderActivity.class)); intent.setComponent(new ComponentName(this, DownloaderActivity.class));
} else { }
else
{
intent.setComponent(new ComponentName(this, DownloadResourcesLegacyActivity.class)); intent.setComponent(new ComponentName(this, DownloadResourcesLegacyActivity.class));
} }
@@ -219,11 +211,14 @@ public class SplashActivity extends AppCompatActivity
finish(); finish();
} }
private boolean isManageSpaceActivity(Intent intent) { private boolean isManageSpaceActivity(Intent intent)
{
var component = intent.getComponent(); var component = intent.getComponent();
if (!Intent.ACTION_VIEW.equals(intent.getAction())) return false; if (!Intent.ACTION_VIEW.equals(intent.getAction()))
if (component == null) return false; return false;
if (component == null)
return false;
var manageSpaceActivityName = BuildConfig.APPLICATION_ID + ".ManageSpaceActivity"; var manageSpaceActivityName = BuildConfig.APPLICATION_ID + ".ManageSpaceActivity";

View File

@@ -7,9 +7,7 @@ import android.net.Uri;
import android.view.View; import android.view.View;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import app.organicmaps.base.OnBackPressListener; import app.organicmaps.base.OnBackPressListener;
import app.organicmaps.sdk.util.UiUtils; import app.organicmaps.sdk.util.UiUtils;
@@ -21,8 +19,7 @@ public abstract class WebContainerDelegate implements OnBackPressListener
@SuppressLint("SetJavaScriptEnabled") @SuppressLint("SetJavaScriptEnabled")
private void initWebView(String url) private void initWebView(String url)
{ {
mWebView.setWebViewClient(new WebViewClient() mWebView.setWebViewClient(new WebViewClient() {
{
@Override @Override
public void onPageFinished(WebView view, String url) public void onPageFinished(WebView view, String url)
{ {
@@ -46,8 +43,7 @@ public abstract class WebContainerDelegate implements OnBackPressListener
return true; return true;
} }
doStartActivity(new Intent(Intent.ACTION_VIEW) doStartActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse(url)));
.setData(Uri.parse(url)));
return true; return true;
} }
}); });

View File

@@ -4,18 +4,23 @@ import android.content.Context;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.SimpleExpandableListAdapter; import android.widget.SimpleExpandableListAdapter;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
* Disables child selections, also fixes bug with SimpleExpandableListAdapter not switching expandedGroupLayout and collapsedGroupLayout correctly. * Disables child selections, also fixes bug with SimpleExpandableListAdapter not switching expandedGroupLayout and
* collapsedGroupLayout correctly.
*/ */
public class DisabledChildSimpleExpandableListAdapter extends SimpleExpandableListAdapter public class DisabledChildSimpleExpandableListAdapter extends SimpleExpandableListAdapter
{ {
public DisabledChildSimpleExpandableListAdapter(Context context, List<? extends Map<String, ?>> groupData, int expandedGroupLayout, int collapsedGroupLayout, String[] groupFrom, int[] groupTo, List<? extends List<? extends Map<String, ?>>> childData, int childLayout, String[] childFrom, int[] childTo) public DisabledChildSimpleExpandableListAdapter(Context context, List<? extends Map<String, ?>> groupData,
int expandedGroupLayout, int collapsedGroupLayout, String[] groupFrom,
int[] groupTo,
List<? extends List<? extends Map<String, ?>>> childData,
int childLayout, String[] childFrom, int[] childTo)
{ {
super(context, groupData, expandedGroupLayout, collapsedGroupLayout, groupFrom, groupTo, childData, childLayout, childFrom, childTo); super(context, groupData, expandedGroupLayout, collapsedGroupLayout, groupFrom, groupTo, childData, childLayout,
childFrom, childTo);
} }
@Override @Override
@@ -29,8 +34,7 @@ public class DisabledChildSimpleExpandableListAdapter extends SimpleExpandableLi
* See http://stackoverflow.com/questions/19520037/simpleexpandablelistadapter-and-expandedgrouplayout for details * See http://stackoverflow.com/questions/19520037/simpleexpandablelistadapter-and-expandedgrouplayout for details
*/ */
@Override @Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent)
ViewGroup parent)
{ {
return super.getGroupView(groupPosition, isExpanded, null, parent); return super.getGroupView(groupPosition, isExpanded, null, parent);
} }

View File

@@ -1,7 +1,6 @@
package app.organicmaps.adapter; package app.organicmaps.adapter;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
public interface OnItemClickListener<T> public interface OnItemClickListener<T>

View File

@@ -1,13 +1,12 @@
package app.organicmaps.background; package app.organicmaps.background;
import android.content.Context; import android.content.Context;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.work.Constraints; import androidx.work.Constraints;
import androidx.work.ExistingWorkPolicy;
import androidx.work.NetworkType; import androidx.work.NetworkType;
import androidx.work.OneTimeWorkRequest; import androidx.work.OneTimeWorkRequest;
import androidx.work.WorkManager; import androidx.work.WorkManager;
import androidx.work.WorkRequest;
import androidx.work.Worker; import androidx.work.Worker;
import androidx.work.WorkerParameters; import androidx.work.WorkerParameters;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
@@ -17,7 +16,6 @@ import app.organicmaps.sdk.util.log.Logger;
public class OsmUploadWork extends Worker public class OsmUploadWork extends Worker
{ {
private static final String TAG = OsmUploadWork.class.getSimpleName(); private static final String TAG = OsmUploadWork.class.getSimpleName();
private final Context mContext; private final Context mContext;
private final WorkerParameters mWorkerParameters; private final WorkerParameters mWorkerParameters;
@@ -34,11 +32,11 @@ public class OsmUploadWork extends Worker
*/ */
public static void startActionUploadOsmChanges(@NonNull Context context) public static void startActionUploadOsmChanges(@NonNull Context context)
{ {
if (Editor.nativeHasSomethingToUpload() && OsmOAuth.isAuthorized(context)) if (Editor.nativeHasSomethingToUpload() && OsmOAuth.isAuthorized())
{ {
final Constraints c = new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build(); final Constraints c = new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build();
final WorkRequest wr = new OneTimeWorkRequest.Builder(OsmUploadWork.class).setConstraints(c).build(); final OneTimeWorkRequest wr = new OneTimeWorkRequest.Builder(OsmUploadWork.class).setConstraints(c).build();
WorkManager.getInstance(context).enqueue(wr); WorkManager.getInstance(context).beginUniqueWork("UploadOsmChanges", ExistingWorkPolicy.KEEP, wr).enqueue();
} }
} }
@@ -46,13 +44,12 @@ public class OsmUploadWork extends Worker
@Override @Override
public Result doWork() public Result doWork()
{ {
final MwmApplication app = MwmApplication.from(mContext); if (!MwmApplication.from(mContext).getOrganicMaps().arePlatformAndCoreInitialized())
if (!app.getOrganicMaps().arePlatformAndCoreInitialized())
{ {
Logger.w(TAG, "Application is not initialized, ignoring " + mWorkerParameters); Logger.w(TAG, "Application is not initialized, ignoring " + mWorkerParameters);
return Result.failure(); return Result.failure();
} }
Editor.uploadChanges(mContext); Editor.uploadChanges();
return Result.success(); return Result.success();
} }
} }

View File

@@ -1,10 +1,9 @@
package app.organicmaps.backup; package app.organicmaps.backup;
import static app.organicmaps.sdk.util.StorageUtils.isFolderWritable;
import static app.organicmaps.settings.BackupSettingsFragment.MAX_BACKUPS_DEFAULT_COUNT; import static app.organicmaps.settings.BackupSettingsFragment.MAX_BACKUPS_DEFAULT_COUNT;
import static app.organicmaps.settings.BackupSettingsFragment.MAX_BACKUPS_KEY; import static app.organicmaps.settings.BackupSettingsFragment.MAX_BACKUPS_KEY;
import static app.organicmaps.sdk.util.StorageUtils.isFolderWritable;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.net.Uri; import android.net.Uri;
@@ -13,30 +12,23 @@ import android.text.SpannableStringBuilder;
import android.text.Spanned; import android.text.Spanned;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.style.AbsoluteSizeSpan; import android.text.style.AbsoluteSizeSpan;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.documentfile.provider.DocumentFile; import androidx.documentfile.provider.DocumentFile;
import app.organicmaps.R;
import java.io.File; import app.organicmaps.sdk.util.UiUtils;
import java.io.FileInputStream; import app.organicmaps.sdk.util.log.Logger;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import app.organicmaps.R;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.sdk.util.log.Logger;
public class BackupUtils public class BackupUtils
{ {
private static final String BACKUP_PREFIX = "backup_"; private static final String BACKUP_PREFIX = "backup_";
private static final String BACKUP_EXTENSION = ".kmz"; private static final String BACKUP_EXTENSION = ".kmz";
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss").withLocale(Locale.US); private static final DateTimeFormatter DATE_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss").withLocale(Locale.US);
private static final String TAG = BackupUtils.class.getSimpleName(); private static final String TAG = BackupUtils.class.getSimpleName();
public static CharSequence formatReadableFolderPath(Context context, @NonNull Uri uri) public static CharSequence formatReadableFolderPath(Context context, @NonNull Uri uri)
@@ -63,8 +55,10 @@ public class BackupUtils
volumeName = context.getString(R.string.maps_storage_removable); volumeName = context.getString(R.string.maps_storage_removable);
SpannableStringBuilder sb = new SpannableStringBuilder(); SpannableStringBuilder sb = new SpannableStringBuilder();
sb.append(volumeName + ": \n", new AbsoluteSizeSpan(UiUtils.dimen(context, R.dimen.text_size_body_3)), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); sb.append(volumeName + ": \n", new AbsoluteSizeSpan(UiUtils.dimen(context, R.dimen.text_size_body_3)),
sb.append("/" + subPath, new AbsoluteSizeSpan(UiUtils.dimen(context, R.dimen.text_size_body_4)), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
sb.append("/" + subPath, new AbsoluteSizeSpan(UiUtils.dimen(context, R.dimen.text_size_body_4)),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return sb; return sb;
} }
@@ -74,12 +68,14 @@ public class BackupUtils
try try
{ {
return Integer.parseInt(rawValue); return Integer.parseInt(rawValue);
} catch (NumberFormatException e) }
catch (NumberFormatException e)
{ {
Logger.e(TAG, "Failed to parse max backups count, raw value: " + rawValue + " set to default: " + MAX_BACKUPS_DEFAULT_COUNT, e); Logger.e(
prefs.edit() TAG,
.putString(MAX_BACKUPS_KEY, String.valueOf(MAX_BACKUPS_DEFAULT_COUNT)) "Failed to parse max backups count, raw value: " + rawValue + " set to default: " + MAX_BACKUPS_DEFAULT_COUNT,
.apply(); e);
prefs.edit().putString(MAX_BACKUPS_KEY, String.valueOf(MAX_BACKUPS_DEFAULT_COUNT)).apply();
return MAX_BACKUPS_DEFAULT_COUNT; return MAX_BACKUPS_DEFAULT_COUNT;
} }
} }

View File

@@ -1,22 +1,14 @@
package app.organicmaps.backup; package app.organicmaps.backup;
import static app.organicmaps.backup.BackupUtils.getBackupName;
import static app.organicmaps.backup.BackupUtils.getBackupFolders; import static app.organicmaps.backup.BackupUtils.getBackupFolders;
import static app.organicmaps.backup.BackupUtils.getBackupName;
import static app.organicmaps.sdk.util.StorageUtils.copyFileToDocumentFile; import static app.organicmaps.sdk.util.StorageUtils.copyFileToDocumentFile;
import static app.organicmaps.sdk.util.StorageUtils.deleteDirectoryRecursive; import static app.organicmaps.sdk.util.StorageUtils.deleteDirectoryRecursive;
import android.app.Activity; import android.app.Activity;
import android.net.Uri; import android.net.Uri;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.documentfile.provider.DocumentFile; import androidx.documentfile.provider.DocumentFile;
import java.io.File;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory; import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager; import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.sdk.bookmarks.data.BookmarkSharingResult; import app.organicmaps.sdk.bookmarks.data.BookmarkSharingResult;
@@ -24,6 +16,11 @@ import app.organicmaps.sdk.bookmarks.data.KmlFileType;
import app.organicmaps.sdk.util.concurrency.ThreadPool; import app.organicmaps.sdk.util.concurrency.ThreadPool;
import app.organicmaps.sdk.util.concurrency.UiThread; import app.organicmaps.sdk.util.concurrency.UiThread;
import app.organicmaps.sdk.util.log.Logger; import app.organicmaps.sdk.util.log.Logger;
import java.io.File;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class LocalBackupManager implements BookmarkManager.BookmarksSharingListener public class LocalBackupManager implements BookmarkManager.BookmarksSharingListener
{ {
@@ -139,8 +136,8 @@ public class LocalBackupManager implements BookmarkManager.BookmarksSharingListe
} }
} }
cleanOldBackups(parentFolder); cleanOldBackups(parentFolder);
}
} catch (Exception e) catch (Exception e)
{ {
Logger.e(TAG, "Failed to save backup", e); Logger.e(TAG, "Failed to save backup", e);
} }

View File

@@ -5,13 +5,10 @@ import static app.organicmaps.backup.BackupUtils.isBackupFolderAvailable;
import static app.organicmaps.settings.BackupSettingsFragment.BACKUP_FOLDER_PATH_KEY; import static app.organicmaps.settings.BackupSettingsFragment.BACKUP_FOLDER_PATH_KEY;
import static app.organicmaps.settings.BackupSettingsFragment.BACKUP_INTERVAL_KEY; import static app.organicmaps.settings.BackupSettingsFragment.BACKUP_INTERVAL_KEY;
import static app.organicmaps.settings.BackupSettingsFragment.LAST_BACKUP_TIME_KEY; import static app.organicmaps.settings.BackupSettingsFragment.LAST_BACKUP_TIME_KEY;
import static app.organicmaps.sdk.util.StorageUtils.isFolderWritable;
import android.app.Activity; import android.app.Activity;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import app.organicmaps.sdk.util.log.Logger; import app.organicmaps.sdk.util.log.Logger;
public class PeriodicBackupRunner public class PeriodicBackupRunner
@@ -68,7 +65,8 @@ public class PeriodicBackupRunner
try try
{ {
return Long.parseLong(prefs.getString(BACKUP_INTERVAL_KEY, defaultValue)); return Long.parseLong(prefs.getString(BACKUP_INTERVAL_KEY, defaultValue));
} catch (NumberFormatException e) }
catch (NumberFormatException e)
{ {
return 0; return 0;
} }
@@ -77,8 +75,7 @@ public class PeriodicBackupRunner
private void performBackup(String backupFolderPath, int maxBackups) private void performBackup(String backupFolderPath, int maxBackups)
{ {
LocalBackupManager backupManager = new LocalBackupManager(activity, backupFolderPath, maxBackups); LocalBackupManager backupManager = new LocalBackupManager(activity, backupFolderPath, maxBackups);
backupManager.setListener(new LocalBackupManager.Listener() backupManager.setListener(new LocalBackupManager.Listener() {
{
@Override @Override
public void onBackupStarted() public void onBackupStarted()
{ {

View File

@@ -3,12 +3,10 @@ package app.organicmaps.base;
import android.app.Application; import android.app.Application;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.StyleRes; import androidx.annotation.StyleRes;
import androidx.fragment.app.DialogFragment; import androidx.fragment.app.DialogFragment;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.util.ThemeUtils; import app.organicmaps.util.ThemeUtils;
@@ -62,5 +60,4 @@ public class BaseMwmDialogFragment extends DialogFragment
throw new IllegalStateException("Before call this method make sure that the context exists"); throw new IllegalStateException("Before call this method make sure that the context exists");
return (Application) context.getApplicationContext(); return (Application) context.getApplicationContext();
} }
} }

View File

@@ -1,9 +1,7 @@
package app.organicmaps.base; package app.organicmaps.base;
import android.content.Context; import android.content.Context;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
public class BaseMwmFragment extends Fragment implements OnBackPressListener public class BaseMwmFragment extends Fragment implements OnBackPressListener
@@ -20,5 +18,4 @@ public class BaseMwmFragment extends Fragment implements OnBackPressListener
{ {
return false; return false;
} }
} }

View File

@@ -7,7 +7,6 @@ import android.graphics.Color;
import android.media.AudioManager; import android.media.AudioManager;
import android.os.Bundle; import android.os.Bundle;
import android.view.MenuItem; import android.view.MenuItem;
import androidx.activity.EdgeToEdge; import androidx.activity.EdgeToEdge;
import androidx.activity.SystemBarStyle; import androidx.activity.SystemBarStyle;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
@@ -18,18 +17,15 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentFactory; import androidx.fragment.app.FragmentFactory;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import com.google.android.material.appbar.MaterialToolbar;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.SplashActivity; import app.organicmaps.SplashActivity;
import app.organicmaps.sdk.util.Config; import app.organicmaps.sdk.util.Config;
import app.organicmaps.util.RtlUtils;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.sdk.util.concurrency.UiThread; import app.organicmaps.sdk.util.concurrency.UiThread;
import app.organicmaps.sdk.util.log.Logger; 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; import java.util.Objects;
public abstract class BaseMwmFragmentActivity extends AppCompatActivity public abstract class BaseMwmFragmentActivity extends AppCompatActivity
@@ -216,11 +212,13 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity
/** /**
* Replace attached fragment with the new one. * Replace attached fragment with the new one.
*/ */
public void replaceFragment(@NonNull Class<? extends Fragment> fragmentClass, @Nullable Bundle args, @Nullable Runnable completionListener) public void replaceFragment(@NonNull Class<? extends Fragment> fragmentClass, @Nullable Bundle args,
@Nullable Runnable completionListener)
{ {
final int resId = getFragmentContentResId(); final int resId = getFragmentContentResId();
if (resId <= 0 || findViewById(resId) == null) if (resId <= 0 || findViewById(resId) == null)
throw new IllegalStateException("Fragment can't be added, since getFragmentContentResId() isn't implemented or returns wrong resourceId."); throw new IllegalStateException(
"Fragment can't be added, since getFragmentContentResId() isn't implemented or returns wrong resourceId.");
String name = fragmentClass.getName(); String name = fragmentClass.getName();
Fragment potentialInstance = getSupportFragmentManager().findFragmentByTag(name); Fragment potentialInstance = getSupportFragmentManager().findFragmentByTag(name);
@@ -230,9 +228,7 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity
final FragmentFactory factory = manager.getFragmentFactory(); final FragmentFactory factory = manager.getFragmentFactory();
final Fragment fragment = factory.instantiate(getClassLoader(), name); final Fragment fragment = factory.instantiate(getClassLoader(), name);
fragment.setArguments(args); fragment.setArguments(args);
manager.beginTransaction() manager.beginTransaction().replace(resId, fragment, name).commitAllowingStateLoss();
.replace(resId, fragment, name)
.commitAllowingStateLoss();
manager.executePendingTransactions(); manager.executePendingTransactions();
if (completionListener != null) if (completionListener != null)
completionListener.run(); completionListener.run();
@@ -240,8 +236,8 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity
} }
/** /**
* Override to automatically attach fragment in onCreate. Tag applied to fragment in back stack is set to fragment name, too. * Override to automatically attach fragment in onCreate. Tag applied to fragment in back stack is set to fragment
* WARNING : if custom layout for activity is set, getFragmentContentResId() must be implemented, too. * name, too. WARNING : if custom layout for activity is set, getFragmentContentResId() must be implemented, too.
* @return class of the fragment, eg FragmentClass.getClass() * @return class of the fragment, eg FragmentClass.getClass()
*/ */
protected Class<? extends Fragment> getFragmentClass() protected Class<? extends Fragment> getFragmentClass()

View File

@@ -5,7 +5,6 @@ import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
import androidx.annotation.LayoutRes; import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@@ -14,14 +13,12 @@ import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.appbar.MaterialToolbar;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.util.UiUtils; import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils.ScrollableContentInsetsListener; import app.organicmaps.util.WindowInsetUtils.ScrollableContentInsetsListener;
import app.organicmaps.widget.PlaceholderView; import app.organicmaps.widget.PlaceholderView;
import com.google.android.material.appbar.MaterialToolbar;
public abstract class BaseMwmRecyclerFragment<T extends RecyclerView.Adapter> extends Fragment public abstract class BaseMwmRecyclerFragment<T extends RecyclerView.Adapter> extends Fragment
{ {
@@ -39,8 +36,7 @@ public abstract class BaseMwmRecyclerFragment<T extends RecyclerView.Adapter> ex
private T mAdapter; private T mAdapter;
@NonNull @NonNull
private final View.OnClickListener mNavigationClickListener private final View.OnClickListener mNavigationClickListener = view -> Utils.navigateToParent(requireActivity());
= view -> Utils.navigateToParent(requireActivity());
@NonNull @NonNull
protected abstract T createAdapter(); protected abstract T createAdapter();

View File

@@ -2,10 +2,8 @@ package app.organicmaps.base;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import app.organicmaps.widget.ToolbarController; import app.organicmaps.widget.ToolbarController;
public class BaseMwmToolbarFragment extends BaseMwmFragment public class BaseMwmToolbarFragment extends BaseMwmFragment

View File

@@ -1,7 +1,6 @@
package app.organicmaps.base; package app.organicmaps.base;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@@ -10,12 +9,10 @@ import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentFactory; import androidx.fragment.app.FragmentFactory;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import com.google.android.material.appbar.MaterialToolbar;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.util.UiUtils; import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener; import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener;
import com.google.android.material.appbar.MaterialToolbar;
public abstract class BaseToolbarActivity extends BaseMwmFragmentActivity public abstract class BaseToolbarActivity extends BaseMwmFragmentActivity
{ {
@@ -73,23 +70,20 @@ public abstract class BaseToolbarActivity extends BaseMwmFragmentActivity
return R.id.fragment_container; return R.id.fragment_container;
} }
public Fragment stackFragment(@NonNull Class<? extends Fragment> fragmentClass, public Fragment stackFragment(@NonNull Class<? extends Fragment> fragmentClass, @Nullable String title,
@Nullable String title, @Nullable Bundle args) @Nullable Bundle args)
{ {
final int resId = getFragmentContentResId(); final int resId = getFragmentContentResId();
if (resId <= 0 || findViewById(resId) == null) if (resId <= 0 || findViewById(resId) == null)
throw new IllegalStateException("Fragment can't be added, since getFragmentContentResId() " + throw new IllegalStateException("Fragment can't be added, since getFragmentContentResId() "
"isn't implemented or returns wrong resourceId."); + "isn't implemented or returns wrong resourceId.");
String name = fragmentClass.getName(); String name = fragmentClass.getName();
final FragmentManager manager = getSupportFragmentManager(); final FragmentManager manager = getSupportFragmentManager();
final FragmentFactory factory = manager.getFragmentFactory(); final FragmentFactory factory = manager.getFragmentFactory();
final Fragment fragment = factory.instantiate(getClassLoader(), name); final Fragment fragment = factory.instantiate(getClassLoader(), name);
fragment.setArguments(args); fragment.setArguments(args);
manager.beginTransaction() manager.beginTransaction().replace(resId, fragment, name).addToBackStack(null).commitAllowingStateLoss();
.replace(resId, fragment, name)
.addToBackStack(null)
.commitAllowingStateLoss();
manager.executePendingTransactions(); manager.executePendingTransactions();
if (title != null) if (title != null)

View File

@@ -1,16 +1,12 @@
package app.organicmaps.bookmarks; package app.organicmaps.bookmarks;
import android.content.Context; import android.content.Context;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory; import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
import java.util.List; import java.util.List;
public abstract class BaseBookmarkCategoryAdapter<V extends RecyclerView.ViewHolder> public abstract class BaseBookmarkCategoryAdapter<V extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<V>
extends RecyclerView.Adapter<V>
{ {
@NonNull @NonNull
private final Context mContext; private final Context mContext;
@@ -54,6 +50,5 @@ public abstract class BaseBookmarkCategoryAdapter<V extends RecyclerView.ViewHol
if (position < 0 || position > categories.size() - 1) if (position < 0 || position > categories.size() - 1)
throw new ArrayIndexOutOfBoundsException(position); throw new ArrayIndexOutOfBoundsException(position);
return categories.get(position); return categories.get(position);
} }
} }

View File

@@ -3,13 +3,11 @@ package app.organicmaps.bookmarks;
import android.app.Activity; import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.StyleRes; import androidx.annotation.StyleRes;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.base.BaseToolbarActivity; import app.organicmaps.base.BaseToolbarActivity;
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory; import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;

View File

@@ -7,16 +7,13 @@ import android.content.Context;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.adapter.OnItemClickListener; import app.organicmaps.adapter.OnItemClickListener;
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory; import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager; import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import java.util.List; import java.util.List;
public class BookmarkCategoriesAdapter extends BaseBookmarkCategoryAdapter<RecyclerView.ViewHolder> public class BookmarkCategoriesAdapter extends BaseBookmarkCategoryAdapter<RecyclerView.ViewHolder>
@@ -122,8 +119,7 @@ public class BookmarkCategoriesAdapter extends BaseBookmarkCategoryAdapter<Recyc
case TYPE_ACTION_HEADER -> case TYPE_ACTION_HEADER ->
{ {
HeaderViewHolder headerViewHolder = (HeaderViewHolder) holder; HeaderViewHolder headerViewHolder = (HeaderViewHolder) holder;
headerViewHolder.setAction(mMassOperationAction, headerViewHolder.setAction(mMassOperationAction, BookmarkManager.INSTANCE.areAllCategoriesInvisible());
BookmarkManager.INSTANCE.areAllCategoriesInvisible());
headerViewHolder.getText().setText(R.string.bookmark_lists); headerViewHolder.getText().setText(R.string.bookmark_lists);
} }
case TYPE_CATEGORY_ITEM -> case TYPE_CATEGORY_ITEM ->
@@ -191,7 +187,6 @@ public class BookmarkCategoriesAdapter extends BaseBookmarkCategoryAdapter<Recyc
private int toCategoryPosition(int adapterPosition) private int toCategoryPosition(int adapterPosition)
{ {
int type = getItemViewType(adapterPosition); int type = getItemViewType(adapterPosition);
if (type != TYPE_CATEGORY_ITEM) if (type != TYPE_CATEGORY_ITEM)
throw new AssertionError("An element at specified position is not category!"); throw new AssertionError("An element at specified position is not category!");

View File

@@ -12,7 +12,6 @@ import android.os.Bundle;
import android.provider.DocumentsContract; import android.provider.DocumentsContract;
import android.view.View; import android.view.View;
import android.widget.Toast; import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
@@ -20,42 +19,36 @@ import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.adapter.OnItemClickListener; import app.organicmaps.adapter.OnItemClickListener;
import app.organicmaps.base.BaseMwmRecyclerFragment; import app.organicmaps.base.BaseMwmRecyclerFragment;
import app.organicmaps.dialog.EditTextDialogFragment;
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory; import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager; import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.sdk.bookmarks.data.BookmarkSharingResult; import app.organicmaps.sdk.bookmarks.data.BookmarkSharingResult;
import app.organicmaps.sdk.bookmarks.data.DataChangedListener;
import app.organicmaps.sdk.bookmarks.data.KmlFileType; import app.organicmaps.sdk.bookmarks.data.KmlFileType;
import app.organicmaps.dialog.EditTextDialogFragment;
import app.organicmaps.util.SharingUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.widget.PlaceholderView;
import app.organicmaps.widget.recycler.DividerItemDecorationWithPadding;
import app.organicmaps.sdk.util.StorageUtils; import app.organicmaps.sdk.util.StorageUtils;
import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment;
import app.organicmaps.util.bottomsheet.MenuBottomSheetItem;
import app.organicmaps.sdk.util.concurrency.ThreadPool; import app.organicmaps.sdk.util.concurrency.ThreadPool;
import app.organicmaps.sdk.util.concurrency.UiThread; import app.organicmaps.sdk.util.concurrency.UiThread;
import app.organicmaps.sdk.util.log.Logger; import app.organicmaps.sdk.util.log.Logger;
import app.organicmaps.util.SharingUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment;
import app.organicmaps.util.bottomsheet.MenuBottomSheetItem;
import app.organicmaps.widget.PlaceholderView;
import app.organicmaps.widget.recycler.DividerItemDecorationWithPadding;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<BookmarkCategoriesAdapter> public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<BookmarkCategoriesAdapter>
implements BookmarkManager.BookmarksLoadingListener, implements BookmarkManager.BookmarksLoadingListener, CategoryListCallback, OnItemClickListener<BookmarkCategory>,
CategoryListCallback, OnItemMoreClickListener<BookmarkCategory>, OnItemLongClickListener<BookmarkCategory>,
OnItemClickListener<BookmarkCategory>, BookmarkManager.BookmarksSharingListener, MenuBottomSheetFragment.MenuBottomSheetInterface
OnItemMoreClickListener<BookmarkCategory>,
OnItemLongClickListener<BookmarkCategory>,
BookmarkManager.BookmarksSharingListener,
MenuBottomSheetFragment.MenuBottomSheetInterface
{ {
private static final String TAG = BookmarkCategoriesFragment.class.getSimpleName(); private static final String TAG = BookmarkCategoriesFragment.class.getSimpleName();
@@ -75,22 +68,25 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<Bookmark
@NonNull @NonNull
private DataChangedListener mCategoriesAdapterObserver; private DataChangedListener mCategoriesAdapterObserver;
private final ActivityResultLauncher<Intent> startBookmarkListForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> { private final ActivityResultLauncher<Intent> startBookmarkListForResult =
registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> {
if (activityResult.getResultCode() == Activity.RESULT_OK) if (activityResult.getResultCode() == Activity.RESULT_OK)
onDeleteActionSelected(getSelectedCategory()); onDeleteActionSelected(getSelectedCategory());
}); });
private final ActivityResultLauncher<Intent> startImportDirectoryForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> private final ActivityResultLauncher<Intent> startImportDirectoryForResult =
{ registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> {
if (activityResult.getResultCode() == Activity.RESULT_OK) if (activityResult.getResultCode() == Activity.RESULT_OK)
onImportDirectoryResult(activityResult.getData()); onImportDirectoryResult(activityResult.getData());
}); });
private final ActivityResultLauncher<Intent> startBookmarkSettingsForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> { private final ActivityResultLauncher<Intent> startBookmarkSettingsForResult =
registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
activityResult
-> {
// not handled at the moment // not handled at the moment
}); });
@Override @Override
@LayoutRes @LayoutRes
protected int getLayoutRes() protected int getLayoutRes()
@@ -119,7 +115,8 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<Bookmark
getAdapter().setCategoryListCallback(this); getAdapter().setCategoryListCallback(this);
RecyclerView rw = getRecyclerView(); RecyclerView rw = getRecyclerView();
if (rw == null) return; if (rw == null)
return;
rw.setNestedScrollingEnabled(false); rw.setNestedScrollingEnabled(false);
RecyclerView.ItemDecoration decor = new DividerItemDecorationWithPadding(requireContext()); RecyclerView.ItemDecoration decor = new DividerItemDecorationWithPadding(requireContext());
@@ -191,27 +188,18 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<Bookmark
ArrayList<MenuBottomSheetItem> items = new ArrayList<>(); ArrayList<MenuBottomSheetItem> items = new ArrayList<>();
if (mSelectedCategory != null) if (mSelectedCategory != null)
{ {
items.add(new MenuBottomSheetItem( items.add(new MenuBottomSheetItem(R.string.edit, R.drawable.ic_settings,
R.string.edit,
R.drawable.ic_settings,
() -> onSettingsActionSelected(mSelectedCategory))); () -> onSettingsActionSelected(mSelectedCategory)));
items.add(new MenuBottomSheetItem( items.add(new MenuBottomSheetItem(mSelectedCategory.isVisible() ? R.string.hide : R.string.show,
mSelectedCategory.isVisible() ? R.string.hide : R.string.show,
mSelectedCategory.isVisible() ? R.drawable.ic_hide : R.drawable.ic_show, mSelectedCategory.isVisible() ? R.drawable.ic_hide : R.drawable.ic_show,
() -> onShowActionSelected(mSelectedCategory))); () -> onShowActionSelected(mSelectedCategory)));
items.add(new MenuBottomSheetItem( items.add(new MenuBottomSheetItem(R.string.export_file, R.drawable.ic_file_kmz,
R.string.export_file,
R.drawable.ic_file_kmz,
() -> onShareActionSelected(mSelectedCategory, KmlFileType.Text))); () -> onShareActionSelected(mSelectedCategory, KmlFileType.Text)));
items.add(new MenuBottomSheetItem( items.add(new MenuBottomSheetItem(R.string.export_file_gpx, R.drawable.ic_file_gpx,
R.string.export_file_gpx,
R.drawable.ic_file_gpx,
() -> onShareActionSelected(mSelectedCategory, KmlFileType.Gpx))); () -> onShareActionSelected(mSelectedCategory, KmlFileType.Gpx)));
// Disallow deleting the last category // Disallow deleting the last category
if (getAdapter().getBookmarkCategories().size() > 1) if (getAdapter().getBookmarkCategories().size() > 1)
items.add(new MenuBottomSheetItem( items.add(new MenuBottomSheetItem(R.string.delete, R.drawable.ic_delete,
R.string.delete,
R.drawable.ic_delete,
() -> onDeleteActionSelected(mSelectedCategory))); () -> onDeleteActionSelected(mSelectedCategory)));
} }
return items; return items;
@@ -245,15 +233,10 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<Bookmark
{ {
mCategoryEditor = BookmarkManager.INSTANCE::createCategory; mCategoryEditor = BookmarkManager.INSTANCE::createCategory;
EditTextDialogFragment dialogFragment = EditTextDialogFragment dialogFragment = EditTextDialogFragment.show(
EditTextDialogFragment.show(getString(R.string.bookmarks_create_new_group), getString(R.string.bookmarks_create_new_group), getString(R.string.bookmarks_new_list_hint),
getString(R.string.bookmarks_new_list_hint), getString(R.string.bookmark_set_name), getString(R.string.create), getString(R.string.cancel),
getString(R.string.bookmark_set_name), MAX_CATEGORY_NAME_LENGTH, this, new CategoryValidator());
getString(R.string.create),
getString(R.string.cancel),
MAX_CATEGORY_NAME_LENGTH,
this,
new CategoryValidator());
dialogFragment.setTextSaveListener(this::onSaveText); dialogFragment.setTextSaveListener(this::onSaveText);
} }
@@ -280,7 +263,8 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<Bookmark
showNoFileManagerError(); showNoFileManagerError();
} }
private void showNoFileManagerError() { private void showNoFileManagerError()
{
new MaterialAlertDialogBuilder(requireActivity()) new MaterialAlertDialogBuilder(requireActivity())
.setMessage(R.string.error_no_file_manager_app) .setMessage(R.string.error_no_file_manager_app)
.setPositiveButton(android.R.string.ok, (dialog, which) -> dialog.dismiss()) .setPositiveButton(android.R.string.ok, (dialog, which) -> dialog.dismiss())
@@ -341,8 +325,7 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<Bookmark
final ContentResolver resolver = context.getContentResolver(); final ContentResolver resolver = context.getContentResolver();
ThreadPool.getStorage().execute(() -> { ThreadPool.getStorage().execute(() -> {
AtomicInteger found = new AtomicInteger(0); AtomicInteger found = new AtomicInteger(0);
StorageUtils.listContentProviderFilesRecursively( StorageUtils.listContentProviderFilesRecursively(resolver, rootUri, uri -> {
resolver, rootUri, uri -> {
if (BookmarkManager.INSTANCE.importBookmarksFile(resolver, uri, tempDir)) if (BookmarkManager.INSTANCE.importBookmarksFile(resolver, uri, tempDir))
found.incrementAndGet(); found.incrementAndGet();
}); });
@@ -350,8 +333,8 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<Bookmark
if (dialog.isShowing()) if (dialog.isShowing())
dialog.dismiss(); dialog.dismiss();
int found_val = found.get(); int found_val = found.get();
String message = context.getResources().getQuantityString( String message =
R.plurals.bookmarks_detect_message, found_val, found_val); context.getResources().getQuantityString(R.plurals.bookmarks_detect_message, found_val, found_val);
Toast.makeText(requireContext(), message, Toast.LENGTH_LONG).show(); Toast.makeText(requireContext(), message, Toast.LENGTH_LONG).show();
}); });
}); });

View File

@@ -1,11 +1,9 @@
package app.organicmaps.bookmarks; package app.organicmaps.bookmarks;
import android.content.Intent; import android.content.Intent;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.base.BaseMwmFragmentActivity; import app.organicmaps.base.BaseMwmFragmentActivity;
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory; import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
@@ -32,7 +30,8 @@ public class BookmarkCategorySettingsActivity extends BaseMwmFragmentActivity
return BookmarkCategorySettingsFragment.class; return BookmarkCategorySettingsFragment.class;
} }
public static void startForResult(@NonNull Fragment fragment, ActivityResultLauncher<Intent> startBookmarkSettingsForResult, public static void startForResult(@NonNull Fragment fragment,
ActivityResultLauncher<Intent> startBookmarkSettingsForResult,
@NonNull BookmarkCategory category) @NonNull BookmarkCategory category)
{ {
android.content.Intent intent = new Intent(fragment.requireActivity(), BookmarkCategorySettingsActivity.class) android.content.Intent intent = new Intent(fragment.requireActivity(), BookmarkCategorySettingsActivity.class)

View File

@@ -11,21 +11,17 @@ import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.base.BaseMwmToolbarFragment; import app.organicmaps.base.BaseMwmToolbarFragment;
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory; import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager; import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.util.Utils;
import app.organicmaps.util.InputUtils; import app.organicmaps.util.InputUtils;
import app.organicmaps.util.Utils;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.textfield.TextInputEditText; import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout; import com.google.android.material.textfield.TextInputLayout;
import java.util.Objects; import java.util.Objects;
public class BookmarkCategorySettingsFragment extends BaseMwmToolbarFragment public class BookmarkCategorySettingsFragment extends BaseMwmToolbarFragment
@@ -49,14 +45,13 @@ public class BookmarkCategorySettingsFragment extends BaseMwmToolbarFragment
{ {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
final Bundle args = requireArguments(); final Bundle args = requireArguments();
mCategory = Objects.requireNonNull(Utils.getParcelable(args, mCategory = Objects.requireNonNull(
BookmarkCategorySettingsActivity.EXTRA_BOOKMARK_CATEGORY, BookmarkCategory.class)); Utils.getParcelable(args, BookmarkCategorySettingsActivity.EXTRA_BOOKMARK_CATEGORY, BookmarkCategory.class));
} }
@Nullable @Nullable
@Override @Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
@Nullable Bundle savedInstanceState)
{ {
View root = inflater.inflate(R.layout.fragment_bookmark_category_settings, container, false); View root = inflater.inflate(R.layout.fragment_bookmark_category_settings, container, false);
setHasOptionsMenu(true); setHasOptionsMenu(true);
@@ -73,10 +68,10 @@ public class BookmarkCategorySettingsFragment extends BaseMwmToolbarFragment
InputFilter[] f = {new InputFilter.LengthFilter(TEXT_LENGTH_LIMIT)}; InputFilter[] f = {new InputFilter.LengthFilter(TEXT_LENGTH_LIMIT)};
mEditCategoryNameView.setFilters(f); mEditCategoryNameView.setFilters(f);
mEditCategoryNameView.requestFocus(); mEditCategoryNameView.requestFocus();
mEditCategoryNameView.addTextChangedListener(new TextWatcher() mEditCategoryNameView.addTextChangedListener(new TextWatcher() {
{
@Override @Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {} public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2)
{}
@Override @Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) public void onTextChanged(CharSequence charSequence, int i, int i1, int i2)
@@ -85,7 +80,8 @@ public class BookmarkCategorySettingsFragment extends BaseMwmToolbarFragment
} }
@Override @Override
public void afterTextChanged(Editable editable) {} public void afterTextChanged(Editable editable)
{}
}); });
mEditDescView = root.findViewById(R.id.edit_description); mEditDescView = root.findViewById(R.id.edit_description);
mEditDescView.setText(mCategory.getDescription()); mEditDescView.setText(mCategory.getDescription());

View File

@@ -3,18 +3,15 @@ package app.organicmaps.bookmarks;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.adapter.OnItemClickListener; import app.organicmaps.adapter.OnItemClickListener;
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory; import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager; import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.sdk.util.UiUtils; import app.organicmaps.sdk.util.UiUtils;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.List; import java.util.List;
@@ -23,7 +20,8 @@ public class BookmarkCollectionAdapter extends RecyclerView.Adapter<RecyclerView
{ {
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@IntDef({TYPE_HEADER_ITEM, TYPE_CATEGORY_ITEM}) @IntDef({TYPE_HEADER_ITEM, TYPE_CATEGORY_ITEM})
public @interface SectionType { } public @interface SectionType
{}
private final static int TYPE_CATEGORY_ITEM = BookmarkManager.CATEGORY; private final static int TYPE_CATEGORY_ITEM = BookmarkManager.CATEGORY;
private final static int TYPE_HEADER_ITEM = 3; private final static int TYPE_HEADER_ITEM = 3;
@@ -63,8 +61,7 @@ public class BookmarkCollectionAdapter extends RecyclerView.Adapter<RecyclerView
} }
} }
BookmarkCollectionAdapter(@NonNull BookmarkCategory bookmarkCategory, BookmarkCollectionAdapter(@NonNull BookmarkCategory bookmarkCategory, @NonNull List<BookmarkCategory> itemsCategories)
@NonNull List<BookmarkCategory> itemsCategories)
{ {
mBookmarkCategory = bookmarkCategory; mBookmarkCategory = bookmarkCategory;
// noinspection AssignmentOrReturnOfFieldWithMutableType // noinspection AssignmentOrReturnOfFieldWithMutableType
@@ -129,18 +126,15 @@ public class BookmarkCollectionAdapter extends RecyclerView.Adapter<RecyclerView
@NonNull @NonNull
@Override @Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, @SectionType int viewType)
@SectionType int viewType)
{ {
LayoutInflater inflater = LayoutInflater.from(parent.getContext()); LayoutInflater inflater = LayoutInflater.from(parent.getContext());
RecyclerView.ViewHolder holder = null; RecyclerView.ViewHolder holder = null;
if (viewType == TYPE_HEADER_ITEM) if (viewType == TYPE_HEADER_ITEM)
holder = new Holders.HeaderViewHolder(inflater.inflate(R.layout.item_bookmark_group_list_header, holder = new Holders.HeaderViewHolder(inflater.inflate(R.layout.item_bookmark_group_list_header, parent, false));
parent, false));
if (viewType == TYPE_CATEGORY_ITEM) if (viewType == TYPE_CATEGORY_ITEM)
holder = new Holders.CollectionViewHolder(inflater.inflate(R.layout.item_bookmark_collection, holder = new Holders.CollectionViewHolder(inflater.inflate(R.layout.item_bookmark_collection, parent, false));
parent, false));
if (holder == null) if (holder == null)
throw new AssertionError("Unsupported view type: " + viewType); throw new AssertionError("Unsupported view type: " + viewType);
@@ -170,8 +164,7 @@ public class BookmarkCollectionAdapter extends RecyclerView.Adapter<RecyclerView
throw new AssertionError("Position not found: " + position); throw new AssertionError("Position not found: " + position);
} }
private void bindCollectionHolder(RecyclerView.ViewHolder holder, SectionPosition position, private void bindCollectionHolder(RecyclerView.ViewHolder holder, SectionPosition position, @SectionType int type)
@SectionType int type)
{ {
final BookmarkCategory category = getGroupByPosition(position, type); final BookmarkCategory category = getGroupByPosition(position, type);
Holders.CollectionViewHolder collectionViewHolder = (Holders.CollectionViewHolder) holder; Holders.CollectionViewHolder collectionViewHolder = (Holders.CollectionViewHolder) holder;
@@ -188,8 +181,7 @@ public class BookmarkCollectionAdapter extends RecyclerView.Adapter<RecyclerView
private void bindHeaderHolder(@NonNull RecyclerView.ViewHolder holder, int nextSectionPosition) private void bindHeaderHolder(@NonNull RecyclerView.ViewHolder holder, int nextSectionPosition)
{ {
Holders.HeaderViewHolder headerViewHolder = (Holders.HeaderViewHolder) holder; Holders.HeaderViewHolder headerViewHolder = (Holders.HeaderViewHolder) holder;
headerViewHolder.getText() headerViewHolder.getText().setText(holder.itemView.getResources().getString(R.string.bookmarks));
.setText(holder.itemView.getResources().getString(R.string.bookmarks));
final boolean visibility = !BookmarkManager.INSTANCE.areAllCategoriesVisible(); final boolean visibility = !BookmarkManager.INSTANCE.areAllCategoriesVisible();
headerViewHolder.setAction(mMassOperationAction, visibility); headerViewHolder.setAction(mMassOperationAction, visibility);
updateVisibility(headerViewHolder.itemView); updateVisibility(headerViewHolder.itemView);
@@ -251,4 +243,3 @@ public class BookmarkCollectionAdapter extends RecyclerView.Adapter<RecyclerView
} }
} }
} }

View File

@@ -2,13 +2,11 @@ package app.organicmaps.bookmarks;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.StyleRes; import androidx.annotation.StyleRes;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.base.BaseToolbarActivity; import app.organicmaps.base.BaseToolbarActivity;
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory; import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
@@ -58,7 +56,8 @@ public class BookmarkListActivity extends BaseToolbarActivity
return R.layout.bookmarks_activity; return R.layout.bookmarks_activity;
} }
static void startForResult(@NonNull Fragment fragment, ActivityResultLauncher<Intent> startBookmarkListForResult, @NonNull BookmarkCategory category) static void startForResult(@NonNull Fragment fragment, ActivityResultLauncher<Intent> startBookmarkListForResult,
@NonNull BookmarkCategory category)
{ {
Bundle args = new Bundle(); Bundle args = new Bundle();
Intent intent = new Intent(fragment.requireActivity(), BookmarkListActivity.class); Intent intent = new Intent(fragment.requireActivity(), BookmarkListActivity.class);

View File

@@ -4,13 +4,9 @@ import android.content.res.Resources;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.textview.MaterialTextView;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory; import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
import app.organicmaps.sdk.bookmarks.data.BookmarkInfo; import app.organicmaps.sdk.bookmarks.data.BookmarkInfo;
@@ -20,7 +16,7 @@ import app.organicmaps.sdk.bookmarks.data.SortedBlock;
import app.organicmaps.sdk.content.DataSource; import app.organicmaps.sdk.content.DataSource;
import app.organicmaps.widget.recycler.RecyclerClickListener; import app.organicmaps.widget.recycler.RecyclerClickListener;
import app.organicmaps.widget.recycler.RecyclerLongClickListener; import app.organicmaps.widget.recycler.RecyclerLongClickListener;
import com.google.android.material.textview.MaterialTextView;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@@ -62,12 +58,14 @@ public class BookmarkListAdapter extends RecyclerView.Adapter<Holders.BaseBookma
mDataSource = dataSource; mDataSource = dataSource;
} }
public BookmarkCategory getCategory() { return mDataSource.getData(); } public BookmarkCategory getCategory()
{
return mDataSource.getData();
}
boolean hasDescription() boolean hasDescription()
{ {
return (!mDataSource.getData().getAnnotation().isEmpty() || return (!mDataSource.getData().getAnnotation().isEmpty() || !mDataSource.getData().getDescription().isEmpty());
!mDataSource.getData().getDescription().isEmpty());
} }
void invalidate() void invalidate()
@@ -115,7 +113,10 @@ public class BookmarkListAdapter extends RecyclerView.Adapter<Holders.BaseBookma
} }
@Override @Override
public int getSectionsCount() { return mSectionsCount; } public int getSectionsCount()
{
return mSectionsCount;
}
@Override @Override
public boolean isEditable(int sectionIndex) public boolean isEditable(int sectionIndex)
@@ -124,7 +125,10 @@ public class BookmarkListAdapter extends RecyclerView.Adapter<Holders.BaseBookma
} }
@Override @Override
public boolean hasTitle(int sectionIndex) { return true; } public boolean hasTitle(int sectionIndex)
{
return true;
}
@Nullable @Nullable
public String getTitle(int sectionIndex, @NonNull Resources rs) public String getTitle(int sectionIndex, @NonNull Resources rs)
@@ -172,15 +176,13 @@ public class BookmarkListAdapter extends RecyclerView.Adapter<Holders.BaseBookma
@Override @Override
public long getBookmarkId(@NonNull SectionPosition pos) public long getBookmarkId(@NonNull SectionPosition pos)
{ {
return BookmarkManager.INSTANCE.getBookmarkIdByPosition(getCategory().getId(), return BookmarkManager.INSTANCE.getBookmarkIdByPosition(getCategory().getId(), pos.getItemIndex());
pos.getItemIndex());
} }
@Override @Override
public long getTrackId(@NonNull SectionPosition pos) public long getTrackId(@NonNull SectionPosition pos)
{ {
return BookmarkManager.INSTANCE.getTrackIdByPosition(getCategory().getId(), return BookmarkManager.INSTANCE.getTrackIdByPosition(getCategory().getId(), pos.getItemIndex());
pos.getItemIndex());
} }
} }
@@ -189,30 +191,47 @@ public class BookmarkListAdapter extends RecyclerView.Adapter<Holders.BaseBookma
@NonNull @NonNull
private final List<Long> mSearchResults; private final List<Long> mSearchResults;
SearchResultsSectionsDataSource(@NonNull DataSource<BookmarkCategory> dataSource, SearchResultsSectionsDataSource(@NonNull DataSource<BookmarkCategory> dataSource, @NonNull List<Long> searchResults)
@NonNull List<Long> searchResults)
{ {
super(dataSource); super(dataSource);
mSearchResults = searchResults; mSearchResults = searchResults;
} }
@Override @Override
public int getSectionsCount() { return 1; } public int getSectionsCount()
{
return 1;
}
@Override @Override
public boolean isEditable(int sectionIndex) { return true; } public boolean isEditable(int sectionIndex)
{
return true;
}
@Override @Override
public boolean hasTitle(int sectionIndex) { return false; } public boolean hasTitle(int sectionIndex)
{
return false;
}
@Nullable @Nullable
public String getTitle(int sectionIndex, @NonNull Resources rs) { return null; } public String getTitle(int sectionIndex, @NonNull Resources rs)
{
return null;
}
@Override @Override
public int getItemsCount(int sectionIndex) { return mSearchResults.size(); } public int getItemsCount(int sectionIndex)
{
return mSearchResults.size();
}
@Override @Override
public int getItemsType(int sectionIndex) { return TYPE_BOOKMARK; } public int getItemsType(int sectionIndex)
{
return TYPE_BOOKMARK;
}
@Override @Override
public void onDelete(@NonNull SectionPosition pos) public void onDelete(@NonNull SectionPosition pos)
@@ -238,8 +257,7 @@ public class BookmarkListAdapter extends RecyclerView.Adapter<Holders.BaseBookma
@NonNull @NonNull
private final List<SortedBlock> mSortedBlocks; private final List<SortedBlock> mSortedBlocks;
SortedSectionsDataSource(@NonNull DataSource<BookmarkCategory> dataSource, SortedSectionsDataSource(@NonNull DataSource<BookmarkCategory> dataSource, @NonNull List<SortedBlock> sortedBlocks)
@NonNull List<SortedBlock> sortedBlocks)
{ {
super(dataSource); super(dataSource);
mSortedBlocks = sortedBlocks; mSortedBlocks = sortedBlocks;
@@ -272,7 +290,10 @@ public class BookmarkListAdapter extends RecyclerView.Adapter<Holders.BaseBookma
} }
@Override @Override
public boolean hasTitle(int sectionIndex) { return true; } public boolean hasTitle(int sectionIndex)
{
return true;
}
@Nullable @Nullable
public String getTitle(int sectionIndex, @NonNull Resources rs) public String getTitle(int sectionIndex, @NonNull Resources rs)
@@ -423,8 +444,7 @@ public class BookmarkListAdapter extends RecyclerView.Adapter<Holders.BaseBookma
{ {
case TYPE_TRACK: case TYPE_TRACK:
Holders.TrackViewHolder trackHolder = Holders.TrackViewHolder trackHolder =
new Holders.TrackViewHolder(inflater.inflate(R.layout.item_track, parent, new Holders.TrackViewHolder(inflater.inflate(R.layout.item_track, parent, false));
false));
trackHolder.setOnClickListener(mClickListener); trackHolder.setOnClickListener(mClickListener);
trackHolder.setOnLongClickListener(mLongClickListener); trackHolder.setOnLongClickListener(mLongClickListener);
trackHolder.setTrackIconClickListener(mIconClickListener); trackHolder.setTrackIconClickListener(mIconClickListener);
@@ -433,8 +453,7 @@ public class BookmarkListAdapter extends RecyclerView.Adapter<Holders.BaseBookma
break; break;
case TYPE_BOOKMARK: case TYPE_BOOKMARK:
Holders.BookmarkViewHolder bookmarkHolder = Holders.BookmarkViewHolder bookmarkHolder =
new Holders.BookmarkViewHolder(inflater.inflate(R.layout.item_bookmark, parent, new Holders.BookmarkViewHolder(inflater.inflate(R.layout.item_bookmark, parent, false));
false));
bookmarkHolder.setOnClickListener(mClickListener); bookmarkHolder.setOnClickListener(mClickListener);
bookmarkHolder.setOnLongClickListener(mLongClickListener); bookmarkHolder.setOnLongClickListener(mLongClickListener);
holder = bookmarkHolder; holder = bookmarkHolder;

View File

@@ -11,7 +11,6 @@ import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
@@ -40,9 +39,9 @@ import app.organicmaps.sdk.bookmarks.data.SortedBlock;
import app.organicmaps.sdk.bookmarks.data.Track; import app.organicmaps.sdk.bookmarks.data.Track;
import app.organicmaps.sdk.search.BookmarkSearchListener; import app.organicmaps.sdk.search.BookmarkSearchListener;
import app.organicmaps.sdk.search.SearchEngine; import app.organicmaps.sdk.search.SearchEngine;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.Graphics; import app.organicmaps.util.Graphics;
import app.organicmaps.util.SharingUtils; import app.organicmaps.util.SharingUtils;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils; import app.organicmaps.util.WindowInsetUtils;
import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment; import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment;
@@ -53,16 +52,13 @@ import app.organicmaps.widget.placepage.EditBookmarkFragment;
import app.organicmaps.widget.recycler.DividerItemDecorationWithPadding; import app.organicmaps.widget.recycler.DividerItemDecorationWithPadding;
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton; import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
import com.google.android.material.imageview.ShapeableImageView; import com.google.android.material.imageview.ShapeableImageView;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter> public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter>
implements BookmarkManager.BookmarksSharingListener, implements BookmarkManager.BookmarksSharingListener, BookmarkManager.BookmarksSortingListener,
BookmarkManager.BookmarksSortingListener, BookmarkManager.BookmarksLoadingListener, BookmarkSearchListener,
BookmarkManager.BookmarksLoadingListener,
BookmarkSearchListener,
ChooseBookmarksSortingTypeFragment.ChooseSortingTypeListener, ChooseBookmarksSortingTypeFragment.ChooseSortingTypeListener,
MenuBottomSheetFragment.MenuBottomSheetInterface MenuBottomSheetFragment.MenuBottomSheetInterface
{ {
@@ -75,12 +71,14 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
private static final String OPTIONS_MENU_ID = "OPTIONS_MENU_BOTTOM_SHEET"; private static final String OPTIONS_MENU_ID = "OPTIONS_MENU_BOTTOM_SHEET";
private ActivityResultLauncher<SharingUtils.SharingIntent> shareLauncher; private ActivityResultLauncher<SharingUtils.SharingIntent> shareLauncher;
private final ActivityResultLauncher<Intent> startBookmarkListForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> { private final ActivityResultLauncher<Intent> startBookmarkListForResult =
registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> {
System.out.println("resultCode: " + activityResult.getResultCode()); System.out.println("resultCode: " + activityResult.getResultCode());
handleActivityResult(); handleActivityResult();
}); });
private final ActivityResultLauncher<Intent> startBookmarkSettingsForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> { private final ActivityResultLauncher<Intent> startBookmarkSettingsForResult =
registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> {
System.out.println("resultCode: " + activityResult.getResultCode()); System.out.println("resultCode: " + activityResult.getResultCode());
handleActivityResult(); handleActivityResult();
}); });
@@ -104,8 +102,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
private ExtendedFloatingActionButton mFabViewOnMap; private ExtendedFloatingActionButton mFabViewOnMap;
@SuppressWarnings("NotNullFieldNotInitialized") @SuppressWarnings("NotNullFieldNotInitialized")
@NonNull @NonNull
private final RecyclerView.OnScrollListener mRecyclerListener = new RecyclerView.OnScrollListener() private final RecyclerView.OnScrollListener mRecyclerListener = new RecyclerView.OnScrollListener() {
{
@Override @Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) public void onScrollStateChanged(RecyclerView recyclerView, int newState)
{ {
@@ -148,18 +145,15 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
{ {
List<BookmarkCategory> mCategoryItems = BookmarkManager.INSTANCE.getChildrenCategories(categoryId); List<BookmarkCategory> mCategoryItems = BookmarkManager.INSTANCE.getChildrenCategories(categoryId);
BookmarkCollectionAdapter adapter = new BookmarkCollectionAdapter(getCategoryOrThrow(), BookmarkCollectionAdapter adapter = new BookmarkCollectionAdapter(getCategoryOrThrow(), mCategoryItems);
mCategoryItems); adapter.setOnClickListener(
adapter.setOnClickListener((v, item) -> { (v, item) -> BookmarkListActivity.startForResult(this, startBookmarkListForResult, item));
BookmarkListActivity.startForResult(this, startBookmarkListForResult, item);
});
return adapter; return adapter;
} }
@Override @Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
@Nullable Bundle savedInstanceState)
{ {
return inflater.inflate(R.layout.fragment_bookmark_list, container, false); return inflater.inflate(R.layout.fragment_bookmark_list, container, false);
} }
@@ -204,8 +198,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
// recycler view already has an InsetListener in BaseMwmRecyclerFragment // recycler view already has an InsetListener in BaseMwmRecyclerFragment
// here we must reset it, because the logic is different from a common use case // here we must reset it, because the logic is different from a common use case
ViewCompat.setOnApplyWindowInsetsListener( ViewCompat.setOnApplyWindowInsetsListener(
getRecyclerView(), getRecyclerView(), new WindowInsetUtils.ScrollableContentInsetsListener(getRecyclerView(), mFabViewOnMap));
new WindowInsetUtils.ScrollableContentInsetsListener(getRecyclerView(), mFabViewOnMap));
updateLoadingPlaceholder(view, false); updateLoadingPlaceholder(view, false);
} }
@@ -263,8 +256,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
private void configureFab(@NonNull View view) private void configureFab(@NonNull View view)
{ {
mFabViewOnMap = view.findViewById(R.id.show_on_map_fab); mFabViewOnMap = view.findViewById(R.id.show_on_map_fab);
mFabViewOnMap.setOnClickListener(v -> mFabViewOnMap.setOnClickListener(v -> {
{
final Intent i = makeMwmActivityIntent(); final Intent i = makeMwmActivityIntent();
i.putExtra(MwmActivity.EXTRA_CATEGORY_ID, mCategoryDataSource.getData().getId()); i.putExtra(MwmActivity.EXTRA_CATEGORY_ID, mCategoryDataSource.getData().getId());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
@@ -290,13 +282,11 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
{ {
if (isEmptySearchResults()) if (isEmptySearchResults())
{ {
requirePlaceholder().setContent(R.string.search_not_found, requirePlaceholder().setContent(R.string.search_not_found, R.string.search_not_found_query);
R.string.search_not_found_query);
} }
else if (isEmpty()) else if (isEmpty())
{ {
requirePlaceholder().setContent(R.string.bookmarks_empty_list_title, requirePlaceholder().setContent(R.string.bookmarks_empty_list_title, R.string.bookmarks_empty_list_message);
R.string.bookmarks_empty_list_message);
} }
boolean isEmptyRecycler = isEmpty() || isEmptySearchResults(); boolean isEmptyRecycler = isEmpty() || isEmptySearchResults();
@@ -332,9 +322,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
SearchEngine.INSTANCE.cancel(); SearchEngine.INSTANCE.cancel();
mLastQueryTimestamp = System.nanoTime(); mLastQueryTimestamp = System.nanoTime();
if (SearchEngine.INSTANCE.searchInBookmarks(query, if (SearchEngine.INSTANCE.searchInBookmarks(query, mCategoryDataSource.getData().getId(), mLastQueryTimestamp))
mCategoryDataSource.getData().getId(),
mLastQueryTimestamp))
{ {
mToolbarController.showProgress(true); mToolbarController.showProgress(true);
} }
@@ -433,8 +421,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
final double lon = hasMyPosition ? loc.getLongitude() : 0; final double lon = hasMyPosition ? loc.getLongitude() : 0;
BookmarkManager.INSTANCE.setLastSortingType(catId, sortingType); BookmarkManager.INSTANCE.setLastSortingType(catId, sortingType);
BookmarkManager.INSTANCE.getSortedCategory(catId, sortingType, hasMyPosition, lat, lon, BookmarkManager.INSTANCE.getSortedCategory(catId, sortingType, hasMyPosition, lat, lon, mLastSortTimestamp);
mLastSortTimestamp);
updateSortingProgressBar(); updateSortingProgressBar();
} }
@@ -448,8 +435,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
@NonNull @NonNull
private BookmarkCollectionAdapter getBookmarkCollectionAdapter() private BookmarkCollectionAdapter getBookmarkCollectionAdapter()
{ {
return (BookmarkCollectionAdapter) getAdapter().getAdapters() return (BookmarkCollectionAdapter) getAdapter().getAdapters().get(INDEX_BOOKMARKS_COLLECTION_ADAPTER);
.get(INDEX_BOOKMARKS_COLLECTION_ADAPTER);
} }
@Override @Override
@@ -527,7 +513,8 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
private int getLastAvailableSortingType() private int getLastAvailableSortingType()
{ {
int currentType = getLastSortingType(); int currentType = getLastSortingType();
@BookmarkManager.SortingType int[] types = getAvailableSortingTypes(); @BookmarkManager.SortingType
int[] types = getAvailableSortingTypes();
for (@BookmarkManager.SortingType int type : types) for (@BookmarkManager.SortingType int type : types)
{ {
if (type == currentType) if (type == currentType)
@@ -538,14 +525,12 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
private boolean isEmpty() private boolean isEmpty()
{ {
return !getBookmarkListAdapter().isSearchResults() return !getBookmarkListAdapter().isSearchResults() && getBookmarkListAdapter().getItemCount() == 0;
&& getBookmarkListAdapter().getItemCount() == 0;
} }
private boolean isEmptySearchResults() private boolean isEmptySearchResults()
{ {
return getBookmarkListAdapter().isSearchResults() return getBookmarkListAdapter().isSearchResults() && getBookmarkListAdapter().getItemCount() == 0;
&& getBookmarkListAdapter().getItemCount() == 0;
} }
private boolean isLastOwnedCategory() private boolean isLastOwnedCategory()
@@ -591,8 +576,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
i.putExtra(MwmActivity.EXTRA_TRACK_ID, track.getTrackId()); i.putExtra(MwmActivity.EXTRA_TRACK_ID, track.getTrackId());
} }
private void onBookmarkClicked(int position, @NonNull Intent i, private void onBookmarkClicked(int position, @NonNull Intent i, @NonNull BookmarkListAdapter adapter)
@NonNull BookmarkListAdapter adapter)
{ {
final BookmarkInfo bookmark = (BookmarkInfo) adapter.getItem(position); final BookmarkInfo bookmark = (BookmarkInfo) adapter.getItem(position);
i.putExtra(MwmActivity.EXTRA_CATEGORY_ID, bookmark.getCategoryId()); i.putExtra(MwmActivity.EXTRA_CATEGORY_ID, bookmark.getCategoryId());
@@ -605,7 +589,8 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
mSelectedPosition = position; mSelectedPosition = position;
final Track mTrack = (Track) adapter.getItem(mSelectedPosition); final Track mTrack = (Track) adapter.getItem(mSelectedPosition);
if (mTrack == null) return; if (mTrack == null)
return;
final Bundle args = new Bundle(); final Bundle args = new Bundle();
args.putInt(BookmarkColorDialogFragment.ICON_TYPE, Icon.getColorPosition(mTrack.getColor())); args.putInt(BookmarkColorDialogFragment.ICON_TYPE, Icon.getColorPosition(mTrack.getColor()));
final FragmentManager manager = getChildFragmentManager(); final FragmentManager manager = getChildFragmentManager();
@@ -620,9 +605,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
if (from == to) if (from == to)
return; return;
BookmarkManager.INSTANCE.changeTrackColor(mTrack.getTrackId(), to); BookmarkManager.INSTANCE.changeTrackColor(mTrack.getTrackId(), to);
Drawable circle = Graphics.drawCircle(to, Drawable circle = Graphics.drawCircle(to, R.dimen.track_circle_size, requireContext().getResources());
R.dimen.track_circle_size,
requireContext().getResources());
v.setImageDrawable(circle); v.setImageDrawable(circle);
}); });
@@ -716,10 +699,8 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
{ {
BookmarkListAdapter adapter = getBookmarkListAdapter(); BookmarkListAdapter adapter = getBookmarkListAdapter();
BookmarkInfo info = (BookmarkInfo) adapter.getItem(mSelectedPosition); BookmarkInfo info = (BookmarkInfo) adapter.getItem(mSelectedPosition);
EditBookmarkFragment.editBookmark( EditBookmarkFragment.editBookmark(info.getCategoryId(), info.getBookmarkId(), requireActivity(),
info.getCategoryId(), info.getBookmarkId(), requireActivity(), getChildFragmentManager(), getChildFragmentManager(), (bookmarkId, movedFromCategory) -> {
(bookmarkId, movedFromCategory) ->
{
if (movedFromCategory) if (movedFromCategory)
resetSearchAndSort(); resetSearchAndSort();
else else
@@ -730,10 +711,8 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
private void onTrackEditActionSelected() private void onTrackEditActionSelected()
{ {
Track track = (Track) getBookmarkListAdapter().getItem(mSelectedPosition); Track track = (Track) getBookmarkListAdapter().getItem(mSelectedPosition);
EditBookmarkFragment.editTrack( EditBookmarkFragment.editTrack(track.getCategoryId(), track.getTrackId(), requireActivity(),
track.getCategoryId(), track.getTrackId(), requireActivity(), getChildFragmentManager(), getChildFragmentManager(), (trackId, movedFromCategory) -> {
(trackId, movedFromCategory) ->
{
if (movedFromCategory) if (movedFromCategory)
resetSearchAndSort(); resetSearchAndSort();
else else
@@ -756,8 +735,8 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
private void onSortOptionSelected() private void onSortOptionSelected()
{ {
ChooseBookmarksSortingTypeFragment.chooseSortingType(getAvailableSortingTypes(), ChooseBookmarksSortingTypeFragment.chooseSortingType(getAvailableSortingTypes(), getLastSortingType(),
getLastSortingType(), requireActivity(), getChildFragmentManager()); requireActivity(), getChildFragmentManager());
} }
private void onShareOptionSelected(KmlFileType kmlFileType) private void onShareOptionSelected(KmlFileType kmlFileType)
@@ -768,7 +747,8 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
private void onSettingsOptionSelected() private void onSettingsOptionSelected()
{ {
BookmarkCategorySettingsActivity.startForResult(this, startBookmarkSettingsForResult, mCategoryDataSource.getData()); BookmarkCategorySettingsActivity.startForResult(this, startBookmarkSettingsForResult,
mCategoryDataSource.getData());
} }
private void onDeleteOptionSelected() private void onDeleteOptionSelected()
@@ -779,14 +759,17 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
private ArrayList<MenuBottomSheetItem> getOptionsMenuItems() private ArrayList<MenuBottomSheetItem> getOptionsMenuItems()
{ {
@BookmarkManager.SortingType int[] types = getAvailableSortingTypes(); @BookmarkManager.SortingType
int[] types = getAvailableSortingTypes();
ArrayList<MenuBottomSheetItem> items = new ArrayList<>(); ArrayList<MenuBottomSheetItem> items = new ArrayList<>();
if (!isEmpty()) if (!isEmpty())
{ {
if (types.length > 0) if (types.length > 0)
items.add(new MenuBottomSheetItem(R.string.sort, R.drawable.ic_sort, this::onSortOptionSelected)); items.add(new MenuBottomSheetItem(R.string.sort, R.drawable.ic_sort, this::onSortOptionSelected));
items.add(new MenuBottomSheetItem(R.string.export_file, R.drawable.ic_file_kmz, () -> onShareOptionSelected(KmlFileType.Text))); items.add(new MenuBottomSheetItem(R.string.export_file, R.drawable.ic_file_kmz,
items.add(new MenuBottomSheetItem(R.string.export_file_gpx, R.drawable.ic_file_gpx, () -> onShareOptionSelected(KmlFileType.Gpx))); () -> onShareOptionSelected(KmlFileType.Text)));
items.add(new MenuBottomSheetItem(R.string.export_file_gpx, R.drawable.ic_file_gpx,
() -> onShareOptionSelected(KmlFileType.Gpx)));
} }
items.add(new MenuBottomSheetItem(R.string.edit, R.drawable.ic_settings, this::onSettingsOptionSelected)); items.add(new MenuBottomSheetItem(R.string.edit, R.drawable.ic_settings, this::onSettingsOptionSelected));
if (!isLastOwnedCategory()) if (!isLastOwnedCategory())
@@ -807,9 +790,12 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
{ {
ArrayList<MenuBottomSheetItem> items = new ArrayList<>(); ArrayList<MenuBottomSheetItem> items = new ArrayList<>();
items.add(new MenuBottomSheetItem(R.string.edit, R.drawable.ic_edit, this::onTrackEditActionSelected)); items.add(new MenuBottomSheetItem(R.string.edit, R.drawable.ic_edit, this::onTrackEditActionSelected));
items.add(new MenuBottomSheetItem(R.string.export_file, R.drawable.ic_file_kmz, () -> onShareTrackSelected(track.getTrackId(), KmlFileType.Text))); items.add(new MenuBottomSheetItem(R.string.export_file, R.drawable.ic_file_kmz,
items.add(new MenuBottomSheetItem(R.string.export_file_gpx, R.drawable.ic_file_gpx, () -> onShareTrackSelected(track.getTrackId(), KmlFileType.Gpx))); () -> onShareTrackSelected(track.getTrackId(), KmlFileType.Text)));
items.add(new MenuBottomSheetItem(R.string.delete, R.drawable.ic_delete, () -> onDeleteTrackSelected(track.getTrackId()))); items.add(new MenuBottomSheetItem(R.string.export_file_gpx, R.drawable.ic_file_gpx,
() -> onShareTrackSelected(track.getTrackId(), KmlFileType.Gpx)));
items.add(new MenuBottomSheetItem(R.string.delete, R.drawable.ic_delete,
() -> onDeleteTrackSelected(track.getTrackId())));
return items; return items;
} }
@@ -855,15 +841,22 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
@Nullable @Nullable
public ArrayList<MenuBottomSheetItem> getMenuBottomSheetItems(String id) public ArrayList<MenuBottomSheetItem> getMenuBottomSheetItems(String id)
{ {
if (id.equals(BOOKMARKS_MENU_ID)) switch (id)
{
case BOOKMARKS_MENU_ID ->
{
return getBookmarkMenuItems(); return getBookmarkMenuItems();
if (id.equals(TRACK_MENU_ID)) }
case TRACK_MENU_ID ->
{ {
final Track track = (Track) getBookmarkListAdapter().getItem(mSelectedPosition); final Track track = (Track) getBookmarkListAdapter().getItem(mSelectedPosition);
return getTrackMenuItems(track); return getTrackMenuItems(track);
} }
if (id.equals(OPTIONS_MENU_ID)) case OPTIONS_MENU_ID ->
{
return getOptionsMenuItems(); return getOptionsMenuItems();
}
}
return null; return null;
} }
} }

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