Compare commits

..

52 Commits

Author SHA1 Message Date
zyphlar
f8e2eb037f Fix conf path 2025-06-20 15:20:10 +00:00
zyphlar
7591e99cef Fix MwmDiff tool building 2025-06-19 12:51:08 +00:00
zyphlar
8584d6634e pastk4: s14>13 for poor 2025-06-19 12:26:02 +00:00
zyphlar
b8b529ca78 WIP Laos test gen 2025-06-19 12:21:14 +00:00
zyphlar
486babe27e Revert "Upgrade all high_f2 to high"
This reverts commit 2e7713568a.
2025-06-17 11:04:38 +00:00
zyphlar
fedbc2d57f pastk3: all > f2, poor > f4, high_f2 > s16 2025-06-17 11:04:19 +00:00
zyphlar
2e7713568a Upgrade all high_f2 to high 2025-06-16 14:18:48 +00:00
zyphlar
dfaac372ee Add all missing as poor 2025-06-16 14:17:19 +00:00
zyphlar
15fd7a0bd5 Upgrade poor to 100m f2 s14 2025-06-16 14:15:38 +00:00
zyphlar
467e97b231 Algeria Central to poor 2025-06-16 14:15:08 +00:00
zyphlar
2075b79dee Add new mwms as poor
Signed-off-by: zyphlar <zyphlar@gmail.com>
2025-06-16 14:12:41 +00:00
zyphlar
55d162f354 WIP Tune isolines profiles
Signed-off-by: zyphlar <zyphlar@gmail.com>
2025-06-16 10:18:44 +00:00
zyphlar
2fa1714575 WIP [cmake] Fix cppjansson build
Signed-off-by: zyphlar <zyphlar@gmail.com>
2025-06-16 10:06:44 +00:00
zyphlar
9a2dc676a7 Update generator scripts for docker/prod
Signed-off-by: zyphlar <zyphlar@gmail.com>
2025-06-11 01:34:00 +00:00
zyphlar
4bcf5a8f98 Add docker run script
Signed-off-by: zyphlar <zyphlar@gmail.com>
2025-06-11 01:04:21 +00:00
Konstantin Pastbin
6afa6a8476 Increase Features threads from 12 to 16
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-06-11 01:04:21 +00:00
zyphlar
b04bda4ff2 Update tools/unix/docker_maps_generator.sh
Signed-off-by: zyphlar <zyphlar@noreply.codeberg.org>
2025-06-11 01:04:21 +00:00
zyphlar
da150c87a5 Tweaks, get subway hooks proper
Signed-off-by: zyphlar <zyphlar@gmail.com>
2025-06-11 01:04:21 +00:00
Konstantin Pastbin
e17e122f0b Update subways path
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-06-11 01:04:21 +00:00
Konstantin Pastbin
96d9cbf1fa Update INI
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-06-11 01:04:21 +00:00
zyphlar
cf2fea216e Fix s3 variables
Signed-off-by: zyphlar <zyphlar@gmail.com>
2025-06-11 01:04:21 +00:00
zyphlar
2c9a85d5a3 Map generation mostly working, but slow and not doing full planet with add-ins yet
Signed-off-by: zyphlar <zyphlar@gmail.com>
2025-06-11 01:04:21 +00:00
zyphlar
42c30cb775 On-server tweaks
Signed-off-by: zyphlar <zyphlar@gmail.com>
2025-06-11 01:04:21 +00:00
zyphlar
c58f915063 Add files to automatically generate maps with Docker
Signed-off-by: zyphlar <zyphlar@gmail.com>
2025-06-11 01:04:21 +00:00
Viktor Govako
d754bf0e0a 4 threads for Taiwan_North search indexer.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-06-11 01:04:21 +00:00
Viktor Govako
622a5bf3bf Avoid py dependencies.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-06-11 01:04:21 +00:00
Viktor Govako
cecb9d9200 Do not inherit "oneway" and "surface" from Relation.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-06-11 01:04:21 +00:00
Viktor Govako
f731ff0612 Fixed hgt tile's grid traversal.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-06-11 01:04:21 +00:00
Alexander Borsuk
2524d074b4 Quotes support for CSV parser
Signed-off-by: Alexander Borsuk <me@alex.bio>
2025-06-11 01:04:21 +00:00
Viktor Govako
d56432e484 Borders 2025-06-11 01:04:21 +00:00
Viktor Govako
04b3c01816 Check default max speeds consistency.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-06-11 01:04:21 +00:00
Viktor Govako
8dc633bfd9 Added SrtmTileManager::GetBilinearHeight.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-06-11 01:04:21 +00:00
Viktor Govako
23f8a73ef6 Print SRTM tiles usage.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-06-11 01:04:21 +00:00
Viktor Govako
099ecde058 Added maxspeed OSM related warnings.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-06-11 01:04:21 +00:00
Viktor Govako
6d6140ee33 Fixed getting url bug.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-06-11 01:04:21 +00:00
Viktor Govako
623c4ed9fe Fixed altitude tiles cache bug.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-06-11 01:04:21 +00:00
Viktor Govako
b4cc6b140b Fixed races.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-06-11 01:04:21 +00:00
Viktor Govako
fca2a64a80 Added SrtmTileManager::GetTriangleHeight.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-06-11 01:04:21 +00:00
Viktor Govako
81c06f1ae7 Use pre-downloaded wiki descriptions.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-06-11 01:04:21 +00:00
Viktor Govako
2bfcf0089b Updated scripts.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-06-11 01:04:21 +00:00
Viktor Govako
0d08a53224 Added "tr" description language.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-06-11 01:04:21 +00:00
Viktor Govako
980bd36d02 Stop running StageMWM when any country was failed.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-06-11 01:04:21 +00:00
Viktor Govako
e16c8f3591 Get all URLs.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-06-11 01:04:21 +00:00
Viktor Govako
727c0db4b0 Enable StageDescriptions.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-06-11 01:04:21 +00:00
Viktor Govako
3b44a61f9d Set boost addr2line option for stacktrace.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-06-11 01:04:21 +00:00
Viktor Govako
3195450519 Fixed some 'double comparison' tests.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-06-11 01:04:20 +00:00
Viktor Govako
58f7c24620 Crash dump in topography_generator_tool.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-06-11 01:04:20 +00:00
Alexander Borsuk
bcf65ee2e5 Use release with debug info for easier crashlog analysis
Note: use tools/unix/build_omim.sh -R
2025-06-11 01:04:20 +00:00
vng
fc859c65d5 [tools] Build Release with Debug info with a script
TODO: Support this configuration in python generator build
2025-06-11 01:04:20 +00:00
vng
794f0f01aa Added LTO and -Ofast.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-06-11 01:04:20 +00:00
Alexander Borsuk
032183414b Fixed reading SRTM from squashfs 2025-06-11 01:04:20 +00:00
vng
aab883171d Added ASTER tif into SRTM hgt converter.
Signed-off-by: vng <viktor.govako@gmail.com>
2025-06-11 01:04:20 +00:00
1130 changed files with 21464 additions and 25407 deletions

View File

@@ -1,8 +0,0 @@
name: dco
on: [pull_request]
jobs:
check:
runs-on: codeberg-tiny
steps:
- uses: https://github.com/KineticCafe/actions-dco@v1

View File

@@ -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 \

View File

@@ -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 \

3
.gitignore vendored
View File

@@ -9,6 +9,7 @@ Makefile.Release
object_script.*.Debug
object_script.*.Release
compile_commands.json
*.local.*
stxxl.errlog
stxxl.log
@@ -62,7 +63,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

View File

