Compare commits
142 Commits
2025.06.25
...
test/2025.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c287dde93f | ||
|
|
f7e4fdad6a | ||
|
|
f59fb509c9 | ||
|
|
9cd3db6f39 | ||
|
|
7138970ea6 | ||
|
|
cbd561ec90 | ||
|
|
048dc60be6 | ||
|
|
40018f5cc8 | ||
|
|
4314f281d1 | ||
|
|
b529a733c0 | ||
|
|
1b8172f744 | ||
|
|
c589aaa3cf | ||
|
|
13b91b36ae | ||
|
|
e523434b36 | ||
|
|
752fcaf09c | ||
|
|
7e2b05573f | ||
|
|
7e63d98cb7 | ||
|
|
304addba58 | ||
|
|
1becd3e0ba | ||
|
|
dee47e7a66 | ||
|
|
2e60bfc289 | ||
|
|
fdbb41e0fd | ||
|
|
090ed5044a | ||
|
|
54b6471400 | ||
|
|
415e2fc0c2 | ||
|
|
f0ed076858 | ||
|
|
57f28fa85b | ||
|
|
7228fe239d | ||
|
|
c294937c73 | ||
|
|
ebf84e7d5b | ||
|
|
19dd760c44 | ||
|
|
8a8ac5c660 | ||
|
|
7a8f7929fc | ||
|
|
b285ef348b | ||
|
|
87dad591ab | ||
|
|
9e49aae49e | ||
|
|
d621636549 | ||
|
|
ec1d2e6c82 | ||
|
|
6d0c52afcc | ||
|
|
3abf354099 | ||
|
|
9a759229f9 | ||
|
|
a3e1666ede | ||
|
|
15c7e71866 | ||
|
|
db1ef9b148 | ||
|
|
9951ebece7 | ||
|
|
7bfb488f1d | ||
|
|
df70ae1b01 | ||
|
|
15b3cda4d7 | ||
|
|
fae8849869 | ||
|
|
3585bd4fad | ||
|
|
99bb468448 | ||
|
|
46ec844398 | ||
|
|
f8d1914037 | ||
|
|
71386ce395 | ||
|
|
8d95d2e9b7 | ||
|
|
05c4413394 | ||
|
|
29bbbb13ee | ||
|
|
e321b1c5be | ||
|
|
736e1aa07b | ||
|
|
e32b01494a | ||
|
|
4496690e0a | ||
|
|
ef9618b3d6 | ||
|
|
13ba20aa25 | ||
|
|
23c23c118d | ||
|
|
5b4d458579 | ||
|
|
1bb2b2274f | ||
|
|
aec82794ac | ||
|
|
927299f4a9 | ||
|
|
87cb0307cf | ||
|
|
de7f60ea37 | ||
|
|
f7fb0e80e5 | ||
|
|
e49a74e287 | ||
|
|
77a7255e93 | ||
|
|
25b3abadef | ||
|
|
01388ae6dd | ||
|
|
4bf61f14f8 | ||
|
|
49603aa0a1 | ||
|
|
890c927bab | ||
|
|
d564f69b58 | ||
|
|
abd15756be | ||
|
|
ea1edec3df | ||
|
|
c17135f5a6 | ||
|
|
2471ff0545 | ||
|
|
a99d1c1a38 | ||
|
|
deb663e4f9 | ||
|
|
3858b0905f | ||
|
|
8db9289b56 | ||
|
|
b31819fcfb | ||
|
|
fdc05a2a6c | ||
|
|
1584adc4cb | ||
|
|
4623291461 | ||
|
|
b409d805cc | ||
|
|
ac30139432 | ||
|
|
df3850b86c | ||
|
|
70c3f725f9 | ||
|
|
a830e4b444 | ||
|
|
142759c4d0 | ||
|
|
5ee1c2a2a0 | ||
|
|
a21f2125bc | ||
|
|
5346193f80 | ||
|
|
a94cb3531d | ||
|
|
ceb94232a6 | ||
|
|
5ea4bfef34 | ||
|
|
6014a899d1 | ||
|
|
c4d8ac0426 | ||
|
|
b6b02ba9d7 | ||
|
|
a274ed927e | ||
|
|
bbadd3f338 | ||
|
|
0e9bc6f960 | ||
|
|
a448422ad6 | ||
|
|
e3d8454b6c | ||
|
|
99be248ec8 | ||
|
|
cd0ffab996 | ||
|
|
2dca80cd0f | ||
|
|
d01de6ade7 | ||
|
|
f7f73f04b1 | ||
|
|
eee299f6cd | ||
|
|
5b43e4ec9b | ||
|
|
733c0ae8a8 | ||
|
|
30ee5c30e1 | ||
|
|
d562f23256 | ||
|
|
ecb44b5ae9 | ||
|
|
c49cf48575 | ||
|
|
4581907f00 | ||
|
|
423d45a1bb | ||
|
|
4d8e7c39fd | ||
|
|
273eeed9f3 | ||
|
|
754748123c | ||
|
|
b58bacddf1 | ||
|
|
a985bf8349 | ||
|
|
b4f115a8fa | ||
|
|
df89761eba | ||
|
|
25e49b0fe1 | ||
|
|
6a10cffe51 | ||
|
|
495167c11f | ||
|
|
d44d671550 | ||
|
|
d44d575368 | ||
|
|
fbddff009e | ||
|
|
58bab61890 | ||
|
|
464b3cf59a | ||
|
|
4a48d43240 | ||
|
|
d68544de13 |
@@ -7,7 +7,11 @@ CoMaps contributors:
|
||||
(in alphabetic order)
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Bastian Greshake Tzovaras
|
||||
clover sage
|
||||
Harry Bond <me@hbond.xyz>
|
||||
vikiawv
|
||||
Yannik Bloscheck
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Organic Maps (formerly OMaps) contributors:
|
||||
|
||||
178
README.md
@@ -1,66 +1,85 @@
|
||||
<!--<div align="center">
|
||||
<img src="qt/res/logo.png" height="100"/>
|
||||
</div>-->
|
||||
|
||||
<!-- a nav bar -->
|
||||
[Project Intro](https://codeberg.org/comaps#comaps)
|
||||
| [Governance](https://codeberg.org/comaps/Governance#comaps-project-governance-docs)
|
||||
| [FAQ](https://codeberg.org/comaps/Governance/src/branch/main/FAQ.md)
|
||||
| [Contribute](#contributing)
|
||||
| [Donate](https://www.comaps.app/donate)
|
||||
| [Keep Connected](https://codeberg.org/comaps#keep-connected)
|
||||
|
||||
# [CoMaps](https://comaps.app) – Hike, Bike, Drive Offline – Easy Map Navigation with Privacy
|
||||
|
||||
[
|
||||

|
||||
](https://github.com/comaps/comaps/actions/workflows/android-check.yaml)
|
||||
[
|
||||

|
||||
](https://github.com/comaps/comaps/actions/workflows/ios-check.yaml)
|
||||
[
|
||||

|
||||
](https://opencollective.com/comaps)
|
||||
[
|
||||

|
||||
](https://liberapay.com/CoMaps)
|
||||
|
||||
|
||||
|
||||
A community-led free & open source maps app based on [OpenStreetMap](https://www.openstreetmap.org) data and reinforced with commitment to transparency, privacy and being not-for-profit. CoMaps is a fork/spin-off of Organic Maps, which in turn is a fork of Maps.ME.
|
||||
|
||||
There are apps for Android and iOS (and ARM MacOS).
|
||||
An alpha Linux / MacOS Qt desktop version, which is also suitable for Linux phones.
|
||||
|
||||
The June app release is available on Google Play, F-Droid and as an APK to download now! We are working on publishing in the iOS App Store as well, please stay tuned!
|
||||
|
||||
<!--
|
||||
[<img src="docs/badges/apple-appstore.png" alt="App Store" width="160">](https://apps.apple.com/app/comaps/id1567437057)
|
||||
-->
|
||||
[<img src="docs/badges/google-play.png" alt="Google Play" width="160">](https://play.google.com/store/apps/details?id=app.comaps.google)
|
||||
[<img src="docs/badges/fdroid.png" alt="F-Droid" width="160">](https://f-droid.org/en/packages/app.comaps.fdroid/)
|
||||
[<img src="docs/badges/codeberg.png" alt="Codeberg" width="160">](https://codeberg.org/comaps/comaps/releases)
|
||||
|
||||
<p float="left">
|
||||
<img src="android/app/src/fdroid/play/listings/en-US/graphics/phone-screenshots/1.jpg" width="180" />
|
||||
<img src="android/app/src/fdroid/play/listings/en-US/graphics/phone-screenshots/2.jpg" width="180" />
|
||||
<img src="android/app/src/fdroid/play/listings/en-US/graphics/phone-screenshots/3.jpg" width="180" />
|
||||
<img src="android/app/src/fdroid/play/listings/en-US/graphics/phone-screenshots/4.jpg" width="180" />
|
||||
<!-- Navigation Bar -->
|
||||
<p align="center">
|
||||
<a href="https://codeberg.org/comaps#comaps">Project Intro</a> |
|
||||
<a href="https://codeberg.org/comaps/Governance#comaps-project-governance-docs">Governance</a> |
|
||||
<a href="https://codeberg.org/comaps/Governance/src/branch/main/FAQ.md">FAQ</a> |
|
||||
<a href="#contributing">Contribute</a> |
|
||||
<a href="https://www.comaps.app/donate">Donate</a> |
|
||||
<a href="https://codeberg.org/comaps#keep-connected">Keep Connected</a>
|
||||
</p>
|
||||
|
||||
**Offline-focused**: Plan and navigate your trip abroad without the need for cellular service, search waypoints while on a distant hike, etc. All app functions are designed to work offline.
|
||||
|
||||
**Respecting Privacy**: The app is designed with privacy in mind - does not identify people, does not track, and does not collect personal information. Ads-free.
|
||||
|
||||
**Simple and Polished**: Essential, easy to use features that just work.
|
||||
<div align="center">
|
||||
<h1><a href="https://comaps.app/">CoMaps</a></h1>
|
||||
<h2>Hike, Bike, Drive Offline - Easy Map Navigation with Privacy</h2>
|
||||
</div>
|
||||
<div align="center">
|
||||
<p align="center">
|
||||
<a href="https://codeberg.org/comaps/comaps/releases">
|
||||
<img src="https://img.shields.io/github/license/comaps/comaps?style=for-the-badge&logo=opensourceinitiative&logoColor=white&color=588157" alt="License" style="width: 90%; max-width: 150px;"/>
|
||||
</a>
|
||||
<a href="https://github.com/comaps/comaps/actions/workflows/android-check.yaml">
|
||||
<img src="https://img.shields.io/github/actions/workflow/status/comaps/comaps/.github/workflows/android-check.yaml?label=Android%20Build&logo=android&logoColor=white&style=for-the-badge&color=588157" alt="Android Build Status" style="width: 90%; max-width: 170px;"/>
|
||||
</a>
|
||||
<a href="https://github.com/comaps/comaps/actions/workflows/ios-check.yaml">
|
||||
<img src="https://img.shields.io/github/actions/workflow/status/comaps/comaps/.github/workflows/ios-check.yaml?label=iOS%20Build&logo=apple&logoColor=white&style=for-the-badge&color=588157" alt="iOS Build Status" style="width: 90%; max-width: 145px;"/>
|
||||
</a>
|
||||
<a href="https://opencollective.com/comaps">
|
||||
<img src="https://img.shields.io/opencollective/all/comaps?label=Open%20Collective%20Donors&logo=opencollective&logoColor=white&style=for-the-badge&color=588157" alt="Open Collective Donors" style="width: 90%; max-width: 191px;"/>
|
||||
</a>
|
||||
<a href="https://liberapay.com/CoMaps">
|
||||
<img src="https://img.shields.io/liberapay/patrons/CoMaps.svg?label=Liberapay%20Patrons&logo=liberapay&logoColor=white&style=for-the-badge&color=588157" alt="Liberapay Patrons" style="width: 90%; max-width: 160px;"/>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
**Saves Your Battery and Space**: Doesn’t drain your battery like other navigation apps. Compact maps save precious space on your phone.
|
||||
---
|
||||
|
||||
**Free and Built by the Community**: People like you helped build the app by adding places to [OpenStreetMap](https://www.openstreetmap.org), testing and giving feedback on features and contributing their development skills and money.
|
||||
A community-led free & open source maps app based on [OpenStreetMap](https://www.openstreetmap.org), built for transparency, privacy, and not-for-profit values. A fork of Organic Maps, originally based on Maps.ME.
|
||||
|
||||
**Open and Transparent Decision-making and Financials, Not-for-profit and Fully Open Source.**
|
||||
**Available for:** Android, iOS, ARM macOS, and alpha Linux/macOS desktop builds (also usable on Linux phones).
|
||||
|
||||
### Main Features
|
||||
<p align="center">
|
||||
<a href="https://apps.apple.com/app/comaps/id6747180809">
|
||||
<img src="docs/badges/apple-appstore.png" alt="App Store" width="160"/>
|
||||
</a>
|
||||
<a href="https://play.google.com/store/apps/details?id=app.comaps.google">
|
||||
<img src="docs/badges/google-play.png" alt="Google Play" width="160"/>
|
||||
</a>
|
||||
<a href="https://f-droid.org/en/packages/app.comaps.fdroid/">
|
||||
<img src="docs/badges/fdroid.png" alt="F-Droid" width="160"/>
|
||||
</a>
|
||||
<a href="https://codeberg.org/comaps/comaps/releases">
|
||||
<img src="docs/badges/codeberg.png" alt="Codeberg" width="160"/>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
||||
<!-- Screenshots -->
|
||||
<p align="center">
|
||||
<img src="android/app/src/fdroid/play/listings/en-US/graphics/phone-screenshots/1.png" width="180" />
|
||||
<img src="android/app/src/fdroid/play/listings/en-US/graphics/phone-screenshots/2.png" width="180" />
|
||||
<img src="android/app/src/fdroid/play/listings/en-US/graphics/phone-screenshots/3.png" width="180" />
|
||||
<img src="android/app/src/fdroid/play/listings/en-US/graphics/phone-screenshots/4.png" width="180" />
|
||||
<img src="android/app/src/fdroid/play/listings/en-US/graphics/phone-screenshots/5.png" width="180" />
|
||||
<img src="android/app/src/fdroid/play/listings/en-US/graphics/phone-screenshots/6.png" width="180" />
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
## ⚡️ Highlights
|
||||
|
||||
- **Offline-first**: Navigate without a connection
|
||||
- **Privacy-respecting**: No tracking, Ads or data collection
|
||||
- **Lightweight**: Battery- and space-efficient
|
||||
- **Simple**: Polished, user-focused interface
|
||||
- **Community-built**: Free, open source, and collaborative
|
||||
- **Transparent**: Open finances and governance
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Main Features
|
||||
|
||||
- Downloadable detailed maps with places which are not available with Google Maps
|
||||
|
||||
@@ -90,37 +109,46 @@ The June app release is available on Google Play, F-Droid and as an APK to downl
|
||||
|
||||
- Android Auto and CarPlay support
|
||||
|
||||
*Freedom Is Here - Discover your journey, navigate the world with privacy and community at the forefront!*
|
||||
***Freedom Is Here – Navigate the world with privacy and community at the forefront.***
|
||||
|
||||
## Contributing
|
||||
---
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
You can help by donating, contributing code, translating, or by telling others about it. To build the best maps app there is a need for software development, design, product, community development, and other areas. Reach out to us and let us know how you want to help.
|
||||
|
||||
If you want to build the project, check [docs/INSTALL.md](docs/INSTALL.md). If you want to help the project,
|
||||
see [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md). You can help in many ways, the ability to code is not necessary.
|
||||
- Build instructions: [docs/INSTALL.md](docs/INSTALL.md)
|
||||
- Contribution guide: [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md)
|
||||
> [!NOTE]
|
||||
> Some docs might be outdated, contain broken links or old references to Organic Maps, etc. Its a work in progress and help is much appreciated!
|
||||
|
||||
Some docs might be outdated, contain broken links or old references to Organic Maps, etc. Its a work in progress and help is much appreciated!
|
||||
There is a dedicated Zulip chat for active contributors: [Zulip](https://comaps.zulipchat.com)
|
||||
|
||||
There is a dedicated Zulip chat for active contributors: [comaps.zulipchat.com](https://comaps.zulipchat.com)
|
||||
---
|
||||
|
||||
### Feedback
|
||||
## 💬 Feedback
|
||||
|
||||
<!-- uncomment when linked resources are ready
|
||||
- **Rate us on the [App Store](https://apps.apple.com/app/comaps/id1567437057)
|
||||
and [Google Play](https://play.google.com/store/apps/details?id=app.comaps)**. -->
|
||||
- Star our repos on Codeberg
|
||||
- Report bugs and discuss features at [the issue tracker](https://codeberg.org/comaps/comaps/issues)
|
||||
- Rate us on [App Store](https://apps.apple.com/app/comaps/id6747180809) and [Google Play](https://play.google.com/store/apps/details?id=app.comaps.google)
|
||||
- Star our repos on Codeberg
|
||||
- Report bugs or request features on the [issue tracker](https://codeberg.org/comaps/comaps/issues)
|
||||
|
||||
## How is development funded?
|
||||
---
|
||||
|
||||
The app is free for everyone, so we rely on donations. Please [donate](https://opencollective.com/comaps/donate) to support the CoMaps community and see this open project thrive!
|
||||
## 💸 Funding
|
||||
|
||||
CoMaps is free. To stay that way, it relies on your support.
|
||||
Donate via [OpenCollective](https://opencollective.com/comaps/donate) or [Liberapay](https://liberapay.com/CoMaps).
|
||||
The project's financial information is completely open and transparent at [our Open Collective](https://opencollective.com/comaps).
|
||||
|
||||
## License and Copyright
|
||||
---
|
||||
|
||||
Licensed under the Apache License, Version 2.0. See
|
||||
[LICENSE](LICENSE),
|
||||
[NOTICE](NOTICE)
|
||||
and [data/copyright.html](data/copyright.html)
|
||||
for more information.
|
||||
## 🔒 Privacy
|
||||
|
||||
The Android app has been reviewed by [Exodus Privacy](https://reports.exodus-privacy.eu.org/fr/reports/app.comaps.google/latest/).
|
||||
|
||||
---
|
||||
|
||||
## ⚖️ License
|
||||
|
||||
Licensed under the Apache License 2.0.
|
||||
See [LICENSE](LICENSE), [NOTICE](NOTICE), and [data/copyright.html](data/copyright.html).
|
||||
@@ -1 +1 @@
|
||||
Jednoduchá navigace v mapě - Objevte více na své cestě ‐ Vyvíjeno komunitou
|
||||
Jednoduchá navigace v mapě – Objevte více na své cestě – Vyvíjeno komunitou
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
• Kartenfarben aufgefrischt – heller, wärmer, freundlicher!
|
||||
• OSM-Editor: „Stockwerk“ Feld hinzugefügt
|
||||
• Symbole für Tankstellen und Ladestationen aktualisiert
|
||||
• Farben einiger UI Elemente überarbeitet
|
||||
• Funktionierende Links zum Teilen von Orten
|
||||
• Falsch angezeigte Kartengröße nach Downloadfehlern korrigiert
|
||||
• Kleine Sprünge des Standortpfeils in bestimmten Fällen behoben
|
||||
• Bugfixes für Android 5 & 6
|
||||
• OpenStreetMap-Daten vom 22. Juni
|
||||
• Optionale automatische Backups von Lesezeichen & Tracks
|
||||
• Neue 100m-Höhenlinien für Regionen die vorher gröbere/keine Isolinien hatten
|
||||
• Vegetation & Spielplätze werden früher angezeigt, neue Farben für Campingplätze & andere Einrichtungen
|
||||
• Pfade & Tracks werden standardmäßig bei höherem Zoom angezeigt, Outdoor-Stil für Detailübersicht
|
||||
• Aktion des linken Button nichtm mehr im Hamburger-Menü, stattdessen werden "Über & Hilfe" dort angezeigt
|
||||
|
||||
|
Before Width: | Height: | Size: 747 KiB |
|
After Width: | Height: | Size: 628 KiB |
|
Before Width: | Height: | Size: 749 KiB |
|
After Width: | Height: | Size: 532 KiB |
|
Before Width: | Height: | Size: 730 KiB |
|
After Width: | Height: | Size: 391 KiB |
|
Before Width: | Height: | Size: 590 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 268 KiB |
|
After Width: | Height: | Size: 263 KiB |
@@ -1,8 +1,7 @@
|
||||
• refresh map colors - lighter, warmer, friendlier!
|
||||
• OSM editor: add a "level" field
|
||||
• update gas and charging stations icons
|
||||
• update colors of some UI elements
|
||||
• fix location sharing links
|
||||
• fix wrong displayed map size after download errors
|
||||
• fix small location arrow jumps in some cases
|
||||
• android 5&6 bugfixes
|
||||
• OpenStreetMap data as of June 22
|
||||
• a setting for automatic bookmarks and tracks backup
|
||||
• added 100m-step altitude isolines to all regions that had worse or no isolines
|
||||
• display vegetation and playground color fills earlier, add fills to camp sites and some amenities
|
||||
• paths & tracks appear on the map later by default - still appear earlier in the outdoor style
|
||||
• hide active custom button action from the hamburger menu, move there About & Help from the settings
|
||||
• update map transport icons
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
• colores del mapa renovados - más claros, cálidos y amigables!
|
||||
• editor OSM: campo "nivel" agregado
|
||||
• actualización de íconos de carga de combustible y electricidad
|
||||
• actualización de colores de algunos elementos de IU
|
||||
• corrección de links para compartir ubicación
|
||||
• corrección de tamaño incorrecto del mapa luego de errores de descarga
|
||||
• corrección de pequeños saltos de flechas de posición en algunos casos
|
||||
• corrección de bugs en Android 5 y 6
|
||||
• datos de OpenStreetMap a 22 de junio
|
||||
• añadido ajuste para la copia de seguridad automática de marcadores y trazas
|
||||
• añadidas isolíneas de 100 m a las regiones que tenían isolíneas peores o no tenían isolíneas
|
||||
• se muestra antes la vegetación y zonas de juego, añadidas áreas a campings y otros servicios
|
||||
• los senderos y pistas aparecen más tarde - siguen igual en estilo de outdoors
|
||||
• se oculta botón personalizado del menú y se mueve allí Acerca de y Ayuda desde los ajustes
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
Komunitateko doako eta iturburu irekiko aplikazioa OpenStreetMap datuetan oinarrituta eta gardentasuna, pribatutasuna eta irabazi asmorik gabeko konpromisoarekin indartua. Comaps Organic Maps-en fork edo aldaera bat da, eta hori, aldi berean, maps.me-ren forka da.
|
||||
|
||||
Irakurri proiektuaren zergatia eta haren norabidea <b> <i> codeberg.org/comaps </ i> </ b>.
|
||||
Sartu komunitatean eta lagundu maparik onena aplikatzen
|
||||
• Erabili aplikazioa eta horren berri eman
|
||||
• Eman feedbacka eta txostenetako gaiak
|
||||
• Eguneratu maparen datuak aplikazioan edo OpenStreetMap webgunean
|
||||
|
||||
‣ <b> Konexiorik gabe fokatuta </ b> Planifikatu eta nabigatu atzerrira bidaiatzea, telefono zerbitzu beharrik gabe, bilaketa-biderapenak urruneko ibilaldian eta abar. Aplikazio funtzio guztiak lineaz kanpo lan egiteko diseinatuta daude.
|
||||
‣ <b> Pribatutasuna errespetatzea </ b> errespetatzea: aplikazioa pribatutasunarekin diseinatuta dago, ez du pertsonak identifikatzen, ez du jarraipena egiten, eta ez du informazio pertsonala biltzen. Iragarkirik ez.
|
||||
‣ <b> Sinplea eta leundua </ b>: Ezinbestekoa da funtzionatzen duten ezaugarriak erabiltzeko.
|
||||
‣ <b> Zure bateria eta espazioa gordetzen ditu </ b>: ez du bateria xahutzen beste nabigazio aplikazioak bezala. Mapa trinkoak. Gorde espazio preziatua zure telefonoan.
|
||||
‣ <b> Librea eta komunitateak eraikitakoa: Jendeak aplikazioa eraikitzen lagundu zuen aplikazioa eraikitzen lagunduz OpenStreetMap, probatu eta funtzioei buruzko iritzia emanez eta garapen trebetasunak eta dirua lagunduz.
|
||||
‣ <b> Erabakiak eta finantza irekiak eta gardena, irabazi asmorik gabeko eta guztiz irekitako iturria. </ B>
|
||||
|
||||
<b> Ezaugarri nagusiak </ b>:
|
||||
• Deskargatu mapa zehatzak Google Maps-ekin eskuragarri ez dauden lekuekin
|
||||
• Mendiko modua nabarmendutako mendi ibilbideak, kanpinak, ur iturriak, gailurrak, sestra-lerroak, etab
|
||||
• Bideak eta bidegorriak
|
||||
• Jatetxe, gas geltokiak, hotelak, dendak, bisitak eta bestelako interesguneak
|
||||
• Bilatu izenaren edo helbide baten arabera edo interes-kategoriaren arabera
|
||||
• Oinez, txirrinduaz edo gidatzeko ahots-oharrekin nabigazioa
|
||||
• Markatu zure gogoko lekuak sakatze bakarrarekin
|
||||
• Lineaz kanpoko Wikipedia artikuluak
|
||||
• Metroaren garraio geruza eta jarraibideak
|
||||
• Arrastoen grabazioa
|
||||
• Laster-markak eta ibilbideak esportatu eta inportatu KML, KMZ, GPX formatuetan
|
||||
• Gauean erabiltzeko modu iluna
|
||||
• Hobetu mapako datuak guztiontzat oinarrizko editore integratua erabiliz
|
||||
|
||||
<b> Askatasuna hemen </ b> da
|
||||
Ezagutu zure bidaia, nabigatu munduan pribatutasunarekin eta komunitatez abangoardian!
|
||||
@@ -1 +1 @@
|
||||
CoMaps- Mendia, bizikleta, autoa. Dena offline eta pribatutasunearekin
|
||||
CoMaps- Mendia, bizikleta, autoa, dena offline
|
||||
|
||||
|
Before Width: | Height: | Size: 737 KiB |
|
After Width: | Height: | Size: 655 KiB |
|
Before Width: | Height: | Size: 765 KiB |
|
After Width: | Height: | Size: 532 KiB |
|
Before Width: | Height: | Size: 735 KiB |
|
After Width: | Height: | Size: 391 KiB |
|
Before Width: | Height: | Size: 594 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 254 KiB |
|
After Width: | Height: | Size: 263 KiB |
@@ -1,8 +1,6 @@
|
||||
• Mise à jour des couleurs de la carte, plus claires, plus chaudes et plus conviviales
|
||||
• Editeur OSM: ajout du champ "level"
|
||||
• Mise à jour des icônes des stations-service et bornes de recharge
|
||||
• Mise à jour des couleurs de certains éléments d'interface
|
||||
• Correction de lien de partage
|
||||
• Correction de la taille d'une carte suite à une erreur de téléchargement
|
||||
• Correction de saut de la localisation dans certaines situations
|
||||
• Corrections de bug sur Android 5&6
|
||||
• Données OpenStreetMap du 22 juin
|
||||
• Sauvegarde automatique des signets et traces GPS en local
|
||||
• Ajout des courbes d'altitude avec un précision de 100 mètres dans toutes les régions qui avaient peu de courbes ou aucune
|
||||
• Ajustements des styles notamment sur la végétation, les aires de jeu et les chemins
|
||||
• Masque l’action active du bouton personnalisé dans le menu hamburger
|
||||
• Correction de certains plantages et bugs
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
Aplicación de mapas gratuíta, de código aberto e xestionada pola comunidade, obtén os datos desde OpenStreetMap e co compromiso reforzado coa transparencia, privacidade e non ter o beneficio económico como obxectivo. CoMaps é unha bifurcación ou derivada de Organic Maps, que pola súa parte ven sendo unha bifurcación de Maps.ME.
|
||||
|
||||
Vai a <b><i>codeberg.org/comaps</i></b> e coñece as razóns da necesidade deste proxecto e as decisións tomadas.
|
||||
Únete alí á comunidade e axuda a que teñamos a mellor aplicación de mapas
|
||||
• Usa a aplicación e dille a outras persoas que o fas
|
||||
• Informa de fallos e publica túa experiencia
|
||||
• Actualiza os datos do mapa na aplicación ou no sitio web OpenStreetMap
|
||||
|
||||
‣ <b>Sen conexión de datos</b>: planea a viaxe e sigue a ruta sen precisar unha conexión á rede móbil, busca lugares relevantes nas andainas máis longas, etc. Todas as características da aplicación están deseñadas para funcionar sen precisar conexión de datos.
|
||||
‣ <b>Respecto pola privacidade</b>: a aplicación está deseñada coa privacidade en primeiro plano - non identifica ás persoas, non te segue, non recolle información sobre ti. Non ten publicidade.
|
||||
‣ <b>Simple e organizada</b>: características esenciais, fáciles de usar e que funcionan.
|
||||
‣ <b>Aforra batería e espazo</b>: non esgota a batería como outras aplicacións de navegación. Os mapas compactos aforran espazo na memoria do dispositivo.
|
||||
‣ <b>Gratuíta e feita pola comunidade</b>: persoas coma ti que axudan a crear a aplicación engadindo lugares en OpenStreetMap, probando novas características e dando a súa opinión, colaborando ao seu desenvolvemento con código ou financiamento.
|
||||
‣ <b>Proceso de toma de decisións Aberto e Transparente para os temas económicos, Sen ánimo de lucro e totalmente de Código Aberto</b>
|
||||
|
||||
<b>Características principais</b>:
|
||||
• Mapas detallados descargables con lugares que non están dispoñibles en Google Maps
|
||||
• Modo para actividades en exterior con camiños para andainas, lugares para acampar, fontes de auga, picos dos montes, curvas de nivel, etc
|
||||
• Rutas a pé e en bicicleta
|
||||
• Puntos de interese como restaurantes, gasoliñeiras, hoteis, tendas, miradores e moitos máis
|
||||
• Busca polo nome ou polo enderezo ou por categoría do punto de interese
|
||||
• Navegación con anuncios por voz para camiñar, ir en bicicleta ou conducir
|
||||
• Marca os lugares favoritos cun só toque
|
||||
• Artigos da Wikipedia sen conexión
|
||||
• Mapas do transporte por Metro
|
||||
• Gravación das rutas
|
||||
• Exportación e Importación de marcadores e rutas nos formatos KML, KMZ e GPX
|
||||
• Modo escuro para a noite
|
||||
• Contribúe a mellorar o mapa para todas as persoas usando o editor básico incluído
|
||||
|
||||
<b>Aquí es Libre</b>
|
||||
Atopa o teu camiño, navega polo mundo con privacidade e coa comunidade como prioridade!
|
||||
@@ -0,0 +1 @@
|
||||
Navegación doada - Descubre máis sobre o teu camiño - Creada pola comunidade
|
||||
1
android/app/src/fdroid/play/listings/gl-ES/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
CoMaps - Aplicación de mapas privada, sen conexión
|
||||
@@ -0,0 +1,32 @@
|
||||
Een door de community ontwikkelde, gratis en open source kaartenapp, gebaseerd op OpenStreetMap-gegevens, met een sterke focus op transparantie en privacy, en zonder winstoogmerk. CoMaps is een fork/spin-off van Organic Maps, welke is afgeleid van Maps.ME.
|
||||
|
||||
Meer informatie over de redenen voor het project en de richting ervan vindt u op <b><i>codeberg.org/comaps</i></b>.
|
||||
Sluit je aan bij de community en help mee aan de ontwikkeling van de beste kaartenapp:
|
||||
• Gebruik de app en deel je ervaringen met anderen
|
||||
• Geef feedback en meld eventuele problemen
|
||||
• Houd de kaarten up-to-date, zowel in de app als op de OpenStreetMap-website
|
||||
|
||||
‣ <b>Offline-georiënteerd</b>: Plan en navigeer je reis in het buitenland zonder internet, zoek waypoints tijdens een lange wandeling, enzovoort. Alle functies zijn ontworpen om offline te functioneren.
|
||||
‣ <b>Respect voor privacy</b>: De app is ontworpen met privacy in gedachten - geen gegevensverzameling en advertentievrij.
|
||||
‣ <b>Eenvoudig en verfijnd</b>: essentiële, gebruiksvriendelijke functies die gewoon werken.
|
||||
‣ <b>Bespaar je batterij en opslag</b>: De app verbruikt minder batterij dan andere navigatie-apps. Compacte kaarten besparen ruimte op je telefoon.
|
||||
‣ <b>Gratis en gebouwd door de community</b>: Mensen zoals jij helpen de app door plaatsen toe te voegen aan OpenStreetMap, functies te testen en feedback te geven, en hun programmervaardigheden bij te dragen of te doneren.
|
||||
‣ <b>Open en transparant besluitvormings- en financieel beleid, geen winstoogmerk en volledig open source.</b>
|
||||
|
||||
<b>Hoofdfuncties</b>:
|
||||
• Downloadbare gedetailleerde kaarten met plaatsen die niet beschikbaar zijn bij Google Maps
|
||||
• Buitenmodus met gemarkeerde wandelpaden, campings, waterbronnen, toppen, hoogtelijnen, enz.
|
||||
• Wandelpaden en fietspaden
|
||||
• Bezienswaardigheden zoals restaurants, tankstations, hotels, winkels en nog veel meer
|
||||
• Zoeken op naam of adres of op categorie
|
||||
• Navigatie met spraakmeldingen voor wandelen, fietsen of autorijden
|
||||
• Sla je favoriete plaatsen op met een enkele klik
|
||||
• Offline Wikipedia-artikelen
|
||||
• Metro laag en routebeschrijvingen
|
||||
• Trackregistratie
|
||||
• Exporteer en importeer bladwijzers en tracks in KML, KMZ, GPX-formaten
|
||||
• Een donkere modus voor gebruik 's nachts
|
||||
• Verbeter kaartgegevens voor iedereen met een eenvoudige ingebouwde editor
|
||||
|
||||
<b>Vrijheid is hier/b>
|
||||
Ontdek je reis, navigeer over de wereld met privacy en community voorop!
|
||||
@@ -0,0 +1 @@
|
||||
Eenvoudige kaartnavigatie - Ontdek meer van je reis - Gemaakt door de community
|
||||
@@ -1,8 +0,0 @@
|
||||
• Atualizadas as cores do mapa - mais claras, quentes e amigáveis!
|
||||
• Editor OSM: adicionado um campo de "andar"
|
||||
• Atualizados ícones de postos de gasolina e recarga
|
||||
• Atualizadas cores de alguns elementos da interface do usuário
|
||||
• Correção de links de compartilhamento de localização
|
||||
• Correção de erros de tamanho de mapa exibidos incorretamente após download
|
||||
• Correção de pequenos saltos na seta de localização em alguns casos
|
||||
• Correções de bugs do Android 5 e 6
|
||||
@@ -1,55 +1,32 @@
|
||||
Um aplicativo de mapas gratuito e de código aberto, liderado pela comunidade, baseado em dados do OpenStreetMap e reforçado pelo compromisso com a transparência, privacidade e sem fins lucrativos. O CoMaps é um fork/spin-off do Organic Maps, que por sua vez é um fork do Maps.ME.
|
||||
|
||||
Leia mais sobre os motivos do projeto e sua direção em <b><i>codeberg.org/comaps</i></b>.
|
||||
|
||||
Junte-se à comunidade e ajude a criar o melhor aplicativo de mapas.
|
||||
|
||||
• Use o aplicativo e divulgue-o.
|
||||
|
||||
• Envie feedback e relate problemas.
|
||||
|
||||
• Atualize os dados do mapa no aplicativo ou no site do OpenStreetMap.
|
||||
|
||||
‣ <b>Foco offline</b>: Planeje e navegue em sua viagem ao exterior sem a necessidade de sinal de celular, pesquise pontos de referência durante uma caminhada distante, etc. Todas as funções do aplicativo foram projetadas para funcionar offline.
|
||||
|
||||
‣ <b>Respeitando a privacidade</b>: O aplicativo foi projetado com a privacidade em mente - não identifica pessoas, não rastreia e não coleta informações pessoais. Sem anúncios.
|
||||
|
||||
‣ <b>Simples e sofisticado</b>: recursos essenciais e fáceis de usar que simplesmente funcionam.
|
||||
|
||||
‣ <b>Economiza bateria e espaço</b>: Não consome muita bateria como outros aplicativos de navegação. Mapas compactos economizam espaço precioso no seu celular.
|
||||
|
||||
‣ <b>Gratuito e desenvolvido pela comunidade</b>: Pessoas como você ajudaram a desenvolver o aplicativo adicionando lugares ao OpenStreetMap, testando e dando feedback sobre os recursos e contribuindo com suas habilidades de desenvolvimento e dinheiro.
|
||||
|
||||
‣ <b>Tomada de decisões e finanças abertas e transparentes, sem fins lucrativos e totalmente de código aberto.</b>
|
||||
|
||||
<b>Principais recursos</b>:
|
||||
|
||||
• Mapas detalhados para download com locais não disponíveis no Google Maps
|
||||
|
||||
• Modo ao ar livre com trilhas em destaque, acampamentos, fontes de água, picos, curvas de nível, etc.
|
||||
|
||||
• Trilhas para caminhada e ciclovias
|
||||
|
||||
• Pontos de interesse como restaurantes, postos de gasolina, hotéis, lojas, pontos turísticos e muito mais
|
||||
|
||||
• Pesquise por nome, endereço ou por categoria de ponto de interesse
|
||||
|
||||
• Navegação com anúncios de voz para caminhadas, ciclismo ou direção
|
||||
|
||||
• Marque seus lugares favoritos com um único toque
|
||||
|
||||
• Artigos offline da Wikipédia
|
||||
|
||||
• Camada e direções de transporte público do metrô
|
||||
|
||||
• Gravação de trilhas
|
||||
|
||||
• Exporte e importe favoritos e trilhas nos formatos KML, KMZ e GPX
|
||||
|
||||
• Um modo escuro para usar à noite
|
||||
|
||||
• Aprimore os dados do mapa para todos usando um editor básico integrado
|
||||
|
||||
<b>A Liberdade Chegou</b>
|
||||
|
||||
Descubra sua jornada, navegue pelo mundo com privacidade e comunidade em primeiro lugar!
|
||||
|
||||
@@ -1 +1 @@
|
||||
Navegação fácil nos mapas - Descobre mais sobre o teu percurso - Feito por todos
|
||||
Navegação fácil nos mapas - Descubra mais sobre o seu percurso - Feito por todos
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
Бесплатное и свободное картографическое приложение, основанное на данных OpenStreetMap и подкреплённое обязательствами по прозрачности, конфиденциальности и некоммерческой направленности. CoMaps — это ответвление от Organic Maps, которое, в свою очередь, является ответвлением от Maps.ME.
|
||||
|
||||
Подробнее о причинах проекта и его направлении читайте на <a href="https://codeberg.org/comaps">сайте</a>.
|
||||
|
||||
Подробнее о причинах проекта и его направлении читайте на сайте <b><i> codeberg.org/comaps </i><b>.
|
||||
Присоединяйтесь к сообществу и помогите создать лучшее приложение с картами
|
||||
• Используйте приложение и распространяйте информацию о нём
|
||||
• Оставляйте отзывы и сообщайте о проблемах
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
• обновлены цвета карты — теперь они светлее, теплее и дружелюбнее
|
||||
• редактор OSM: добавлено поле «этаж»
|
||||
• обновлены иконки заправок и зарядных станций
|
||||
• обновлены цвета некоторых элементов интерфейса
|
||||
• исправлена ссылка на карту при попытке поделиться местоположением
|
||||
• исправлено неверное отображение размера карты после ошибок загрузки
|
||||
• исправлены мелкие скачки стрелки местоположения в некоторых случаях
|
||||
• исправления ошибок для Android 5 и 6
|
||||
• карты OpenStreetMap от 22 июня
|
||||
• автоматическое резервное копирование меток и треков
|
||||
• линии высот с шагом 100м для всех регионов, где линии с этим шагом отсутствовали
|
||||
• цветная заливка растительности и игровых площадок отображается раньше, добавлена заливка для кемпингов и других объектов
|
||||
• тропы и грунтовки отображаются позже в стиле по умолчанию - используйте стиль «Активный отдых» для обзора троп
|
||||
• выбранная функция настраиваемой кнопки больше не дублируется в пунктах меню
|
||||
|
||||
@@ -1 +1 @@
|
||||
Простая навигация по карте — Откройте больше за ваше путешествие. От сообщества
|
||||
Простая навигация по карте — Откройте больше за ваше путешествие — От сообщества
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
Бесплатна апликација отвореног кода коју је обављала заједница и заснива се на ОпенСтреетМап-у подацима, усмерени транспарентност, приватност и непрофитни. ЦОМПАПС је Апликације за органске карте виљушка, које је пак форк мапс.ме.
|
||||
Бесплатна апликација отвореног кода коју је обављала заједница и заснива се на ОpenStreetMap-у подацима, усмерени транспарентност, приватност и непрофитни. CoMaps је Апликације за органске карте виљушка, које је пак форк Maps.ME.
|
||||
|
||||
Прочитајте о разлозима пројекта и његовог правца на <b><i>codeberg.org/comaps</i></b>
|
||||
Придружите се отвореној заједници и помозите да направимо најбољу апликацију за мапе
|
||||
• Користите апликацију и проширите глас о томе
|
||||
• Дајте повратне информације и пријавите проблеме
|
||||
• Ажурирајте податке на мапи у апликацији или на веб локацији OpenStreetMap
|
||||
‣<b>фокусирано на офлајн Вар </b>: Планирајте и управљајте путовањем у иностранству без потребе за мобилним услугама, тражите путне тачке док је на даљинском покрету, итд.
|
||||
|
||||
Све апликације су дизајниране за рад ван мреже.
|
||||
‣<b> Поштовање приватности </b>: Апликација је осмишљена задржавања у уму приватност - не идентификује људе, не прати или прикупља личне податке. Нема реклама.
|
||||
‣ <b> фокусирано на офлајн Вар </b>: Планирајте и управљајте путовањем у иностранству без потребе за мобилним услугама, тражите путне тачке док је на даљинском покрету, итд. Све апликације су дизајниране за рад ван мреже.
|
||||
‣ <b> Поштовање приватности </b>: Апликација је осмишљена задржавања у уму приватност - не идентификује људе, не прати или прикупља личне податке. Нема реклама.
|
||||
‣ <b> Једноставно и елегантно </b>: Апликација је тривијална за употребу и једноставно функционише.
|
||||
‣ <b> Чува вашу батерију и простор </b>: не конзумира батерију као остале навигационе апликације. Компактне картице сачувајте драгоцени простор на вашем телефону.
|
||||
‣ <b> Отворено и направио је заједницу </b>: Људи попут вас је помогли да додају апликацију додавањем локација на OpenStreetMap-у, тестирању и давање повратних информација о апликацији и доприносе вашим развојним вештинама и новцу.
|
||||
‣ <b> Отворено и транспарентно доношење одлука и употреба финансија, непрофитна и потпуно отворена извора. </ Б>
|
||||
‣ <b> Отворено и транспарентно доношење одлука и употреба финансија, непрофитна и потпуно отворена извора. </b>
|
||||
|
||||
<b> Главне карактеристике </b>:
|
||||
• Преузмите детаљне мапе са локацијама које нису доступне са Гоогле мапама
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
• освежене су боје мапе – светлије, топлије, пријатније!
|
||||
• у OSM едитору је додато поље „спрат“
|
||||
• ажуриране су иконице бензинских пумпи и станица за пуњење
|
||||
• ажуриране су боје неких елемената корисничког интерфејса
|
||||
• поправљени су линкови за дељење локације
|
||||
• поправљена је погрешно приказана величина мапе након грешака при преузимању
|
||||
• исправљена су мала поскакивања стрелице локације у неким случајевима
|
||||
• исправљене су грешке за Android 5 и 6
|
||||
@@ -1 +1 @@
|
||||
Kolayca gezinin - Seyahat etmenin ötesini bulun - Gönüllüler tarafından yapıldı
|
||||
Kullanımı kolay harita - Yolculuğun ötesine geçin - topluluğun katkılarıyla
|
||||
|
||||
@@ -1 +1 @@
|
||||
CoMaps - İnternetsiz Seyahat Edin
|
||||
CoMaps - Gizlilikle Yürüyün, Sürün, Gezin
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
• 刷新地图颜色-更浅、更暖、更友好!
|
||||
• OSM 编辑器:添加“楼层”字段
|
||||
• 更新加油站和充电站图标
|
||||
• 更新部分用户界面组件的颜色
|
||||
• 修复位置共享的链接
|
||||
• 修复下载后错误显示地图大小的问题
|
||||
• 修复定位箭头偶尔轻微跳动的问题
|
||||
• Android 5&6 错误修复
|
||||
@@ -1,8 +0,0 @@
|
||||
• 刷新地圖顏色-更淺、更暖、更友好!
|
||||
• OSM 編輯器:新增「樓層」欄位
|
||||
• 更新加油站和充電站圖示
|
||||
• 更新某些使用者介面元件的顏色
|
||||
• 修正位置分享的連結
|
||||
• 修正下載後錯誤顯示地圖尺寸的問題
|
||||
• 修正定位箭頭偶爾輕微跳動的問題
|
||||
• Android 5&6 錯誤修正
|
||||
@@ -1 +1 @@
|
||||
Jednoduchá navigace v mapě - Objevte více na své cestě ‐ Vyvíjeno komunitou
|
||||
Jednoduchá navigace v mapě – Objevte více na své cestě – Vyvíjeno komunitou
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Mapa nabigazio erraza - Ezagutu gehiago zure bidaiaz - Komunitatean egina
|
||||
@@ -0,0 +1,35 @@
|
||||
Aplicación de mapas gratuíta, de código aberto e xestionada pola comunidade, obtén os datos desde OpenStreetMap e co compromiso reforzado coa transparencia, privacidade e non ter o beneficio económico como obxectivo.
|
||||
|
||||
Únete á comunidade e axuda a que teñamos a mellor aplicación de mapas
|
||||
• Usa a aplicación e dille a outras persoas que o fas
|
||||
• Informa de fallos e publica túa experiencia
|
||||
• Actualiza os datos do mapa na aplicación ou no sitio web OpenStreetMap
|
||||
|
||||
<i>Os teus comentarios e recensións de 5 estrelas son a mellor axuda para nós!
|
||||
|
||||
‣ <b>Sen conexión de datos</b>: planea a viaxe e sigue a ruta sen precisar unha conexión á rede móbil, busca lugares relevantes nas andainas máis longas, etc. Todas as características da aplicación están deseñadas para funcionar sen precisar conexión de datos.
|
||||
‣ <b>Respecto pola privacidade</b>: a aplicación está deseñada coa privacidade en primeiro plano - non identifica ás persoas, non te segue, non recolle información sobre ti. Non ten publicidade.
|
||||
‣ <b>Simple e organizada</b>: características esenciais, fáciles de usar e que funcionan.
|
||||
‣ <b>Aforra batería e espazo</b>: non esgota a batería como outras aplicacións de navegación. Os mapas compactos aforran espazo na memoria do dispositivo.
|
||||
‣ <b>Gratuíta e feita pola comunidade</b>: persoas coma ti que axudan a crear a aplicación engadindo lugares en OpenStreetMap, probando novas características e dando a súa opinión, colaborando ao seu desenvolvemento con código ou financiamento.
|
||||
‣ <b>Proceso de toma de decisións Aberto e Transparente para os temas económicos, Sen ánimo de lucro e totalmente de Código Aberto</b>
|
||||
|
||||
<b>Características principais</b>:
|
||||
• Mapas detallados descargables con lugares que non están dispoñibles en Google Maps
|
||||
• Modo para actividades en exterior con camiños para andainas, lugares para acampar, fontes de auga, picos dos montes, curvas de nivel, etc
|
||||
• Rutas a pé e en bicicleta
|
||||
• Puntos de interese como restaurantes, gasoliñeiras, hoteis, tendas, miradores e moitos máis
|
||||
• Busca polo nome ou polo enderezo ou por categoría do punto de interese
|
||||
• Navegación con anuncios por voz para camiñar, ir en bicicleta ou conducir
|
||||
• Marca os lugares favoritos cun só toque
|
||||
• Artigos da Wikipedia sen conexión
|
||||
• Mapas do transporte por Metro
|
||||
• Gravación das rutas
|
||||
• Exportación e Importación de marcadores e rutas nos formatos KML, KMZ e GPX
|
||||
• Modo escuro para a noite
|
||||
• Contribúe a mellorar o mapa para todas as persoas usando o editor básico incluído
|
||||
|
||||
Por favor informa de calquera incidencia que xurda así como suxire novas funcións na nosa comunidade en <b><i>comaps.app</i></b>
|
||||
|
||||
<b>Aquí es Libre</b>
|
||||
Atopa o teu camiño, navega polo mundo con privacidade e coa comunidade como prioridade!
|
||||
@@ -0,0 +1 @@
|
||||
Navegación doada - Descubre máis sobre o teu camiño - Creada pola comunidade
|
||||
1
android/app/src/google/play/listings/gl-ES/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
CoMaps -Navega con Privacidade
|
||||
@@ -0,0 +1,36 @@
|
||||
Een door de community ontwikkelde, gratis en open source kaartenapp, gebaseerd op OpenStreetMap-gegevens, met een sterke focus op transparantie en privacy, en zonder winstoogmerk.
|
||||
|
||||
Sluit je aan bij de community en help mee aan de ontwikkeling van de beste kaartenapp:
|
||||
• Gebruik de app en deel je ervaringen met anderen
|
||||
• Geef feedback en meld eventuele problemen
|
||||
• Houd de kaarten up-to-date, zowel in de app als op de OpenStreetMap-website
|
||||
|
||||
<i>Jouw feedback en 5-sterrenbeoordelingen zijn de beste steun voor ons!!</i>
|
||||
|
||||
‣ <b>Eenvoudig en verfijnd</b>: essentiële, gebruiksvriendelijke functies die gewoon werken.
|
||||
‣ <b>Offline-georiënteerd</b>: Plan en navigeer je reis in het buitenland zonder internet, zoek waypoints tijdens een lange wandeling, enzovoort. Alle functies zijn ontworpen om offline te functioneren.
|
||||
‣ <b>Respect voor privacy</b>: De app is ontworpen met privacy in gedachten - geen gegevensverzameling en advertentievrij.
|
||||
‣ <b>Bespaar je batterij en opslag</b>: De app verbruikt minder batterij dan andere navigatie-apps. Compacte kaarten besparen ruimte op je telefoon.
|
||||
‣ <b>Gratis en gebouwd door de community</b>: Mensen zoals jij helpen de app door plaatsen toe te voegen aan OpenStreetMap, functies te testen en feedback te geven, en hun programmervaardigheden bij te dragen of te doneren.
|
||||
‣ <b>Open en transparant besluitvormings- en financieel beleid, geen winstoogmerk en volledig open source.</b>
|
||||
|
||||
<b>Hoofdfuncties</b>:
|
||||
• Downloadbare gedetailleerde kaarten met plaatsen die niet beschikbaar zijn bij Google Maps
|
||||
• Buitenmodus met gemarkeerde wandelpaden, campings, waterbronnen, toppen, hoogtelijnen, enz.
|
||||
• Wandelpaden en fietspaden
|
||||
• Bezienswaardigheden zoals restaurants, tankstations, hotels, winkels en nog veel meer
|
||||
• Zoeken op naam of adres of op categorie
|
||||
• Navigatie met spraakmeldingen voor wandelen, fietsen of autorijden
|
||||
• Sla je favoriete plaatsen op met een enkele klik
|
||||
• Offline Wikipedia-artikelen
|
||||
• Metro laag en routebeschrijvingen
|
||||
• Trackregistratie
|
||||
• Exporteer en importeer bladwijzers en tracks in KML, KMZ, GPX-formaten
|
||||
• Een donkere modus voor gebruik 's nachts
|
||||
• Verbeter kaartgegevens voor iedereen met een eenvoudige ingebouwde editor
|
||||
• Ondersteuning voor Android Auto
|
||||
|
||||
Meld app-problemen, stel nieuwe functies voor en sluit je aan bij onze community op de <b><i>comaps.app</i></b> website.
|
||||
|
||||
<b>Vrijheid is hier/b>
|
||||
Ontdek je reis, navigeer over de wereld met privacy en community voorop!
|
||||
@@ -0,0 +1 @@
|
||||
Navegação fácil nos mapas - Descubra mais sobre o seu percurso - Feito por todos
|
||||
1
android/app/src/google/play/listings/pt-PT/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
CoMaps - Viaje com Privacidade
|
||||
@@ -1 +1 @@
|
||||
Простая навигация по карте — Откройте больше за ваше путешествие. От сообщества
|
||||
Простая навигация по карте — Откройте больше за ваше путешествие — От сообщества
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
OpenStreetMap verilerine dayanan, kâr amacı gütmeyen, gizlilik ve şeffaflık odaklı, topluluk tarafından yönetilen, özgür ve açık kaynak kodlu bir harita uygulaması.
|
||||
|
||||
Topluluğa katılın ve en iyi harita uygulamasını oluşturmamıza yardım edin
|
||||
• Uygulamayı kullanın ve çevrenize yayın
|
||||
• Geri bildirim verin ve sorunları bildirin
|
||||
• Harita verilerini uygulamadan veya OpenStreetMap üzerinden düzenleyin
|
||||
|
||||
<i>Geri bildirimleriniz ve 5 yıldızlı yorumlarınız bizim için en iyi destektir!</i>
|
||||
|
||||
‣ <b>Basit ve Temiz</b>: Sadece temel, kullanımı basit, işe yarayan özellikler.
|
||||
‣ <b>Çevrimdışı Odaklı</b>: Mobil veriye ihtiyaç duymadan yurt dışı seyahatinizi planlayın ve gezin, uzun bir yürüyüş sırasında rotanızdaki noktaları bulun ve daha fazlası . Tüm özellikler çevrimdışı çalışmak üzere tasarlanmıştır.
|
||||
‣ <b>Gizliliğe Saygılı</b>: Uygulama gizliliğe saygılı olarak tasarlanmıştır. Kullanıcı profilinizi çıkarmaz, sizi takip etmez ve kişisel bilgi toplamaz. Üstelik tamamen reklamsızdır.
|
||||
‣ <b>Pil ve Depolamanızdan Tasarruf Eder</b>: Diğer navigasyon uygulamaları gibi pilinizi sömürmez. Compact maps değerli depolama alanınızdan tasarruf eder.
|
||||
‣ <b>Ücretsizdir ve Gücünü Topluluktan Alır</b>: Sizin gibi insanlar OpenStreetMap'e yer ekleyerek, yeni özellikleri test ederek, geri bildirimde bulunarak, program geliştirme becerileri ve bağışlarla katkıda bulunarak uygulamanın oluşturulmasına yardımcı oldu.
|
||||
‣ <b>Açık ve Şeffaf Şekilde Yürütülen Karar Alma ve Fonlama Süreçleri, Kâr Amacı Gütmez ve Tamamen Açık Kaynaklı.</b>
|
||||
|
||||
<b>Ana Özellikler</b>:
|
||||
• Google Haritalar'da bulunmayan yerleri içeren, çevrimdışı detaylı haritalar
|
||||
• Yürüyüş parkurları, kamp alanları, su kaynakları, zirveler, kontur çizgileri vb. nesneleri vurgulayan açık hava modu
|
||||
• Yürüyüş ve bisiklet yolları
|
||||
• Restoran, benzin istasyonu, otel, mağaza, görülecek yerler ve çok daha fazla harita noktası
|
||||
• İsim, adres veya harita noktası kategorisine göre arama yapın
|
||||
• Sesli yönlendirmeye sahip yürüyüş, bisiklet ve araç navigasyonu
|
||||
• En sevdiğiniz mekanları tek dokunuşla yer imlerinize kaydedin
|
||||
• Çevrimdışı Vikipedi makaleleri
|
||||
• Metro ulaşım katmanı ve rotaları
|
||||
• GPS izinizi kaydedin
|
||||
• Yer imi ve GPS izlerinizi KML, KMZ ve GPX biçimlerinde dışa veya içe aktarın
|
||||
• Gece boyunca kullanmanızı sağlayacak koyu mod
|
||||
• Uygulama içi düzenleyiciyi kullanarak harita verilerini herkes için daha iyi hale getirin
|
||||
• Android Auto desteği
|
||||
|
||||
Lütfen <b><i>comaps.app</i></b> adresinden uygulama sorunlarını bildirin, önerilerinizi paylaşın ve topluluğumuza katılın.
|
||||
|
||||
<b>Özgürlük Buradan Başlıyor</b>
|
||||
Yolculuğunuzun ötesine geçin, gizlilik ve topluluğu ön planda tutarak dünyada gezinin!
|
||||
@@ -1 +1 @@
|
||||
Kolayca gezinin - Seyahat etmenin ötesini bulun - Gönüllüler tarafından yapıldı
|
||||
Kullanımı kolay harita - Yolculuğun ötesine geçin - topluluğun katkılarıyla
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
<uses-feature
|
||||
android:name="android.hardware.location.gps"
|
||||
android:required="false"/>
|
||||
<uses-permission
|
||||
android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="22" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
|
||||
|
||||
@@ -171,7 +171,7 @@ extern "C"
|
||||
curFile.GetRemoteSize(),
|
||||
std::bind(&DownloadFileFinished, ptr, _1),
|
||||
std::bind(&DownloadFileProgress, ptr, _1),
|
||||
512 * 1024, false));
|
||||
0, false));
|
||||
});
|
||||
|
||||
return ERR_FILE_IN_PROGRESS;
|
||||
|
||||
@@ -1804,74 +1804,4 @@ Java_app_organicmaps_Framework_nativeMemoryWarning(JNIEnv *, jclass)
|
||||
return frm()->MemoryWarning();
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_app_organicmaps_Framework_nativeShouldShowProducts(JNIEnv * env, jclass)
|
||||
{
|
||||
return frm()->ShouldShowProducts();
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_app_organicmaps_Framework_nativeGetProductsConfiguration(JNIEnv * env, jclass)
|
||||
{
|
||||
auto config = frm()->GetProductsConfiguration();
|
||||
if (!config) return nullptr;
|
||||
|
||||
static jclass const productClass = jni::GetGlobalClassRef(
|
||||
env,
|
||||
"app/organicmaps/products/Product"
|
||||
);
|
||||
static jmethodID const productConstructor = jni::GetConstructorID(
|
||||
env,
|
||||
productClass,
|
||||
"(Ljava/lang/String;Ljava/lang/String;)V"
|
||||
);
|
||||
|
||||
jobjectArray products = jni::ToJavaArray(
|
||||
env,
|
||||
productClass,
|
||||
config->GetProducts(),
|
||||
[](JNIEnv * env, products::ProductsConfig::Product const & product)
|
||||
{
|
||||
jni::TScopedLocalRef const title(env, jni::ToJavaString(env, product.GetTitle()));
|
||||
jni::TScopedLocalRef const link(env, jni::ToJavaString(env, product.GetLink()));
|
||||
|
||||
return env->NewObject(
|
||||
productClass,
|
||||
productConstructor,
|
||||
title.get(),
|
||||
link.get()
|
||||
);
|
||||
});
|
||||
|
||||
static jclass const productsConfigClass = jni::GetGlobalClassRef(
|
||||
env,
|
||||
"app/organicmaps/products/ProductsConfig"
|
||||
);
|
||||
static jmethodID const productsConfigConstructor = jni::GetConstructorID(
|
||||
env,
|
||||
productsConfigClass,
|
||||
"(Ljava/lang/String;[Lapp/organicmaps/products/Product;)V"
|
||||
);
|
||||
|
||||
jni::TScopedLocalRef const placePagePrompt(env, jni::ToJavaString(env, config->GetPlacePagePrompt()));
|
||||
return env->NewObject(productsConfigClass, productsConfigConstructor, placePagePrompt.get(), products);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_app_organicmaps_Framework_nativeDidCloseProductsPopup(JNIEnv * env, jclass, jstring reason)
|
||||
{
|
||||
frm()->DidCloseProductsPopup(frm()->FromString(jni::ToNativeString(env, reason)));
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_app_organicmaps_Framework_nativeDidSelectProduct(JNIEnv * env, jclass, jstring title, jstring link)
|
||||
{
|
||||
products::ProductsConfig::Product product(
|
||||
jni::ToNativeString(env, title),
|
||||
jni::ToNativeString(env, link)
|
||||
);
|
||||
|
||||
frm()->DidSelectProduct(product);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -321,4 +321,30 @@ Java_app_organicmaps_editor_OpeningHours_nativeIsTimetableStringValid(JNIEnv * e
|
||||
{
|
||||
return OpeningHours(jni::ToNativeString(env, jSource)).IsValid();
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_app_organicmaps_editor_OpeningHours_nativeCurrentState(JNIEnv * env, jclass clazz, jobjectArray jTts)
|
||||
{
|
||||
TimeTableSet tts = NativeTimetableSet(env, jTts);
|
||||
time_t const now = time(nullptr);
|
||||
|
||||
/// @todo We should check closed/open time for specific feature's timezone.
|
||||
OpeningHours::InfoT ohInfo = MakeOpeningHours(tts).GetInfo(now);
|
||||
jclass ohStateClass = jni::GetGlobalClassRef(env, "app/organicmaps/editor/OhState");
|
||||
jclass ruleStateClass = jni::GetGlobalClassRef(env, "app/organicmaps/editor/OhState$State");
|
||||
|
||||
static const std::unordered_map<RuleState, const char*> ruleState = {
|
||||
{RuleState::Open, "Open"},
|
||||
{RuleState::Closed, "Closed"},
|
||||
{RuleState::Unknown, "Unknown"}
|
||||
};
|
||||
|
||||
jfieldID stateField = env->GetStaticFieldID(ruleStateClass, ruleState.at(ohInfo.state), "Lapp/organicmaps/editor/OhState$State;");
|
||||
jobject stateObj = env->GetStaticObjectField(ruleStateClass, stateField);
|
||||
jmethodID constructor = env->GetMethodID(ohStateClass, "<init>", "(Lapp/organicmaps/editor/OhState$State;JJ)V");
|
||||
jobject javaOhState = env->NewObject(ohStateClass, constructor, stateObj, (jlong) ohInfo.nextTimeOpen, (jlong) ohInfo.nextTimeClosed);
|
||||
|
||||
return javaOhState;
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
@@ -17,17 +17,9 @@ using namespace jni;
|
||||
|
||||
bool LoadOsmUserPreferences(std::string const & oauthToken, UserPreferences & outPrefs)
|
||||
{
|
||||
try
|
||||
{
|
||||
ServerApi06 const api(OsmOAuth::ServerAuth(oauthToken));
|
||||
outPrefs = api.GetUserPreferences();
|
||||
return true;
|
||||
}
|
||||
catch (std::exception const & ex)
|
||||
{
|
||||
LOG(LWARNING, ("Can't load user preferences from server: ", ex.what()));
|
||||
}
|
||||
return false;
|
||||
ServerApi06 const api(OsmOAuth::ServerAuth(oauthToken));
|
||||
outPrefs = api.GetUserPreferences();
|
||||
return (outPrefs.m_id != 0);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ import app.organicmaps.api.RequestType;
|
||||
import app.organicmaps.bookmarks.data.DistanceAndAzimut;
|
||||
import app.organicmaps.bookmarks.data.FeatureId;
|
||||
import app.organicmaps.bookmarks.data.MapObject;
|
||||
import app.organicmaps.products.ProductsConfig;
|
||||
import app.organicmaps.sdk.routing.JunctionInfo;
|
||||
import app.organicmaps.sdk.routing.RouteMarkData;
|
||||
import app.organicmaps.sdk.routing.RouteMarkType;
|
||||
@@ -347,15 +346,5 @@ public class Framework
|
||||
public static native boolean nativeHasPlacePageInfo();
|
||||
|
||||
public static native void nativeMemoryWarning();
|
||||
|
||||
public static native boolean nativeShouldShowProducts();
|
||||
|
||||
@Nullable
|
||||
public static native ProductsConfig nativeGetProductsConfiguration();
|
||||
|
||||
public static native void nativeDidCloseProductsPopup(String reason);
|
||||
|
||||
public static native void nativeDidSelectProduct(String title, String link);
|
||||
|
||||
public static native void nativeSaveRoute();
|
||||
}
|
||||
|
||||
@@ -41,9 +41,9 @@ public class MapFragment extends BaseMwmFragment implements View.OnTouchListener
|
||||
mMap.updateMyPositionRoutingOffset(offsetY);
|
||||
}
|
||||
|
||||
public void destroySurface()
|
||||
public void destroySurface(boolean activityIsChangingConfigurations)
|
||||
{
|
||||
mMap.onSurfaceDestroyed(requireActivity().isChangingConfigurations(), isAdded());
|
||||
mMap.onSurfaceDestroyed(activityIsChangingConfigurations, isAdded());
|
||||
}
|
||||
|
||||
public boolean isContextCreated()
|
||||
|
||||
@@ -44,6 +44,7 @@ import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import app.organicmaps.api.Const;
|
||||
import app.organicmaps.backup.PeriodicBackupRunner;
|
||||
import app.organicmaps.base.BaseMwmFragmentActivity;
|
||||
import app.organicmaps.base.OnBackPressListener;
|
||||
import app.organicmaps.bookmarks.BookmarkCategoriesActivity;
|
||||
@@ -139,6 +140,7 @@ 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.util.PowerManagment.POWER_MANAGEMENT_TAG;
|
||||
import static app.organicmaps.util.concurrency.UiThread.runLater;
|
||||
|
||||
public class MwmActivity extends BaseMwmFragmentActivity
|
||||
implements PlacePageActivationListener,
|
||||
@@ -253,6 +255,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
@NonNull
|
||||
private DisplayManager mDisplayManager;
|
||||
|
||||
private PeriodicBackupRunner backupRunner;
|
||||
|
||||
ManageRouteBottomSheet mManageRouteBottomSheet;
|
||||
|
||||
private boolean mRemoveDisplayListener = true;
|
||||
@@ -607,6 +611,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
*/
|
||||
if (Map.isEngineCreated())
|
||||
onRenderingInitializationFinished();
|
||||
|
||||
backupRunner = new PeriodicBackupRunner(this);
|
||||
}
|
||||
|
||||
private void onSettingsResult(ActivityResult activityResult)
|
||||
@@ -838,7 +844,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
@Override
|
||||
public String getPrefsName()
|
||||
{
|
||||
return getString(R.string.help);
|
||||
return getString(R.string.about_help);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1297,7 +1303,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
{
|
||||
// Explicitly destroy surface before activity recreation.
|
||||
if (mMapFragment != null)
|
||||
mMapFragment.destroySurface();
|
||||
mMapFragment.destroySurface(true);
|
||||
super.recreate();
|
||||
}
|
||||
|
||||
@@ -1352,6 +1358,11 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
final String backUrl = Framework.nativeGetParsedBackUrl();
|
||||
if (!TextUtils.isEmpty(backUrl))
|
||||
Utils.openUri(this, Uri.parse(backUrl), null);
|
||||
|
||||
if (backupRunner != null && !backupRunner.isAlreadyChecked() && backupRunner.isTimeToBackup())
|
||||
{
|
||||
backupRunner.doBackup();
|
||||
}
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
@@ -2584,20 +2595,28 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
{
|
||||
if (id.equals(MAIN_MENU_ID))
|
||||
{
|
||||
final String activeLeftButton = buttonsHolder.getActiveButtonCode();
|
||||
ArrayList<MenuBottomSheetItem> items = new ArrayList<>();
|
||||
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
|
||||
));
|
||||
mDonatesUrl = Config.getDonateUrl(getApplicationContext());
|
||||
if (!TextUtils.isEmpty(mDonatesUrl))
|
||||
|
||||
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.download_maps, R.drawable.ic_download, getDownloadMapsCounter(), this::onDownloadMapsOptionSelected));
|
||||
|
||||
if (!Config.getDonateUrl(getApplicationContext()).isEmpty())
|
||||
items.add(new MenuBottomSheetItem(R.string.donate, R.drawable.ic_donate, this::onDonateOptionSelected));
|
||||
items.add(new MenuBottomSheetItem(R.string.settings, R.drawable.ic_settings, this::onSettingsOptionSelected));
|
||||
items.add(new MenuBottomSheetItem(R.string.start_track_recording, R.drawable.ic_track_recording_off, -1, this::onTrackRecordingOptionSelected));
|
||||
|
||||
if (!BUTTON_SETTINGS_CODE.equals(activeLeftButton))
|
||||
items.add(new MenuBottomSheetItem(R.string.settings, R.drawable.ic_settings, this::onSettingsOptionSelected));
|
||||
|
||||
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.share_my_location, R.drawable.ic_share, this::onShareLocationOptionSelected));
|
||||
|
||||
if (!BUTTON_HELP_CODE.equals(activeLeftButton))
|
||||
items.add(new MenuBottomSheetItem(R.string.about_help, R.drawable.ic_question_mark, this::showHelp));
|
||||
|
||||
return items;
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -8,6 +8,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
@@ -16,6 +17,10 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.OnApplyWindowInsetsListener;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
|
||||
import app.organicmaps.display.DisplayManager;
|
||||
import app.organicmaps.downloader.DownloaderActivity;
|
||||
@@ -69,6 +74,17 @@ public class SplashActivity extends AppCompatActivity
|
||||
|
||||
UiThread.cancelDelayedTasks(mInitCoreDelayedTask);
|
||||
setContentView(R.layout.activity_splash);
|
||||
|
||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.root_view), new OnApplyWindowInsetsListener() {
|
||||
@NonNull
|
||||
@Override
|
||||
public WindowInsetsCompat onApplyWindowInsets(@NonNull View v, @NonNull WindowInsetsCompat insets)
|
||||
{
|
||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||
v.setPadding(0, 0, 0, systemBars.bottom);
|
||||
return insets;
|
||||
}
|
||||
});
|
||||
mPermissionRequest = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(),
|
||||
result -> Config.setLocationRequested());
|
||||
mApiRequest = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
package app.organicmaps.backup;
|
||||
|
||||
import static app.organicmaps.settings.BackupSettingsFragment.MAX_BACKUPS_DEFAULT_COUNT;
|
||||
import static app.organicmaps.settings.BackupSettingsFragment.MAX_BACKUPS_KEY;
|
||||
import static app.organicmaps.util.StorageUtils.isFolderWritable;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.provider.DocumentsContract;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.AbsoluteSizeSpan;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.documentfile.provider.DocumentFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.util.UiUtils;
|
||||
import app.organicmaps.util.log.Logger;
|
||||
|
||||
public class BackupUtils
|
||||
{
|
||||
private static final String BACKUP_PREFIX = "backup_";
|
||||
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 String TAG = BackupUtils.class.getSimpleName();
|
||||
|
||||
public static CharSequence formatReadableFolderPath(Context context, @NonNull Uri uri)
|
||||
{
|
||||
String docId = DocumentsContract.getTreeDocumentId(uri);
|
||||
String volumeId;
|
||||
String subPath = "";
|
||||
|
||||
int colonIndex = docId.indexOf(':');
|
||||
if (colonIndex >= 0)
|
||||
{
|
||||
volumeId = docId.substring(0, colonIndex);
|
||||
subPath = docId.substring(colonIndex + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
volumeId = docId;
|
||||
}
|
||||
|
||||
String volumeName;
|
||||
if ("primary".equalsIgnoreCase(volumeId))
|
||||
volumeName = context.getString(R.string.maps_storage_shared);
|
||||
else
|
||||
volumeName = context.getString(R.string.maps_storage_removable);
|
||||
|
||||
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("/" + subPath, new AbsoluteSizeSpan(UiUtils.dimen(context, R.dimen.text_size_body_4)), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
return sb;
|
||||
}
|
||||
|
||||
public static int getMaxBackups(SharedPreferences prefs)
|
||||
{
|
||||
String rawValue = prefs.getString(MAX_BACKUPS_KEY, String.valueOf(MAX_BACKUPS_DEFAULT_COUNT));
|
||||
try
|
||||
{
|
||||
return Integer.parseInt(rawValue);
|
||||
} catch (NumberFormatException e)
|
||||
{
|
||||
Logger.e(TAG, "Failed to parse max backups count, raw value: " + rawValue + " set to default: " + MAX_BACKUPS_DEFAULT_COUNT, e);
|
||||
prefs.edit()
|
||||
.putString(MAX_BACKUPS_KEY, String.valueOf(MAX_BACKUPS_DEFAULT_COUNT))
|
||||
.apply();
|
||||
return MAX_BACKUPS_DEFAULT_COUNT;
|
||||
}
|
||||
}
|
||||
|
||||
public static DocumentFile createUniqueBackupFolder(@NonNull DocumentFile parentDir, LocalDateTime backupTime)
|
||||
{
|
||||
String folderName = BACKUP_PREFIX + backupTime.format(DATE_FORMATTER);
|
||||
return parentDir.createDirectory(folderName);
|
||||
}
|
||||
|
||||
public static String getBackupName(LocalDateTime backupTime)
|
||||
{
|
||||
String formattedBackupTime = backupTime.format(DATE_FORMATTER);
|
||||
return BACKUP_PREFIX + formattedBackupTime + BACKUP_EXTENSION;
|
||||
}
|
||||
|
||||
public static DocumentFile[] getBackupFolders(DocumentFile parentDir)
|
||||
{
|
||||
List<DocumentFile> backupFolders = new ArrayList<>();
|
||||
for (DocumentFile file : parentDir.listFiles())
|
||||
{
|
||||
if (file.isDirectory() && file.getName() != null && file.getName().startsWith(BACKUP_PREFIX))
|
||||
backupFolders.add(file);
|
||||
}
|
||||
return backupFolders.toArray(new DocumentFile[0]);
|
||||
}
|
||||
|
||||
public static boolean isBackupFolderAvailable(Context context, String storedFolderPath)
|
||||
{
|
||||
return !TextUtils.isEmpty(storedFolderPath) && isFolderWritable(context, storedFolderPath);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
package app.organicmaps.backup;
|
||||
|
||||
import static app.organicmaps.backup.BackupUtils.getBackupName;
|
||||
import static app.organicmaps.backup.BackupUtils.getBackupFolders;
|
||||
import static app.organicmaps.util.StorageUtils.copyFileToDocumentFile;
|
||||
import static app.organicmaps.util.StorageUtils.deleteDirectoryRecursive;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
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.bookmarks.data.BookmarkCategory;
|
||||
import app.organicmaps.bookmarks.data.BookmarkManager;
|
||||
import app.organicmaps.bookmarks.data.BookmarkSharingResult;
|
||||
import app.organicmaps.bookmarks.data.KmlFileType;
|
||||
import app.organicmaps.util.concurrency.ThreadPool;
|
||||
import app.organicmaps.util.concurrency.UiThread;
|
||||
import app.organicmaps.util.log.Logger;
|
||||
|
||||
public class LocalBackupManager implements BookmarkManager.BookmarksSharingListener
|
||||
{
|
||||
public static final String TAG = LocalBackupManager.class.getSimpleName();
|
||||
|
||||
private final Activity activity;
|
||||
private final String backupFolderPath;
|
||||
private final int maxBackups;
|
||||
private Listener listener;
|
||||
|
||||
public LocalBackupManager(@NonNull Activity activity, @NonNull String backupFolderPath, int maxBackups)
|
||||
{
|
||||
this.activity = activity;
|
||||
this.backupFolderPath = backupFolderPath;
|
||||
this.maxBackups = maxBackups;
|
||||
}
|
||||
|
||||
public void doBackup()
|
||||
{
|
||||
BookmarkManager.INSTANCE.addSharingListener(this);
|
||||
|
||||
prepareBookmarkCategoriesForSharing();
|
||||
|
||||
if (listener != null)
|
||||
listener.onBackupStarted();
|
||||
}
|
||||
|
||||
public void setListener(@NonNull Listener listener)
|
||||
{
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreparedFileForSharing(@NonNull BookmarkSharingResult result)
|
||||
{
|
||||
BookmarkManager.INSTANCE.removeSharingListener(this);
|
||||
|
||||
ThreadPool.getWorker().execute(() -> {
|
||||
ErrorCode errorCode = null;
|
||||
switch (result.getCode())
|
||||
{
|
||||
case BookmarkSharingResult.SUCCESS ->
|
||||
{
|
||||
if (!saveBackup(result))
|
||||
{
|
||||
Logger.e(TAG, "Failed to save backup. See system log above");
|
||||
errorCode = ErrorCode.FILE_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.i(TAG, "Backup was created and saved successfully");
|
||||
}
|
||||
}
|
||||
case BookmarkSharingResult.EMPTY_CATEGORY ->
|
||||
{
|
||||
errorCode = ErrorCode.EMPTY_CATEGORY;
|
||||
Logger.e(TAG, "Failed to create backup. Category is empty");
|
||||
}
|
||||
case BookmarkSharingResult.ARCHIVE_ERROR ->
|
||||
{
|
||||
errorCode = ErrorCode.ARCHIVE_ERROR;
|
||||
Logger.e(TAG, "Failed to create archive of bookmarks");
|
||||
}
|
||||
case BookmarkSharingResult.FILE_ERROR ->
|
||||
{
|
||||
errorCode = ErrorCode.FILE_ERROR;
|
||||
Logger.e(TAG, "Failed create file for archive");
|
||||
}
|
||||
default ->
|
||||
{
|
||||
errorCode = ErrorCode.UNSUPPORTED;
|
||||
Logger.e(TAG, "Failed to create backup. Unknown error");
|
||||
}
|
||||
}
|
||||
|
||||
ErrorCode finalErrorCode = errorCode;
|
||||
UiThread.run(() -> {
|
||||
if (listener != null)
|
||||
{
|
||||
if (finalErrorCode == null)
|
||||
listener.onBackupFinished();
|
||||
else
|
||||
listener.onBackupFailed(finalErrorCode);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private boolean saveBackup(@NonNull BookmarkSharingResult result)
|
||||
{
|
||||
boolean isSuccess = false;
|
||||
Uri folderUri = Uri.parse(backupFolderPath);
|
||||
try
|
||||
{
|
||||
DocumentFile parentFolder = DocumentFile.fromTreeUri(activity, folderUri);
|
||||
if (parentFolder != null && parentFolder.canWrite())
|
||||
{
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
DocumentFile backupFolder = BackupUtils.createUniqueBackupFolder(parentFolder, now);
|
||||
if (backupFolder != null)
|
||||
{
|
||||
String backupName = getBackupName(now);
|
||||
DocumentFile backupFile = backupFolder.createFile(result.getMimeType(), backupName);
|
||||
if (backupFile != null && copyFileToDocumentFile(activity, new File(result.getSharingPath()), backupFile))
|
||||
{
|
||||
Logger.i(TAG, "Backup saved to " + backupFile.getUri());
|
||||
isSuccess = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.e(TAG, "Failed to create backup folder");
|
||||
}
|
||||
}
|
||||
cleanOldBackups(parentFolder);
|
||||
|
||||
} catch (Exception e)
|
||||
{
|
||||
Logger.e(TAG, "Failed to save backup", e);
|
||||
}
|
||||
return isSuccess;
|
||||
}
|
||||
|
||||
public void cleanOldBackups(DocumentFile parentDir)
|
||||
{
|
||||
DocumentFile[] backupFolders = getBackupFolders(parentDir);
|
||||
if (backupFolders.length > maxBackups)
|
||||
{
|
||||
Arrays.sort(backupFolders, Comparator.comparing(DocumentFile::getName));
|
||||
for (int i = 0; i < backupFolders.length - maxBackups; i++)
|
||||
{
|
||||
Logger.i(TAG, "Delete old backup " + backupFolders[i].getUri());
|
||||
deleteDirectoryRecursive(backupFolders[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareBookmarkCategoriesForSharing()
|
||||
{
|
||||
List<BookmarkCategory> categories = BookmarkManager.INSTANCE.getCategories();
|
||||
long[] categoryIds = new long[categories.size()];
|
||||
for (int i = 0; i < categories.size(); i++)
|
||||
categoryIds[i] = categories.get(i).getId();
|
||||
BookmarkManager.INSTANCE.prepareCategoriesForSharing(categoryIds, KmlFileType.Text);
|
||||
}
|
||||
|
||||
public interface Listener
|
||||
{
|
||||
void onBackupStarted();
|
||||
|
||||
void onBackupFinished();
|
||||
|
||||
void onBackupFailed(ErrorCode errorCode);
|
||||
}
|
||||
|
||||
public enum ErrorCode
|
||||
{
|
||||
EMPTY_CATEGORY,
|
||||
ARCHIVE_ERROR,
|
||||
FILE_ERROR,
|
||||
UNSUPPORTED,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package app.organicmaps.backup;
|
||||
|
||||
import static app.organicmaps.backup.BackupUtils.getMaxBackups;
|
||||
import static app.organicmaps.backup.BackupUtils.isBackupFolderAvailable;
|
||||
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.LAST_BACKUP_TIME_KEY;
|
||||
import static app.organicmaps.util.StorageUtils.isFolderWritable;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import app.organicmaps.util.log.Logger;
|
||||
|
||||
public class PeriodicBackupRunner
|
||||
{
|
||||
private final Activity activity;
|
||||
private static final String TAG = PeriodicBackupRunner.class.getSimpleName();
|
||||
private final SharedPreferences prefs;
|
||||
private boolean alreadyChecked = false;
|
||||
|
||||
public PeriodicBackupRunner(Activity activity)
|
||||
{
|
||||
this.activity = activity;
|
||||
this.prefs = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||
}
|
||||
|
||||
public boolean isAlreadyChecked()
|
||||
{
|
||||
return alreadyChecked;
|
||||
}
|
||||
|
||||
public boolean isTimeToBackup()
|
||||
{
|
||||
long intervalMs = getBackupIntervalMs();
|
||||
|
||||
if (intervalMs <= 0)
|
||||
return false;
|
||||
|
||||
long lastBackupTime = prefs.getLong(LAST_BACKUP_TIME_KEY, 0);
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
alreadyChecked = true;
|
||||
|
||||
return (now - lastBackupTime) >= intervalMs;
|
||||
}
|
||||
|
||||
public void doBackup()
|
||||
{
|
||||
String storedFolderPath = prefs.getString(BACKUP_FOLDER_PATH_KEY, null);
|
||||
|
||||
if (isBackupFolderAvailable(activity, storedFolderPath))
|
||||
{
|
||||
Logger.i(TAG, "Performing periodic backup");
|
||||
performBackup(storedFolderPath, getMaxBackups(prefs));
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.w(TAG, "Backup folder is not writable, passed path: " + storedFolderPath);
|
||||
}
|
||||
}
|
||||
|
||||
private long getBackupIntervalMs()
|
||||
{
|
||||
String defaultValue = "0";
|
||||
try
|
||||
{
|
||||
return Long.parseLong(prefs.getString(BACKUP_INTERVAL_KEY, defaultValue));
|
||||
} catch (NumberFormatException e)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void performBackup(String backupFolderPath, int maxBackups)
|
||||
{
|
||||
LocalBackupManager backupManager = new LocalBackupManager(activity, backupFolderPath, maxBackups);
|
||||
backupManager.setListener(new LocalBackupManager.Listener()
|
||||
{
|
||||
@Override
|
||||
public void onBackupStarted()
|
||||
{
|
||||
Logger.i(TAG, "Periodic backup started");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackupFinished()
|
||||
{
|
||||
prefs.edit().putLong(LAST_BACKUP_TIME_KEY, System.currentTimeMillis()).apply();
|
||||
Logger.i(TAG, "Periodic backup finished");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackupFailed(LocalBackupManager.ErrorCode errorCode)
|
||||
{
|
||||
Logger.e(TAG, "Periodic backup was failed with code: " + errorCode);
|
||||
}
|
||||
});
|
||||
|
||||
backupManager.doBackup();
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,6 @@ import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -172,7 +171,7 @@ public class BookmarkCategorySettingsFragment extends BaseMwmToolbarFragment
|
||||
return !TextUtils.equals(mCategory.getDescription(), categoryDesc);
|
||||
}
|
||||
|
||||
private void clearAndFocus(TextView textView)
|
||||
private void clearAndFocus(TextInputEditText textView)
|
||||
{
|
||||
textView.getEditableText().clear();
|
||||
textView.requestFocus();
|
||||
|
||||
@@ -4,12 +4,13 @@ import android.content.res.Resources;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.bookmarks.data.BookmarkCategory;
|
||||
import app.organicmaps.bookmarks.data.BookmarkInfo;
|
||||
@@ -439,14 +440,14 @@ public class BookmarkListAdapter extends RecyclerView.Adapter<Holders.BaseBookma
|
||||
holder = bookmarkHolder;
|
||||
break;
|
||||
case TYPE_SECTION:
|
||||
TextView tv = (TextView) inflater.inflate(R.layout.item_category_title, parent, false);
|
||||
MaterialTextView tv = (MaterialTextView) inflater.inflate(R.layout.item_category_title, parent, false);
|
||||
holder = new Holders.SectionViewHolder(tv);
|
||||
break;
|
||||
case TYPE_DESC:
|
||||
View desc = inflater.inflate(R.layout.item_category_description, parent, false);
|
||||
TextView moreBtn = desc.findViewById(R.id.more_btn);
|
||||
TextView text = desc.findViewById(R.id.text);
|
||||
TextView title = desc.findViewById(R.id.title);
|
||||
MaterialTextView moreBtn = desc.findViewById(R.id.more_btn);
|
||||
MaterialTextView text = desc.findViewById(R.id.text);
|
||||
MaterialTextView title = desc.findViewById(R.id.title);
|
||||
setMoreButtonVisibility(text, moreBtn);
|
||||
holder = new Holders.DescriptionViewHolder(desc, mSectionsDataSource.getCategory());
|
||||
text.setOnClickListener(v -> onMoreButtonClicked(text, moreBtn));
|
||||
@@ -537,12 +538,12 @@ public class BookmarkListAdapter extends RecyclerView.Adapter<Holders.BaseBookma
|
||||
}
|
||||
}
|
||||
|
||||
private void setMoreButtonVisibility(TextView text, TextView moreBtn)
|
||||
private void setMoreButtonVisibility(MaterialTextView text, MaterialTextView moreBtn)
|
||||
{
|
||||
text.post(() -> setShortModeDescription(text, moreBtn));
|
||||
}
|
||||
|
||||
private void onMoreButtonClicked(TextView textView, TextView moreBtn)
|
||||
private void onMoreButtonClicked(MaterialTextView textView, MaterialTextView moreBtn)
|
||||
{
|
||||
if (isShortModeDescription(textView))
|
||||
{
|
||||
@@ -554,18 +555,18 @@ public class BookmarkListAdapter extends RecyclerView.Adapter<Holders.BaseBookma
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isShortModeDescription(TextView text)
|
||||
private boolean isShortModeDescription(MaterialTextView text)
|
||||
{
|
||||
return text.getMaxLines() == MAX_VISIBLE_LINES;
|
||||
}
|
||||
|
||||
private void setExpandedModeDescription(TextView textView, TextView moreBtn)
|
||||
private void setExpandedModeDescription(MaterialTextView textView, MaterialTextView moreBtn)
|
||||
{
|
||||
textView.setMaxLines(Integer.MAX_VALUE);
|
||||
moreBtn.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private void setShortModeDescription(TextView textView, TextView moreBtn)
|
||||
private void setShortModeDescription(MaterialTextView textView, MaterialTextView moreBtn)
|
||||
{
|
||||
textView.setMaxLines(MAX_VISIBLE_LINES);
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
@@ -53,6 +52,7 @@ import app.organicmaps.widget.placepage.BookmarkColorDialogFragment;
|
||||
import app.organicmaps.widget.placepage.EditBookmarkFragment;
|
||||
import app.organicmaps.widget.recycler.DividerItemDecorationWithPadding;
|
||||
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
|
||||
import com.google.android.material.imageview.ShapeableImageView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -599,7 +599,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
|
||||
i.putExtra(MwmActivity.EXTRA_BOOKMARK_ID, bookmark.getBookmarkId());
|
||||
}
|
||||
|
||||
private void showColorDialog(ImageView v, int position)
|
||||
private void showColorDialog(ShapeableImageView v, int position)
|
||||
{
|
||||
BookmarkListAdapter adapter = getBookmarkListAdapter();
|
||||
|
||||
|
||||
@@ -4,12 +4,13 @@ import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.radiobutton.MaterialRadioButton;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.bookmarks.data.BookmarkCategory;
|
||||
|
||||
@@ -101,8 +102,8 @@ public class ChooseBookmarkCategoryAdapter extends BaseBookmarkCategoryAdapter<C
|
||||
|
||||
static class SingleChoiceHolder extends RecyclerView.ViewHolder
|
||||
{
|
||||
TextView name;
|
||||
RadioButton checked;
|
||||
MaterialTextView name;
|
||||
MaterialRadioButton checked;
|
||||
|
||||
public SingleChoiceHolder(View convertView)
|
||||
{
|
||||
|
||||
@@ -6,15 +6,16 @@ import android.location.Location;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.PluralsRes;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.imageview.ShapeableImageView;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
import com.google.android.material.checkbox.MaterialCheckBox;
|
||||
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.adapter.OnItemClickListener;
|
||||
import app.organicmaps.bookmarks.data.BookmarkCategory;
|
||||
@@ -34,9 +35,9 @@ public class Holders
|
||||
public static class GeneralViewHolder extends RecyclerView.ViewHolder
|
||||
{
|
||||
@NonNull
|
||||
private final TextView mText;
|
||||
private final MaterialTextView mText;
|
||||
@NonNull
|
||||
private final ImageView mImage;
|
||||
private final ShapeableImageView mImage;
|
||||
|
||||
GeneralViewHolder(@NonNull View itemView)
|
||||
{
|
||||
@@ -46,13 +47,13 @@ public class Holders
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public TextView getText()
|
||||
public MaterialTextView getText()
|
||||
{
|
||||
return mText;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public ImageView getImage()
|
||||
public ShapeableImageView getImage()
|
||||
{
|
||||
return mImage;
|
||||
}
|
||||
@@ -61,9 +62,9 @@ public class Holders
|
||||
public static class HeaderViewHolder extends RecyclerView.ViewHolder
|
||||
{
|
||||
@NonNull
|
||||
private final TextView mButton;
|
||||
private final MaterialTextView mButton;
|
||||
@NonNull
|
||||
private final TextView mText;
|
||||
private final MaterialTextView mText;
|
||||
|
||||
|
||||
HeaderViewHolder(@NonNull View itemView)
|
||||
@@ -74,13 +75,13 @@ public class Holders
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public TextView getText()
|
||||
public MaterialTextView getText()
|
||||
{
|
||||
return mText;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public TextView getButton()
|
||||
public MaterialTextView getButton()
|
||||
{
|
||||
return mButton;
|
||||
}
|
||||
@@ -168,7 +169,7 @@ public class Holders
|
||||
protected BookmarkCategory mEntity;
|
||||
|
||||
@NonNull
|
||||
protected final TextView mSize;
|
||||
protected final MaterialTextView mSize;
|
||||
|
||||
public CategoryViewHolderBase(@NonNull View root)
|
||||
{
|
||||
@@ -229,9 +230,9 @@ public class Holders
|
||||
@NonNull
|
||||
private final View mView;
|
||||
@NonNull
|
||||
private final TextView mName;
|
||||
private final MaterialTextView mName;
|
||||
@NonNull
|
||||
private final CheckBox mVisibilityMarker;
|
||||
private final MaterialCheckBox mVisibilityMarker;
|
||||
|
||||
CollectionViewHolder(@NonNull View root)
|
||||
{
|
||||
@@ -268,11 +269,11 @@ public class Holders
|
||||
static class CategoryViewHolder extends CategoryViewHolderBase
|
||||
{
|
||||
@NonNull
|
||||
private final TextView mName;
|
||||
private final MaterialTextView mName;
|
||||
@NonNull
|
||||
CheckBox mVisibilityMarker;
|
||||
MaterialCheckBox mVisibilityMarker;
|
||||
@NonNull
|
||||
ImageView mMoreButton;
|
||||
ShapeableImageView mMoreButton;
|
||||
|
||||
CategoryViewHolder(@NonNull View root)
|
||||
{
|
||||
@@ -338,11 +339,11 @@ public class Holders
|
||||
static class BookmarkViewHolder extends BaseBookmarkHolder
|
||||
{
|
||||
@NonNull
|
||||
private final ImageView mIcon;
|
||||
private final ShapeableImageView mIcon;
|
||||
@NonNull
|
||||
private final TextView mName;
|
||||
private final MaterialTextView mName;
|
||||
@NonNull
|
||||
private final TextView mDistance;
|
||||
private final MaterialTextView mDistance;
|
||||
|
||||
BookmarkViewHolder(@NonNull View itemView)
|
||||
{
|
||||
@@ -384,12 +385,12 @@ public class Holders
|
||||
static class TrackViewHolder extends BaseBookmarkHolder
|
||||
{
|
||||
@NonNull
|
||||
private final ImageView mIcon;
|
||||
private final ShapeableImageView mIcon;
|
||||
@NonNull
|
||||
private final TextView mName;
|
||||
private final MaterialTextView mName;
|
||||
@NonNull
|
||||
private final TextView mDistance;
|
||||
private final ImageView mMoreButton;
|
||||
private final MaterialTextView mDistance;
|
||||
private final ShapeableImageView mMoreButton;
|
||||
|
||||
TrackViewHolder(@NonNull View itemView)
|
||||
{
|
||||
@@ -424,16 +425,16 @@ public class Holders
|
||||
|
||||
public void setTrackIconClickListener(IconClickListener listener)
|
||||
{
|
||||
mIcon.setOnClickListener(v -> listener.onItemClick((ImageView) v, getBindingAdapterPosition()));
|
||||
mIcon.setOnClickListener(v -> listener.onItemClick((ShapeableImageView) v, getBindingAdapterPosition()));
|
||||
}
|
||||
}
|
||||
|
||||
public static class SectionViewHolder extends BaseBookmarkHolder
|
||||
{
|
||||
@NonNull
|
||||
private final TextView mView;
|
||||
private final MaterialTextView mView;
|
||||
|
||||
SectionViewHolder(@NonNull TextView itemView)
|
||||
SectionViewHolder(@NonNull MaterialTextView itemView)
|
||||
{
|
||||
super(itemView);
|
||||
mView = itemView;
|
||||
@@ -452,9 +453,9 @@ public class Holders
|
||||
static final float SPACING_MULTIPLE = 1.0f;
|
||||
static final float SPACING_ADD = 0.0f;
|
||||
@NonNull
|
||||
private final TextView mTitle;
|
||||
private final MaterialTextView mTitle;
|
||||
@NonNull
|
||||
private final TextView mDescText;
|
||||
private final MaterialTextView mDescText;
|
||||
|
||||
DescriptionViewHolder(@NonNull View itemView, @NonNull BookmarkCategory category)
|
||||
{
|
||||
|
||||
@@ -6,7 +6,8 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.google.android.material.imageview.ShapeableImageView;
|
||||
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.bookmarks.data.Icon;
|
||||
@@ -61,7 +62,7 @@ public class IconsAdapter extends ArrayAdapter<Icon>
|
||||
|
||||
private static class SpinnerViewHolder
|
||||
{
|
||||
final ImageView icon;
|
||||
final ShapeableImageView icon;
|
||||
|
||||
SpinnerViewHolder(View convertView)
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package app.organicmaps.bookmarks.data;
|
||||
|
||||
import android.widget.ImageView;
|
||||
import com.google.android.material.imageview.ShapeableImageView;
|
||||
|
||||
public interface IconClickListener
|
||||
{
|
||||
void onItemClick(ImageView v, int position);
|
||||
void onItemClick(ShapeableImageView v, int position);
|
||||
}
|
||||
|
||||
@@ -69,7 +69,8 @@ public class Metadata implements Parcelable
|
||||
FMD_OUTDOOR_SEATING(48),
|
||||
FMD_NETWORK(49),
|
||||
FMD_CONTACT_FEDIVERSE(50),
|
||||
FMD_CONTACT_BLUESKY(51);
|
||||
FMD_CONTACT_BLUESKY(51),
|
||||
FMD_PANORAMAX(52);
|
||||
private final int mMetaType;
|
||||
|
||||
MetadataType(int metadataType)
|
||||
|
||||
@@ -41,7 +41,7 @@ public class HelpScreen extends BaseMapScreen
|
||||
{
|
||||
final Header.Builder builder = new Header.Builder();
|
||||
builder.setStartHeaderAction(Action.BACK);
|
||||
builder.setTitle(getCarContext().getString(R.string.help));
|
||||
builder.setTitle(getCarContext().getString(R.string.about_help));
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ public class SettingsScreen extends BaseMapScreen
|
||||
private Item createHelpItem()
|
||||
{
|
||||
final Row.Builder builder = new Row.Builder();
|
||||
builder.setTitle(getCarContext().getString(R.string.help));
|
||||
builder.setTitle(getCarContext().getString(R.string.about_help));
|
||||
builder.setOnClickListener(() -> getScreenManager().push(new HelpScreen(getCarContext(), getSurfaceRenderer())));
|
||||
builder.setBrowsable(true);
|
||||
return builder.build();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package app.organicmaps.downloader;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.util.StringUtils;
|
||||
@@ -14,7 +14,7 @@ class BottomPanel
|
||||
{
|
||||
private final DownloaderFragment mFragment;
|
||||
private final FloatingActionButton mFab;
|
||||
private final Button mButton;
|
||||
private final MaterialButton mButton;
|
||||
|
||||
private final View.OnClickListener mDownloadListener = new View.OnClickListener()
|
||||
{
|
||||
@@ -45,6 +45,15 @@ class BottomPanel
|
||||
}
|
||||
};
|
||||
|
||||
private final View.OnClickListener mRetryListener = new View.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View v)
|
||||
{
|
||||
MapManager.warn3gAndRetry(mFragment.requireActivity(), mFragment.getCurrentRoot(), null);
|
||||
}
|
||||
};
|
||||
|
||||
BottomPanel(DownloaderFragment fragment, View frame)
|
||||
{
|
||||
mFragment = fragment;
|
||||
@@ -72,6 +81,12 @@ class BottomPanel
|
||||
mButton.setOnClickListener(mDownloadListener);
|
||||
}
|
||||
|
||||
private void setRetryFailedStates()
|
||||
{
|
||||
mButton.setText(R.string.downloader_retry);
|
||||
mButton.setOnClickListener(mRetryListener);
|
||||
}
|
||||
|
||||
private void setCancelState()
|
||||
{
|
||||
mButton.setText(R.string.downloader_cancel_all);
|
||||
@@ -101,7 +116,7 @@ class BottomPanel
|
||||
} // Special case for "Countries" node when no maps currently downloaded.
|
||||
case STATUS_DOWNLOADABLE, STATUS_DONE, STATUS_PARTLY -> show = false;
|
||||
case STATUS_PROGRESS, STATUS_APPLYING, STATUS_ENQUEUED -> setCancelState();
|
||||
case STATUS_FAILED -> setDownloadAllState();
|
||||
case STATUS_FAILED -> setRetryFailedStates();
|
||||
default -> throw new IllegalArgumentException("Inappropriate status for \"" + root + "\": " + status);
|
||||
}
|
||||
}
|
||||
@@ -119,6 +134,7 @@ class BottomPanel
|
||||
}
|
||||
case STATUS_DONE -> show = false;
|
||||
case STATUS_PROGRESS, STATUS_APPLYING, STATUS_ENQUEUED -> setCancelState();
|
||||
case STATUS_FAILED -> setRetryFailedStates();
|
||||
default -> setDownloadAllState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ class ChunkTask extends AsyncTask<Void, byte[], Integer>
|
||||
// @TODO Else display received web page to user - router is redirecting us to some page
|
||||
}
|
||||
|
||||
return downloadFromStream(new BufferedInputStream(urlConnection.getInputStream(), 65536));
|
||||
return downloadFromStream(new BufferedInputStream(urlConnection.getInputStream(), 128 * Constants.KB));
|
||||
} catch (final MalformedURLException ex)
|
||||
{
|
||||
Logger.e(TAG, "Invalid url: " + mUrl, ex);
|
||||
@@ -229,7 +229,7 @@ class ChunkTask extends AsyncTask<Void, byte[], Integer>
|
||||
{
|
||||
// Because of timeouts in InputStream.read (for bad connection),
|
||||
// try to introduce dynamic buffer size to read in one query.
|
||||
final int[] arrSize = {64, 32, 1};
|
||||
final int[] arrSize = {128, 32, 1};
|
||||
int ret = IO_EXCEPTION;
|
||||
|
||||
for (int size : arrSize)
|
||||
@@ -240,7 +240,7 @@ class ChunkTask extends AsyncTask<Void, byte[], Integer>
|
||||
break;
|
||||
} catch (final IOException ex)
|
||||
{
|
||||
Logger.e(TAG, "IOException in downloadFromStream for chunk size: " + size, ex);
|
||||
Logger.e(TAG, "IOException in downloadFromStream for buffer size: " + size, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,13 +6,14 @@ import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.base.BaseMwmFragment;
|
||||
import app.organicmaps.base.BaseMwmFragmentActivity;
|
||||
@@ -30,10 +31,10 @@ public class CountrySuggestFragment extends BaseMwmFragment implements View.OnCl
|
||||
private LinearLayout mLlSelectDownload;
|
||||
private LinearLayout mLlActiveDownload;
|
||||
private WheelProgressView mWpvDownloadProgress;
|
||||
private TextView mTvCountry;
|
||||
private TextView mTvActiveCountry;
|
||||
private TextView mTvProgress;
|
||||
private Button mBtnDownloadMap;
|
||||
private MaterialTextView mTvCountry;
|
||||
private MaterialTextView mTvActiveCountry;
|
||||
private MaterialTextView mTvProgress;
|
||||
private MaterialButton mBtnDownloadMap;
|
||||
|
||||
private CountryItem mCurrentCountry;
|
||||
private CountryItem mDownloadingCountry;
|
||||
@@ -150,7 +151,7 @@ public class CountrySuggestFragment extends BaseMwmFragment implements View.OnCl
|
||||
mLlNoLocation = view.findViewById(R.id.ll__location_unknown);
|
||||
mBtnDownloadMap = view.findViewById(R.id.btn__download_map);
|
||||
mBtnDownloadMap.setOnClickListener(this);
|
||||
Button selectMap = view.findViewById(R.id.btn__select_map);
|
||||
MaterialButton selectMap = view.findViewById(R.id.btn__select_map);
|
||||
selectMap.setOnClickListener(this);
|
||||
mWpvDownloadProgress = view.findViewById(R.id.wpv__download_progress);
|
||||
mWpvDownloadProgress.setOnClickListener(this);
|
||||
|
||||
@@ -11,7 +11,6 @@ import android.text.style.StyleSpan;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -28,6 +27,7 @@ import app.organicmaps.util.UiUtils;
|
||||
import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment;
|
||||
import app.organicmaps.util.bottomsheet.MenuBottomSheetItem;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -362,10 +362,10 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
|
||||
private class ItemViewHolder extends BaseInnerViewHolder<CountryItem>
|
||||
{
|
||||
private final DownloaderStatusIcon mStatusIcon;
|
||||
private final TextView mName;
|
||||
private final TextView mSubtitle;
|
||||
private final TextView mFoundName;
|
||||
private final TextView mSize;
|
||||
private final MaterialTextView mName;
|
||||
private final MaterialTextView mSubtitle;
|
||||
private final MaterialTextView mFoundName;
|
||||
private final MaterialTextView mSize;
|
||||
|
||||
private void processClick(boolean clickOnStatus)
|
||||
{
|
||||
@@ -510,7 +510,7 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
|
||||
static class HeaderViewHolder extends BaseInnerViewHolder<String>
|
||||
{
|
||||
@NonNull
|
||||
private final TextView mTitle;
|
||||
private final MaterialTextView mTitle;
|
||||
|
||||
HeaderViewHolder(@NonNull View frame)
|
||||
{
|
||||
|
||||
@@ -124,7 +124,7 @@ public class DownloaderNotifier
|
||||
return new NotificationCompat.Builder(mContext, CHANNEL_ID)
|
||||
.setAutoCancel(true)
|
||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||
.setSmallIcon(R.drawable.ic_launcher)
|
||||
.setSmallIcon(R.drawable.ic_launcher_small)
|
||||
.setColor(ContextCompat.getColor(mContext, R.color.notification))
|
||||
.setShowWhen(true)
|
||||
.setContentTitle(title)
|
||||
|
||||
@@ -2,11 +2,12 @@ package app.organicmaps.downloader;
|
||||
|
||||
import android.util.SparseIntArray;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.AttrRes;
|
||||
import androidx.annotation.DrawableRes;
|
||||
|
||||
import com.google.android.material.imageview.ShapeableImageView;
|
||||
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.widget.WheelProgressView;
|
||||
import app.organicmaps.util.ThemeUtils;
|
||||
@@ -15,7 +16,7 @@ import app.organicmaps.util.UiUtils;
|
||||
public class DownloaderStatusIcon
|
||||
{
|
||||
private final View mFrame;
|
||||
protected final ImageView mIcon;
|
||||
protected final ShapeableImageView mIcon;
|
||||
private final WheelProgressView mProgress;
|
||||
|
||||
private static final SparseIntArray sIconsCache = new SparseIntArray();
|
||||
|
||||
@@ -4,11 +4,13 @@ import android.location.Location;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
|
||||
import app.organicmaps.MwmActivity;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.location.LocationHelper;
|
||||
@@ -28,11 +30,11 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
|
||||
|
||||
private final MwmActivity mActivity;
|
||||
private final View mFrame;
|
||||
private final TextView mParent;
|
||||
private final TextView mTitle;
|
||||
private final TextView mSize;
|
||||
private final MaterialTextView mParent;
|
||||
private final MaterialTextView mTitle;
|
||||
private final MaterialTextView mSize;
|
||||
private final WheelProgressView mProgress;
|
||||
private final Button mButton;
|
||||
private final MaterialButton mButton;
|
||||
|
||||
private int mStorageSubscriptionSlot;
|
||||
|
||||
|
||||
@@ -7,8 +7,6 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.webkit.WebView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -20,7 +18,10 @@ import app.organicmaps.util.Constants;
|
||||
import app.organicmaps.util.Graphics;
|
||||
import app.organicmaps.util.InputUtils;
|
||||
import app.organicmaps.util.UiUtils;
|
||||
|
||||
import com.google.android.material.imageview.ShapeableImageView;
|
||||
import com.google.android.material.textfield.TextInputEditText;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
|
||||
public class AdvancedTimetableFragment extends BaseMwmFragment
|
||||
implements View.OnClickListener, TimetableProvider
|
||||
@@ -28,8 +29,8 @@ public class AdvancedTimetableFragment extends BaseMwmFragment
|
||||
private boolean mIsExampleShown;
|
||||
private TextInputEditText mInput;
|
||||
private WebView mExample;
|
||||
private TextView mExamplesTitle;
|
||||
private static ImageView mSaveButton;
|
||||
private MaterialTextView mExamplesTitle;
|
||||
private static ShapeableImageView mSaveButton;
|
||||
@Nullable
|
||||
private String mInitTimetables;
|
||||
@Nullable
|
||||
|
||||
@@ -3,13 +3,14 @@ package app.organicmaps.editor;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.checkbox.MaterialCheckBox;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
|
||||
import app.organicmaps.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -100,8 +101,8 @@ public class CuisineAdapter extends RecyclerView.Adapter<CuisineAdapter.ViewHold
|
||||
|
||||
protected class ViewHolder extends RecyclerView.ViewHolder implements CompoundButton.OnCheckedChangeListener
|
||||
{
|
||||
final TextView cuisine;
|
||||
final CheckBox selected;
|
||||
final MaterialTextView cuisine;
|
||||
final MaterialCheckBox selected;
|
||||
|
||||
public ViewHolder(View itemView)
|
||||
{
|
||||
|
||||
@@ -8,8 +8,6 @@ import android.text.method.LinkMovementMethod;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.DrawableRes;
|
||||
@@ -22,8 +20,11 @@ import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.imageview.ShapeableImageView;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
import com.google.android.material.textfield.TextInputEditText;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
|
||||
import app.organicmaps.Framework;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.base.BaseMwmFragment;
|
||||
@@ -46,7 +47,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
|
||||
{
|
||||
final static String LAST_INDEX_OF_NAMES_ARRAY = "LastIndexOfNamesArray";
|
||||
|
||||
private TextView mCategory;
|
||||
private MaterialTextView mCategory;
|
||||
private View mCardName;
|
||||
private View mCardAddress;
|
||||
private View mCardDetails;
|
||||
@@ -89,20 +90,20 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
|
||||
};
|
||||
|
||||
private MultilanguageAdapter mNamesAdapter;
|
||||
private TextView mNamesCaption;
|
||||
private TextView mAddLanguage;
|
||||
private TextView mMoreLanguages;
|
||||
private MaterialTextView mNamesCaption;
|
||||
private MaterialTextView mAddLanguage;
|
||||
private MaterialTextView mMoreLanguages;
|
||||
|
||||
private TextView mStreet;
|
||||
private MaterialTextView mStreet;
|
||||
private TextInputEditText mHouseNumber;
|
||||
private TextInputEditText mBuildingLevels;
|
||||
|
||||
// Define Metadata entries, that have more tricky logic, separately.
|
||||
private TextView mPhone;
|
||||
private TextView mEditPhoneLink;
|
||||
private TextView mCuisine;
|
||||
private MaterialTextView mPhone;
|
||||
private MaterialTextView mEditPhoneLink;
|
||||
private MaterialTextView mCuisine;
|
||||
private SwitchCompat mWifi;
|
||||
private TextView mSelfService;
|
||||
private MaterialTextView mSelfService;
|
||||
private SwitchCompat mOutdoorSeating;
|
||||
|
||||
// Default Metadata entries.
|
||||
@@ -132,12 +133,12 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
|
||||
private TextInputLayout mInputBuildingLevels;
|
||||
|
||||
private View mEmptyOpeningHours;
|
||||
private TextView mOpeningHours;
|
||||
private MaterialTextView mOpeningHours;
|
||||
private View mEditOpeningHours;
|
||||
private TextInputEditText mDescription;
|
||||
private final Map<Metadata.MetadataType, View> mDetailsBlocks = new HashMap<>();
|
||||
private final Map<Metadata.MetadataType, View> mSocialMediaBlocks = new HashMap<>();
|
||||
private TextView mReset;
|
||||
private MaterialTextView mReset;
|
||||
|
||||
private EditorHostFragment mParent;
|
||||
|
||||
@@ -489,7 +490,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
|
||||
mOpeningHours.setOnClickListener(this);
|
||||
final View cardMore = view.findViewById(R.id.cv__more);
|
||||
mDescription = findInput(cardMore);
|
||||
TextView osmInfo = view.findViewById(R.id.osm_info);
|
||||
MaterialTextView osmInfo = view.findViewById(R.id.osm_info);
|
||||
osmInfo.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
mReset = view.findViewById(R.id.reset);
|
||||
mReset.setOnClickListener(this);
|
||||
@@ -529,7 +530,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
|
||||
|
||||
private static TextInputEditText findInputAndInitBlock(View blockWithInput, @DrawableRes int icon, String hint)
|
||||
{
|
||||
((ImageView) blockWithInput.findViewById(R.id.icon)).setImageResource(icon);
|
||||
((ShapeableImageView) blockWithInput.findViewById(R.id.icon)).setImageResource(icon);
|
||||
final TextInputLayout input = blockWithInput.findViewById(R.id.custom_input);
|
||||
input.setHint(hint);
|
||||
return input.findViewById(R.id.input);
|
||||
|
||||
@@ -4,12 +4,13 @@ import android.text.method.LinkMovementMethod;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.editor.data.FeatureCategory;
|
||||
import app.organicmaps.util.UiUtils;
|
||||
@@ -78,7 +79,7 @@ public class FeatureCategoryAdapter extends RecyclerView.Adapter<RecyclerView.Vi
|
||||
protected class FeatureViewHolder extends RecyclerView.ViewHolder
|
||||
{
|
||||
@NonNull
|
||||
private final TextView mName;
|
||||
private final MaterialTextView mName;
|
||||
@NonNull
|
||||
private final View mSelected;
|
||||
|
||||
@@ -106,7 +107,7 @@ public class FeatureCategoryAdapter extends RecyclerView.Adapter<RecyclerView.Vi
|
||||
FooterViewHolder(@NonNull View itemView)
|
||||
{
|
||||
super(itemView);
|
||||
TextView categoryUnsuitableText = itemView.findViewById(R.id.editor_category_unsuitable_text);
|
||||
MaterialTextView categoryUnsuitableText = itemView.findViewById(R.id.editor_category_unsuitable_text);
|
||||
categoryUnsuitableText.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import android.text.format.DateFormat;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TimePicker;
|
||||
|
||||
import androidx.annotation.IntRange;
|
||||
@@ -21,6 +20,8 @@ import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.base.BaseMwmDialogFragment;
|
||||
import app.organicmaps.editor.data.HoursMinutes;
|
||||
@@ -134,19 +135,19 @@ public class HoursMinutesPickerFragment extends BaseMwmDialogFragment
|
||||
if (id != 0)
|
||||
{
|
||||
mPickerHoursLabel = mPicker.findViewById(id);
|
||||
if (!(mPickerHoursLabel instanceof TextView))
|
||||
if (!(mPickerHoursLabel instanceof MaterialTextView))
|
||||
mPickerHoursLabel = null;
|
||||
}
|
||||
|
||||
mTabs = root.findViewById(R.id.tabs);
|
||||
TextView tabView = (TextView) inflater.inflate(R.layout.tab_timepicker, mTabs, false);
|
||||
MaterialTextView tabView = (MaterialTextView) inflater.inflate(R.layout.tab_timepicker, mTabs, false);
|
||||
tabView.setText(getResources().getString(R.string.editor_time_from));
|
||||
final ColorStateList textColor = AppCompatResources.getColorStateList(requireContext(),
|
||||
ThemeUtils.isNightTheme(requireContext()) ? R.color.accent_color_selector_night
|
||||
: R.color.accent_color_selector);
|
||||
tabView.setTextColor(textColor);
|
||||
mTabs.addTab(mTabs.newTab().setCustomView(tabView), true);
|
||||
tabView = (TextView) inflater.inflate(R.layout.tab_timepicker, mTabs, false);
|
||||
tabView = (MaterialTextView) inflater.inflate(R.layout.tab_timepicker, mTabs, false);
|
||||
tabView.setText(getResources().getString(R.string.editor_time_to));
|
||||
tabView.setTextColor(textColor);
|
||||
mTabs.addTab(mTabs.newTab().setCustomView(tabView), true);
|
||||
|
||||
@@ -3,11 +3,12 @@ package app.organicmaps.editor;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.editor.data.Language;
|
||||
|
||||
@@ -42,12 +43,12 @@ public class LanguagesAdapter extends RecyclerView.Adapter<LanguagesAdapter.Hold
|
||||
|
||||
protected class Holder extends RecyclerView.ViewHolder
|
||||
{
|
||||
TextView name;
|
||||
MaterialTextView name;
|
||||
|
||||
public Holder(View itemView)
|
||||
{
|
||||
super(itemView);
|
||||
name = (TextView) itemView;
|
||||
name = (MaterialTextView) itemView;
|
||||
itemView.setOnClickListener(v -> mFragment.onLanguageSelected(mLanguages[getBindingAdapterPosition()]));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package app.organicmaps.editor;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
|
||||
// Used by JNI.
|
||||
@Keep
|
||||
public class OhState
|
||||
{
|
||||
public enum State
|
||||
{
|
||||
Open,
|
||||
Closed,
|
||||
Unknown
|
||||
}
|
||||
|
||||
public State state;
|
||||
/** Unix timestamp in seconds**/
|
||||
public long nextTimeOpen;
|
||||
/** Unix timestamp in seconds **/
|
||||
public long nextTimeClosed;
|
||||
|
||||
// Used by JNI.
|
||||
@Keep
|
||||
public OhState(State state, long nextTimeOpen, long nextTimeClosed)
|
||||
{
|
||||
this.state = state;
|
||||
this.nextTimeOpen = nextTimeOpen;
|
||||
this.nextTimeClosed = nextTimeClosed;
|
||||
}
|
||||
}
|
||||
@@ -60,4 +60,6 @@ public final class OpeningHours
|
||||
* @return true if timetable string is valid OSM timetable.
|
||||
*/
|
||||
public static native boolean nativeIsTimetableStringValid(String source);
|
||||
|
||||
public static native OhState nativeCurrentState(@NonNull Timetable[] timetables);
|
||||
}
|
||||
|
||||
@@ -4,11 +4,11 @@ import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.imageview.ShapeableImageView;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
import com.google.android.material.textfield.TextInputEditText;
|
||||
import app.organicmaps.R;
|
||||
@@ -94,7 +94,7 @@ public class PhoneListAdapter extends RecyclerView.Adapter<PhoneListAdapter.View
|
||||
{
|
||||
private int mPosition = -1;
|
||||
private final TextInputEditText mInput;
|
||||
private final ImageView deleteButton;
|
||||
private final ShapeableImageView deleteButton;
|
||||
|
||||
public ViewHolder(@NonNull View itemView)
|
||||
{
|
||||
@@ -116,7 +116,7 @@ public class PhoneListAdapter extends RecyclerView.Adapter<PhoneListAdapter.View
|
||||
deleteButton.setOnClickListener(this);
|
||||
// TODO: setting icons from code because icons defined in layout XML are white.
|
||||
deleteButton.setImageResource(R.drawable.ic_delete);
|
||||
((ImageView) itemView.findViewById(R.id.phone_icon)).setImageResource(R.drawable.ic_phone);
|
||||
((ShapeableImageView) itemView.findViewById(R.id.phone_icon)).setImageResource(R.drawable.ic_phone);
|
||||
}
|
||||
|
||||
public void setPosition(int position)
|
||||
|
||||
@@ -4,12 +4,13 @@ import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.radiobutton.MaterialRadioButton;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.util.Utils;
|
||||
|
||||
@@ -51,8 +52,8 @@ public class SelfServiceAdapter extends RecyclerView.Adapter<SelfServiceAdapter.
|
||||
|
||||
protected class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
|
||||
{
|
||||
final TextView selfServiceDef;
|
||||
final CompoundButton selected;
|
||||
final MaterialTextView selfServiceDef;
|
||||
final MaterialRadioButton selected;
|
||||
|
||||
public ViewHolder(View itemView)
|
||||
{
|
||||
|
||||
@@ -4,11 +4,8 @@ import android.util.SparseArray;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.annotation.IntRange;
|
||||
@@ -17,6 +14,10 @@ import androidx.appcompat.widget.SwitchCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.google.android.material.checkbox.MaterialCheckBox;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.editor.data.HoursMinutes;
|
||||
import app.organicmaps.editor.data.TimeFormatUtils;
|
||||
@@ -185,15 +186,15 @@ class SimpleTimetableAdapter extends RecyclerView.Adapter<SimpleTimetableAdapter
|
||||
// Limit closed spans to avoid dynamic inflation of views in recycler's children. Yeah, its a hack.
|
||||
static final int MAX_CLOSED_SPANS = 10;
|
||||
|
||||
SparseArray<CheckBox> days = new SparseArray<>(7);
|
||||
SparseArray<MaterialCheckBox> days = new SparseArray<>(7);
|
||||
View allday;
|
||||
SwitchCompat swAllday;
|
||||
View schedule;
|
||||
View openClose;
|
||||
View open;
|
||||
View close;
|
||||
TextView tvOpen;
|
||||
TextView tvClose;
|
||||
MaterialTextView tvOpen;
|
||||
MaterialTextView tvClose;
|
||||
View[] closedHours = new View[MAX_CLOSED_SPANS];
|
||||
View addClosed;
|
||||
View deleteTimetable;
|
||||
@@ -316,7 +317,7 @@ class SimpleTimetableAdapter extends RecyclerView.Adapter<SimpleTimetableAdapter
|
||||
else
|
||||
{
|
||||
UiUtils.show(closedHours[i]);
|
||||
((TextView) closedHours[i].findViewById(R.id.tv__closed)).setText(timespan.toString());
|
||||
((MaterialTextView) closedHours[i].findViewById(R.id.tv__closed)).setText(timespan.toString());
|
||||
}
|
||||
|
||||
i++;
|
||||
@@ -333,18 +334,18 @@ class SimpleTimetableAdapter extends RecyclerView.Adapter<SimpleTimetableAdapter
|
||||
private void addDay(@IntRange(from = 1, to = 7) final int dayIndex, @IdRes int id)
|
||||
{
|
||||
final View day = itemView.findViewById(id);
|
||||
final CheckBox checkBox = day.findViewById(R.id.chb__day);
|
||||
final MaterialCheckBox checkBox = day.findViewById(R.id.chb__day);
|
||||
// Save index of the day to get it back when checkbox will be toggled.
|
||||
checkBox.setTag(dayIndex);
|
||||
days.put(dayIndex, checkBox);
|
||||
day.setOnClickListener(v -> checkBox.toggle());
|
||||
|
||||
((TextView) day.findViewById(R.id.tv__day)).setText(TimeFormatUtils.formatShortWeekday(dayIndex));
|
||||
((MaterialTextView) day.findViewById(R.id.tv__day)).setText(TimeFormatUtils.formatShortWeekday(dayIndex));
|
||||
}
|
||||
|
||||
private void switchWorkingDay(@IntRange(from = 1, to = 7) int dayIndex)
|
||||
{
|
||||
final CheckBox checkBox = days.get(dayIndex);
|
||||
final MaterialCheckBox checkBox = days.get(dayIndex);
|
||||
if (checkBox.isChecked())
|
||||
addWorkingDay(dayIndex, getBindingAdapterPosition());
|
||||
else
|
||||
@@ -361,7 +362,7 @@ class SimpleTimetableAdapter extends RecyclerView.Adapter<SimpleTimetableAdapter
|
||||
|
||||
private class AddTimetableViewHolder extends BaseTimetableViewHolder
|
||||
{
|
||||
private final Button mAdd;
|
||||
private final MaterialButton mAdd;
|
||||
|
||||
AddTimetableViewHolder(View itemView)
|
||||
{
|
||||
|
||||
@@ -4,12 +4,13 @@ import android.content.res.Resources;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.radiobutton.MaterialRadioButton;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
|
||||
import app.organicmaps.MwmApplication;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.dialog.EditTextDialogFragment;
|
||||
@@ -86,9 +87,9 @@ public class StreetAdapter extends RecyclerView.Adapter<StreetAdapter.BaseViewHo
|
||||
|
||||
protected class StreetViewHolder extends BaseViewHolder implements View.OnClickListener
|
||||
{
|
||||
final TextView streetDef;
|
||||
final TextView streetLoc;
|
||||
final CompoundButton selected;
|
||||
final MaterialTextView streetDef;
|
||||
final MaterialTextView streetLoc;
|
||||
final MaterialRadioButton selected;
|
||||
|
||||
public StreetViewHolder(View itemView)
|
||||
{
|
||||
|
||||
@@ -7,7 +7,6 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -19,6 +18,7 @@ import app.organicmaps.R;
|
||||
import app.organicmaps.base.BaseMwmFragment;
|
||||
import app.organicmaps.util.UiUtils;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
|
||||
public class TimetableContainerFragment extends BaseMwmFragment implements TimetableChangedListener
|
||||
{
|
||||
@@ -71,7 +71,7 @@ public class TimetableContainerFragment extends BaseMwmFragment implements Timet
|
||||
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@NonNull
|
||||
private TextView mSwitchMode;
|
||||
private MaterialTextView mSwitchMode;
|
||||
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@NonNull
|
||||
|
||||
@@ -43,7 +43,7 @@ public class CopyrightFragment extends BaseMwmFragment
|
||||
{
|
||||
if (!mDelegate.onBackPressed())
|
||||
{
|
||||
((HelpActivity) requireActivity()).stackFragment(HelpFragment.class, getString(R.string.help), null);
|
||||
((HelpActivity) requireActivity()).stackFragment(HelpFragment.class, getString(R.string.about_help), null);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||