mirror of
https://codeberg.org/comaps/comaps
synced 2026-01-07 21:13:55 +00:00
Compare commits
12 Commits
test/2025.
...
test/2025.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86b266a579 | ||
|
|
a9c9caaeb5 | ||
|
|
85fa291e3e | ||
|
|
082403f506 | ||
|
|
af8b4a99a9 | ||
|
|
d5e0919079 | ||
|
|
d736fa2399 | ||
|
|
ed796c1ffe | ||
|
|
71142c794b | ||
|
|
1bfc448af4 | ||
|
|
d4bb911fe2 | ||
|
|
36b8da5aec |
@@ -1,8 +0,0 @@
|
||||
name: dco
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: codeberg-tiny
|
||||
steps:
|
||||
- uses: https://github.com/KineticCafe/actions-dco@v1
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
LANG: en_US.UTF-8 # Fastlane complains that the terminal is using ASCII.
|
||||
LANGUAGE: en_US.UTF-8
|
||||
LC_ALL: en_US.UTF-8
|
||||
TEST_RESULTS_BUNDLE_NAME: CoMaps-Test-Results
|
||||
TEST_RESULTS_BUNDLE_NAME: OMaps-Test-Results
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -74,8 +74,8 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
xcodebuild test \
|
||||
-workspace xcode/CoMaps.xcworkspace \
|
||||
-scheme CoMaps \
|
||||
-workspace xcode/omim.xcworkspace \
|
||||
-scheme OMaps \
|
||||
-configuration Debug \
|
||||
-sdk iphonesimulator \
|
||||
-destination 'platform=iOS Simulator,name=iPhone 16 Pro Max,OS=latest' \
|
||||
@@ -97,8 +97,8 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
xcodebuild build \
|
||||
-workspace xcode/CoMaps.xcworkspace \
|
||||
-scheme CoMaps \
|
||||
-workspace xcode/omim.xcworkspace \
|
||||
-scheme OMaps \
|
||||
-configuration Release \
|
||||
-destination 'generic/platform=iOS' \
|
||||
-quiet \
|
||||
|
||||
14
.github/workflows/ios-check.yaml
vendored
14
.github/workflows/ios-check.yaml
vendored
@@ -15,7 +15,6 @@ jobs:
|
||||
LANGUAGE: en_US.UTF-8
|
||||
LC_ALL: en_US.UTF-8
|
||||
TEST_RESULTS_BUNDLE_NAME: CoMaps-Test-Results
|
||||
SIMULATOR_DEVICE: 'iPhone 16 Pro Max'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -51,15 +50,12 @@ jobs:
|
||||
if: matrix.buildType == 'Debug'
|
||||
shell: bash
|
||||
run: |
|
||||
# Start sim before the build to make sure it's booted when tests start.
|
||||
xcrun simctl boot "${{ env.SIMULATOR_DEVICE }}" || true
|
||||
xcrun simctl bootstatus "${{ env.SIMULATOR_DEVICE }}" -b
|
||||
xcodebuild test \
|
||||
-workspace xcode/CoMaps.xcworkspace \
|
||||
-scheme CoMaps \
|
||||
-workspace xcode/omim.xcworkspace \
|
||||
-scheme OMaps \
|
||||
-configuration Debug \
|
||||
-sdk iphonesimulator \
|
||||
-destination "platform=iOS Simulator,name=${{ env.SIMULATOR_DEVICE }},OS=latest" \
|
||||
-destination 'platform=iOS Simulator,name=iPhone 16 Pro Max,OS=latest' \
|
||||
-quiet \
|
||||
-resultBundlePath ${{ env.TEST_RESULTS_BUNDLE_NAME }}.xcresult \
|
||||
CODE_SIGNING_REQUIRED=NO \
|
||||
@@ -78,8 +74,8 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
xcodebuild build \
|
||||
-workspace xcode/CoMaps.xcworkspace \
|
||||
-scheme CoMaps \
|
||||
-workspace xcode/omim.xcworkspace \
|
||||
-scheme OMaps \
|
||||
-configuration Release \
|
||||
-destination 'generic/platform=iOS' \
|
||||
-quiet \
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -62,7 +62,7 @@ iphone/*/build/*
|
||||
tools/emacsmode/build
|
||||
**/DerivedData/*
|
||||
**/xcshareddata/*
|
||||
!iphone/Maps/Maps.xcodeproj/xcshareddata/xcschemes/CoMaps.xcscheme
|
||||
!iphone/Maps/Maps.xcodeproj/xcshareddata/xcschemes/OMaps.xcscheme
|
||||
**/xcuserdata
|
||||
**/xcschemes
|
||||
iphone/**/*.moved-aside
|
||||
|
||||
@@ -7,10 +7,6 @@ CoMaps contributors:
|
||||
(in alphabetic order)
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
clover sage
|
||||
Harry Bond <me@hbond.xyz>
|
||||
vikiawv
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Organic Maps (formerly OMaps) contributors:
|
||||
(in alphabetic order)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
To build, install and run e.g. a Web Debug version on your device/emulator: './gradlew runWebDebug'
|
||||
|
||||
Or to compile a redistributable Fdroid Test apk for testing: './gradlew assembleFdroidBeta'
|
||||
Or to compile a redistributable Fdroid Beta apk for testing: './gradlew assembleFdroidBeta'
|
||||
|
||||
Or to build test apks for all flavors: './gradlew assembleBeta'
|
||||
Or to build beta apks for all flavors: './gradlew assembleBeta'
|
||||
|
||||
To see all available build targets './gradlew tasks'
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ buildscript {
|
||||
// Detect flavors from the task name.
|
||||
def taskName = getGradle().getStartParameter().getTaskRequests().toString().toLowerCase()
|
||||
def isFdroid = taskName.contains('fdroid')
|
||||
def isBeta = taskName.contains('beta')
|
||||
|
||||
dependencies {
|
||||
classpath libs.android.tools
|
||||
@@ -296,6 +297,7 @@ android {
|
||||
ndk.debugSymbolLevel = 'symbol_table'
|
||||
}
|
||||
|
||||
// TODO(@pastk): rename to "test" everywhere in code
|
||||
beta {
|
||||
applicationIdSuffix '.test'
|
||||
versionNameSuffix '-test'
|
||||
|
||||
@@ -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,8 @@
|
||||
• 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 2. Juni
|
||||
• Neue Einstellungsoption zum Ändern oder Ausblenden der "Über CoMaps" Schaltfläche ganz links
|
||||
• Routen als GPS Track speichern
|
||||
• Qingdao Metro, Gärtnereien, Leitplanken, Leitern, Studios, Tanzsäle, Feuerstellen und Stundenhotels hinzugefügt
|
||||
• transparente Navigationsleiste im Light Mode
|
||||
• Mastodon und Bluesky Kontaktoptionen für POIs und im OSM-Editor hinzugefügt
|
||||
• Anzeige der Kompassgradzahl in der Richtungspfeilansicht
|
||||
• Übersetzungen aktualisiert
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
• 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 2
|
||||
• add a setting to change the leftmost button or hide it
|
||||
• save built routes as tracks
|
||||
• add Qingdao metro, plant nurseries, highway guard rails, ladders, studios, dance venues, firepits, love hotels
|
||||
• transparent system navigation bar in the light mode
|
||||
• add Mastodon and Bluesky contact options to POIs and OSM editor
|
||||
• display Azimuth angle in direction arrow view
|
||||
• update translations
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
• 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
|
||||
@@ -1,32 +0,0 @@
|
||||
Yhteisövetoinen, ilmainen ja avoimeen lähdekoodiin perustuva karttasovellus, jonka pohjalla käytetään OpenStreetMapin avointa karttadataa. Sovelluksen kehityksessä on sitouduttu läpinäkyvyyteen, yksityisyyteen ja voittoa tavoittelemattomuuteen. CoMapsin projekti on haarautunut Organic Mapsista, joka taas on haarautunut aiemmin Maps.ME:stä
|
||||
|
||||
Lue lisää projektin tavotteista ja suunnasta osoitteesta <b><i>codeberg.org/comaps</i></b>.
|
||||
Liity yhteisöön ja auta kehittämään paras saatavilla oleva karttasovellus
|
||||
• Käytä sovellusta ja kerro siitä myös muille
|
||||
• Anna palautetta ja raportoi ongelmia
|
||||
• Päivitä karttoja, joko sovelluksessa tai OpenStreetMapin verkkosivuilla
|
||||
|
||||
‣ <b>Offline-painotteinen</b>: Suunnittele ja navigoi ulkomailla ilman mobiiliverkkoja. Kaikki sovelluksen toiminnot on suunniteltu käytettäväksi ilman verkkoyhteyttä.
|
||||
‣ <b>Kunnioittaa yksityisyyttä</b>: Sovellus on suunniteltu yksilön yksityisyys silmälläpitäen. Sovellus ei tunnista tai kerää tietoja sinusta. Mainosvapaa.
|
||||
‣ <b>Yksinkertainen ja viimeistelty</b>: Olennaiset ominaisuudet, joita on helppo käyttää.
|
||||
‣ <b>Säästä akkua ja tallennustilaa</b>: Ei kuluta akkua, kuten muut navigointisovellukset. Kompaktit kartat säästävät arvokasta tallennustilaa puhelimessasi.
|
||||
‣ <b>Ilmainen ja yhteisön luoma</b>: Vapaaehtoiset, kuten sinä olette auttaneet sovelluksen kehityksessä lisäämällä paikkoja OpenStreetMap:iin, testaamalla sovellusta ja antamalla palautetta. Voit myös auttaa kehittämällä ominaisuuksia ja lahjoittamalla sovelluskehitykseen
|
||||
‣ <b>Avoin ja läpinäkyvä päätöksenteko sekä rahoitus. Voittoa tavoittelematon ja täysin avoimeen lähdekoodiin perustuva.</b>
|
||||
|
||||
<b>Tärkeimmät ominaisuudet</b>:
|
||||
• Ladattavat yksityiskohtaiset kartat paikoista, joita ei löydy edes Google Maps:sta
|
||||
• Ulkoilutila, josta löytyy korostettuna reitit, leirintäpaikat, vesipisteet, huiput ja korkeuserot yms.
|
||||
• Kävely- ja pyörätiet
|
||||
• Kiinnostavat paikat, kuten ravintolat, huoltoasemat, hotellit, kaupat, nähtävyydet ja monta muuta
|
||||
• Etsi nimellä, osoitteella tai kiinnostavan paikan kategorialla
|
||||
• Navigointi ääni-ilmoituksilla kävellessä, pyöräillessä tai ajaessa
|
||||
• Tallenna suosikkipaikkasi yhdellä napautuksella
|
||||
• Offline Wikipedia-artikkelit
|
||||
• Maanalaisen liikenteen tasot ja ohjeet
|
||||
• Reittien tallennus
|
||||
• Tuo ja vie kirjanmerkkejä ja reittejä KML-, KMZ- ja GPX-formaateissa
|
||||
• Tumma tila iltaa ja yötä varten
|
||||
• Paranna karttadataa kaikille sisäänrakennetulla editorilla
|
||||
|
||||
<b>Vapaus on täällä</b>
|
||||
Löydä matkasi ja navigoi maailmalla yksityisyyden ja yhteisön tukemana!
|
||||
@@ -1 +1 @@
|
||||
CoMaps - Navigoi ilman verkkoyhteyttä yksityisesti
|
||||
CoMaps - Vaella, pyöräile, autoile ilman verkkoyhteyttä, yksityisesti
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
• 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 02 juin
|
||||
• Ajout d'une option pour personnaliser le bouton tout à gauche sur l'écran principal
|
||||
• Ajout de la possibilité d'enregistrer un itinéraire en tant que traces GPS
|
||||
• Ajout du métro de Qingdao, et divers objets sur la carte
|
||||
• Support de la barre de navigation transparent en mode clair
|
||||
• Ajout des tags Mastodon et Bluesky sur les lieux et dans l'éditeur
|
||||
• Affichage de l'azimut
|
||||
• Mise à jour des traductions
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
• Data di OpenStreetmap fino a giugno 2°
|
||||
• Nuova impostazione per cambiare o modificare la positione del tasto sinistra
|
||||
• Salvare i percorsi costruiti come tracce
|
||||
• È stato aggiunto: metropolitana di Qingdao, giardinaggi, guardrail, scale, studio,
|
||||
sala da ballo, focolari, love hotel
|
||||
• Barra di navigatione transparente di sisteme in moda luce
|
||||
• Aggiungi le opzioni di contatto Mastodon e Bluesky ai POI e all'editor di OSM
|
||||
• Visualizza l'angolo di azimut nella freccia di direzione
|
||||
@@ -1 +0,0 @@
|
||||
CoMaps - Wandel, fiets, rijdt offline met privacy
|
||||
@@ -1,8 +1,8 @@
|
||||
• 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
|
||||
• Dados do OSM de 2/06
|
||||
• Adicionada uma configuração para alterar ou ocultar o botão mais à esquerda
|
||||
• Salve rotas construídas como trilhas
|
||||
• Adicionado metrô de Qingdao, viveiros de plantas, guarda-corpos de rodovias, escadas, estúdios, casas de dança, fogueiras e motéis
|
||||
• Barra de navegação do sistema transparente no modo claro
|
||||
• Adicionadas opções de contato Mastodon e Bluesky aos POIs e ao editor OSM
|
||||
• Exibição de ângulo de azimute na visualização de seta de direção
|
||||
• Novas traduções
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
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 +0,0 @@
|
||||
Navegação fácil nos mapas - Descobre mais sobre o teu percurso - Feito por todos
|
||||
@@ -1 +1 @@
|
||||
CoMaps - Mapas e Navegação - Offline e Privada
|
||||
CoMaps - Andar, Pedalar, Dirigir Offline com Privacidade
|
||||
|
||||
@@ -1,33 +1,26 @@
|
||||
Бесплатное и свободное картографическое приложение, основанное на данных OpenStreetMap и подкреплённое обязательствами по прозрачности, конфиденциальности и некоммерческой направленности. CoMaps — это ответвление от Organic Maps, которое, в свою очередь, является ответвлением от Maps.ME.
|
||||
Бесплатное картографическое приложение с открытым исходным кодом, основанное на данных OpenStreetMap и подкрепленное обязательствами по прозрачности, конфиденциальности и некоммерческому характеру. CoMaps - это форк/ответвление Organic Maps, который, в свою очередь, является форком Maps.ME.
|
||||
|
||||
Подробнее о причинах проекта и его направлении читайте на <a href="https://codeberg.org/comaps">сайте</a>.
|
||||
|
||||
Присоединяйтесь к сообществу и помогите создать лучшее приложение с картами
|
||||
• Используйте приложение и распространяйте информацию о нём
|
||||
• Оставляйте отзывы и сообщайте о проблемах
|
||||
• Обновляйте данные карт в приложении или на веб-сайте OpenStreetMap
|
||||
|
||||
‣ <b>Приоритет на работу без интернета</b>: Планируйте и ориентируйтесь в путешествии за границей, не нуждаясь в сотовой связи и т.д. Всё в приложении рассчитано на работу в автономном режиме.
|
||||
‣ <b>Соблюдение конфиденциальности</b>: Приложение разработано с учётом требований конфиденциальности — оно не идентифицирует людей, не отслеживает и не собирает личную информацию. Без рекламы.
|
||||
‣ <b>Простота и отточенность</b>: Основные и простые в использовании функции, которые просто работают.
|
||||
‣ <b>Приоритет на работу без интернета</b>: Планируйте и ориентируйтесь в путешествии за границей, не нуждаясь в сотовой связи и т.д. Все функции приложения рассчитаны на работу в автономном режиме.
|
||||
‣ <b>Соблюдение конфиденциальности</b>: Приложение разработано с учетом требований конфиденциальности - оно не идентифицирует людей, не отслеживает и не собирает личную информацию. Без рекламы.
|
||||
‣ <b>Простота и Элегантность</b>: Необходимые и легкие в использовании функции, которые просто работают.
|
||||
‣ <b>Экономия заряда батареи и места на устройстве</b>: Не разряжает аккумулятор, как другие приложения для навигации. Компактные карты экономят драгоценное место на вашем телефоне.
|
||||
‣ <b>Бесплатное и созданное сообществом</b>: Такие люди, как и вы, помогали создавать приложение, добавляя места в OpenStreetMap, протестировав и оставляя отзывы о функциях, а также вложив свои навыки и деньги в разработку.
|
||||
‣ <b>Открытое и прозрачное принятие решений, финансовая отчётность, некоммерческая организация и полностью открытый исходный код.</b>
|
||||
‣ <b>Бесплатное и созданное сообществом</b>: Люди, подобные вам, помогали создавать приложение, добавляя места в OpenStreetMap, тестируя и оставляя отзывы о функциях, а также вкладывая свои навыки и деньги в разработку..
|
||||
‣ <b>Открытое и прозрачное принятие решений, финансовая отчетность, некоммерческая организация и полностью открытый исходный код.</b>
|
||||
|
||||
<b>Главные возможности</b>:
|
||||
• Скачиваемые и подробные карты с местами, которые недоступны в Google Maps
|
||||
• Уличный режим с отмеченными туристическими тропами, кемпингами, источниками воды, вершинами, контурными линиями и т.д.
|
||||
<b>Главные особенности</b>:
|
||||
• Загружаемые и подробные карты с местами, которые недоступны в Google Maps
|
||||
• Режим Outdoor с отмеченными туристическими тропами, кемпингами, источниками воды, вершинами, контурными линиями и т.д.
|
||||
• Пешеходные переходы и велодорожки
|
||||
• Интересные места, такие как: рестораны, заправочные станции, гостиницы, магазины, достопримечательности и многое другое
|
||||
• Поиск по названию или адресу или по категории достопримечательностей
|
||||
• Точки интереса, такие как: рестораны, заправочные станции, отели, магазины, достопримечательности и многое другое
|
||||
• Поиск по имени, адресу или категории достопримечательностей
|
||||
• Навигация с голосовыми уведомлениями для пешеходов, велосипедистов или водителей
|
||||
• Возможность добавлять любимые места в закладки одним нажатием
|
||||
• Скачиваемые страницы Википедии
|
||||
• Возможность добавлять любимые места в закладки одним касанием
|
||||
• Загружаемые страницы Википедии
|
||||
• Слой общественного транспорта (метро)
|
||||
• Запись маршрута
|
||||
• Экспорт и импорт закладок и маршрутов в форматах KML, KMZ, GPX
|
||||
• Тёмный режим для использования в ночное время
|
||||
• Улучшение данных карты для всех с помощью базового встроенного редактора
|
||||
• Темный режим для использования в ночное время
|
||||
• Улучшение картографических данных для всех с помощью базового встроенного редактора
|
||||
• Поддержка Android Auto и CarPlay
|
||||
|
||||
<b>Свобода здесь</b>
|
||||
Откройте для себя путешествия, навигацию по миру, ставя во главе приватность и сообщество!
|
||||
<i>Свобода здесь - Открой для себя поездки, навигацию по миру, ставя приватность и сообщество во главе</i>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
• обновлены цвета карты — теперь они светлее, теплее и дружелюбнее
|
||||
• редактор OSM: добавлено поле «этаж»
|
||||
• обновлены иконки заправок и зарядных станций
|
||||
• обновлены цвета некоторых элементов интерфейса
|
||||
• исправлена ссылка на карту при попытке поделиться местоположением
|
||||
• исправлено неверное отображение размера карты после ошибок загрузки
|
||||
• исправлены мелкие скачки стрелки местоположения в некоторых случаях
|
||||
• исправления ошибок для Android 5 и 6
|
||||
• карты OpenStreetMap от 2 июня
|
||||
• настройка для изменения функции левой кнопки или её скрытия
|
||||
• сохранение построенных маршрутов в виде треков
|
||||
• добавлены: метро в Qingdao, питомники растений, отбойники на шоссе, постоянные лестницы-стремянки, студии, места для танцев, кострища, отели любви
|
||||
• прозрачная полоска с системными кнопками (в светлом режиме)
|
||||
• в объекты на карте (а также в их редактор) добавлены Mastodon и Bluesky контакты
|
||||
• к стрелке направления на выбранный объект добавлен азимут
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Простая навигация по карте — Откройте больше за ваше путешествие. От сообщества
|
||||
@@ -1 +0,0 @@
|
||||
CoMaps - Карты и путешествия с приватностью
|
||||
@@ -1,8 +0,0 @@
|
||||
• освежене су боје мапе – светлије, топлије, пријатније!
|
||||
• у OSM едитору је додато поље „спрат“
|
||||
• ажуриране су иконице бензинских пумпи и станица за пуњење
|
||||
• ажуриране су боје неких елемената корисничког интерфејса
|
||||
• поправљени су линкови за дељење локације
|
||||
• поправљена је погрешно приказана величина мапе након грешака при преузимању
|
||||
• исправљена су мала поскакивања стрелице локације у неким случајевима
|
||||
• исправљене су грешке за Android 5 и 6
|
||||
@@ -1 +1 @@
|
||||
Једноставна навигација - Сазнајте више о свом путовању - Покреће је заједница
|
||||
Једноставна навигација - Сазнајте више о свом путовању - Захваљујући заједници
|
||||
|
||||
@@ -1,32 +1,2 @@
|
||||
OpenStreetMap'in verilerine ve kar amacı gütmeyen olma taahhüdündeki topluluk liderliğine dayanan şeffaflık, gizlilik, ücretsiz ve açık kaynaklı haritalar uygulaması. Comaps, Organic Maps çatalı/düzenlemesidir, bu da bir Maps.ME çatalıdır.
|
||||
|
||||
Projenin sebepleri ve rotası hakkında <b><i>codeberg.org/comaps</i></b> adresinden bilgi edinebilirsiniz.
|
||||
Oradaki topluluğa katılın ve en iyi harita uygulamasını yapmanıza yardımcı olun
|
||||
• Uygulamayı kullanın ve bu bilgiyi yayın
|
||||
• Geri bildirim verin ve sorunları bildirin
|
||||
• Uygulamada veya OpenStreetMap internet sitesinde harita verilerini güncelleyin
|
||||
|
||||
‣ <b>Çevrimdışı odaklı</b>: Hücresel veriye ihtiyaç duymadan yurt dışında seyahatinizi planlayın ve gezin, uzak bir yürüyüş sırasında durak noktaları arama, vb. Tüm uygulama işlevleri çevrimdışı çalışacak şekilde tasarlanmıştır.
|
||||
‣ <b>Gizliliğe saygı gösterir</b>: Uygulama gizlilik göz önünde bulundurularak tasarlanmıştır - insanları fişlemez, izlemez ve kişisel bilgileri toplamaz. Reklamsızdır.
|
||||
‣ <b>Basit ve parlak</b>: Sadece işe yarayan kullanımı kolay özellikler.
|
||||
‣ <b>Pilinizi ve hafızanızı kurtarın</b>: Pilinizi diğer gezinme uygulamaları gibi boşaltmaz. Sıkıştırılmış haritalar telefonunuzdaki değerli hafızadan tasarruf eder.
|
||||
‣ <b>Özgür ve topluluk tarafından inşa edilmiştir</b>: Sizin gibi insanlar, OpenStreetMap'e yerler ekleyerek, özellikleri test edip hakkında geri bildirim vererek, geliştirme becerileri ve paralarıyla katkıda bulunarak uygulamanın oluşturulmasına yardımcı oldu.
|
||||
‣ <b>Açık, şeffaf finans ve karar verme, kar amacı gütmeyen ve tamamen açık kaynaklı.</b>
|
||||
|
||||
<b>Ana Özellikler</b>:
|
||||
• Google Haritalarda mevcut olmayan yerlerle, indirilebilir ve ayrıntılı haritalar
|
||||
• Vurgulanmış yürüyüş parkurları, kamp alanları, su kaynakları, zirveler, yükseklik çizgileri, vb.
|
||||
• Yürüyüş ve bisiklet yolları
|
||||
• Lokantalar, benzin istasyonları, oteller, mağazalar, şahin tepeleri ve daha fazla ilgi çekici nokta
|
||||
• Ada, adrese veya ilgi alanına göre arayın
|
||||
• Yürüyüş, bisiklete binme veya sürüş için sesli bildirimlerle gezinme
|
||||
• En sevdiğiniz yerlere tek bir dokunuşla yer işareti koyun
|
||||
• Çevrimdışı Vikipedi makaleleri
|
||||
• Metro katmanı ve tarifler
|
||||
• Rota kaydı
|
||||
• KML, KMZ, GPX biçimlerindeki yer imlerini ve izlerini dışa veya içe aktarın
|
||||
• Gece boyunca kullanılacak karanlık kip
|
||||
• Temel yerleşik bir arayüz kullanan herkes için harita verilerini geliştirin
|
||||
|
||||
<b>Özgürlük Burada</b>
|
||||
Yolculuğunuzu keşfedin, dünyayı gizlilik ve topluluk desteğiyle gezin!
|
||||
Gönüllüler tarafından yürütülen, OpenStreetMap harita verisini kullanan, şeffaf, mahremiyete saygılı, kamu yararına olma kararlılığıyla güçlendirilmiş bir özgür yazılım. CoMaps OrganicMaps isimli, esasen Maps.ME'nin çatalı olan bir özgür yazılımın çatalıdır.
|
||||
Projenin ortaya çıkma sebebini ve gidişatını <b><i>codeberg.org/comaps</i></b>'den okuyabilirsiniz.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1 +1 @@
|
||||
CoMaps - Navigace se soukromím
|
||||
CoMaps – Navigace se soukromím
|
||||
|
||||
@@ -1 +1 @@
|
||||
CoMaps - Navi mit Datenschutz
|
||||
CoMaps: Navigation Datenschutz
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Una app sviluppata dalla comunità, gratuita e open-source, basata su OpenStreetMap e sull'impegno alla trasparenza, al rispetto della Privacy senza scopo di lucro.
|
||||
Una app sviluppata dalla comunità, gratuita e open-source, basata su OpenStreetMap e sull'impegno alla trasparenza, al rispetto della Privacy senza scopo di lucro. CoMaps è uno spin-off di Organic Maps, che a sua volta deriva da Maps.ME.
|
||||
|
||||
Unisciti alla nostra comunità e aiutaci a creare la migliore app di mappe.
|
||||
• usa l'app e consigliala
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Eenvoudige kaartnavigatie - Ontdek meer van je reis - Gemaakt door de community
|
||||
@@ -1 +0,0 @@
|
||||
CoMaps - Navigeer met privacy
|
||||
@@ -1,38 +0,0 @@
|
||||
Бесплатное и открытое приложение с картами, созданное сообществом на основе картографических данных OpenStreetMap и подкрепленное стремлением к прозрачности, уважению конфиденциальности и некоммерческой направленностью.
|
||||
|
||||
Подробнее о причинах проекта и его направлении читайте на <a href="https://codeberg.org/comaps">сайте</a>.
|
||||
|
||||
Присоединяйтесь к сообществу и помогите создать лучшее приложение с картами
|
||||
• Используйте приложение и распространяйте информацию о нём
|
||||
• Оставляйте отзывы и сообщайте о проблемах
|
||||
• Обновляйте данные карт в приложении или на веб-сайте OpenStreetMap
|
||||
|
||||
<i>Ваши отзыв и звёздочки будут для нас лучшей поддержкой!</i>
|
||||
|
||||
‣ <b>Приоритет на работу без интернета</b>: Планируйте и ориентируйтесь в путешествии за границей, не нуждаясь в сотовой связи и т.д. Всё в приложении рассчитано на работу в автономном режиме.
|
||||
‣ <b>Соблюдение конфиденциальности</b>: Приложение разработано с учётом требований конфиденциальности — оно не идентифицирует людей, не отслеживает и не собирает личную информацию. Без рекламы.
|
||||
‣ <b>Простота и отточенность</b>: Основные и простые в использовании функции, которые просто работают.
|
||||
‣ <b>Экономия заряда батареи и места на устройстве</b>: Не разряжает аккумулятор, как другие приложения для навигации. Компактные карты экономят драгоценное место на вашем телефоне.
|
||||
‣ <b>Бесплатное и созданное сообществом</b>: Такие люди, как и вы, помогали создавать приложение, добавляя места в OpenStreetMap, протестировав и оставляя отзывы о функциях, а также вложив свои навыки и деньги в разработку.
|
||||
‣ <b>Открытое и прозрачное принятие решений, финансовая отчётность, некоммерческая организация и полностью открытый исходный код.</b>
|
||||
|
||||
<b>Главные возможности</b>:
|
||||
• Скачиваемые и подробные карты с местами, которые недоступны в Google Maps
|
||||
• Уличный режим с отмеченными туристическими тропами, кемпингами, источниками воды, вершинами, контурными линиями и т.д.
|
||||
• Пешеходные переходы и велодорожки
|
||||
• Интересные места, такие как: рестораны, заправочные станции, гостиницы, магазины, достопримечательности и многое другое
|
||||
• Поиск по названию или адресу или по категории достопримечательностей
|
||||
• Навигация с голосовыми уведомлениями для пешеходов, велосипедистов или водителей
|
||||
• Возможность добавлять любимые места в закладки одним нажатием
|
||||
• Скачиваемые страницы Википедии
|
||||
• Слой общественного транспорта (метро)
|
||||
• Запись маршрута
|
||||
• Экспорт и импорт закладок и маршрутов в форматах KML, KMZ, GPX
|
||||
• Тёмный режим для использования в ночное время
|
||||
• Улучшение данных карты для всех с помощью базового встроенного редактора
|
||||
• Поддержка Андроид Авто
|
||||
|
||||
Пожалуйста сообщайте о ошибках, предлагайте идеи и присоединяйтесь к сообществу на сайте <a href="https://comaps.app">comaps.app</a>.
|
||||
|
||||
<b>Свобода!</b>
|
||||
Откройте для себя путешествия, навигацию по миру, ставя во главе приватность и сообщество!
|
||||
@@ -1 +0,0 @@
|
||||
Простая навигация по карте — Откройте больше за ваше путешествие. От сообщества
|
||||
@@ -1 +0,0 @@
|
||||
CoMaps - Оффлайн навигация
|
||||
@@ -1,6 +1,6 @@
|
||||
Бесплатна апликација за мапе отвореног кода коју води заједница заснована на OpenStreetMap подацима и ојачана посвећеношћу транспарентности, приватности и непрофитности.
|
||||
|
||||
Придружите се заједници и помозите да направимо најбољу навигацију
|
||||
Придружите се заједници и помозите да направите најбољу навигацију
|
||||
• Користите апликацију и ширите информације о њој
|
||||
• Оставите повратне информације и пријавите проблеме
|
||||
• Ажурирајте мапе из апликације или на сајту OpenStreetMap
|
||||
@@ -32,5 +32,5 @@
|
||||
|
||||
Молимо Вас да пријавите проблеме са апликацијом, предложите идеје и придружите се нашој заједници на <b><i>comaps.app</i></b> страни.
|
||||
|
||||
<b>Сад је слободна</b>
|
||||
<b>Сад је слободно</b>
|
||||
Откријте своје путовање, путујте светом с приватношћу и заједницом на челу!
|
||||
|
||||
@@ -1 +1 @@
|
||||
Једноставна навигација - Сазнајте више о свом путовању - Покреће је заједница
|
||||
Једноставна навигација - Сазнајте више о свом путовању - Захваљујући заједници
|
||||
|
||||
@@ -1 +1 @@
|
||||
CoMaps - Navigacija
|
||||
CoMaps - навигација
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
OpenStreetMap verilerine dayanan ve şeffaflık, gizlilik ve kar amacı gütmeyen olma taahhüdüyle güçlendirilen, topluluk tarafından yönetilen ücretsiz ve açık kaynaklı bir harita uygulaması.
|
||||
|
||||
Topluluğa katılın ve en iyi harita uygulamasını oluşturmaya yardımcı olun
|
||||
• Uygulamayı kullanın ve bunu herkese duyurun
|
||||
• Geri bildirimde bulunun ve sorunları bildirin
|
||||
• Harita verilerini uygulamada veya OpenStreetMap web sitesinde güncelleyin
|
||||
|
||||
<i>Geri bildirimleriniz ve 5 yıldızlı yorumlarınız bizim için en iyi destektir!</i>
|
||||
|
||||
‣ <b>Basit ve Cilalı</b>: sadece işe yarayan, kullanımı kolay temel özellikler.
|
||||
‣ <b>Çevrim dışı odaklı</b>: Cep telefonu hizmetine ihtiyaç duymadan yurtdışı seyahatinizi planlayın ve gezinin, uzun bir yürüyüş sırasında rota noktalarını arayın, vb. Tüm uygulama işlevleri çevrimdışı çalışmak üzere tasarlanmıştır.
|
||||
‣ <b>Gizliliğe Saygı</b>: Uygulama gizlilik düşünülerek tasarlanmıştır; kişileri tanımlamaz, takip etmez ve kişisel bilgi toplamaz. Reklamsız.
|
||||
‣ <b>Pilinizden ve Alanınızdan Tasarruf Edin</b>: Diğer navigasyon uygulamaları gibi pilinizi tüketmez. Kompakt haritalar telefonunuzda değerli alan tasarrufu sağlar.
|
||||
‣ <b>Ücretsiz ve Topluluk Tarafından Oluşturuldu</b>: Sizin gibi insanlar, OpenStreetMap'e yerler ekleyerek, özellikleri test ederek ve geri bildirimde bulunarak ve geliştirme becerilerinizi ve paranızı katkıda bulunarak uygulamanın oluşturulmasına yardımcı oldunuz..
|
||||
‣ <b>Açık ve Şeffaf Karar Alma ve Finansman, Kar Amacı Gütmeyen ve Tamamen Açık Kaynak.</b>
|
||||
|
||||
<b>Ana Özellikleri</b>:
|
||||
• Google Haritalar'da bulunmayan yerleri içeren indirilebilir detaylı haritalar
|
||||
• Vurgulanan yürüyüş parkurları, kamp alanları, su kaynakları, zirveler, kontur çizgileriyle açık hava modu gibi
|
||||
• Yürüyüş yolları ve bisiklet yolları
|
||||
• Restoranlar, benzin istasyonları, oteller, mağazalar, turistik yerler gibi ilgi çekici noktalar ve daha fazlası
|
||||
• İsme veya adrese göre veya ilgi noktası kategorisine göre arama yapın
|
||||
• Yürüyerek, bisikletle veya araçla seyahat edenler için sesli duyurularla navigasyon
|
||||
• Favori yerlerinizi tek bir dokunuşla yer imlerine ekleyin
|
||||
• Çevrim dışı Wikipedia makaleleri
|
||||
• Metro geçiş katmanı ve yönleri
|
||||
• Rota kaydı
|
||||
• Yer imlerini ve parkurları KML, KMZ, GPX formatlarında dışa ve içe aktarın
|
||||
• Geceleri kullanmak için karanlık mod
|
||||
• Temel bir yerleşik düzenleyici kullanarak herkes için harita verilerini iyileştirin
|
||||
• Android Auto desteği
|
||||
|
||||
Lütfen uygulama sorunlarını bildirin, fikir önerin ve <b><i>comaps.app</i></b> web sitesinde topluluğumuza katılın.
|
||||
|
||||
<b>Özgürlük Burada</b>
|
||||
Yolculuğunuzu keşfedin, gizlilik ve topluluk ön planda tutularak dünyayı keşfedin!
|
||||
@@ -1 +1 @@
|
||||
CoMaps - Gizlilikle Gezin
|
||||
CoMaps - Mahremiyetli Seyahat
|
||||
|
||||
@@ -44,7 +44,6 @@ 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;
|
||||
@@ -140,7 +139,6 @@ 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,
|
||||
@@ -255,8 +253,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
@NonNull
|
||||
private DisplayManager mDisplayManager;
|
||||
|
||||
private PeriodicBackupRunner backupRunner;
|
||||
|
||||
ManageRouteBottomSheet mManageRouteBottomSheet;
|
||||
|
||||
private boolean mRemoveDisplayListener = true;
|
||||
@@ -611,8 +607,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
*/
|
||||
if (Map.isEngineCreated())
|
||||
onRenderingInitializationFinished();
|
||||
|
||||
backupRunner = new PeriodicBackupRunner(this);
|
||||
}
|
||||
|
||||
private void onSettingsResult(ActivityResult activityResult)
|
||||
@@ -844,7 +838,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
@Override
|
||||
public String getPrefsName()
|
||||
{
|
||||
return getString(R.string.about_help);
|
||||
return getString(R.string.help);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1358,11 +1352,6 @@ 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
|
||||
@@ -2595,28 +2584,20 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
{
|
||||
if (id.equals(MAIN_MENU_ID))
|
||||
{
|
||||
final String activeLeftButton = buttonsHolder.getActiveButtonCode();
|
||||
ArrayList<MenuBottomSheetItem> items = new ArrayList<>();
|
||||
|
||||
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.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))
|
||||
items.add(new MenuBottomSheetItem(R.string.donate, R.drawable.ic_donate, this::onDonateOptionSelected));
|
||||
|
||||
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.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));
|
||||
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;
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,189 +0,0 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package app.organicmaps.bookmarks;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
@@ -20,9 +21,6 @@ import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
|
||||
import app.organicmaps.MwmApplication;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.adapter.OnItemClickListener;
|
||||
@@ -281,7 +279,7 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<Bookmark
|
||||
}
|
||||
|
||||
private void showNoFileManagerError() {
|
||||
new MaterialAlertDialogBuilder(requireActivity())
|
||||
new AlertDialog.Builder(requireActivity())
|
||||
.setMessage(R.string.error_no_file_manager_app)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> dialog.dismiss())
|
||||
.show();
|
||||
|
||||
@@ -69,8 +69,7 @@ public class Metadata implements Parcelable
|
||||
FMD_OUTDOOR_SEATING(48),
|
||||
FMD_NETWORK(49),
|
||||
FMD_CONTACT_FEDIVERSE(50),
|
||||
FMD_CONTACT_BLUESKY(51),
|
||||
FMD_PANORAMAX(52);
|
||||
FMD_CONTACT_BLUESKY(51);
|
||||
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.about_help));
|
||||
builder.setTitle(getCarContext().getString(R.string.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.about_help));
|
||||
builder.setTitle(getCarContext().getString(R.string.help));
|
||||
builder.setOnClickListener(() -> getScreenManager().push(new HelpScreen(getCarContext(), getSurfaceRenderer())));
|
||||
builder.setBrowsable(true);
|
||||
return builder.build();
|
||||
|
||||
@@ -11,6 +11,7 @@ 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;
|
||||
@@ -27,7 +28,6 @@ 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 MaterialTextView mName;
|
||||
private final MaterialTextView mSubtitle;
|
||||
private final MaterialTextView mFoundName;
|
||||
private final MaterialTextView mSize;
|
||||
private final TextView mName;
|
||||
private final TextView mSubtitle;
|
||||
private final TextView mFoundName;
|
||||
private final TextView 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 MaterialTextView mTitle;
|
||||
private final TextView mTitle;
|
||||
|
||||
HeaderViewHolder(@NonNull View frame)
|
||||
{
|
||||
|
||||
@@ -3,14 +3,13 @@ package app.organicmaps.downloader;
|
||||
import static android.Manifest.permission.POST_NOTIFICATIONS;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
|
||||
import android.app.ForegroundServiceStartNotAllowedException;
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.ServiceCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import java.util.List;
|
||||
@@ -41,11 +40,19 @@ public class DownloaderService extends Service implements MapManager.StorageCall
|
||||
Logger.i(TAG, "Downloading: " + MapManager.nativeIsDownloading());
|
||||
|
||||
var notification = mNotifier.buildProgressNotification();
|
||||
Logger.i(TAG, "Starting Downloader Foreground Service");
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
|
||||
ServiceCompat.startForeground(this, DownloaderNotifier.NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC);
|
||||
else
|
||||
ServiceCompat.startForeground(this, DownloaderNotifier.NOTIFICATION_ID, notification, 0);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
|
||||
{
|
||||
try
|
||||
{
|
||||
startForeground(DownloaderNotifier.NOTIFICATION_ID, notification);
|
||||
} catch (ForegroundServiceStartNotAllowedException e)
|
||||
{
|
||||
Logger.e(TAG, "Oops! ForegroundService is not allowed", e);
|
||||
}
|
||||
} else
|
||||
{
|
||||
startForeground(DownloaderNotifier.NOTIFICATION_ID, notification);
|
||||
}
|
||||
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
@@ -2,12 +2,11 @@ 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;
|
||||
@@ -16,7 +15,7 @@ import app.organicmaps.util.UiUtils;
|
||||
public class DownloaderStatusIcon
|
||||
{
|
||||
private final View mFrame;
|
||||
protected final ShapeableImageView mIcon;
|
||||
protected final ImageView mIcon;
|
||||
private final WheelProgressView mProgress;
|
||||
|
||||
private static final SparseIntArray sIconsCache = new SparseIntArray();
|
||||
|
||||
@@ -43,7 +43,7 @@ public class CopyrightFragment extends BaseMwmFragment
|
||||
{
|
||||
if (!mDelegate.onBackPressed())
|
||||
{
|
||||
((HelpActivity) requireActivity()).stackFragment(HelpFragment.class, getString(R.string.about_help), null);
|
||||
((HelpActivity) requireActivity()).stackFragment(HelpFragment.class, getString(R.string.help), null);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -43,21 +43,15 @@ public class LeftButtonsHolder
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getActiveButtonCode()
|
||||
public LeftButton getActiveButton()
|
||||
{
|
||||
String activeButtonCode = prefs.getString(leftButtonPreferenceKey, DEFAULT_BUTTON_CODE);
|
||||
if (!TextUtils.isEmpty(activeButtonCode))
|
||||
return activeButtonCode;
|
||||
return availableButtons.get(activeButtonCode);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public LeftButton getActiveButton()
|
||||
{
|
||||
return availableButtons.get(getActiveButtonCode());
|
||||
}
|
||||
|
||||
public Collection<LeftButton> getAllButtons()
|
||||
{
|
||||
return availableButtons.values();
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package app.organicmaps.location;
|
||||
|
||||
import android.app.ForegroundServiceStartNotAllowedException;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.location.Location;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
@@ -17,7 +17,6 @@ import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.app.NotificationChannelCompat;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.core.app.ServiceCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import app.organicmaps.MwmActivity;
|
||||
import app.organicmaps.MwmApplication;
|
||||
@@ -159,11 +158,21 @@ public class TrackRecordingService extends Service implements LocationListener
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
Logger.i(TAG, "Starting Track Recording Foreground service");
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
|
||||
ServiceCompat.startForeground(this, TrackRecordingService.TRACK_REC_NOTIFICATION_ID, getNotificationBuilder(this).build(), ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION);
|
||||
Logger.i(TAG, "Starting foreground service");
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
|
||||
{
|
||||
try
|
||||
{
|
||||
startForeground(TrackRecordingService.TRACK_REC_NOTIFICATION_ID, getNotificationBuilder(this).build());
|
||||
} catch (ForegroundServiceStartNotAllowedException e)
|
||||
{
|
||||
Logger.e(TAG, "Oops! ForegroundService is not allowed", e);
|
||||
}
|
||||
}
|
||||
else
|
||||
ServiceCompat.startForeground(this, TrackRecordingService.TRACK_REC_NOTIFICATION_ID, getNotificationBuilder(this).build(), 0);
|
||||
{
|
||||
startForeground(TrackRecordingService.TRACK_REC_NOTIFICATION_ID, getNotificationBuilder(this).build());
|
||||
}
|
||||
|
||||
final LocationHelper locationHelper = LocationHelper.from(this);
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ public class LayerBottomSheetItem
|
||||
case SUBWAY:
|
||||
disabledResource = R.attr.subwayMenuDisabled;
|
||||
enabledResource = R.attr.subwayMenuEnabled;
|
||||
buttonTextResource = R.string.subway;
|
||||
buttonTextResource = R.string.button_layer_subway;
|
||||
break;
|
||||
case ISOLINES:
|
||||
disabledResource = R.attr.isoLinesMenuDisabled;
|
||||
|
||||
@@ -43,7 +43,6 @@ public class LayersAdapter extends RecyclerView.Adapter<LayerHolder>
|
||||
boolean isEnabled = item.getMode().isEnabled(context);
|
||||
|
||||
holder.mButton.setSelected(isEnabled);
|
||||
holder.mButton.setContentDescription(context.getString(item.getTitle()));
|
||||
holder.mTitle.setSelected(isEnabled);
|
||||
holder.mTitle.setText(item.getTitle());
|
||||
boolean isNewLayer = SharedPropertiesUtils.shouldShowNewMarkerForLayerMode(context,
|
||||
|
||||
@@ -213,13 +213,11 @@ public class MapButtonsController extends Fragment
|
||||
)
|
||||
{
|
||||
leftButtonView.setImageResource(R.drawable.ic_christmas_tree);
|
||||
leftButtonView.setContentDescription(getString(R.string.about_help));
|
||||
leftButtonView.setOnClickListener((v) -> mMapButtonClickListener.onMapButtonClick(MapButtons.help));
|
||||
}
|
||||
else
|
||||
{
|
||||
mLeftButton.drawIcon(leftButtonView);
|
||||
leftButtonView.setContentDescription(mLeftButton.getPrefsName());
|
||||
leftButtonView.setOnClickListener((v) -> mLeftButton.onClick(leftButtonView));
|
||||
}
|
||||
// else
|
||||
@@ -484,10 +482,7 @@ public class MapButtonsController extends Fragment
|
||||
.build();
|
||||
ViewCompat.setOnApplyWindowInsetsListener(mFrame, insetsListener);
|
||||
// Fixes insets on older Androids and with a search opened via API on all Androids.
|
||||
if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.Q)
|
||||
mFrame.postDelayed(() -> ViewCompat.requestApplyInsets(mFrame), 1250);
|
||||
else
|
||||
mFrame.post(() -> ViewCompat.requestApplyInsets(mFrame));
|
||||
mFrame.post(() -> ViewCompat.requestApplyInsets(mFrame));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -266,8 +266,7 @@ public class NavigationController implements TrafficManager.TrafficCallback,
|
||||
mSpeedLimit.setSpeedLimit(0, false);
|
||||
return;
|
||||
}
|
||||
final int fSpeedLimit = StringUtils.nativeFormatSpeed(info.speedLimitMps);
|
||||
final boolean speedLimitExceeded = fSpeedLimit < StringUtils.nativeFormatSpeed(location.getSpeed());
|
||||
mSpeedLimit.setSpeedLimit(fSpeedLimit, speedLimitExceeded);
|
||||
final boolean speedLimitExceeded = info.speedLimitMps < location.getSpeed();
|
||||
mSpeedLimit.setSpeedLimit(StringUtils.nativeFormatSpeed(info.speedLimitMps), speedLimitExceeded);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static app.organicmaps.util.Constants.Vendor.XIAOMI;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.ForegroundServiceStartNotAllowedException;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.location.Location;
|
||||
@@ -27,7 +27,6 @@ import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.app.NotificationChannelCompat;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.core.app.ServiceCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import app.organicmaps.Framework;
|
||||
@@ -225,11 +224,21 @@ public class NavigationService extends Service implements LocationListener
|
||||
return START_NOT_STICKY; // The service will be stopped by stopSelf().
|
||||
}
|
||||
|
||||
Logger.i(TAG, "Starting Navigation Foreground service");
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
|
||||
ServiceCompat.startForeground(this, NavigationService.NOTIFICATION_ID, getNotificationBuilder(this).build(), ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION);
|
||||
Logger.i(TAG, "Starting foreground");
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
|
||||
{
|
||||
try
|
||||
{
|
||||
startForeground(NavigationService.NOTIFICATION_ID, getNotificationBuilder(this).build());
|
||||
} catch (ForegroundServiceStartNotAllowedException e)
|
||||
{
|
||||
Logger.e(TAG, "Oops! ForegroundService is not allowed", e);
|
||||
}
|
||||
}
|
||||
else
|
||||
ServiceCompat.startForeground(this, NavigationService.NOTIFICATION_ID, getNotificationBuilder(this).build(), 0);
|
||||
{
|
||||
startForeground(NavigationService.NOTIFICATION_ID, getNotificationBuilder(this).build());
|
||||
}
|
||||
|
||||
final LocationHelper locationHelper = LocationHelper.from(this);
|
||||
|
||||
|
||||
@@ -28,9 +28,6 @@ import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.imageview.ShapeableImageView;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
|
||||
import app.organicmaps.Framework;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.bookmarks.data.DistanceAndAzimut;
|
||||
@@ -70,21 +67,21 @@ final class RoutingBottomMenuController implements View.OnClickListener
|
||||
@NonNull
|
||||
private final ImageView mAltitudeChart;
|
||||
@NonNull
|
||||
private final MaterialTextView mTime;
|
||||
private final TextView mTime;
|
||||
@NonNull
|
||||
private final MaterialTextView mAltitudeDifference;
|
||||
private final TextView mAltitudeDifference;
|
||||
@NonNull
|
||||
private final TextView mTimeVehicle;
|
||||
@Nullable
|
||||
private final MaterialTextView mArrival;
|
||||
private final TextView mArrival;
|
||||
@NonNull
|
||||
private final View mActionFrame;
|
||||
@NonNull
|
||||
private final MaterialTextView mActionMessage;
|
||||
private final TextView mActionMessage;
|
||||
@NonNull
|
||||
private final View mActionButton;
|
||||
@NonNull
|
||||
private final ShapeableImageView mActionIcon;
|
||||
private final ImageView mActionIcon;
|
||||
@NonNull
|
||||
private final DotDividerItemDecoration mTransitViewDecorator;
|
||||
|
||||
@@ -101,10 +98,10 @@ final class RoutingBottomMenuController implements View.OnClickListener
|
||||
TextView error = (TextView) getViewById(activity, frame, R.id.error);
|
||||
Button start = (Button) getViewById(activity, frame, R.id.start);
|
||||
ImageView altitudeChart = (ImageView) getViewById(activity, frame, R.id.altitude_chart);
|
||||
MaterialTextView time = (MaterialTextView) getViewById(activity, frame, R.id.time);
|
||||
TextView time = (TextView) getViewById(activity, frame, R.id.time);
|
||||
TextView timeVehicle = (TextView) getViewById(activity, frame, R.id.time_vehicle);
|
||||
MaterialTextView altitudeDifference = (MaterialTextView) getViewById(activity, frame, R.id.altitude_difference);
|
||||
MaterialTextView arrival = (MaterialTextView) getViewById(activity, frame, R.id.arrival);
|
||||
TextView altitudeDifference = (TextView) getViewById(activity, frame, R.id.altitude_difference);
|
||||
TextView arrival = (TextView) getViewById(activity, frame, R.id.arrival);
|
||||
View actionFrame = getViewById(activity, frame, R.id.routing_action_frame);
|
||||
|
||||
return new RoutingBottomMenuController(activity, altitudeChartFrame, timeElevationLine, transitFrame,
|
||||
@@ -127,10 +124,10 @@ final class RoutingBottomMenuController implements View.OnClickListener
|
||||
@NonNull TextView error,
|
||||
@NonNull Button start,
|
||||
@NonNull ImageView altitudeChart,
|
||||
@NonNull MaterialTextView time,
|
||||
@NonNull MaterialTextView altitudeDifference,
|
||||
@NonNull TextView time,
|
||||
@NonNull TextView altitudeDifference,
|
||||
@NonNull TextView timeVehicle,
|
||||
@Nullable MaterialTextView arrival,
|
||||
@Nullable TextView arrival,
|
||||
@NonNull View actionFrame,
|
||||
@Nullable RoutingBottomMenuListener listener)
|
||||
{
|
||||
@@ -201,12 +198,12 @@ final class RoutingBottomMenuController implements View.OnClickListener
|
||||
|
||||
scrollToBottom(rv);
|
||||
|
||||
MaterialTextView totalTimeView = mTransitFrame.findViewById(R.id.total_time);
|
||||
TextView totalTimeView = mTransitFrame.findViewById(R.id.total_time);
|
||||
totalTimeView.setText(RoutingController.formatRoutingTime(mContext, info.getTotalTime(),
|
||||
R.dimen.text_size_routing_number));
|
||||
View dotView = mTransitFrame.findViewById(R.id.dot);
|
||||
View pedestrianIcon = mTransitFrame.findViewById(R.id.pedestrian_icon);
|
||||
MaterialTextView distanceView = mTransitFrame.findViewById(R.id.total_distance);
|
||||
TextView distanceView = mTransitFrame.findViewById(R.id.total_distance);
|
||||
UiUtils.showIf(info.getTotalPedestrianTimeInSec() > 0, dotView, pedestrianIcon, distanceView);
|
||||
distanceView.setText(info.getTotalPedestrianDistance() + " " + info.getTotalPedestrianDistanceUnits());
|
||||
}
|
||||
|
||||
@@ -38,17 +38,15 @@ public class RoutingErrorDialogFragment extends BaseRoutingErrorDialogFragment
|
||||
ResultCodesHelper.getDialogTitleSubtitle(requireContext(), mResultCode, mMissingMaps.size());
|
||||
Pair<String, String> titleMessage = resHolder.getTitleMessage();
|
||||
|
||||
if (!TextUtils.isEmpty(titleMessage.first))
|
||||
{
|
||||
TextView titleView = new TextView(requireContext());
|
||||
titleView.setText(titleMessage.first);
|
||||
titleView.setPadding(65, 32, 32, 16);
|
||||
titleView.setTextSize(18);
|
||||
titleView.setMaxLines(4);
|
||||
titleView.setEllipsize(TextUtils.TruncateAt.END);
|
||||
titleView.setTypeface(null, Typeface.BOLD);
|
||||
builder.setCustomTitle(titleView);
|
||||
}
|
||||
TextView titleView = new TextView(requireContext());
|
||||
titleView.setText(titleMessage.first);
|
||||
titleView.setPadding(65, 32, 32, 16);
|
||||
titleView.setTextSize(18);
|
||||
titleView.setMaxLines(4);
|
||||
titleView.setEllipsize(TextUtils.TruncateAt.END);
|
||||
titleView.setTypeface(null, Typeface.BOLD);
|
||||
builder.setCustomTitle(titleView);
|
||||
|
||||
mMessage = titleMessage.second;
|
||||
builder.setNegativeButton(resHolder.getCancelBtnResId(), null);
|
||||
if (ResultCodesHelper.isDownloadable(mResultCode, mMissingMaps.size()))
|
||||
|
||||
@@ -1,384 +0,0 @@
|
||||
package app.organicmaps.settings;
|
||||
|
||||
import static app.organicmaps.backup.BackupUtils.formatReadableFolderPath;
|
||||
import static app.organicmaps.backup.BackupUtils.getMaxBackups;
|
||||
import static app.organicmaps.backup.BackupUtils.isBackupFolderAvailable;
|
||||
import static app.organicmaps.util.StorageUtils.isFolderWritable;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.preference.ListPreference;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
|
||||
import java.text.DateFormat;
|
||||
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.backup.LocalBackupManager;
|
||||
import app.organicmaps.util.log.Logger;
|
||||
|
||||
|
||||
public class BackupSettingsFragment
|
||||
extends BaseXmlSettingsFragment
|
||||
{
|
||||
private ActivityResultLauncher<Intent> folderPickerLauncher;
|
||||
|
||||
private static final String TAG = LocalBackupManager.class.getSimpleName();
|
||||
public static final String BACKUP_FOLDER_PATH_KEY = "backup_location";
|
||||
public static final String LAST_BACKUP_TIME_KEY = "last_backup_time";
|
||||
private static final String BACKUP_NOW_KEY = "backup_now";
|
||||
public static final String BACKUP_INTERVAL_KEY = "backup_history_interval";
|
||||
public static final String MAX_BACKUPS_KEY = "backup_history_count";
|
||||
public static final int MAX_BACKUPS_DEFAULT_COUNT = 10;
|
||||
public static final String DEFAULT_BACKUP_INTERVAL = "86400000"; // 24 hours in ms
|
||||
|
||||
private LocalBackupManager mBackupManager;
|
||||
private SharedPreferences prefs;
|
||||
|
||||
@Override
|
||||
protected int getXmlResources()
|
||||
{
|
||||
return R.xml.prefs_backup;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@SuppressWarnings("NotNullFieldNotInitialized")
|
||||
Preference backupLocationOption;
|
||||
@NonNull
|
||||
@SuppressWarnings("NotNullFieldNotInitialized")
|
||||
ListPreference backupIntervalOption;
|
||||
@NonNull
|
||||
@SuppressWarnings("NotNullFieldNotInitialized")
|
||||
Preference maxBackupsOption;
|
||||
@NonNull
|
||||
@SuppressWarnings("NotNullFieldNotInitialized")
|
||||
Preference backupNowOption;
|
||||
@NonNull
|
||||
@SuppressWarnings("NotNullFieldNotInitialized")
|
||||
Preference advancedCategory;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
folderPickerLauncher = registerForActivityResult(
|
||||
new ActivityResultContracts.StartActivityForResult(),
|
||||
result -> {
|
||||
boolean isSuccess = false;
|
||||
|
||||
String lastFolderPath = prefs.getString(BACKUP_FOLDER_PATH_KEY, null);
|
||||
|
||||
if (result.getResultCode() == Activity.RESULT_OK)
|
||||
{
|
||||
Intent data = result.getData();
|
||||
Logger.i(TAG, "Folder selection result: " + data);
|
||||
if (data == null)
|
||||
return;
|
||||
|
||||
Uri uri = data.getData();
|
||||
if (uri != null)
|
||||
{
|
||||
takePersistableUriPermission(uri);
|
||||
Logger.i(TAG, "Backup location changed to " + uri);
|
||||
prefs.edit().putString(BACKUP_FOLDER_PATH_KEY, uri.toString()).apply();
|
||||
setFormattedBackupPath(uri);
|
||||
|
||||
runBackup();
|
||||
|
||||
isSuccess = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.w(TAG, "Folder selection result is null");
|
||||
}
|
||||
}
|
||||
else if (result.getResultCode() == Activity.RESULT_CANCELED)
|
||||
{
|
||||
Logger.w(TAG, "User canceled folder selection");
|
||||
if (TextUtils.isEmpty(lastFolderPath))
|
||||
{
|
||||
prefs.edit().putString(BACKUP_FOLDER_PATH_KEY, null).apply();
|
||||
Logger.i(TAG, "Backup settings reset");
|
||||
initBackupLocationOption();
|
||||
}
|
||||
else if (isFolderWritable(requireActivity(), lastFolderPath))
|
||||
{
|
||||
Logger.i(TAG, "Backup location not changed, using previous value " + lastFolderPath);
|
||||
isSuccess = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.e(TAG, "Backup location not changed, but last folder is not writable: " + lastFolderPath);
|
||||
}
|
||||
}
|
||||
|
||||
resetLastBackupTime();
|
||||
updateStatusSummaryOption();
|
||||
|
||||
Logger.i(TAG, "Folder selection result: " + isSuccess);
|
||||
applyAdvancedSettings(isSuccess);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey)
|
||||
{
|
||||
super.onCreatePreferences(savedInstanceState, rootKey);
|
||||
|
||||
prefs = PreferenceManager.getDefaultSharedPreferences(requireContext());
|
||||
backupLocationOption = findPreference(BACKUP_FOLDER_PATH_KEY);
|
||||
backupIntervalOption = findPreference(BACKUP_INTERVAL_KEY);
|
||||
maxBackupsOption = findPreference(MAX_BACKUPS_KEY);
|
||||
backupNowOption = findPreference(BACKUP_NOW_KEY);
|
||||
|
||||
initBackupLocationOption();
|
||||
initBackupIntervalOption();
|
||||
initMaxBackupsOption();
|
||||
initBackupNowOption();
|
||||
}
|
||||
|
||||
|
||||
private void initBackupLocationOption()
|
||||
{
|
||||
String storedFolderPath = prefs.getString(BACKUP_FOLDER_PATH_KEY, null);
|
||||
boolean isEnabled = false;
|
||||
if (!TextUtils.isEmpty(storedFolderPath))
|
||||
{
|
||||
if (isFolderWritable(requireContext(), storedFolderPath))
|
||||
{
|
||||
setFormattedBackupPath(Uri.parse(storedFolderPath));
|
||||
isEnabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.e(TAG, "Backup location is not available, path: " + storedFolderPath);
|
||||
showBackupErrorAlertDialog(requireContext().getString(R.string.dialog_report_error_missing_folder));
|
||||
backupLocationOption.setSummary(requireContext().getString(R.string.pref_backup_now_summary_folder_unavailable));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
backupLocationOption.setSummary(requireContext().getString(R.string.pref_backup_location_summary_initial));
|
||||
}
|
||||
|
||||
applyAdvancedSettings(isEnabled);
|
||||
|
||||
backupLocationOption.setOnPreferenceClickListener(preference -> {
|
||||
launchFolderPicker();
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private void setFormattedBackupPath(@NonNull Uri uri)
|
||||
{
|
||||
backupLocationOption.setSummary(formatReadableFolderPath(requireContext(), uri));
|
||||
}
|
||||
|
||||
private void initBackupIntervalOption()
|
||||
{
|
||||
String backupInterval = prefs.getString(BACKUP_INTERVAL_KEY, DEFAULT_BACKUP_INTERVAL);
|
||||
|
||||
CharSequence entry = getEntryForValue(backupIntervalOption, backupInterval);
|
||||
if (entry != null)
|
||||
backupIntervalOption.setSummary(entry);
|
||||
|
||||
backupIntervalOption.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
CharSequence newEntry = getEntryForValue(backupIntervalOption, newValue.toString());
|
||||
Logger.i(TAG, "auto backup interval changed to " + newEntry);
|
||||
if (newEntry != null)
|
||||
backupIntervalOption.setSummary(newEntry);
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private void initMaxBackupsOption()
|
||||
{
|
||||
maxBackupsOption.setSummary(String.valueOf(getMaxBackups(prefs)));
|
||||
|
||||
maxBackupsOption.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
maxBackupsOption.setSummary(newValue.toString());
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private void initBackupNowOption()
|
||||
{
|
||||
updateStatusSummaryOption();
|
||||
backupNowOption.setOnPreferenceClickListener(preference -> {
|
||||
runBackup();
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private void updateStatusSummaryOption()
|
||||
{
|
||||
long lastBackupTime = prefs.getLong(LAST_BACKUP_TIME_KEY, 0L);
|
||||
|
||||
String summary;
|
||||
if (lastBackupTime > 0)
|
||||
{
|
||||
String time = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(lastBackupTime);
|
||||
summary = requireContext().getString(R.string.pref_backup_status_summary_success) + ": " + time;
|
||||
}
|
||||
else
|
||||
{
|
||||
summary = requireContext().getString(R.string.pref_backup_now_summary);
|
||||
}
|
||||
|
||||
backupNowOption.setSummary(summary);
|
||||
}
|
||||
|
||||
private void resetLastBackupTime()
|
||||
{
|
||||
prefs.edit().remove(LAST_BACKUP_TIME_KEY).apply();
|
||||
}
|
||||
|
||||
private void applyAdvancedSettings(boolean isBackupEnabled)
|
||||
{
|
||||
backupIntervalOption.setVisible(isBackupEnabled);
|
||||
maxBackupsOption.setVisible(isBackupEnabled);
|
||||
backupNowOption.setVisible(isBackupEnabled);
|
||||
}
|
||||
|
||||
|
||||
private void runBackup()
|
||||
{
|
||||
String currentFolderPath = prefs.getString(BACKUP_FOLDER_PATH_KEY, null);
|
||||
if (!TextUtils.isEmpty(currentFolderPath))
|
||||
{
|
||||
if (isFolderWritable(requireContext(), currentFolderPath))
|
||||
{
|
||||
mBackupManager = new LocalBackupManager(requireActivity(), currentFolderPath, getMaxBackups(prefs));
|
||||
mBackupManager.setListener(new LocalBackupManager.Listener()
|
||||
{
|
||||
@Override
|
||||
public void onBackupStarted()
|
||||
{
|
||||
Logger.i(TAG, "Manual backup started");
|
||||
|
||||
backupNowOption.setEnabled(false);
|
||||
backupNowOption.setSummary(R.string.pref_backup_now_summary_progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackupFinished()
|
||||
{
|
||||
Logger.i(TAG, "Manual backup successful");
|
||||
|
||||
backupNowOption.setEnabled(true);
|
||||
backupNowOption.setSummary(R.string.pref_backup_now_summary_ok);
|
||||
|
||||
prefs.edit().putLong(LAST_BACKUP_TIME_KEY, System.currentTimeMillis()).apply();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackupFailed(LocalBackupManager.ErrorCode errorCode)
|
||||
{
|
||||
String errorMessage = switch (errorCode)
|
||||
{
|
||||
case EMPTY_CATEGORY -> requireContext().getString(R.string.pref_backup_now_summary_empty_lists);
|
||||
default -> requireContext().getString(R.string.pref_backup_now_summary_failed);
|
||||
};
|
||||
|
||||
Logger.e(TAG, "Manual backup was failed with code: " + errorCode);
|
||||
|
||||
backupNowOption.setEnabled(true);
|
||||
backupNowOption.setSummary(errorMessage);
|
||||
|
||||
showBackupErrorAlertDialog(requireContext().getString(R.string.dialog_report_error_with_logs));
|
||||
}
|
||||
});
|
||||
|
||||
mBackupManager.doBackup();
|
||||
}
|
||||
else
|
||||
{
|
||||
backupNowOption.setSummary(R.string.pref_backup_now_summary_folder_unavailable);
|
||||
showBackupErrorAlertDialog(requireContext().getString(R.string.dialog_report_error_missing_folder));
|
||||
Logger.e(TAG, "Manual backup error: folder " + currentFolderPath + " unavailable");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
backupNowOption.setSummary(R.string.pref_backup_now_summary_folder_unavailable);
|
||||
Logger.e(TAG, "Manual backup error: no folder selected");
|
||||
}
|
||||
}
|
||||
|
||||
private void launchFolderPicker()
|
||||
{
|
||||
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
||||
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
intent.putExtra("android.content.extra.SHOW_ADVANCED", true);
|
||||
|
||||
PackageManager packageManager = requireActivity().getPackageManager();
|
||||
if (intent.resolveActivity(packageManager) != null)
|
||||
folderPickerLauncher.launch(intent);
|
||||
else
|
||||
showNoFileManagerError();
|
||||
}
|
||||
|
||||
private void showNoFileManagerError()
|
||||
{
|
||||
new MaterialAlertDialogBuilder(requireActivity())
|
||||
.setMessage(R.string.error_no_file_manager_app)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> dialog.dismiss())
|
||||
.show();
|
||||
}
|
||||
|
||||
private void showBackupErrorAlertDialog(String message)
|
||||
{
|
||||
requireActivity().runOnUiThread(() -> {
|
||||
new MaterialAlertDialogBuilder(requireActivity())
|
||||
.setTitle(R.string.pref_backup_now_summary_failed)
|
||||
.setMessage(message)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> dialog.dismiss())
|
||||
.show();
|
||||
});
|
||||
}
|
||||
|
||||
private void takePersistableUriPermission(Uri uri)
|
||||
{
|
||||
requireContext().getContentResolver().takePersistableUriPermission(
|
||||
uri,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static CharSequence getEntryForValue(@NonNull ListPreference listPref, @NonNull CharSequence value)
|
||||
{
|
||||
CharSequence[] entryValues = listPref.getEntryValues();
|
||||
CharSequence[] entries = listPref.getEntries();
|
||||
|
||||
if (entryValues == null || entries == null)
|
||||
return null;
|
||||
|
||||
for (int i = 0; i < entryValues.length; i++)
|
||||
{
|
||||
if (entryValues[i].equals(value))
|
||||
return entries[i];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -184,15 +184,15 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment implements La
|
||||
{
|
||||
getSettingsActivity().stackFragment(VoiceInstructionsSettingsFragment.class, getString(R.string.pref_tts_enable_title), null);
|
||||
}
|
||||
else if (key.equals(getString(R.string.pref_help)))
|
||||
{
|
||||
startActivity(new Intent(requireActivity(), HelpActivity.class));
|
||||
}
|
||||
else if (key.equals(getString(R.string.pref_map_locale)))
|
||||
{
|
||||
LanguagesFragment langFragment = (LanguagesFragment)getSettingsActivity().stackFragment(LanguagesFragment.class, getString(R.string.change_map_locale), null);
|
||||
langFragment.setListener(this);
|
||||
}
|
||||
else if (key.equals(getString(R.string.pref_backup)))
|
||||
{
|
||||
getSettingsActivity().stackFragment(BackupSettingsFragment.class, getString(R.string.pref_backup_title), null);
|
||||
}
|
||||
}
|
||||
return super.onPreferenceTreeClick(preference);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package app.organicmaps.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -11,13 +10,10 @@ import android.provider.DocumentsContract;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.FileProvider;
|
||||
import androidx.documentfile.provider.DocumentFile;
|
||||
|
||||
import app.organicmaps.BuildConfig;
|
||||
import app.organicmaps.util.log.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
@@ -327,76 +323,4 @@ public class StorageUtils
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean copyFileToDocumentFile(
|
||||
@NonNull Activity activity,
|
||||
@NonNull File sourceFile,
|
||||
@NonNull DocumentFile targetFile
|
||||
)
|
||||
{
|
||||
try (
|
||||
InputStream in = new FileInputStream(sourceFile);
|
||||
OutputStream out = activity.getContentResolver().openOutputStream(targetFile.getUri())
|
||||
)
|
||||
{
|
||||
if (out == null)
|
||||
{
|
||||
Logger.e(TAG, "Failed to open output stream for " + targetFile.getUri());
|
||||
return false;
|
||||
}
|
||||
|
||||
byte[] buffer = new byte[8192];
|
||||
int length;
|
||||
|
||||
while ((length = in.read(buffer)) > 0)
|
||||
out.write(buffer, 0, length);
|
||||
|
||||
out.flush();
|
||||
return true;
|
||||
} catch (IOException e)
|
||||
{
|
||||
Logger.e(TAG, "Failed to copy file from " + sourceFile.getAbsolutePath() + " to " + targetFile.getUri(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void deleteDirectoryRecursive(@NonNull DocumentFile dir)
|
||||
{
|
||||
try
|
||||
{
|
||||
for (DocumentFile file : dir.listFiles())
|
||||
{
|
||||
if (file.isDirectory())
|
||||
deleteDirectoryRecursive(file);
|
||||
else
|
||||
file.delete();
|
||||
}
|
||||
dir.delete();
|
||||
} catch (Exception e)
|
||||
{
|
||||
Logger.e(TAG, "Failed to delete directory: " + dir.getUri(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isFolderWritable(Context context, String folderPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
Uri folderUri = Uri.parse(folderPath);
|
||||
DocumentFile folder = DocumentFile.fromTreeUri(context, folderUri);
|
||||
if (folder != null && folder.canWrite())
|
||||
{
|
||||
DocumentFile tempFile = folder.createFile("application/octet-stream", "temp_file");
|
||||
if (tempFile != null)
|
||||
{
|
||||
tempFile.delete();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
Logger.e(TAG, "Failed to check if folder is writable: " + folderPath, e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,6 @@ public final class PlacePageButtons extends Fragment implements Observer<List<Pl
|
||||
TextView title = parent.findViewById(R.id.title);
|
||||
|
||||
title.setText(current.getTitle());
|
||||
parent.setContentDescription(getString(current.getTitle()));
|
||||
@AttrRes final int tint = current.getType() == ButtonType.BOOKMARK_DELETE
|
||||
? R.attr.iconTintActive
|
||||
: R.attr.iconTint;
|
||||
|
||||
@@ -56,9 +56,6 @@ public class PlacePageLinksFragment extends Fragment implements Observer<MapObje
|
||||
private View mWikimedia;
|
||||
private TextView mTvWikimedia;
|
||||
|
||||
private View mPanoramax;
|
||||
private TextView mTvPanoramax;
|
||||
|
||||
private PlacePageViewModel mViewModel;
|
||||
private MapObject mMapObject;
|
||||
|
||||
@@ -166,11 +163,6 @@ public class PlacePageLinksFragment extends Fragment implements Observer<MapObje
|
||||
mTvLinePage = mFrame.findViewById(R.id.tv__place_line_page);
|
||||
mLinePage.setOnClickListener((v) -> openUrl(Metadata.MetadataType.FMD_CONTACT_LINE));
|
||||
mLinePage.setOnLongClickListener((v) -> copyUrl(mLinePage, Metadata.MetadataType.FMD_CONTACT_LINE));
|
||||
|
||||
mPanoramax = mFrame.findViewById(R.id.ll__place_panoramax);
|
||||
mTvPanoramax = mFrame.findViewById(R.id.tv__place_panoramax);
|
||||
mPanoramax.setOnClickListener((v) -> openUrl(Metadata.MetadataType.FMD_PANORAMAX));
|
||||
mTvPanoramax.setOnLongClickListener((v) -> copyUrl(mPanoramax, Metadata.MetadataType.FMD_PANORAMAX));
|
||||
}
|
||||
|
||||
private void openUrl(Metadata.MetadataType type)
|
||||
@@ -234,9 +226,6 @@ public class PlacePageLinksFragment extends Fragment implements Observer<MapObje
|
||||
|
||||
final String line = mMapObject.getMetadata(Metadata.MetadataType.FMD_CONTACT_LINE);
|
||||
refreshMetadataOrHide(line, mLinePage, mTvLinePage);
|
||||
|
||||
final String panoramax = mMapObject.getMetadata(Metadata.MetadataType.FMD_PANORAMAX);
|
||||
refreshMetadataOrHide(panoramax, mPanoramax, mTvPanoramax);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -23,7 +23,7 @@
|
||||
android:orientation="vertical"
|
||||
android:layout_marginEnd="@dimen/margin_base"
|
||||
android:layout_gravity="center_vertical" >
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -33,7 +33,7 @@
|
||||
tools:text="5 h 55 min • 1555km"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/altitude_difference"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/time"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="5 h 55 min • 1555km"/>
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/altitude_difference"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/altitude_chart_time_distance_height"
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
android:orientation="vertical"
|
||||
android:layout_marginEnd="@dimen/margin_base"
|
||||
android:layout_gravity="center_vertical" >
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -33,7 +33,7 @@
|
||||
tools:text="5 h 55 min • 1555km"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/altitude_difference"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -64,7 +64,7 @@
|
||||
tools:text="5 h 55 min • 1555km"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/arrival"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
android:id="@+id/numbers"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -13,7 +13,7 @@
|
||||
android:ellipsize="end"
|
||||
android:layout_marginBottom="4dp"
|
||||
tools:text="5 h 55 min • 1555km"/>
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/arrival"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -23,7 +23,7 @@
|
||||
tools:text="Arrival 13:03"
|
||||
style="@style/MwmWidget.TextView.PlanDetail.Number.Secondary"
|
||||
android:textSize="@dimen/text_size_routing_plan_detail_arrival"/>
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/altitude_difference"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<include
|
||||
layout="@layout/toolbar_extended"/>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="@dimen/settings_width"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="?actionBarSize"
|
||||
@@ -18,6 +18,6 @@
|
||||
style="@style/MwmWidget.FrameLayout.Elevation"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="@dimen/margin_half"
|
||||
android:layout_marginBottom="@dimen/margin_half">
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/time"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -31,7 +31,7 @@
|
||||
tools:text="5 h 55 min • 1555km"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/altitude_difference"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/altitude_chart_time_distance_height"
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
android:paddingEnd="@dimen/margin_base_plus"
|
||||
android:textAppearance="@style/MwmTextAppearance.Body2"
|
||||
android:visibility="gone"
|
||||
tools:text="Select maps to download"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<View
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
android:layout_marginEnd="@dimen/margin_base"
|
||||
android:layout_centerVertical="true"/>
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/size"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -37,7 +37,7 @@
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toEndOf="@id/downloader_status_frame"
|
||||
android:layout_toStartOf="@id/size">
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/found_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -46,7 +46,7 @@
|
||||
tools:text="Крымск"
|
||||
tools:background="#60FF00FF"/>
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -54,7 +54,7 @@
|
||||
tools:text="Донецкая область"
|
||||
tools:background="#40FF0000"/>
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/subtitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:background="#400000FF">
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
wheel:wheelSecondaryColor="?dividerHorizontal"
|
||||
wheel:wheelThickness="@dimen/margin_eighth"/>
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
<ImageView
|
||||
android:id="@+id/downloader_status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:textColorHint="?android:textColorSecondary"
|
||||
app:endIconMode="custom"
|
||||
app:endIconCheckable="false"
|
||||
app:endIconContentDescription="@string/clear"
|
||||
app:endIconDrawable="@drawable/ic_clear_rounded"
|
||||
app:endIconTint="?android:textColorSecondary">
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
@@ -81,7 +79,6 @@
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignEnd="@id/divideerrr"
|
||||
android:background="?clickableBackground"
|
||||
android:contentDescription="@string/bookmark_color"
|
||||
android:padding="@dimen/margin_half"
|
||||
tools:src="@drawable/ic_bookmark_none" />
|
||||
</RelativeLayout>
|
||||
|
||||
@@ -218,7 +218,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:textAppearance"
|
||||
android:text="@string/elevation_profile_time" />
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/help_button"
|
||||
style="@style/MwmWidget.MapButton.Square"
|
||||
android:contentDescription="@string/help"
|
||||
android:tint="@null"
|
||||
app:shapeAppearanceOverlay="@style/MwmWidget.MapButton.Square"
|
||||
app:srcCompat="@drawable/ic_question_mark" />
|
||||
@@ -21,5 +21,4 @@
|
||||
<include layout="@layout/place_page_line" />
|
||||
<include layout="@layout/place_page_bluesky" />
|
||||
<include layout="@layout/place_page_wikimedia" />
|
||||
<include layout="@layout/place_page_panoramax" />
|
||||
</LinearLayout>
|
||||
@@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/ll__place_panoramax"
|
||||
style="@style/PlacePageItemFrame"
|
||||
android:tag="website"
|
||||
tools:background="#20FF0000"
|
||||
tools:visibility="visible">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv__place_panoramax"
|
||||
style="@style/PlacePageMetadataIcon"
|
||||
app:srcCompat="@drawable/ic_panoramax"
|
||||
app:tint="?colorAccent"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv__place_panoramax"
|
||||
android:textAlignment="viewStart"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/MwmTextAppearance.PlacePage.Accent"
|
||||
tools:text="@string/panoramax"/>
|
||||
</LinearLayout>
|
||||
@@ -15,14 +15,14 @@
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:background="?clickableBackground">
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/ic_search"
|
||||
app:tint="?colorAccent"
|
||||
android:layout_marginStart="@dimen/margin_base"
|
||||
android:layout_marginEnd="@dimen/margin_base"/>
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/tv__message"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -49,7 +49,7 @@
|
||||
android:layout_marginBottom="@dimen/margin_half"
|
||||
android:layout_marginTop="@dimen/margin_half"
|
||||
android:background="?dividerHorizontal"/>
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
<ImageView
|
||||
android:id="@+id/iv__icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
android:paddingEnd="@dimen/margin_base"
|
||||
android:paddingBottom="@dimen/margin_half"
|
||||
android:paddingTop="@dimen/margin_half_plus">
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/total_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -18,7 +18,7 @@
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
style="@style/MwmWidget.TextView.PlanDetail.Number.Time"
|
||||
tools:text="40 min"/>
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/dot"
|
||||
style="@style/MwmWidget.TextView.PlanDetail.Number.Secondary"
|
||||
android:layout_marginStart="@dimen/margin_quarter_plus"
|
||||
@@ -28,7 +28,7 @@
|
||||
app:layout_constraintStart_toEndOf="@id/total_time"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:ignore="HardcodedText"/>
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
<ImageView
|
||||
android:id="@+id/pedestrian_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -37,7 +37,7 @@
|
||||
app:layout_constraintBottom_toBottomOf="@id/total_time"
|
||||
app:layout_constraintStart_toEndOf="@id/dot"
|
||||
app:tint="?iconTint"/>
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/total_distance"
|
||||
style="@style/MwmWidget.TextView.PlanDetail.Number.Secondary"
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/altitude_chart_time_distance_margin_bottom">
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/altitude_difference"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/altitude_chart_time_distance_height"
|
||||
@@ -19,7 +19,7 @@
|
||||
android:visibility="gone"
|
||||
tools:text="43 m"
|
||||
tools:visibility="visible"/>
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
<TextView
|
||||
android:id="@+id/time"
|
||||
android:layout_width="wrap_content"
|
||||
android:maxLines="2"
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_centerInParent="true"
|
||||
android:contentDescription="@string/route_type"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<app.organicmaps.widget.RoutingToolbarButton
|
||||
@@ -46,7 +45,6 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/routing_selector_wheel_margin"
|
||||
android:contentDescription="@string/vehicle"
|
||||
tools:button="@drawable/ic_car"
|
||||
tools:buttonTint="?colorAccent" />
|
||||
|
||||
@@ -56,7 +54,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:contentDescription="@string/pedestrian"
|
||||
tools:button="@drawable/ic_pedestrian"
|
||||
tools:buttonTint="?iconTintLight" />
|
||||
|
||||
@@ -65,7 +62,6 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/margin_half_plus"
|
||||
android:contentDescription="@string/subway"
|
||||
tools:button="@drawable/ic_transit"
|
||||
tools:buttonTint="?iconTintLight" />
|
||||
|
||||
@@ -74,7 +70,6 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:contentDescription="@string/bicycle"
|
||||
tools:button="@drawable/ic_bike"
|
||||
tools:buttonTint="?iconTintLight" />
|
||||
|
||||
@@ -83,7 +78,6 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:contentDescription="@string/ruler"
|
||||
tools:button="@drawable/ic_ruler_route"
|
||||
tools:buttonTint="?iconTintLight" />
|
||||
</RadioGroup>
|
||||
|
||||
@@ -493,7 +493,7 @@
|
||||
<!-- Title for OSM note section in the editor -->
|
||||
<string name="editor_other_info">Nota aan OpenStreetMap-vrywilligers (opsioneel)</string>
|
||||
<!-- Hint of the input field in the OSM note section of the editor -->
|
||||
<string name="editor_note_hint">Beskryf foute in die kaart of wat nie met CoMaps geredigeer kan word nie</string>
|
||||
<string name="editor_note_hint">Beskryf foute in die kaart of wat nie met Organiese Kaarte geredigeer kan word nie</string>
|
||||
<!-- Information about OSM at the top of the editing page -->
|
||||
<string name="editor_about_osm">Jou wysigings word opgelaai na die publieke <a href="https://wiki.openstreetmap.org/wiki/About_OpenStreetMap">OpenStreetMap</a>-databasis. Moet asseblief nie persoonlike of kopiereginligting byvoeg nie.</string>
|
||||
<string name="editor_more_about_osm">Meer oor OpenStreetMap</string>
|
||||
@@ -503,7 +503,7 @@
|
||||
<!-- To indicate the operator of ATMs, bicycle rentals, electric vehicle charging stations... -->
|
||||
<string name="operator">Operateur: %s</string>
|
||||
<string name="editor_category_unsuitable_title">Kan u nie \'n geskikte kategorie vind nie?</string>
|
||||
<string name="editor_category_unsuitable_text">CoMaps laat toe om slegs eenvoudige puntkategorieë by te voeg, dit beteken geen dorpe, paaie, mere, gebouomlynings, ens. Voeg asseblief sulke kategorieë direk by <a href="https://www.openstreetmap.org">OpenStreetMap.org</a>. Gaan ons <a href="https://www.comaps.app/support/advanced-map-editing/">gids</a> na vir gedetailleerde stap-vir-stap-instruksies.</string>
|
||||
<string name="editor_category_unsuitable_text">Organiese kaarte laat toe om slegs eenvoudige puntkategorieë by te voeg, dit beteken geen dorpe, paaie, mere, gebouomlynings, ens. Voeg asseblief sulke kategorieë direk by <a href="https://www.openstreetmap.org">OpenStreetMap.org</a>. Gaan ons <a href="https://www.comaps.app/support/advanced-map-editing/">gids</a> na vir gedetailleerde stap-vir-stap-instruksies.</string>
|
||||
<string name="downloader_no_downloaded_maps_title">U het geen kaarte afgelaai nie</string>
|
||||
<string name="downloader_no_downloaded_maps_message">Laai kaarte af om die ligging te soek en vanlyn te navigeer.</string>
|
||||
<string name="current_location_unknown_error_title">Huidige ligging is onbekend.</string>
|
||||
@@ -546,7 +546,7 @@
|
||||
<string name="editor_share_to_all_dialog_title">Wil u dit na alle gebruikers stuur?</string>
|
||||
<!-- Dialog before publishing the modifications to the public map. -->
|
||||
<string name="editor_share_to_all_dialog_message_1">Maak seker u het geen privaat of persoonlike data ingevoer nie.</string>
|
||||
<string name="editor_share_to_all_dialog_message_2">OpenStreetMap-redigeerders sal die verandeirnge nagaan en u kontak indien hulle vrae het.</string>
|
||||
<string name="editor_share_to_all_dialog_message_2">OpenStraatMap-redigeerders sal die verandeirnge nagaan en u kontak indien hulle vrae het.</string>
|
||||
<!-- Shown as toast when starting the recent track recording -->
|
||||
<string name="track_recording">Opname van die spoor</string>
|
||||
<!-- For the first routing -->
|
||||
@@ -616,7 +616,7 @@
|
||||
<string name="privacy_policy">Privaatheidsbeleid</string>
|
||||
<string name="terms_of_use">Gebruiksvoorwaardes</string>
|
||||
<string name="button_layer_traffic">Verkeer</string>
|
||||
<string name="subway">Moltrein</string>
|
||||
<string name="button_layer_subway">Moltrein</string>
|
||||
<string name="layers_title">Kaartstyle en -lae</string>
|
||||
<string name="subway_data_unavailable">Moltreinkaart is onbeskikbaar</string>
|
||||
<string name="bookmarks_empty_list_title">Hierdie lys is leeg</string>
|
||||
@@ -797,10 +797,4 @@
|
||||
<string name="uri_open_location_failed">Geen toepassing geïnstalleer wat die ligging kan oopmaak nie</string>
|
||||
<!-- preference string for using auto theme only in navigation mode -->
|
||||
<string name="nav_auto">Outo in navigasie</string>
|
||||
<string name="telegram_url">https://t.me/CoMapsApp/</string>
|
||||
<string name="osm_wiki_about_url">https://wiki.openstreetmap.org/wiki/About_OpenStreetMap</string>
|
||||
<string name="comma_separated_pair">%1$s, %2$s</string>
|
||||
<string name="tts_info_link">https://www.comaps.app/support/tts-configuration-guide-for-android/</string>
|
||||
<string name="translated_om_site_url">https://comaps.app/</string>
|
||||
<string name="instagram_url">https://www.instagram.com/comapscommunity</string>
|
||||
</resources>
|
||||
|
||||
@@ -567,6 +567,7 @@
|
||||
<string name="type.landuse.education">Opvoedkundige fasiliteit</string>
|
||||
<string name="type.landuse.farmland">Landbougrond</string>
|
||||
<string name="type.landuse.farmyard">Plaaswerf</string>
|
||||
<string name="type.landuse.field">Veld</string>
|
||||
<string name="type.landuse.forest">Woud</string>
|
||||
<string name="type.landuse.forest.coniferous">Naaldwoud</string>
|
||||
<string name="type.landuse.forest.deciduous">Loofwoud</string>
|
||||
|
||||
@@ -503,7 +503,7 @@
|
||||
<!-- Text in About and OSM Login screens. First %@ is replaced by a local, human readable date. -->
|
||||
<string name="osm_presentation">بيانات OpenStreetMap التي أنشأها المجتمع اعتبارًا من %s. تعرف على المزيد حول كيفية تعديل الخريطة وتحديثها على OpenStreetMap.org</string>
|
||||
<!-- OSM explanation on Android login screen -->
|
||||
<string name="login_osm_presentation">OpenStreetMap.org (OSM) هو مشروع مجتمعي لبناء خريطة مجانية ومفتوحة. إنه المصدر الرئيسي لبيانات الخرائط في CoMaps ويعمل على غرار ويكيبيديا. يمكنك إضافة الأماكن أو تعديلها وتصبح متاحة لملايين المستخدمين في جميع أنحاء العالم.\nنضم إلى المجتمع وساعد في إنشاء خريطة أفضل للجميع!</string>
|
||||
<string name="login_osm_presentation">OpenStreetMap.org (OSM) هو مشروع مجتمعي لبناء خريطة مجانية ومفتوحة. إنه المصدر الرئيسي لبيانات الخرائط في الخرائط العضوية ويعمل على غرار ويكيبيديا. يمكنك إضافة الأماكن أو تعديلها وتصبح متاحة لملايين المستخدمين في جميع أنحاء العالم. نضم إلى المجتمع وساعد في إنشاء خريطة أفضل للجميع!</string>
|
||||
<string name="login_to_make_edits_visible">أنشئ حساباً على OpenStreetMap أو سجّل الدخول لنشر تعديلاتك على الخريطة للعالم.</string>
|
||||
<!-- Downloaded 10 **of** 20 <- it is that "of" -->
|
||||
<string name="downloader_of">%1$d من%2$d</string>
|
||||
@@ -519,7 +519,7 @@
|
||||
<!-- Title for OSM note section in the editor -->
|
||||
<string name="editor_other_info">ملاحظة لمتطوعي OpenStreetMap (اختياري)</string>
|
||||
<!-- Hint of the input field in the OSM note section of the editor -->
|
||||
<string name="editor_note_hint">وصف الأخطاء على الخريطة أو الأشياء التي لا يمكن تحريرها باستخدام CoMaps</string>
|
||||
<string name="editor_note_hint">وصف الأخطاء على الخريطة أو الأشياء التي لا يمكن تحريرها باستخدام الخرائط العضوية</string>
|
||||
<!-- Information about OSM at the top of the editing page -->
|
||||
<string name="editor_about_osm">يتم تحميل تعديلاتك على قاعدة البيانات العامة <a href="https://wiki.openstreetmap.org/wiki/Ar:About_OpenStreetMap">OpenStreetMap</a>. يرجى عدم إضافة معلومات شخصية أو محمية بحقوق الطبع والنشر.</string>
|
||||
<string name="editor_more_about_osm">المزيد عن خريطة الشارع المفتوحة</string>
|
||||
@@ -598,7 +598,7 @@
|
||||
<!-- Settings: "Send general feedback" button -->
|
||||
<string name="feedback_general">تعقيب عام</string>
|
||||
<string name="prefs_languages_information">نحن نستخدم نظام تحويل النص إلى كلام (TTS) للتعليمات الصوتية. تستخدم العديد من أجهزة أندرويد نظام Google TTS، يمكنك تنزيله من أو تحديثه من متجر Play (https://play.google.com/store/apps/details?id=com.google.android.tts)</string>
|
||||
<string name="prefs_languages_information_off">بالنسبة لبعض اللغات، ستحتاج إلى تنزيل تطبيق تحويل النص إلى كلام أو حزمة لغات إضافية من متجر التطبيقات (متجر Play، متجر Galaxy، معرض التطبيقات، FDroid).\nافتح إعدادات جهازك، ثم اللغة والإدخال، ثم تحويل النص إلى كلام.\nهنا يمكنك إدارة إعدادات نظامي تحويل النص إلى كلام (على سبيل المثال، تنزيل حزمة لغات للاستخدام دون اتصال بالإنترنت).</string>
|
||||
<string name="prefs_languages_information_off">بالنسبة لبعض اللغات، ستحتاج إلى تنزيل تطبيق تحويل النص إلى كلام أو حزمة لغات إضافية من متجر التطبيقات(متجر Play، Galaxy Store، App Gallery، FDroid(. \nافتح إعدادات جهازك ثم اللغة والإدخال ثم تحويل النص إلى كلام. \nهنا يمكنك إدارة الإعدادات لأنظمة تحويل النص إلى كلا(على سبيل المثال، تنزيل حزمة اللغة للاستجدام دون اتصال انترنيت)</string>
|
||||
<string name="prefs_languages_information_off_link">لمزيد من المعلومات الرجاء مراجعة هذا الدليل.</string>
|
||||
<string name="transliteration_title">كتابة جميع الاسماء بالحروف اللاتينية بشكل حرفي</string>
|
||||
<string name="learn_more">معرفة المزيد</string>
|
||||
@@ -667,7 +667,7 @@
|
||||
<string name="privacy_policy">سياسة الخصوصية</string>
|
||||
<string name="terms_of_use">شروط الاستخدام</string>
|
||||
<string name="button_layer_traffic">حركة مرور</string>
|
||||
<string name="subway">مترو الانفاق</string>
|
||||
<string name="button_layer_subway">مترو الانفاق</string>
|
||||
<string name="layers_title">أنماط الخريطة وطبقاتها</string>
|
||||
<string name="subway_data_unavailable">خريطة مترو الانفاق غير متوفرة</string>
|
||||
<string name="bookmarks_empty_list_title">هذه اللائحة فارغة</string>
|
||||
@@ -821,9 +821,9 @@
|
||||
<!-- App tip #09 -->
|
||||
<string name="app_tip_09">هدفنا الرئيسي هو إنشاء خرائط سريعة وسهلة الاستخدام تركز على الخصوصية والتي ستعجبك.</string>
|
||||
<!-- Text on the Android Auto or CarPlay placeholder screen that maps are displayed on the phone screen -->
|
||||
<string name="car_used_on_the_phone_screen">أنت الآن تستخدم CoMaps على شاشة الهاتف</string>
|
||||
<string name="car_used_on_the_phone_screen">أنت الآن تستخدم الخرائط العضوية على شاشة الهاتف</string>
|
||||
<!-- Text on the phone placeholder screen that maps are displayed on the car screen -->
|
||||
<string name="car_used_on_the_car_screen">أنت الآن تستخدم CoMaps على شاشة السيارة</string>
|
||||
<string name="car_used_on_the_car_screen">أنت الآن تستخدم الخرائط العضوية على شاشة السيارة</string>
|
||||
<!-- Displayed on the phone screen. Android Auto connected -->
|
||||
<string name="aa_connected_title">أنت متصل بـ Android Auto</string>
|
||||
<!-- Displayed on the phone screen. Button to display maps on the phone screen instead of a car -->
|
||||
@@ -831,11 +831,11 @@
|
||||
<!-- Displayed on the Android Auto or CarPlay screen. Button to display maps on the car screen instead of a phone. Must be no more than 18 symbols! -->
|
||||
<string name="car_continue_in_the_car">إلى شاشة السيارة</string>
|
||||
<!-- Ask user to grant location permissions -->
|
||||
<string name="aa_location_permissions_request">تحتاج CoMaps ة إلى الوصول إلى الموقع. عندما يكون الوضع آمنًا، تحقق من الإشعارات الموجودة على هاتفك.</string>
|
||||
<string name="aa_location_permissions_request">تحتاج الخرائط العضوية إلى الوصول إلى الموقع. عندما يكون الوضع آمنًا، تحقق من الإشعارات الموجودة على هاتفك.</string>
|
||||
<!-- Notification title for permission request from AA. -->
|
||||
<string name="aa_request_permission_notification">هذا التطبيق يحتاج إلى إذنك</string>
|
||||
<!-- The text in the activity for location permission request. -->
|
||||
<string name="aa_request_permission_activity_text">تحتاج CoMaps في Android Auto إلى إذن تحديد الموقع للعمل بفعالية</string>
|
||||
<string name="aa_request_permission_activity_text">تحتاج الخرائط العضوية في Android Auto إلى إذن تحديد الموقع للعمل بفعالية</string>
|
||||
<!-- Grant Permissions button. -->
|
||||
<string name="aa_grant_permissions">أذونات المنح</string>
|
||||
<!-- Outdoors/hiking map style (activity) name in the Styles and Layers dialog -->
|
||||
@@ -886,9 +886,4 @@
|
||||
<string name="uri_open_location_failed">لم يتم تثبيت أي تطبيق يمكنه فتح الموقع</string>
|
||||
<!-- preference string for using auto theme only in navigation mode -->
|
||||
<string name="nav_auto">تلقائي في التنقل</string>
|
||||
<string name="translated_om_site_url">https://comaps.app/ar</string>
|
||||
<string name="telegram_url">https://t.me/CoMapsApp</string>
|
||||
<string name="tts_info_link">https://www.comaps.app/support/tts-configuration-guide-for-android</string>
|
||||
<string name="instagram_url">https://www.instagram.com/comapscommunity</string>
|
||||
<string name="wikimedia_commons">ويكيميديا كومنز</string>
|
||||
</resources>
|
||||
|
||||
@@ -594,6 +594,7 @@
|
||||
<string name="type.landuse.construction">منطقة بناء</string>
|
||||
<string name="type.landuse.education">مؤسسة تعليمية</string>
|
||||
<string name="type.landuse.farmland">حقل</string>
|
||||
<string name="type.landuse.field">حقل</string>
|
||||
<string name="type.landuse.flowerbed">مشتل أزهار</string>
|
||||
<string name="type.landuse.forest">غابة</string>
|
||||
<string name="type.landuse.forest.coniferous">غابة صنوبرية</string>
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
<string name="privacy">Privacidá</string>
|
||||
<string name="layers_title">Estilos y capes del mapa</string>
|
||||
<string name="subway_data_unavailable">El mapa del metro nun ta disponible</string>
|
||||
<string name="subway">Metro</string>
|
||||
<string name="button_layer_subway">Metro</string>
|
||||
<string name="delete_list">Desaniciar llista</string>
|
||||
<string name="public_access">Accesu públicu</string>
|
||||
<string name="bookmarks_empty_list_title">Esta llista ta balera</string>
|
||||
@@ -176,10 +176,4 @@
|
||||
<string name="choose_street">Escueyi una cai</string>
|
||||
<string name="select_option">Esbilla una opción</string>
|
||||
<string name="choose_color">Escueyi un color</string>
|
||||
<string name="telegram_url">https://t.me/CoMapsApp/</string>
|
||||
<string name="translated_om_site_url">https://comaps.app/</string>
|
||||
<string name="osm_wiki_about_url">https://wiki.openstreetmap.org/wiki/About_OpenStreetMap</string>
|
||||
<string name="tts_info_link">https://www.comaps.app/support/tts-configuration-guide-for-android/</string>
|
||||
<string name="instagram_url">https://www.instagram.com/comapscommunity</string>
|
||||
<string name="wikimedia_commons">Wikimedia Commons</string>
|
||||
</resources>
|
||||
|
||||
@@ -492,7 +492,7 @@
|
||||
<!-- Text in About and OSM Login screens. First %@ is replaced by a local, human readable date. -->
|
||||
<string name="osm_presentation">%s tarixinə icma tərəfindən yaradılmış OpenStreetMap datası. OpenStreetMap.org saytında xəritəni necə redaktə etmək və yeniləmək haqqında ətraflı məlumat əldə edin</string>
|
||||
<!-- OSM explanation on Android login screen -->
|
||||
<string name="login_osm_presentation">OpenStreetMap.org (OSM) pulsuz və açıq xəritə yaratmaq üçün icma layihəsidir. O, CoMaps xəritə məlumatlarının əsas mənbəyidir və Vikipediyaya oxşar işləyir. Siz yerlər əlavə edə və ya redaktə edə bilərsiniz və onlar bütün dünyada milyonlarla istifadəçi üçün əlçatan olur. \nİcmaya qoşulun və hər kəs üçün daha yaxşı xəritə yaratmağa kömək edin!</string>
|
||||
<string name="login_osm_presentation">OpenStreetMap.org (OSM) pulsuz və açıq xəritə yaratmaq üçün icma layihəsidir. O, Üzvi Xəritələrdə xəritə məlumatlarının əsas mənbəyidir və Vikipediyaya oxşar işləyir. Siz yerlər əlavə edə və ya redaktə edə bilərsiniz və onlar bütün dünyada milyonlarla istifadəçi üçün əlçatan olur. \nİcmaya qoşulun və hər kəs üçün daha yaxşı xəritə yaratmağa kömək edin!</string>
|
||||
<string name="login_to_make_edits_visible">OpenStreetMap hesabı yaradın və ya xəritə redaktələrinizi dünyada dərc etmək üçün daxil olun.</string>
|
||||
<!-- Downloaded 10 **of** 20 <- it is that "of" -->
|
||||
<string name="downloader_of">%1$d/%2$d</string>
|
||||
@@ -508,7 +508,7 @@
|
||||
<!-- Title for OSM note section in the editor -->
|
||||
<string name="editor_other_info">OpenStreetMap könüllüləri üçün qeyd (isteğe bağlı)</string>
|
||||
<!-- Hint of the input field in the OSM note section of the editor -->
|
||||
<string name="editor_note_hint">Xəritədəki səhvləri və ya CoMaps istifadə edərək redaktə edilə bilməyənləri təsvir edin</string>
|
||||
<string name="editor_note_hint">Xəritədəki səhvləri və ya Üzvi Xəritələrdən istifadə edərək redaktə edilə bilməyənləri təsvir edin</string>
|
||||
<!-- Information about OSM at the top of the editing page -->
|
||||
<string name="editor_about_osm">Redaktələriniz ictimai <a href="https://wiki.openstreetmap.org/wiki/Tr:About">OpenStreetMap</a> verilənlər bazasına yüklənir. Zəhmət olmasa şəxsi və ya müəllif hüquqları ilə qorunan məlumatları əlavə etməyin.</string>
|
||||
<string name="editor_more_about_osm">OpenStreetMap haqqında əlavə məlumat</string>
|
||||
@@ -518,7 +518,7 @@
|
||||
<!-- To indicate the operator of ATMs, bicycle rentals, electric vehicle charging stations... -->
|
||||
<string name="operator">Operator: %s</string>
|
||||
<string name="editor_category_unsuitable_title">Uyğun kateqoriya tapa bilmirsiniz?</string>
|
||||
<string name="editor_category_unsuitable_text">CoMaps yalnız sadə nöqtə kateqoriyaları əlavə etməyə imkan verir, bu o deməkdir ki, şəhərlər, yollar, göllər, bina konturları və s. yoxdur. Lütfən, belə kateqoriyaları birbaşa <a href="https://www.openstreetmap.org">OpenStreetMap.org</a> saytına əlavə edin. Ətraflı addım-addım təlimatlar üçün <a href="https://www.comaps.app/support/advanced-map-editing/">bələdçimizi</a> yoxlayın.</string>
|
||||
<string name="editor_category_unsuitable_text">Üzvi Xəritələr yalnız sadə nöqtə kateqoriyaları əlavə etməyə imkan verir, bu o deməkdir ki, şəhərlər, yollar, göllər, bina konturları və s. yoxdur. Lütfən, belə kateqoriyaları birbaşa <a href="https://www.openstreetmap.org">OpenStreetMap.org</a> saytına əlavə edin. Ətraflı addım-addım təlimatlar üçün <a href="https://www.comaps.app/support/advanced-map-editing/">bələdçimizi</a> yoxlayın.</string>
|
||||
<string name="downloader_no_downloaded_maps_title">Siz heç bir xəritə endirməmisiniz</string>
|
||||
<string name="downloader_no_downloaded_maps_message">Ünvanları tapmaq və oflayn naviqasiya etmək üçün xəritələri endirin.</string>
|
||||
<string name="current_location_unknown_error_title">Cari yer məlum deyil.</string>
|
||||
@@ -644,7 +644,7 @@
|
||||
<string name="privacy_policy">Gizlilik Siyasəti</string>
|
||||
<string name="terms_of_use">İstifadə qaydaları</string>
|
||||
<string name="button_layer_traffic">Nəqliyyat</string>
|
||||
<string name="subway">Metro</string>
|
||||
<string name="button_layer_subway">Metro</string>
|
||||
<string name="layers_title">Xəritə Üslubları və Qatları</string>
|
||||
<string name="subway_data_unavailable">Metro xəritəsi mövcud deyil</string>
|
||||
<string name="bookmarks_empty_list_title">Bu siyahı boşdur</string>
|
||||
@@ -671,7 +671,7 @@
|
||||
<string name="power_managment_setting_never">Heç vaxt</string>
|
||||
<string name="power_managment_setting_auto">Avtomatik</string>
|
||||
<string name="power_managment_setting_manual_max">Maksimum enerji qənaəti</string>
|
||||
<string name="enable_logging_warning_message">Yardım dialoq qutusunda “Problemi bildir” istifadə etməklə probleminizlə bağlı ətraflı diaqnostik jurnalları qeyd etmək və bizə göndərmək üçün bu seçimi müvəqqəti aktivləşdirin. Qeydlərə məkan məlumatı daxil ola bilər.</string>
|
||||
<string name="enable_logging_warning_message">Yardım dialoq qutusunda “Problemi bildir” istifadə etməklə probleminizlə bağlı ətraflı diaqnostik jurnalları qeyd etmək və bizə göndərmək üçün bu seçimi müvəqqəti aktivləşdirin. Qeydlərə məkan məlumatı daxil ola bilər</string>
|
||||
<string name="access_rules_author_only">Onlayn redaktə</string>
|
||||
<string name="driving_options_title">Marşrutlaşdırma seçimləri</string>
|
||||
<!-- Recommended length for CarPlay and Android Auto is around 25-27 characters -->
|
||||
@@ -682,7 +682,7 @@
|
||||
<string name="avoid_ferry">Bərə keçidlərindən çəkinin</string>
|
||||
<string name="avoid_motorways">Magistral yoldan çəkinin</string>
|
||||
<string name="unable_to_calc_alert_title">Marşrutu hesablamaq mümkün deyil</string>
|
||||
<string name="unable_to_calc_alert_subtitle">Təəssüf ki, seçdiyiniz seçimlərə görə marşrut tapa bilmədik. Seçimləri dəyişdirin və yenidən cəhd edin.</string>
|
||||
<string name="unable_to_calc_alert_subtitle">Təəssüf ki, seçdiyiniz seçimlərə görə marşrut tapa bilmədik. Seçimləri dəyişdirin və yenidən cəhd edin</string>
|
||||
<string name="define_to_avoid_btn">Qarşısını almaq üçün yolları müəyyənləşdirin</string>
|
||||
<string name="change_driving_options_btn">Sürmə seçimləri aktiv edildi</string>
|
||||
<string name="toll_road">Ücrətli yol</string>
|
||||
@@ -777,7 +777,7 @@
|
||||
<!-- Translated CoMaps site, add new translations here: https://github.com/organicmaps/organicmaps.github.io/tree/master/content -->
|
||||
<string name="translated_om_site_url">https://comaps.app/tr/</string>
|
||||
<!-- Link to OSM wiki for Editor, Profile and About pages -->
|
||||
<string name="osm_wiki_about_url">https://wiki.openstreetmap.org/wiki/Az:Layihə_haqqında</string>
|
||||
<string name="osm_wiki_about_url">https://wiki.openstreetmap.org/wiki/Tr:About</string>
|
||||
<!-- App Tip #00 -->
|
||||
<string name="app_tip_00">İcma tərəfindən yaradılmış xəritələrimizdən istifadə etdiyiniz üçün təşəkkür edirik!</string>
|
||||
<!-- App tip #04 -->
|
||||
@@ -840,8 +840,4 @@
|
||||
<string name="uri_open_location_failed">Məkanı aça biləcək proqram quraşdırılmayıb</string>
|
||||
<!-- preference string for using auto theme only in navigation mode -->
|
||||
<string name="nav_auto">Naviqasiyada avtomatik</string>
|
||||
<string name="telegram_url">https://t.me/CoMapsApp/</string>
|
||||
<string name="tts_info_link">https://www.comaps.app/support/tts-configuration-guide-for-android/</string>
|
||||
<string name="instagram_url">https://www.instagram.com/comapscommunity</string>
|
||||
<string name="wikimedia_commons">Vikianbar</string>
|
||||
</resources>
|
||||
|
||||
@@ -585,6 +585,7 @@
|
||||
<string name="type.landuse.construction">Struktur</string>
|
||||
<string name="type.landuse.farmland">Kənd Təsərrüfatı Torpaqları</string>
|
||||
<string name="type.landuse.farmyard">Ferma rayonu</string>
|
||||
<string name="type.landuse.field">Ərazi</string>
|
||||
<string name="type.landuse.flowerbed">Çiçəklik</string>
|
||||
<string name="type.landuse.forest">Meşə</string>
|
||||
<string name="type.landuse.forest.coniferous">Şam meşəsi</string>
|
||||
|
||||
@@ -636,7 +636,7 @@
|
||||
<string name="privacy_policy">Палітыка прыватнасці</string>
|
||||
<string name="terms_of_use">Умовы выкарыстання</string>
|
||||
<string name="button_layer_traffic">Рух</string>
|
||||
<string name="subway">Метро</string>
|
||||
<string name="button_layer_subway">Метро</string>
|
||||
<string name="layers_title">Стылі і слаі карты</string>
|
||||
<string name="subway_data_unavailable">Карта метро недаступная</string>
|
||||
<string name="bookmarks_empty_list_title">Гэты спіс пусты</string>
|
||||
@@ -880,8 +880,7 @@
|
||||
<item quantity="other">Знойдзена %d файлаў. Вы можаце ўбачыць іх пасля пераўтварэння.</item>
|
||||
</plurals>
|
||||
<string name="error_enter_correct_vk_page">Увядзіце сапраўднае імя карыстальніка або спасылку VK</string>
|
||||
<string name="wikimedia_commons">Вікісховішча</string>
|
||||
<string name="wikimedia_commons">Wikimedia Commons</string>
|
||||
<string name="comma_separated_pair">%1$s, %2$s</string>
|
||||
<string name="osm_wiki_about_url">https://wiki.openstreetmap.org/wiki/RU:О_проекте</string>
|
||||
<string name="instagram_url">https://www.instagram.com/comapscommunity</string>
|
||||
<string name="osm_wiki_about_url">https://wiki.openstreetmap.org/wiki/About_OpenStreetMap</string>
|
||||
</resources>
|
||||
|
||||
@@ -542,7 +542,7 @@
|
||||
<!-- Settings: "Send general feedback" button -->
|
||||
<string name="feedback_general">Обща обратна връзка</string>
|
||||
<string name="prefs_languages_information">Навигирането се озвучава от системен синтезатор на реч (TTS). Много устройства използват Google TTS, който може да бъде изтеглен или актуализиран от Google Play (https://play.google.com/store/apps/details?id=com.google.android.tts).</string>
|
||||
<string name="prefs_languages_information_off">За някои езици може да се наложи да инсталирате допълнителен синтезатор на реч (TTS) от магазина за приложения (Google Play, Samsung Galaxy Store, Huawei AppGallery, F-Droid). \nЗа да настроите синтезатора на реч, отидете в Настройки → Езици и въвеждане → Синтезиран говор. \nТук можете да инсталирате допълнителни езикови пакети или да изберете синтезатор на реч.</string>
|
||||
<string name="prefs_languages_information_off">За някои езици може да се наложи да инсталирате допълнителен синтезатор на реч (TTS) от магазина за приложения (Google Play Магазин, Galaxy Store). \nЗа да настроите синтезатора на реч, отидете в Настройки → Езици и въвеждане → Синтезиран говор. \nТук можете да инсталирате допълнителни езикови пакети или да изберете синтезатор на реч.</string>
|
||||
<string name="prefs_languages_information_off_link">За повече информация вижте това ръководство.</string>
|
||||
<string name="transliteration_title">Изпиши на латиница</string>
|
||||
<string name="learn_more">Научете повече</string>
|
||||
@@ -594,7 +594,7 @@
|
||||
<string name="privacy_policy">Политика за поверителност</string>
|
||||
<string name="terms_of_use">Условия за ползване</string>
|
||||
<string name="button_layer_traffic">Трафик</string>
|
||||
<string name="subway">Метро</string>
|
||||
<string name="button_layer_subway">Метро</string>
|
||||
<string name="layers_title">Стилове и слоеве на картата</string>
|
||||
<string name="subway_data_unavailable">Картата на метрото не е налична</string>
|
||||
<string name="bookmarks_empty_list_title">Този списък е празен</string>
|
||||
@@ -690,7 +690,7 @@
|
||||
<!-- OpenStreetMap text on splash screen -->
|
||||
<string name="splash_subtitle">Картографски данни от OpenStreetMap</string>
|
||||
<!-- Link to OSM wiki for Editor, Profile and About pages -->
|
||||
<string name="osm_wiki_about_url">https://wiki.openstreetmap.org/wiki/Bg:About_OpenStreetMap</string>
|
||||
<string name="osm_wiki_about_url">https://wiki.openstreetmap.org/wiki/Bg:About</string>
|
||||
<!-- App Tip #00 -->
|
||||
<string name="app_tip_00">Благодарим ви, че използвате нашите карти, създадени от общността!</string>
|
||||
<!-- App tip #01 -->
|
||||
@@ -824,7 +824,7 @@
|
||||
<string name="miles_per_hour">мили/ч</string>
|
||||
<string name="animals">Животни</string>
|
||||
<string name="buildings">Сгради</string>
|
||||
<string name="translated_om_site_url">https://comaps.app/</string>
|
||||
<string name="translated_om_site_url">https://www.comaps.app/</string>
|
||||
<string name="hotels">Хотели</string>
|
||||
<string name="others_sorttype">Други</string>
|
||||
<string name="month_ago_sorttype">Преди месец</string>
|
||||
@@ -838,5 +838,4 @@
|
||||
<string name="trip_finished">Пристигнахте!</string>
|
||||
<string name="instagram">Instagram</string>
|
||||
<string name="downloader_loading_ios">Изтегляне</string>
|
||||
<string name="wikimedia_commons">Общомедия</string>
|
||||
</resources>
|
||||
|
||||
@@ -10,30 +10,8 @@
|
||||
<string name="search">অনুসন্ধান</string>
|
||||
<string name="download_has_failed">ডাউনলোড ব্যর্থ। আবার চেষ্টা করতে টিপ দাও।</string>
|
||||
<string name="mb">এমবি</string>
|
||||
<string name="search_map">ম্যাপ অনুসন্ধান</string>
|
||||
<string name="search_map">মানচিত্র অনুসন্ধান</string>
|
||||
<string name="gb">জিবি</string>
|
||||
<string name="kilometres">কিলোমিটার</string>
|
||||
<string name="downloading">ডাউনলোডরত…</string>
|
||||
<string name="telegram_url">https://t.me/CoMapsApp/</string>
|
||||
<string name="osm_wiki_about_url">https://wiki.openstreetmap.org/wiki/About_OpenStreetMap</string>
|
||||
<string name="translated_om_site_url">https://comaps.app/</string>
|
||||
<string name="tts_info_link">https://www.comaps.app/support/tts-configuration-guide-for-android/</string>
|
||||
<string name="instagram_url">https://www.instagram.com/comapscommunity</string>
|
||||
<string name="app_site_url">https://comaps.app/</string>
|
||||
<string name="location_is_disabled_long_text">আপনার ডিভাইস বা অ্যাপ এর সব লোকেশন পরিষেবা বন্ধ করা আছে। দয়া করে সেটিংস থেকে চালু করুন।</string>
|
||||
<string name="close">বন্ধ</string>
|
||||
<string name="download">ডাউনলোড</string>
|
||||
<string name="limited_accuracy">সীমিত সঠিকতা</string>
|
||||
<string name="precise_location_is_disabled_long_text">সঠিক ন্যাভিগেশনের জন্য সেটিংস থেকে নিখুঁত লোকেশন অন করুন।</string>
|
||||
<string name="zoom_to_country">ম্যাপে দেখান</string>
|
||||
<string name="country_status_download_failed">ডাউনলোড ব্যর্থ হল</string>
|
||||
<string name="try_again">আবার চেষ্টা করুন</string>
|
||||
<string name="about_menu_title">CoMaps এর ব্যাপারে</string>
|
||||
<string name="about_headline">উন্মুক্ত প্রকল্প, তার সমাজ দ্বারা চলিত</string>
|
||||
<string name="location_settings">লোকেশন সেটিংস</string>
|
||||
<string name="about_proposition_1">• ব্যবহার করা সহজ এবং দেখতে সুন্দর</string>
|
||||
<string name="about_proposition_2">• গোপনীয়তা বান্ধব এবং বিজ্ঞাপন মুক্ত</string>
|
||||
<string name="about_proposition_3">• অফলাইন, দ্রুত এবং ছোট সাইজ</string>
|
||||
<string name="about_developed_by_enthusiasts">পুরোপুরি ওপেন সোর্স, অলাভজনক, প্রকাশ্য সিদ্ধান্ত করণ এবং অর্থায়ন।</string>
|
||||
<string name="wikimedia_commons">উইকিমিডিয়া কমন্স</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user