@@ -31,6 +31,7 @@ if (NOT WITH_SYSTEM_PROVIDED_3PARTY)
set(JANSSON_WITHOUT_TESTS ON)
add_subdirectory(jansson/jansson/)
target_include_directories(jansson INTERFACE "${PROJECT_BINARY_DIR}/3party/jansson/jansson/include")
add_library(jansson::jansson ALIAS jansson)
# Add gflags library.
set(GFLAGS_BUILD_TESTING OFF)

View File

@@ -94,6 +94,11 @@ if (PLATFORM_WIN)
)
endif()
# Try fast native arch.
if (PLATFORM_LINUX)
add_compile_options(-march=native)
endif()
# Built-in CMake configurations: Debug, Release, RelWithDebInfo, MinSizeRel
if (${CMAKE_BUILD_TYPE} STREQUAL "Debug")
add_definitions(-DDEBUG)
@@ -103,12 +108,29 @@ if (${CMAKE_BUILD_TYPE} STREQUAL "Debug")
elseif (${CMAKE_BUILD_TYPE} MATCHES "Rel")
add_definitions(-DRELEASE)
if (NOT MSVC)
add_compile_options(-Ofast) # Also enables -ffast-math
add_compile_options(-Ofast $<$<CXX_COMPILER_ID:GNU>:-flto=auto>) # Also enables -ffast-math
endif()
else()
message(FATAL_ERROR "Unknown build type: " ${CMAKE_BUILD_TYPE})
endif()
if (${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo")
add_compile_options(-fno-omit-frame-pointer)
endif()
# Linux GCC LTO plugin fix.
if (PLATFORM_LINUX AND (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND (CMAKE_BUILD_TYPE MATCHES "^Rel"))
# To force errors if LTO was not enabled.
add_compile_options(-fno-fat-lto-objects)
# To fix ar and ranlib "plugin needed to handle lto object".
string(REGEX MATCH "[0-9]+" GCC_MAJOR_VERSION ${CMAKE_CXX_COMPILER_VERSION})
file(GLOB_RECURSE plugin /usr/lib/gcc/*/${GCC_MAJOR_VERSION}/liblto_plugin.so)
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> --plugin ${plugin} qcs <TARGET> <OBJECTS>")
set(CMAKE_C_ARCHIVE_FINISH "<CMAKE_RANLIB> --plugin ${plugin} <TARGET>")
set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> --plugin ${plugin} qcs <TARGET> <OBJECTS>")
set(CMAKE_CXX_ARCHIVE_FINISH "<CMAKE_RANLIB> --plugin ${plugin} <TARGET>")
endif()
message(STATUS "Build type: " ${CMAKE_BUILD_TYPE})
if (PLATFORM_LINUX OR PLATFORM_ANDROID)

View File

@@ -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)

View File

@@ -29,16 +29,16 @@
A community-led free & open source maps app based on [OpenStreetMap](https://www.openstreetmap.org) data and reinforced with commitment to transparency, privacy and being not-for-profit. CoMaps is a fork/spin-off of Organic Maps, which in turn is a fork of Maps.ME.
There are apps for Android and iOS (and ARM MacOS).
An alpha Linux / MacOS Qt desktop version, which is also suitable for Linux phones.
There are apps for Android and iOS (and ARM macOS).
An alpha linux / macOS Qt desktop version, which is also suitable for linux phones.
The June app release is available on Google Play, F-Droid and as an APK to download now! We are working on publishing in the iOS App Store as well, please stay tuned!
The first app release is available as an APK download now! We are still working on publishing on F-Droid, Google Play Store and iOS App Store as well, please stay tuned!
<!--
[<img src="docs/badges/apple-appstore.png" alt="App Store" width="160">](https://apps.apple.com/app/comaps/id1567437057)
[<img src="docs/badges/google-play.png" alt="Google Play" width="160">](https://play.google.com/store/apps/details?id=app.comaps)
[<img src="docs/badges/fdroid.png" alt="F-Droid" width="160">](https://f-droid.org/en/packages/app.comaps/)
-->
[<img src="docs/badges/google-play.png" alt="Google Play" width="160">](https://play.google.com/store/apps/details?id=app.comaps.google)
[<img src="docs/badges/fdroid.png" alt="F-Droid" width="160">](https://f-droid.org/en/packages/app.comaps.fdroid/)
[<img src="docs/badges/codeberg.png" alt="Codeberg" width="160">](https://codeberg.org/comaps/comaps/releases)
<p float="left">
@@ -52,7 +52,7 @@ The June app release is available on Google Play, F-Droid and as an APK to downl
**Respecting Privacy**: The app is designed with privacy in mind - does not identify people, does not track, and does not collect personal information. Ads-free.
**Simple and Polished**: Essential, easy to use features that just work.
**Simple and Polished**: essential easy to use features that just work.
**Saves Your Battery and Space**: Doesnt drain your battery like other navigation apps. Compact maps save precious space on your phone.

View File

@@ -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'

View File

@@ -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
@@ -168,7 +169,6 @@ android {
fdroid {
dimension 'default'
applicationIdSuffix '.fdroid'
versionName = android.defaultConfig.versionName + '-FDroid'
buildConfigField 'String', 'SUPPORT_MAIL', '"fdroid@comaps.app"'
}
@@ -296,6 +296,7 @@ android {
ndk.debugSymbolLevel = 'symbol_table'
}
// TODO(@pastk): rename to "test" everywhere in code
beta {
applicationIdSuffix '.test'
versionNameSuffix '-test'

View File

@@ -14,19 +14,21 @@ Můžete se zde také připojit ke komunitě pomáhat s vytvářením nejlepší
• <b>Otevřené a transparentní rozhodování a nakládání s financemi, neziskovost a plně otevřený zdrojový kód.</b>
<b>Hlavní funkce</b>:
• Stahovatelné podrobné mapy s místy, která nenajdete ani v Mapách Google
• Outdoorový režim se zvýrazněnými turistickými trasami, tábořišti, vodními zdroji, vrcholy, vrstevnicemi atd.
• Pěší trasy a cyklostezky
• Body zájmu, jako jsou restaurace, čerpací stanice, hotely, obchody, vyhlídky a mnoho dalšího
• Hledání podle názvu nebo adresy nebo podle kategorie bodů zájmu
• Navigace s hlasovými pokyny pro chůzi, jízdu na kole nebo řízení
• Uložení oblíbených míst jedním klepnutím
• Offline články z Wikipedie
• Vrstva metra a navigace v něm
• Záznam tras
• Export a import záložek a tras ve formátech KML, KMZ a GPX
• Tmavý režim k použití během noci
• Zlepšování mapových dat pro všechny pomocí jednoduchého vestavěného editoru
<ul>
<li>Stahovatelné podrobné mapy s místy, která nenajdete ani v Mapách Google</li>
<li>Outdoorový režim se zvýrazněnými turistickými trasami, tábořišti, vodními zdroji, vrcholy, vrstevnicemi atd.</li>
<li>Pěší trasy a cyklostezky</li>
<li>Body zájmu, jako jsou restaurace, čerpací stanice, hotely, obchody, vyhlídky a mnoho dalšího</li>
<li>Hledání podle názvu nebo adresy nebo podle kategorie bodů zájmu</li>
<li>Navigace s hlasovými pokyny pro chůzi, jízdu na kole nebo řízení</li>
<li>Uložení oblíbených míst jedním klepnutím</li>
<li>Offline články z Wikipedie</li>
<li>Vrstva metra a navigace v něm</li>
<li>Záznam tras</li>
<li>Export a import záložek a tras ve formátech KML, KMZ a GPX</li>
<li>Tmavý režim k použití během noci</li>
<li>Zlepšování mapových dat pro všechny pomocí jednoduchého vestavěného editoru</li>
</ul>
<b>Svoboda je tady</b>
Objevujte své cesty, navigujte se světem se soukromím a komunitou na prvním místě!

View File

@@ -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

View File

@@ -14,6 +14,7 @@ Werde Teil der Community und hilf mit, die beste Karten-App zu entwickeln
‣ <b>Offen und transparent bei Entscheidungen und Finanzen, gemeinnützig und vollständig Open-Source</b>
<b>Hauptfunktionen</b>:
<ul>
• Detaillierte, herunterladbare Karten mit Orten, die bei Google Maps oft fehlen
• Outdoor-Modus mit hervorgehobenen Wanderwegen, Campingplätzen, Wasserquellen, Gipfeln, Höhenlinien usw.
• Geh- und Radwege

View File

@@ -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

View File

@@ -14,19 +14,21 @@ Join the community there and help make the best maps app
‣ <b>Open and Transparent Decision-making and Financials, Not-for-profit and Fully Open Source.</b>
<b>Main Features</b>:
• Downloadable detailed maps with places which are not available with Google Maps
• Outdoor mode with highlighted hiking trails, campsites, water sources, peaks, contour lines, etc
• Walking paths and cycleways
• Points of interest like restaurants, gas stations, hotels, shops, sightseeings and many more
• Search by name or an address or by point of interest category
• Navigation with voice announcements for walking, cycling, or driving
• Bookmark your favorite places with a single tap
• Offline Wikipedia articles
• Subway transit layer and directions
• Track recording
• Export and import bookmarks and tracks in KML, KMZ, GPX formats
• A dark mode to use during the night
• Improve map data for everyone using a basic built-in editor
<ul>
<li>Downloadable detailed maps with places which are not available with Google Maps</li>
<li>Outdoor mode with highlighted hiking trails, campsites, water sources, peaks, contour lines, etc</li>
<li>Walking paths and cycleways</li>
<li>Points of interest like restaurants, gas stations, hotels, shops, sightseeings and many more</li>
<li>Search by name or an address or by point of interest category</li>
<li>Navigation with voice announcements for walking, cycling, or driving</li>
<li>Bookmark your favorite places with a single tap</li>
<li>Offline Wikipedia articles</li>
<li>Subway transit layer and directions</li>
<li>Track recording</li>
<li>Export and import bookmarks and tracks in KML, KMZ, GPX formats</li>
<li>A dark mode to use during the night</li>
<li>Improve map data for everyone using a basic built-in editor</li>
</ul>
<b>Freedom Is Here</b>
Discover your journey, navigate the world with privacy and community at the forefront!

View File

@@ -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

View File

@@ -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

View File

@@ -14,19 +14,21 @@ Liitu kogukonnaga ja aita luua parimat kaardirakendust:
‣ <b>Organisatsioon on avatud ja kasutab läbipaistvat otsustusprotsessi ning rahastamist ega taotle kasumit. Rakendus on avatud lähtekoodiga.</b>
<b>Põhifunktsionaalsused</b>:
• Allalaaditavad detailsed kaardid, mille sisu tihtipeale ei leia Google Mapsist
• Kaardivaade välitingimuste jaoks, kus matkarajad, laagriplatsid, allikad, mäetipud, kontuurjooned ja palju muud vajalikku on esile tõstetud
• Jalgrajad, rattateed ning maanteed
• Huvipunktid, nagu restoranid, tanklad, hotellid, poed, vaatamisväärsused ja palju muud
• Otsida saad nime, aadressi või huvipunkti kategooria alusel
• Tee juhatamine hääljuhiste abil toimib nii kõndimisel, rattasõidul kui auto juhtimisel
• Ühe puudutusega saad oma lemmikkohad märkida järjehoidjana
• Vikipeedia artiklid, mida saad lugeda ilma võrguühenduseta
• Metroode plaanid ja suunajuhised
• Raja või teekonna salvestamise võimalus
• Järjehoidjate ja radade eksport ning import KML, KMZ ja GPX vormingutes
• Tume kaardivaade kasutamiseks öösel
• Kasutades lihtsat muutmisliidest saad kaarti kõikide huvides täiendada
<ul>
<li>Allalaaditavad detailsed kaardid, mille sisu tihtipeale ei leia Google Mapsist</li>
<li>Kaardivaade välitingimuste jaoks, kus matkarajad, laagriplatsid, allikad, mäetipud, kontuurjooned ja palju muud vajalikku on esile tõstetud</li>
<li>Jalgrajad, rattateed ning maanteed</li>
<li>Huvipunktid, nagu restoranid, tanklad, hotellid, poed, vaatamisväärsused ja palju muud</li>
<li>Otsida saad nime, aadressi või huvipunkti kategooria alusel</li>
<li>Tee juhatamine hääljuhiste abil toimib nii kõndimisel, rattasõidul kui auto juhtimisel</li>
<li>Ühe puudutusega saad oma lemmikkohad märkida järjehoidjana</li>
<li>Vikipeedia artiklid, mida saad lugeda ilma võrguühenduseta</li>
<li>Metroode plaanid ja suunajuhised</li>
<li>Raja või teekonna salvestamise võimalus</li>
<li>Järjehoidjate ja radade eksport ning import KML, KMZ ja GPX vormingutes</li>
<li>Tume kaardivaade kasutamiseks öösel</li>
<li>Kasutades lihtsat muutmisliidest saad kaarti kõikide huvides täiendada</li>
</ul>
<b>Vabadus on siin</b>
Uuri maailma ja avasta uusi teid - tee seda privaatselt ja kogukonnaga arvestades!

View File

@@ -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!

View File

@@ -1 +1 @@
CoMaps - Navigoi ilman verkkoyhteyttä yksityisesti
CoMaps - Patikoi, pyöräile, autoile ilman verkkoyhteyttä yksityisesti

View File

@@ -14,19 +14,21 @@ Rejoignez la communauté et aidez-nous à créer la meilleure application de nav
‣ <b>Prises de décisions et comptes clairs et transparents, but non lucratif et complètement open source.</b>
<b>Fonctionnalités principales :</b>
• Cartes détaillées téléchargeables avec des lieux non disponibles sur Google Maps
• Mode extérieur avec sentiers de randonnée, campings, sources d'eau, sommets, courbes de niveau, etc. surlignés
• Chemins piétons et pistes cyclables
• Points d'intérêt comme des restaurants, stations-service, hôtels, magasins, lieux touristiques et bien plus
• Recherche par nom, adresse ou catégorie de point d'intérêt
• Navigation avec annonces vocales pour la marche, le vélo ou la conduite
• Mettez en favori vos lieux préférés en un seul clic
• Articles Wikipédia hors-ligne
• Plan de métro et indications pour s'y rendre
• Enregistrement des parcours
• Exportez et importez vos favoris aux formats KML, KMZ et GPX
• Mode sombre pour utiliser pendant la nuit
• Amélioration de la carte par tout le monde avec un éditeur simple intégré
<ul>
<li>Cartes détaillées téléchargeables avec des lieux non disponibles sur Google Maps</li>
<li>Mode extérieur avec sentiers de randonnée, campings, sources d'eau, sommets, courbes de niveau, etc. surlignés</li>
<li>Chemins piétons et pistes cyclables</li>
<li>Points d'intérêt comme des restaurants, stations-service, hôtels, magasins, lieux touristiques et bien plus</li>
<li>Recherche par nom, adresse ou catégorie de point d'intérêt</li>
<li>Navigation avec annonces vocales pour la marche, le vélo ou la conduite</li>
<li>Mettez en favori vos lieux préférés en un seul clic</li>
<li>Articles Wikipédia hors-ligne</li>
<li>Plan de métro et indications pour s'y rendre</li>
<li>Enregistrement des parcours</li>
<li>Exportez et importez vos favoris aux formats KML, KMZ et GPX</li>
<li>Mode sombre pour utiliser pendant la nuit</li>
<li>Amélioration de la carte par tout le monde avec un éditeur simple intégré</li>
</ul>
<b>La liberté est ici</b>
Découvrez votre voyage, naviguez dans le monde en plaçant la vie privée et la communauté au premier plan !

View File

@@ -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

View File

@@ -1 +1 @@
CoMaps - Rando, vélo, conduite hors ligne & privée
CoMaps - Randonnée, vélo, conduite hors ligne en toute confidentialité

View File

@@ -14,19 +14,21 @@ Pridružite se otvorenoj zajednici i pomozite izraditi najbolju aplikaciju za ka
‣ <b>Otvoreno i transparentno donošenje odluka i korištenja financija, Neprofitna i potpuno Otvorenog koda.</b>
<b>Glavne značajke</b>:
• Preuzimanje detaljnih karti s lokacijama koje nisu dostupne s Google kartama
• Karte za izlete s istaknutim pješačkim stazama, kampovima, izvorima vode, planinskim vrhovima, konturnim linijama itd.
• Pješačke i biciklističke staze
• Točke interesa kao što su restorani, benzinske crpke, hoteli, trgovine, vidikovci i još mnogo toga
• Pretražujte po nazivu ili adresi ili po kategoriji interesa
• Navigacija s glasovnim najavama za hodanje, vožnju biciklom ili automobilom
• Obilježite svoja omiljena mjesta jednim dodirom
• Offline članci Wikipedije
• Tranzitni sloj podzemne željeznice sa navigacijom
• Snimanje GPS tragova
• Izvoz i uvoz oznaka i staza u KML, KMZ, i GPX formatima
• Tamni način rada za korištenje tijekom noći
• Poboljšajte kartu za sve korisnike, koristeći osnovni ugrađeni uređivač karte
<ul>
<li>Preuzimanje detaljnih karti s lokacijama koje nisu dostupne s Google kartama</li>
<li>Karte za izlete s istaknutim pješačkim stazama, kampovima, izvorima vode, planinskim vrhovima, konturnim linijama itd.</li>
<li>Pješačke i biciklističke staze</li>
<li>Točke interesa kao što su restorani, benzinske crpke, hoteli, trgovine, vidikovci i još mnogo toga</li>
<li>Pretražujte po nazivu ili adresi ili po kategoriji interesa</li>
<li>Navigacija s glasovnim najavama za hodanje, vožnju biciklom ili automobilom</li>
<li>Obilježite svoja omiljena mjesta jednim dodirom</li>
<li>Offline članci Wikipedije</li>
<li>Tranzitni sloj podzemne željeznice sa navigacijom</li>
<li>Snimanje GPS tragova</li>
<li>Izvoz i uvoz oznaka i staza u KML, KMZ, i GPX formatima</li>
<li>Tamni način rada za korištenje tijekom noći</li>
<li>Poboljšajte kartu za sve korisnike, koristeći osnovni ugrađeni uređivač karte</li>
</ul>
<b>Sloboda je ovdje</b>
Otkrijte svoje putovanje, navigirajte svijetom s privatnošću i zajednicom na prvom mjestu!

View File

@@ -14,19 +14,21 @@ Unisciti alla nostra comunità e aiutaci a creare la migliore app di mappe.
‣ <b>Aperta e Trasparente nel Processo Decisionale e Finanziario, Senza Scopo di Lucro e Completamente Open Source</b>
<b>Funzionalità principali</b>:
• Scarica mappe dettagliate di luoghi che non sono disponibili su Google Maps
• Modalità Outdoor con percorsi escursionistici, campeggi, sorgenti d'acqua, picchi, dislivelli ed altro evidenziati
• Strade pedonali e piste ciclabili
• Punti d'interesse come ristoranti, stazioni di benzina, hotel, negozi, luoghi turistici e molto altro
• Cerca per nome, indirizzo o categoria
• Navigazione con assistente vocale a piedi, in bici o in macchina
• Salva i tuoi luoghi preferiti con un tocco
• Leggi gli articoli Wikipedia Offline
• Cartina delle metropolitane con direzioni
• Registrazione del percorso
• Esporta ed importa i tuoi luoghi preferiti e percorsi nei formati KML, KMZ o GPX
• Modalità notturna per la notte
• Migliora le mappe per tutti usando l'editor interno
<ul>
<li>Scarica mappe dettagliate di luoghi che non sono disponibili su Google Maps</li>
<li>Modalità Outdoor con percorsi escursionistici, campeggi, sorgenti d'acqua, picchi, dislivelli ed altro evidenziati</li>
<li>Strade pedonali e piste ciclabili</li>
<li>Punti d'interesse come ristoranti, stazioni di benzina, hotel, negozi, luoghi turistici e molto altro</li>
<li>Cerca per nome, indirizzo o categoria</li>
<li>Navigazione con assistente vocale a piedi, in bici o in macchina</li>
<li>Salva i tuoi luoghi preferiti con un tocco</li>
<li>Leggi gli articoli Wikipedia Offline</li>
<li>Cartina delle metropolitane con direzioni</li>
<li>Registrazione del percorso</li>
<li>Esporta ed importa i tuoi luoghi preferiti e percorsi nei formati KML, KMZ o GPX</li>
<li>Modalità notturna per la notte</li>
<li>Migliora le mappe per tutti usando l'editor interno</li>
</ul>
<b>La Libertà è Qui</b>
Esplora la tua nuova avventura, naviga il mondo con Privacy e la comunità in prima linea!

View File

@@ -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

View File

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

View File

@@ -15,19 +15,21 @@ Junte-se à comunidade e ajude a criar o melhor aplicativo de mapas.
‣ <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 categoria de ponto de interesse
• Navegação com anúncios de voz para caminhada, ciclismo ou direção
• Marque seus lugares favoritos com um único toque
• Artigos offline da Wikipédia
• Caminho de transporte e direções do metrô
• Gravação de trilhas
• Exporte e importe favoritos e trilhas em Formatos KML, KMZ, GPX
• Um modo escuro para usar à noite
• Aprimore os dados do mapa para todos usando um editor básico integrado
<ul>
<li>Mapas detalhados para download com locais não disponíveis no Google Maps</li>
<li>Modo ao ar livre com trilhas em destaque, acampamentos, fontes de água, picos, curvas de nível, etc.</li>
<li>Trilhas para caminhada e ciclovias</li>
<li>Pontos de interesse como restaurantes, postos de gasolina, hotéis, lojas, pontos turísticos e muito mais</li>
<li>Pesquise por nome, endereço ou categoria de ponto de interesse</li>
<li>Navegação com anúncios de voz para caminhada, ciclismo ou direção</li>
<li>Marque seus lugares favoritos com um único toque</li>
<li>Artigos offline da Wikipédia</li>
<li>Caminho de transporte e direções do metrô</li>
<li>Gravação de trilhas</li>
<li>Exporte e importe favoritos e trilhas em Formatos KML, KMZ, GPX</li>
<li>Um modo escuro para usar à noite</li>
<li>Aprimore os dados do mapa para todos usando um editor básico integrado</li>
</ul>
<b>A Liberdade Chegou</b>
Descubra sua jornada, navegue pelo mundo com privacidade e comunidade em primeiro lugar!

View File

@@ -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

View File

@@ -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!

View File

@@ -1 +0,0 @@
Navegação fácil nos mapas - Descobre mais sobre o teu percurso - Feito por todos

View File

@@ -1 +0,0 @@
CoMaps - Mapas e Navegação - Offline e Privada

View File

@@ -1,33 +1,28 @@
Бесплатное и свободное картографическое приложение, основанное на данных 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
• Уличный режим с отмеченными туристическими тропами, кемпингами, источниками воды, вершинами, контурными линиями и т.д.
• Пешеходные переходы и велодорожки
• Интересные места, такие как: рестораны, заправочные станции, гостиницы, магазины, достопримечательности и многое другое
• Поиск по названию или адресу или по категории достопримечательностей
• Навигация с голосовыми уведомлениями для пешеходов, велосипедистов или водителей
• Возможность добавлять любимые места в закладки одним нажатием
• Скачиваемые страницы Википедии
• Слой общественного транспорта (метро)
• Запись маршрута
• Экспорт и импорт закладок и маршрутов в форматах KML, KMZ, GPX
• Тёмный режим для использования в ночное время
• Улучшение данных карты для всех с помощью базового встроенного редактора
<b>Главные особенности</b>:
<ul>
<li>Загружаемые и подробные карты с местами, которые недоступны в Google Maps</li>
<li>Режим Outdoor с отмеченными туристическими тропами, кемпингами, источниками воды, вершинами, контурными линиями и т.д.</li>
<li>Пешеходные переходы и велодорожки</li>
<li>Точки интереса, такие как: рестораны, заправочные станции, отели, магазины, достопримечательности и многое другое</li>
<li>Поиск по имени, адресу или категории достопримечательностей</li>
<li>Навигация с голосовыми уведомлениями для пешеходов, велосипедистов или водителей</li>
<li>Возможность добавлять любимые места в закладки одним касанием</li>
<li>Загружаемые страницы Википедии</li>
<li>Слой общественного транспорта (метро)</li>
<li>Запись маршрута</li>
<li>Экспорт и импорт закладок и маршрутов в форматах KML, KMZ, GPX</li>
<li>Темный режим для использования в ночное время</li>
<li>Улучшение картографических данных для всех с помощью базового встроенного редактора</li>
<li>Поддержка Android Auto и CarPlay</li>
</ul>
<b>Свобода здесь</b>
Откройте для себя путешествия, навигацию по миру, ставя во главе приватность и сообщество!
<i>Свобода здесь - Открой для себя поездки, навигацию по миру, ставя приватность и сообщество во главе</i>

View File

@@ -1,8 +1,7 @@
обновлены цвета карты — теперь они светлее, теплее и дружелюбнее
редактор OSM: добавлено поле «этаж»
обновлены иконки заправок и зарядных станций
обновлены цвета некоторых элементов интерфейса
исправлена ссылка на карту при попытке поделиться местоположением
исправлено неверное отображение размера карты после ошибок загрузки
исправлены мелкие скачки стрелки местоположения в некоторых случаях
• исправления ошибок для Android 5 и 6
карты OpenStreetMap от 2 июня
настройка для изменения функции левой кнопки или её скрытия
сохранение построенных маршрутов в виде треков
добавлены: метро в Qingdao, питомники растений, отбойники на шоссе, постоянные лестницы-стремянки, студии, места для танцев, кострища, отели любви
прозрачная полоска с системными кнопками (в светлом режиме)
в объекты на карте (а также в их редактор) добавлены Mastodon и Bluesky контакты
к стрелке направления на выбранный объект добавлен азимут

View File

@@ -1 +0,0 @@
Простая навигация по карте — Откройте больше за ваше путешествие. От сообщества

View File

@@ -1 +0,0 @@
CoMaps - Карты и путешествия с приватностью

View File

@@ -1,33 +0,0 @@
Бесплатна апликација отвореног кода коју је обављала заједница и заснива се на ОпенСтреетМап-у подацима, усмерени транспарентност, приватност и непрофитни. ЦОМПАПС је Апликације за органске карте виљушка, које је пак форк мапс.ме.
Прочитајте о разлозима пројекта и његовог правца на <b><i>codeberg.org/comaps</i></b>
Придружите се отвореној заједници и помозите да направимо најбољу апликацију за мапе
• Користите апликацију и проширите глас о томе
• Дајте повратне информације и пријавите проблеме
• Ажурирајте податке на мапи у апликацији или на веб локацији OpenStreetMap
‣<b>фокусирано на офлајн Вар </b>: Планирајте и управљајте путовањем у иностранству без потребе за мобилним услугама, тражите путне тачке док је на даљинском покрету, итд.
Све апликације су дизајниране за рад ван мреже.
‣<b> Поштовање приватности </b>: Апликација је осмишљена задржавања у уму приватност - не идентификује људе, не прати или прикупља личне податке. Нема реклама.
‣ <b> Једноставно и елегантно </b>: Апликација је тривијална за употребу и једноставно функционише.
‣ <b> Чува вашу батерију и простор </b>: не конзумира батерију као остале навигационе апликације. Компактне картице сачувајте драгоцени простор на вашем телефону.
‣ <b> Отворено и направио је заједницу </b>: Људи попут вас је помогли да додају апликацију додавањем локација на OpenStreetMap-у, тестирању и давање повратних информација о апликацији и доприносе вашим развојним вештинама и новцу.
‣ <b> Отворено и транспарентно доношење одлука и употреба финансија, непрофитна и потпуно отворена извора. </ Б>
<b> Главне карактеристике </b>:
• Преузмите детаљне мапе са локацијама које нису доступне са Гоогле мапама
• Улазнице за излете са истакнутим планинарским стазама, камповима, изворима воде, планинске врхове, контурне линије итд.
• Стазе за планинарење и бицикле
• Тачке интереса као што су ресторани, бензинске пумпе, хотели, продавнице, погледа и још много тога
• Претражите име или адресу или по категоријама камате
• навигација са гласовним најавама за ходање, бициклизам или аутомобил
• Означите своја омиљена места једним додиром
• Офлајн чланци Википедије
• транзитни слој подземне пруге са навигацијом
• Снимање ГПС трагова
• Ознака и увоз и увоз у KML, KMZ, GPX формате
• Тамни режим за употребу током ноћи
• Побољшајте карту за све кориснике, користећи основни уредни уредник мапе
<b> Слобода је овде </b>
Откријте своје путовање, крећете се са свијетом са приватношћу и заједницом на првом месту!

View File

@@ -1,8 +0,0 @@
• освежене су боје мапе светлије, топлије, пријатније!
у OSM едитору је додато поље „спрат“
• ажуриране су иконице бензинских пумпи и станица за пуњење
• ажуриране су боје неких елемената корисничког интерфејса
• поправљени су линкови за дељење локације
• поправљена је погрешно приказана величина мапе након грешака при преузимању
• исправљена су мала поскакивања стрелице локације у неким случајевима
• исправљене су грешке за Android 5 и 6

View File

@@ -1 +1 @@
Једноставна навигација - Сазнајте више о свом путовању - Покреће је заједница
Једноставна навигација - Сазнајте више о свом путовању - Захваљујући заједници

View File

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

View File

@@ -1 +0,0 @@
Kolayca gezinin - Seyahat etmenin ötesini bulun - Gönüllüler tarafından yapıldı

View File

@@ -1 +0,0 @@
CoMaps - İnternetsiz Seyahat Edin

View File

@@ -14,19 +14,21 @@
‣ <b>决策问责、财务透明、非营利性、完全开源。</b>
<b>主要功能</b>
• 可下载详细的地图包括许多Google地图中未显示的地方
• 突出显示远足路线、露营地、水源、山峰、等高线等的户外模式
• 步行道和自行车道
• 餐厅、加油站、酒店、商店、景点等众多兴趣点
• 按名称、地址或兴趣点类别搜索
• 步行、骑车或驾驶时,可通过语音提示进行导航
• 一键收藏您中意的地点
• 离线阅读维基百科文章
• 地铁交通图层和路线指示
• 轨迹记录
• 以 KML、KMZ 和 GPX 格式导出和导入书签和轨迹
• 选择天暗后自动开启的黑暗模式
• 使用基本的内置编辑器来编辑 OpenStreetMap 地点,帮助大家改进地图数据
<ul>
<li>可下载详细的地图包括许多Google地图中未显示的地方</li>
<li>突出显示远足路线、露营地、水源、山峰、等高线等的户外模式</li>
<li>步行道和自行车道</li>
<li>餐厅、加油站、酒店、商店、景点等众多兴趣点</li>
<li>按名称、地址或兴趣点类别搜索</li>
<li>步行、骑车或驾驶时,可通过语音提示进行导航</li>
<li>一键收藏您中意的地点</li>
<li>离线阅读维基百科文章</li>
<li>地铁交通图层和路线指示</li>
<li>轨迹记录</li>
<li>以 KML、KMZ 和 GPX 格式导出和导入书签和轨迹</li>
<li>选择天暗后自动开启的黑暗模式</li>
<li>使用基本的内置编辑器来编辑 OpenStreetMap 地点,帮助大家改进地图数据</li>
</ul>
<b>自由在此</b>
探索您的旅程,以隐私和社区为本,畅游世界!

View File

@@ -1,8 +0,0 @@
• 刷新地图颜色-更浅、更暖、更友好!
• OSM 编辑器:添加“楼层”字段
• 更新加油站和充电站图标
• 更新部分用户界面组件的颜色
• 修复位置共享的链接
• 修复下载后错误显示地图大小的问题
• 修复定位箭头偶尔轻微跳动的问题
• Android 5&6 错误修复

View File

@@ -14,19 +14,21 @@
‣ <b>決策問責、財務透明、非營利性、完全開源。</b>
<b>主要功能</b>
• 可下載詳細的地圖包括許多Google地圖中未顯示的地方
• 突出顯示遠足路線、露營地、水源、山峰、等高線等的戶外模式
• 步道和自行車道
• 餐廳、加油站、旅館、商店、景點等眾多興趣點
• 按名稱、地址或興趣點類別搜尋
• 步行、騎車或駕駛時,可透過語音提示進行導航
• 一鍵收藏您喜愛的地點
• 離線閱讀維基百科文章
• 列車運輸圖層及路線指示
• 軌跡記錄
• 以 KML、KMZ 和 GPX 格式匯出和匯入書籤和軌跡
• 選擇天暗後自動開啟的黑暗模式
• 使用基本的內建編輯器來編輯 OpenStreetMap 地點,幫助大家改進地圖資料
<ul>
<li>可下載詳細的地圖包括許多Google地圖中未顯示的地方</li>
<li>突出顯示遠足路線、露營地、水源、山峰、等高線等的戶外模式</li>
<li>步道和自行車道</li>
<li>餐廳、加油站、旅館、商店、景點等眾多興趣點</li>
<li>按名稱、地址或興趣點類別搜尋</li>
<li>步行、騎車或駕駛時,可透過語音提示進行導航</li>
<li>一鍵收藏您喜愛的地點</li>
<li>離線閱讀維基百科文章</li>
<li>列車運輸圖層及路線指示</li>
<li>軌跡記錄</li>
<li>以 KML、KMZ 和 GPX 格式匯出和匯入書籤和軌跡</li>
<li>選擇天暗後自動開啟的黑暗模式</li>
<li>使用基本的內建編輯器來編輯 OpenStreetMap 地點,幫助大家改進地圖資料</li>
</ul>
<b>自由在此</b>
探索您的旅程,以隱私和社群為本,暢遊世界!

View File

@@ -1,8 +0,0 @@
• 刷新地圖顏色-更淺、更暖、更友好!
• OSM 編輯器:新增「樓層」欄位
• 更新加油站和充電站圖示
• 更新某些使用者介面元件的顏色
• 修正位置分享的連結
• 修正下載後錯誤顯示地圖尺寸的問題
• 修正定位箭頭偶爾輕微跳動的問題
• Android 5&6 錯誤修正

View File

@@ -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

View File

@@ -1 +1 @@
CoMaps - Navigace se soukromím
CoMaps Navigace se soukromím

View File

@@ -1 +1 @@
CoMaps - Navi mit Datenschutz
CoMaps: Navigation Datenschutz

View File

@@ -1,36 +0,0 @@
Yhteisön johtama vapaa ja avoimeen lähdekoodiin perustuva karttasovellus, jonka karttadata perustuu OpenStreetMap:n avoimeen dataan. Sovelluksessa painottuu vahva sitoutuminen läpinäkyvyyteen, yksityisyyteen ja voittoa tavoittelemattomaan toimintaan.
Liity yhteisöön ja auta kehittämään parasta karttasovellusta
• Käytä sovellusta ja levitä sanaa
• Anna palautetta ja raportoi ongelmista
• Päivitä karttadataa sovelluksessa tai OpenStreetMap:n verkkosivuilla
<i>Palautteesi ja 5-tähden arvostelu on paras tukesi meille!</i>
‣ <b>Yksinkertainen ja viimeistelty</b>: Olennaiset ominaisuudet, joita on helppo käyttää.
‣ <b>Offline-painotteinen</b>: Suunnittele ja navigoi matkasi ilman verkkoyhteyttä. Etsi reittipisteitä retkilläsi. Kaikki sovelluksen toiminnot on suunniteltu käytettäväksi ilman verkkoyhteyttä.
‣ <b>Kunnioittaa yksityisyyttä</b>: Sovellus on suunniteltu yksityisyyttä silmälläpitäen. Sovellu ei tunnista ihmisä, seuraa toimintaasi, eikä kerää henkilökohtaisia tietojasi. Mainosvapaa.
‣ <b>Säästää akkua ja tilaa</b>: Ei kuluta akkua, kuten toiset karttasovellukset. Kompaktit kartat säästävät tilaa puhelimessasi.
‣ <b>Ilmainen ja yhteisön rakentama</b>: Ihmiset, kuten sinä ovat auttaneet sovelluksen kehityksessä lisäämällä paikkoja OpenStreetMap:iin, testaamalla sovellusta ja antamalla palautetta. Voit auttaa myös kehittämällä sovellusta ja lahjoittamalla sovelluskehitykseen.
‣ <b>Avoin ja läpinäkyvä päätöksenteko ja 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
• Android Auto -tuki
Raportoi sovellusvirheistä, ehdota ideoita liity yhteisöön osoitteessa <b><i>comaps.app</i></b>
<b>Vapaus on täällä</b>
Löydä matkasi, navigoi maailmassa yksityisyyden ja yhteisön tukemana!

View File

@@ -1,4 +1,4 @@
Una app sviluppata dalla comunità, gratuita e open-source, basata su OpenStreetMap e sull'impegno alla trasparenza, al rispetto della Privacy senza scopo di lucro.
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

View File

@@ -1 +0,0 @@
Eenvoudige kaartnavigatie - Ontdek meer van je reis - Gemaakt door de community

View File

@@ -1 +0,0 @@
CoMaps - Navigeer met privacy

View File

@@ -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>
Откройте для себя путешествия, навигацию по миру, ставя во главе приватность и сообщество!

View File

@@ -1 +0,0 @@
Простая навигация по карте — Откройте больше за ваше путешествие. От сообщества

View File

@@ -1 +0,0 @@
CoMaps - Оффлайн навигация

View File

@@ -1,6 +1,6 @@
Бесплатна апликација за мапе отвореног кода коју води заједница заснована на OpenStreetMap подацима и ојачана посвећеношћу транспарентности, приватности и непрофитности.
Придружите се заједници и помозите да направимо најбољу навигацију
Придружите се заједници и помозите да направите најбољу навигацију
• Користите апликацију и ширите информације о њој
• Оставите повратне информације и пријавите проблеме
• Ажурирајте мапе из апликације или на сајту OpenStreetMap
@@ -32,5 +32,5 @@
Молимо Вас да пријавите проблеме са апликацијом, предложите идеје и придружите се нашој заједници на <b><i>comaps.app</i></b> страни.
<b>Сад је слободна</b>
<b>Сад је слободно</b>
Откријте своје путовање, путујте светом с приватношћу и заједницом на челу!

View File

@@ -1 +1 @@
Једноставна навигација - Сазнајте више о свом путовању - Покреће је заједница
Једноставна навигација - Сазнајте више о свом путовању - Захваљујући заједници

View File

@@ -1 +1 @@
CoMaps - Navigacija
CoMaps - навигација

View File

@@ -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!

View File

@@ -1 +0,0 @@
Kolayca gezinin - Seyahat etmenin ötesini bulun - Gönüllüler tarafından yapıldı

View File

@@ -1 +0,0 @@
CoMaps - Gizlilikle Gezin

View File

@@ -119,7 +119,7 @@
<data android:scheme="http"/>
<data android:scheme="https"/>
<data android:host="comaps.at"/>
<data android:host="comaps.app"/>
</intent-filter>
<intent-filter>

View File

@@ -34,6 +34,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StyleRes;
import androidx.annotation.UiThread;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.view.ViewCompat;
@@ -44,7 +45,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;
@@ -120,8 +120,6 @@ import app.organicmaps.widget.menu.MainMenu;
import app.organicmaps.widget.placepage.PlacePageController;
import app.organicmaps.widget.placepage.PlacePageData;
import app.organicmaps.widget.placepage.PlacePageViewModel;
import com.google.android.material.appbar.MaterialToolbar;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
@@ -140,7 +138,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,
@@ -190,7 +187,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
private MapFragment mMapFragment;
private View mPointChooser;
private MaterialToolbar mPointChooserToolbar;
private Toolbar mPointChooserToolbar;
private RoutingPlanInplaceController mRoutingPlanInplaceController;
@@ -255,8 +252,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
@NonNull
private DisplayManager mDisplayManager;
private PeriodicBackupRunner backupRunner;
ManageRouteBottomSheet mManageRouteBottomSheet;
private boolean mRemoveDisplayListener = true;
@@ -611,8 +606,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
*/
if (Map.isEngineCreated())
onRenderingInitializationFinished();
backupRunner = new PeriodicBackupRunner(this);
}
private void onSettingsResult(ActivityResult activityResult)
@@ -844,7 +837,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
@Override
public String getPrefsName()
{
return getString(R.string.about_help);
return getString(R.string.help);
}
@Override
@@ -1358,11 +1351,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 +2583,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;

View File

@@ -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);
}
}

View File

@@ -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,
}
}

View File

@@ -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();
}
}

View File

@@ -15,12 +15,11 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StyleRes;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentFactory;
import androidx.fragment.app.FragmentManager;
import com.google.android.material.appbar.MaterialToolbar;
import app.organicmaps.MwmApplication;
import app.organicmaps.R;
import app.organicmaps.SplashActivity;
@@ -149,7 +148,7 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity
onBackPressed();
}
protected MaterialToolbar getToolbar()
protected Toolbar getToolbar()
{
return findViewById(R.id.toolbar);
}

View File

@@ -10,13 +10,11 @@ import androidx.annotation.CallSuper;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.appbar.MaterialToolbar;
import app.organicmaps.R;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils;
@@ -25,7 +23,7 @@ import app.organicmaps.widget.PlaceholderView;
public abstract class BaseMwmRecyclerFragment<T extends RecyclerView.Adapter> extends Fragment
{
private MaterialToolbar mToolbar;
private Toolbar mToolbar;
@SuppressWarnings("NotNullFieldNotInitialized")
@NonNull

View File

@@ -6,13 +6,11 @@ import androidx.annotation.CallSuper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentFactory;
import androidx.fragment.app.FragmentManager;
import com.google.android.material.appbar.MaterialToolbar;
import app.organicmaps.R;
import app.organicmaps.util.UiUtils;
import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener;
@@ -28,7 +26,7 @@ public abstract class BaseToolbarActivity extends BaseMwmFragmentActivity
{
super.onSafeCreate(savedInstanceState);
MaterialToolbar toolbar = getToolbar();
Toolbar toolbar = getToolbar();
if (toolbar != null)
{
int title = getToolbarTitle();
@@ -44,7 +42,7 @@ public abstract class BaseToolbarActivity extends BaseMwmFragmentActivity
}
}
protected void setupHomeButton(@NonNull MaterialToolbar toolbar)
protected void setupHomeButton(@NonNull Toolbar toolbar)
{
UiUtils.showHomeUpButton(toolbar);
}
@@ -94,7 +92,7 @@ public abstract class BaseToolbarActivity extends BaseMwmFragmentActivity
if (title != null)
{
MaterialToolbar toolbar = getToolbar();
Toolbar toolbar = getToolbar();
if (toolbar != null && toolbar.getTitle() != null)
{
mLastTitle = toolbar.getTitle().toString();

View File

@@ -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();

View File

@@ -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)

View File

@@ -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();
}

View File

@@ -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();

View File

@@ -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)
{
@@ -480,13 +480,6 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
UiUtils.showIf(mSearchResultsMode && !TextUtils.isEmpty(found), mFoundName);
long size = getMapDisplaySize();
mSize.setText(StringUtils.getFileSizeString(mFragment.requireContext(), size));
mStatusIcon.update(mItem);
}
private long getMapDisplaySize()
{
long size;
if (mItem.status == CountryItem.STATUS_ENQUEUED ||
mItem.status == CountryItem.STATUS_PROGRESS ||
@@ -494,23 +487,20 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
{
size = mItem.enqueuedSize;
}
else if (mItem.status == CountryItem.STATUS_FAILED ||
mItem.status == CountryItem.STATUS_DOWNLOADABLE)
{
size = mItem.totalSize;
}
else
{
size = ((!mSearchResultsMode && mMyMapsMode) ? mItem.size : mItem.totalSize);
}
return size;
mSize.setText(StringUtils.getFileSizeString(mFragment.requireContext(), size));
mStatusIcon.update(mItem);
}
}
static class HeaderViewHolder extends BaseInnerViewHolder<String>
{
@NonNull
private final MaterialTextView mTitle;
private final TextView mTitle;
HeaderViewHolder(@NonNull View frame)
{

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -189,7 +189,6 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
initMetadataEntry(Metadata.MetadataType.FMD_WEBSITE, R.string.error_enter_correct_web);
initMetadataEntry(Metadata.MetadataType.FMD_WEBSITE_MENU, R.string.error_enter_correct_web);
initMetadataEntry(Metadata.MetadataType.FMD_EMAIL, R.string.error_enter_correct_email);
initMetadataEntry(Metadata.MetadataType.FMD_LEVEL, R.string.error_enter_correct_level);
initMetadataEntry(Metadata.MetadataType.FMD_CONTACT_FEDIVERSE, R.string.error_enter_correct_fediverse_page);
initMetadataEntry(Metadata.MetadataType.FMD_CONTACT_FACEBOOK, R.string.error_enter_correct_facebook_page);
initMetadataEntry(Metadata.MetadataType.FMD_CONTACT_INSTAGRAM, R.string.error_enter_correct_instagram_page);
@@ -432,7 +431,8 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
// Details
View mBlockLevels = view.findViewById(R.id.block_levels);
mBuildingLevels = findInputAndInitBlock(mBlockLevels, R.drawable.ic_floor, R.string.editor_building_levels);
mBuildingLevels = findInputAndInitBlock(mBlockLevels, R.drawable.ic_floor,
getString(R.string.editor_storey_number, Editor.nativeGetMaxEditableBuildingLevels()));
mBuildingLevels.setInputType(InputType.TYPE_CLASS_NUMBER);
mInputBuildingLevels = mBlockLevels.findViewById(R.id.custom_input);
View blockPhone = view.findViewById(R.id.block_phone);
@@ -446,8 +446,6 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
R.drawable.ic_website_menu, R.string.website_menu, InputType.TYPE_TEXT_VARIATION_URI);
View emailBlock = initBlock(view, Metadata.MetadataType.FMD_EMAIL, R.id.block_email,
R.drawable.ic_email, R.string.email, InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
View levelBlock = initBlock(view, Metadata.MetadataType.FMD_LEVEL, R.id.block_level,
R.drawable.ic_level_white, R.string.editor_level, InputType.TYPE_CLASS_NUMBER);
View fediverseContactBlock = initBlock(view, Metadata.MetadataType.FMD_CONTACT_FEDIVERSE, R.id.block_fediverse,
R.drawable.ic_mastodon_white, R.string.mastodon, InputType.TYPE_TEXT_VARIATION_URI);
View facebookContactBlock = initBlock(view, Metadata.MetadataType.FMD_CONTACT_FACEBOOK, R.id.block_facebook,
@@ -505,7 +503,6 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
mDetailsBlocks.put(Metadata.MetadataType.FMD_WEBSITE, websiteBlock);
mDetailsBlocks.put(Metadata.MetadataType.FMD_WEBSITE_MENU, websiteMenuBlock);
mDetailsBlocks.put(Metadata.MetadataType.FMD_EMAIL, emailBlock);
mDetailsBlocks.put(Metadata.MetadataType.FMD_LEVEL, levelBlock);
mDetailsBlocks.put(Metadata.MetadataType.FMD_OPERATOR, operatorBlock);
mSocialMediaBlocks.put(Metadata.MetadataType.FMD_CONTACT_FEDIVERSE, fediverseContactBlock);

View File

@@ -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;

View File

@@ -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();

View File

@@ -213,7 +213,7 @@ public class LocationHelper implements BaseLocationProvider.Listener
if (mSavedLocation != null)
{
if (!LocationUtils.isLocationBetterThanLast(location, mSavedLocation))
if (!LocationUtils.isFromFusedProvider(location) && !LocationUtils.isLocationBetterThanLast(location, mSavedLocation))
{
Logger.d(TAG, "The new " + location + " is worse than the last " + mSavedLocation);
return;

View File

@@ -2,7 +2,6 @@ package app.organicmaps.location;
import android.content.Context;
import android.location.Location;
import android.os.SystemClock;
import androidx.annotation.NonNull;
@@ -58,7 +57,6 @@ class RouteSimulationProvider extends BaseLocationProvider
location.setLatitude(mPoints[mCurrentPoint].mLat);
location.setLongitude(mPoints[mCurrentPoint].mLon);
location.setAccuracy(1.0f);
location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
mListener.onLocationChanged(location);
mCurrentPoint += 1;
UiThread.runLater(this::nextPoint, INTERVAL_MS);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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,

View File

@@ -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
@@ -483,11 +481,6 @@ public class MapButtonsController extends Fragment
.setAllSides()
.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));
}
@Override

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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());
}

View File

@@ -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()))

View File

@@ -16,6 +16,7 @@ import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.CallSuper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
@@ -46,7 +47,6 @@ import app.organicmaps.util.WindowInsetUtils;
import app.organicmaps.widget.PlaceholderView;
import app.organicmaps.widget.SearchToolbarController;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.MaterialToolbar;
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
import com.google.android.material.tabs.TabLayout;
@@ -226,7 +226,7 @@ public class SearchFragment extends BaseMwmFragment
private void updateFrames()
{
final boolean hasQuery = mToolbarController.hasQuery();
MaterialToolbar toolbar = mToolbarController.getToolbar();
Toolbar toolbar = mToolbarController.getToolbar();
AppBarLayout.LayoutParams lp = (AppBarLayout.LayoutParams) toolbar.getLayoutParams();
lp.setScrollFlags(hasQuery ? AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS
| AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL : 0);

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -13,7 +13,7 @@ public final class Constants
public static class Url
{
public static final String SHORT_SHARE_PREFIX = "cm://";
public static final String HTTP_SHARE_PREFIX = "https://comaps.at/";
public static final String HTTP_SHARE_PREFIX = "https://comaps.app/";
public static final String MAILTO_SCHEME = "mailto:";
public static final String MAIL_SUBJECT = "?subject=";
@@ -23,6 +23,7 @@ public final class Constants
public static final String MASTODON = "https://floss.social/@comaps";
public static final String FB_OM_COMMUNITY_HTTP = "https://www.facebook.com/profile.php?id=61575286559965";
public static final String FB_OM_COMMUNITY_NATIVE = "fb://profile/61575286559965";
//public static final String TWITTER = "https://twitter.com/user";
public static final String CODE_REPO = "https://codeberg.org/comaps/comaps";

View File

@@ -84,9 +84,6 @@ public class LocationUtils
public static boolean isLocationBetterThanLast(@NonNull Location newLocation, @NonNull Location lastLocation)
{
if (newLocation.getElapsedRealtimeNanos() < lastLocation.getElapsedRealtimeNanos())
return false;
// As described in isAccuracySatisfied, GPS may have zero accuracy "for some reasons".
if (isFromGpsProvider(lastLocation) && lastLocation.getAccuracy() == 0.0f)
return true;

View File

@@ -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;
}
}

View File

@@ -27,6 +27,7 @@ import androidx.annotation.DimenRes;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.core.content.res.ResourcesCompat;
import androidx.core.graphics.Insets;
@@ -36,8 +37,6 @@ import androidx.core.view.WindowInsetsControllerCompat;
import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.MwmApplication;
import app.organicmaps.R;
import com.google.android.material.appbar.MaterialToolbar;
import com.google.android.material.textfield.TextInputLayout;
import java.util.Objects;
@@ -194,7 +193,7 @@ public final class UiUtils
hide(tv);
}
public static void showHomeUpButton(MaterialToolbar toolbar)
public static void showHomeUpButton(Toolbar toolbar)
{
toolbar.setNavigationIcon(ThemeUtils.getResource(toolbar.getContext(), androidx.appcompat.R.attr.homeAsUpIndicator));
}
@@ -298,7 +297,7 @@ public final class UiUtils
systemInsets.right, view.getPaddingBottom());
}
public static void setupNavigationIcon(@NonNull MaterialToolbar toolbar,
public static void setupNavigationIcon(@NonNull Toolbar toolbar,
@NonNull View.OnClickListener listener)
{
View customNavigationButton = toolbar.findViewById(R.id.back);
@@ -312,14 +311,14 @@ public final class UiUtils
}
}
public static void setupHomeUpButtonAsNavigationIcon(@NonNull MaterialToolbar toolbar,
public static void setupHomeUpButtonAsNavigationIcon(@NonNull Toolbar toolbar,
@NonNull View.OnClickListener listener)
{
UiUtils.showHomeUpButton(toolbar);
toolbar.setNavigationOnClickListener(listener);
}
public static void clearHomeUpButton(@NonNull MaterialToolbar toolbar)
public static void clearHomeUpButton(@NonNull Toolbar toolbar)
{
toolbar.setNavigationIcon(null);
toolbar.setNavigationOnClickListener(null);

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