Compare commits

..

1 Commits

Author SHA1 Message Date
map-per
762797684e [fdroid] Release version 2025.11.19-2
Signed-off-by: map-per <map-per@gmx.de>
2025-11-19 09:40:04 +01:00
665 changed files with 10155 additions and 27838 deletions

View File

@@ -1,55 +1,69 @@
# All non-assigned.
* @organicmaps/mergers
# Visual design. # Visual design.
/android/app/src/main/res/drawable*/ @comaps/design /android/app/src/main/res/drawable*/ @organicmaps/design
/android/app/src/main/res/font/ @comaps/design /android/app/src/main/res/font/ @organicmaps/design
/android/app/src/main/res/mipmap*/ @comaps/design /android/app/src/main/res/mipmap*/ @organicmaps/design
/data/*.ttf @comaps/design /data/*.ttf @organicmaps/design
/data/resources-svg/ @comaps/design /data/resources-svg/ @organicmaps/design
/data/search-icons/ @comaps/design /data/search-icons/ @organicmaps/design
/iphone/Maps/Images.xcassets/ @comaps/design /iphone/Maps/Images.xcassets/ @organicmaps/design
# Android. # Android.
/android/ @comaps/android /android/ @organicmaps/android
/android/app/src/main/java/app/comaps/car/ @comaps/android-auto /android/app/src/main/java/app/organicmaps/car/ @organicmaps/android-auto
/docs/ANDROID_LOCATION_TEST.md @comaps/android /docs/ANDROID_LOCATION_TEST.md @organicmaps/android
/docs/JAVA_STYLE.md @comaps/android /docs/JAVA_STYLE.md @organicmaps/android
# no owner for translation changes # no owner for translation changes
/android/app/src/main/res/values*/strings.xml /android/app/src/main/res/values*/strings.xml
# iOS. # iOS.
/iphone/ @comaps/ios /iphone/ @organicmaps/ios
/xcode/ @comaps/ios /xcode/ @organicmaps/ios
/docs/OBJC_STYLE.md @comaps/ios /docs/OBJC_STYLE.md @organicmaps/ios
# no owner for translation changes # no owner for translation changes
/iphone/plist.txt /iphone/plist.txt
/iphone/Maps/LocalizedStrings/ /iphone/Maps/LocalizedStrings/
# Qt
/qt/ @organicmaps/qt
# Rendering
/drape/ @organicmaps/rendering
/drape_frontend/ @organicmaps/rendering
# Map Data.
/tools/python/maps_generator/ @organicmaps/data
/generator/ @organicmaps/data
/topography_generator/ @organicmaps/data
/data/borders/ @organicmaps/data
/data/conf/isolines/ @organicmaps/data
/docs/SUBWAY_GENERATION.md @organicmaps/data
/docs/MAPS.md @organicmaps/data
/docs/EXPERIMENTAL_PUBLIC_TRANSPORT_SUPPORT.md @organicmaps/data
# no owner (changed often to add a new POI) # no owner (changed often to add a new POI)
/generator/generator_tests/osm_type_test.cpp /generator/generator_tests/osm_type_test.cpp
# Map Styles. # Map Styles.
/data/styles/ @comaps/styles /data/styles/ @organicmaps/styles
/data/types.txt @comaps/styles /data/types.txt @organicmaps/styles
/data/visibility.txt @comaps/styles /data/visibility.txt @organicmaps/styles
/data/mapcss-mapping.csv @comaps/styles /data/mapcss-mapping.csv @organicmaps/styles
/data/replaced_tags.txt @comaps/styles /data/replaced_tags.txt @organicmaps/styles
/data/classificator.txt @comaps/styles /data/classificator.txt @organicmaps/styles
/data/drules_* @comaps/styles /data/drules_* @organicmaps/styles
/docs/STYLES.md /docs/STYLES.md
/tools/kothic/ @comaps/styles /tools/kothic/ @organicmaps/styles
# DevOps. # DevOps.
/.forgejo/workflows @comaps/devops /.forgejo/workflows @organicmaps/devops
/android/*gradle* @comaps/devops /android/*gradle* @organicmaps/devops
/docs/RELEASE_MANAGEMENT.md @comaps/devops /docs/RELEASE_MANAGEMENT.md @organicmaps/devops
/xcode/fastlane/ @comaps/devops /xcode/fastlane/ @organicmaps/devops
/tools/python/maps_generator/ @comaps/devops # Growth.
/generator/ @comaps/devops README.md @organicmaps/growth
/topography_generator/ @comaps/devops /.forgejo/FUNDING.yml @organicmaps/growth
/data/borders/ @comaps/devops /android/app/src/fdroid/play/ @organicmaps/growth
/data/conf/isolines/ @comaps/devops /android/app/src/google/play/ @organicmaps/growth
/docs/SUBWAY_GENERATION.md @comaps/devops /iphone/metadata/ @organicmaps/growth
/docs/MAPS.md @comaps/devops
/docs/EXPERIMENTAL_PUBLIC_TRANSPORT_SUPPORT.md @comaps/devops
# Legal. # Legal.
LEGAL @comaps/admins LEGAL @organicmaps/legal
LICENSE @comaps/admins LICENSE @organicmaps/legal
NOTICE @comaps/admins NOTICE @organicmaps/legal
CONTRIBUTORS @comaps/admins CONTRIBUTORS @organicmaps/legal
/docs/CODE_OF_CONDUCT.md @comaps/admins /docs/CODE_OF_CONDUCT.md @organicmaps/legal
/docs/DCO.md @comaps/admins /docs/DCO.md @organicmaps/legal
/docs/GOVERNANCE.md @comaps/admins /docs/GOVERNANCE.md @organicmaps/legal

View File

@@ -1,3 +1 @@
open_collective: comaps open_collective: comaps
liberapay: comaps
custom: ["https://comaps.app/donate/"]

View File

@@ -2,73 +2,38 @@ name: map-generator
on: on:
workflow_dispatch: # Manual trigger workflow_dispatch: # Manual trigger
inputs: inputs:
map-generator-test: jobs:
description: 'Test (non-prod) generation?' description: 'Which job(s) to run right now?'
required: false required: true
default: false default: 'all-except-upload'
type: boolean type: choice
# run-copy-coasts: options:
# description: 'Copy last used coastlines?' - all-except-upload
# required: false - copy-coasts
# default: true - planet
# type: boolean - wiki
run-isolines: - isolines
description: 'Update altitude isolines?' - subways
required: false - tiger
default: false - maps
type: boolean - upload
run-tiger:
description: 'Update TIGER address data?'
required: false
default: true
type: boolean
run-planet-pbf:
description: 'Update PBF planet (for Wiki & subways)?'
required: false
default: true
type: boolean
run-subways:
description: 'Update subways?'
required: false
default: true
type: boolean
run-wiki:
description: 'Update Wikipedia descriptions?'
required: false
default: true
type: boolean
run-planet-o5m:
description: 'Update O5M planet (for mapgen)?'
required: false
default: true
type: boolean
run-mapgen:
description: 'Run maps generation?'
required: false
default: true
type: boolean
map-generator-continue: map-generator-continue:
description: 'Continue previous map generation?' description: 'Continue previous map generation?'
required: false required: false
default: false default: false
type: boolean type: boolean
# map-generator-countries: map-generator-countries:
# description: 'Generate specific MWMs? (i.e. "US_New York_*, foo")' description: 'Generate specific MWMs? (i.e. "US_New York_*, foo")'
# required: false
# type: string
run-upload:
description: 'Upload latest maps to CDN?'
required: false required: false
default: false type: string
type: boolean reset:
# reset: description: 'Reset part of the system?'
# description: 'Reset part of the system?' required: false
# required: false default: 'no'
# default: 'no' type: choice
# type: choice options:
# options: - 'no'
# - 'no' - wiki-ratelimit
# - wiki-ratelimit
## RCLONE_CONF is multi-line text containing keys and credentials for us2,ru1,fi1,de1 servers ## RCLONE_CONF is multi-line text containing keys and credentials for us2,ru1,fi1,de1 servers
@@ -78,11 +43,10 @@ env:
WIKIMEDIA_PASSWORD: ${{ secrets.WIKIMEDIA_PASSWORD }} WIKIMEDIA_PASSWORD: ${{ secrets.WIKIMEDIA_PASSWORD }}
ZULIP_BOT_EMAIL: ${{ secrets.ZULIP_BOT_EMAIL }} ZULIP_BOT_EMAIL: ${{ secrets.ZULIP_BOT_EMAIL }}
ZULIP_API_KEY: ${{ secrets.ZULIP_API_KEY }} ZULIP_API_KEY: ${{ secrets.ZULIP_API_KEY }}
MWMTEST: ${{ inputs.map-generator-test }}
MWMCONTINUE: ${{ inputs.map-generator-continue }} MWMCONTINUE: ${{ inputs.map-generator-continue }}
# MWMCOUNTRIES: ${{ inputs.map-generator-countries }} MWMCOUNTRIES: ${{ inputs.map-generator-countries }}
DEBIAN_FRONTEND: noninteractive DEBIAN_FRONTEND: noninteractive
TZ: Etc/UTC TZ: Etc/UTC
jobs: jobs:
clone-repos: clone-repos:
@@ -105,22 +69,24 @@ jobs:
run: | run: |
echo "Cloning $FORGEJO_SERVER_URL/$FORGEJO_REPOSITORY branch $FORGEJO_REF_NAME" echo "Cloning $FORGEJO_SERVER_URL/$FORGEJO_REPOSITORY branch $FORGEJO_REF_NAME"
cd ~ cd ~
git clone --depth 1 --recurse-submodules --shallow-submodules -b $FORGEJO_REF_NAME --single-branch $FORGEJO_SERVER_URL/$FORGEJO_REPOSITORY.git comaps git clone --recurse-submodules --shallow-submodules -b $FORGEJO_REF_NAME --single-branch $FORGEJO_SERVER_URL/$FORGEJO_REPOSITORY.git comaps
- name: Checkout wikiparser repo - name: Checkout wikiparser repo
shell: bash shell: bash
run: | run: |
cd ~ cd ~
git clone --depth 1 --single-branch https://codeberg.org/comaps/wikiparser.git git clone https://codeberg.org/comaps/wikiparser.git
- name: Checkout subways repo - name: Checkout subways repo
shell: bash shell: bash
run: | run: |
cd ~ cd ~
git clone --depth 1 --single-branch https://codeberg.org/comaps/subways.git git clone https://codeberg.org/comaps/subways.git
copy-coasts: copy-coasts:
# if: inputs.run-copy-coasts if: inputs.jobs == 'copy-coasts' || inputs.jobs == 'all-except-upload'
name: Copy Previously Generated Coasts name: Copy Previously Generated Coasts
runs-on: mapfilemaker runs-on: mapfilemaker
needs:
- clone-repos
container: container:
image: codeberg.org/comaps/maps_generator:f6d53d54f794 image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes: volumes:
@@ -140,7 +106,7 @@ jobs:
echo "Before:" echo "Before:"
ls -al /home/planet/latest_coasts* ls -al /home/planet/latest_coasts*
# TODO: don't copy coasts from test generations
cp -p /mnt/4tbexternal/osm-maps/*/intermediate_data/WorldCoasts.geom /home/planet/latest_coasts.geom cp -p /mnt/4tbexternal/osm-maps/*/intermediate_data/WorldCoasts.geom /home/planet/latest_coasts.geom
cp -p /mnt/4tbexternal/osm-maps/*/intermediate_data/WorldCoasts.rawgeom /home/planet/latest_coasts.rawgeom cp -p /mnt/4tbexternal/osm-maps/*/intermediate_data/WorldCoasts.rawgeom /home/planet/latest_coasts.rawgeom
@@ -153,103 +119,12 @@ jobs:
fi fi
update-isolines: update-planet:
if: inputs.run-isolines if: inputs.jobs == 'planet' || inputs.jobs == 'all-except-upload'
name: Update Isolines name: Update Planet
runs-on: mapfilemaker runs-on: mapfilemaker
needs: needs:
- clone-repos - clone-repos
container:
image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes:
- /mnt/4tbexternal/:/mnt/4tbexternal/
- /mnt/4tbexternal/osm-planet:/home/planet
concurrency:
group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- uses: actions/cache@v4
with:
path: "~"
key: cache-${{ github.run_id }}-${{ github.run_attempt }}
# TODO: we only need to update these if our SRTM or countries change
# TODO: after update, verify that sizable files exist: /home/planet/isolines/*.isolines
- name: Update Isolines
shell: bash
# TODO: preserve previous isolines version?
# TODO: cleanup the tmp-tiles dir after completion
run: |
cd ~/comaps/
./tools/unix/build_omim.sh -p ~ -R topography_generator_tool
rm -rf /home/planet/isolines/
mkdir /home/planet/isolines/
~/omim-build-relwithdebinfo/topography_generator_tool \
--profiles_path=./data/conf/isolines/isolines-profiles.json \
--countries_to_generate_path=./data/conf/isolines/countries-to-generate.json \
--tiles_isolines_out_dir=/home/planet/isolines/tmp-tiles/ \
--countries_isolines_out_dir=/home/planet/isolines/ \
--data_dir=./data/ \
--srtm_path=/home/planet/SRTM-patched-europe/ \
--threads=96
- name: Check isolines
shell: bash
run: |
NUMISO=$(ls -al /home/planet/isolines/*.isolines | wc -l)
echo "Found $NUMISO isolines"
if [ $NUMISO -lt 10 ]; then
echo "ERROR: Did generation fail?"
exit 1
fi
- name: Notify Zulip
run: |
curl -X POST https://comaps.zulipchat.com/api/v1/messages \
-u $ZULIP_BOT_EMAIL:$ZULIP_API_KEY \
--data-urlencode type=stream \
--data-urlencode 'to="DevOps"' \
--data-urlencode topic=codeberg-bot \
--data-urlencode 'content=Isolines are done!'
update-tiger:
if: inputs.run-tiger
name: Update TIGER
runs-on: mapfilemaker
needs:
- clone-repos
container:
image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes:
- /mnt/4tbexternal/:/mnt/4tbexternal/
- /mnt/4tbexternal/osm-planet:/home/planet
concurrency:
group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- uses: actions/cache@v4
with:
path: "~"
key: cache-${{ github.run_id }}-${{ github.run_attempt }}
- name: Build address_parser
shell: bash
run: |
cd ~/comaps
#rm -rf ~/omim-build-relwithdebinfo/CMakeCache.txt
#rm -rf ~/omim-build-relwithdebinfo/CMakeFiles
./tools/unix/build_omim.sh -p ~ -R address_parser_tool
- name: Update TIGER from Nominatim
shell: bash
# TODO: use curl instead of wget2
run: |
# TODO: maybe remove old osm-planet/tiger first?
cd /home/planet/
mkdir -p tiger
wget2 https://nominatim.org/data/tiger-nominatim-preprocessed-latest.csv.tar.gz
cd ~/comaps
tar -xOzf /home/planet/tiger-nominatim-preprocessed-latest.csv.tar.gz | ~/omim-build-relwithdebinfo/address_parser_tool --output_path=/home/planet/tiger
update-planet-pbf:
if: inputs.run-planet-pbf
name: Update PBF Planet
runs-on: mapfilemaker
container: container:
image: codeberg.org/comaps/maps_generator:f6d53d54f794 image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes: volumes:
@@ -272,13 +147,20 @@ jobs:
else else
echo "planet-latest.osm.pbf was found, raw download not required." echo "planet-latest.osm.pbf was found, raw download not required."
fi fi
- name: Update PBF Planet - name: Update Planet
shell: bash shell: bash
run: | run: |
cd /home/planet/planet/ cd /home/planet/planet/
rm -f planet-latest-new.osm.pbf rm -f planet-latest-new.osm.pbf
pyosmium-up-to-date planet-latest.osm.pbf -o planet-latest-new.osm.pbf -v --size 16384 pyosmium-up-to-date planet-latest.osm.pbf -o planet-latest-new.osm.pbf -v --size 16384
mv planet-latest-new.osm.pbf planet-latest.osm.pbf mv planet-latest-new.osm.pbf planet-latest.osm.pbf
- name: Converting planet-latest.osm.pbf to planet.o5m
# TODO: better to run osmupdate (not convert) just before starting the maps jobs - for max fresh data.
run: |
echo "Starting..."
cd /home/planet/planet/
osmconvert -v --drop-author --drop-version --hash-memory=4000 planet-latest.osm.pbf -o=planet.o5m
echo "Done."
- name: Notify Zulip - name: Notify Zulip
run: | run: |
curl -X POST https://comaps.zulipchat.com/api/v1/messages \ curl -X POST https://comaps.zulipchat.com/api/v1/messages \
@@ -286,44 +168,10 @@ jobs:
--data-urlencode type=stream \ --data-urlencode type=stream \
--data-urlencode 'to="DevOps"' \ --data-urlencode 'to="DevOps"' \
--data-urlencode topic=codeberg-bot \ --data-urlencode topic=codeberg-bot \
--data-urlencode 'content=PBF planet update is done!' --data-urlencode 'content=Planet update is done!'
update-subways:
if: inputs.run-subways
name: Update Subways
runs-on: mapfilemaker
needs:
- clone-repos
container:
image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes:
- /mnt/4tbexternal/:/mnt/4tbexternal/
- /mnt/4tbexternal/osm-planet:/home/planet
concurrency:
group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- uses: actions/cache@v4
with:
path: "~"
key: cache-${{ github.run_id }}-${{ github.run_attempt }}
- name: Update Subways
shell: bash
run: |
cd ~/comaps/
cp tools/unix/maps/settings.sh.prod tools/unix/maps/settings.sh
./tools/unix/maps/generate_subways.sh
- name: Notify Zulip
run: |
curl -X POST https://comaps.zulipchat.com/api/v1/messages \
-u $ZULIP_BOT_EMAIL:$ZULIP_API_KEY \
--data-urlencode type=stream \
--data-urlencode 'to="DevOps"' \
--data-urlencode topic=codeberg-bot \
--data-urlencode 'content=Subways are done!'
wiki-update: wiki-update:
if: inputs.run-wiki if: inputs.jobs == 'wiki' || inputs.jobs == 'all-except-upload'
name: Update Wikipedia name: Update Wikipedia
runs-on: mapfilemaker runs-on: mapfilemaker
needs: needs:
@@ -430,10 +278,12 @@ jobs:
--data-urlencode topic=codeberg-bot \ --data-urlencode topic=codeberg-bot \
--data-urlencode 'content=Wiki update is done!' --data-urlencode 'content=Wiki update is done!'
update-planet-o5m: update-isolines:
if: inputs.run-planet-o5m if: inputs.jobs == 'isolines' || inputs.jobs == 'all-except-upload'
name: Update O5M Planet name: Update Isolines
runs-on: mapfilemaker runs-on: mapfilemaker
needs:
- clone-repos
container: container:
image: codeberg.org/comaps/maps_generator:f6d53d54f794 image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes: volumes:
@@ -443,32 +293,38 @@ jobs:
group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }} group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true cancel-in-progress: true
steps: steps:
- name: Check for O5M Planet File - uses: actions/cache@v4
with:
path: "~"
key: cache-${{ github.run_id }}-${{ github.run_attempt }}
# TODO: we only need to update these if our SRTM or countries change
# TODO: after update, verify that sizable files exist: /home/planet/isolines/*.isolines
- name: Update Isolines
shell: bash
# TODO: preserve previous isolines version?
# TODO: cleanup the tmp-tiles dir after completion
run: |
cd ~/comaps/
./tools/unix/build_omim.sh -p ~ -R topography_generator_tool
rm -rf /home/planet/isolines/
mkdir /home/planet/isolines/
~/omim-build-relwithdebinfo/topography_generator_tool \
--profiles_path=./data/conf/isolines/isolines-profiles.json \
--countries_to_generate_path=./data/conf/isolines/countries-to-generate.json \
--tiles_isolines_out_dir=/home/planet/isolines/tmp-tiles/ \
--countries_isolines_out_dir=/home/planet/isolines/ \
--data_dir=./data/ \
--srtm_path=/home/planet/SRTM-patched-europe/ \
--threads=96
- name: Check isolines
shell: bash shell: bash
run: | run: |
if [ ! -f /home/planet/planet/planet.o5m ]; then NUMISO=$(ls -al /home/planet/isolines/*.isolines | wc -l)
echo "WARN: No file at /home/planet/planet/planet.o5m" echo "Found $NUMISO isolines"
if [ $NUMISO -lt 10 ]; then
if [ ! -f /home/planet/planet/planet-latest.osm.pbf ]; then echo "ERROR: Did generation fail?"
echo "ERROR: No file at /home/planet/planet/planet-latest.osm.pbf"
ls -al /home/planet/
ls -al /home/planet/planet/
exit 1 exit 1
fi fi
echo "Converting planet-latest.osm.pbf to planet.o5m"
cd /home/planet/planet/
osmconvert -v --drop-author --drop-version --hash-memory=4000 planet-latest.osm.pbf -o=planet.o5m
echo "Conversion is done."
fi
- name: Update O5M planet
run: |
echo "Starting..."
cd /home/planet/planet/
rm -f planet-new.o5m
osmupdate -v --drop-author --drop-version --hash-memory=4000 --max-merge=32 --out-o5m planet.o5m planet-new.o5m
mv planet-new.o5m planet.o5m
echo "Done."
- name: Notify Zulip - name: Notify Zulip
run: | run: |
curl -X POST https://comaps.zulipchat.com/api/v1/messages \ curl -X POST https://comaps.zulipchat.com/api/v1/messages \
@@ -476,10 +332,81 @@ jobs:
--data-urlencode type=stream \ --data-urlencode type=stream \
--data-urlencode 'to="DevOps"' \ --data-urlencode 'to="DevOps"' \
--data-urlencode topic=codeberg-bot \ --data-urlencode topic=codeberg-bot \
--data-urlencode 'content=O5M planet update is done!' --data-urlencode 'content=Isolines are done!'
update-subways:
if: inputs.jobs == 'subways' || inputs.jobs == 'all-except-upload'
name: Update Subways
runs-on: mapfilemaker
needs:
- clone-repos
container:
image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes:
- /mnt/4tbexternal/:/mnt/4tbexternal/
- /mnt/4tbexternal/osm-planet:/home/planet
concurrency:
group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- uses: actions/cache@v4
with:
path: "~"
key: cache-${{ github.run_id }}-${{ github.run_attempt }}
- name: Update Subways
shell: bash
run: |
cd ~/comaps/
cp tools/unix/maps/settings.sh.prod tools/unix/maps/settings.sh
./tools/unix/maps/generate_subways.sh
- name: Notify Zulip
run: |
curl -X POST https://comaps.zulipchat.com/api/v1/messages \
-u $ZULIP_BOT_EMAIL:$ZULIP_API_KEY \
--data-urlencode type=stream \
--data-urlencode 'to="DevOps"' \
--data-urlencode topic=codeberg-bot \
--data-urlencode 'content=Subways are done!'
update-tiger:
if: inputs.jobs == 'tiger' || inputs.jobs == 'all-except-upload'
name: Update TIGER
runs-on: mapfilemaker
needs:
- clone-repos
container:
image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes:
- /mnt/4tbexternal/:/mnt/4tbexternal/
- /mnt/4tbexternal/osm-planet:/home/planet
concurrency:
group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- uses: actions/cache@v4
with:
path: "~"
key: cache-${{ github.run_id }}-${{ github.run_attempt }}
- name: Build address_parser
shell: bash
run: |
cd ~/comaps
#rm -rf ~/omim-build-relwithdebinfo/CMakeCache.txt
#rm -rf ~/omim-build-relwithdebinfo/CMakeFiles
./tools/unix/build_omim.sh -p ~ -R address_parser_tool
- name: Update TIGER from Nominatim
shell: bash
# TODO: use curl instead of wget2
run: |
# TODO: maybe remove old osm-planet/tiger first?
cd /home/planet/
mkdir -p tiger
wget2 https://nominatim.org/data/tiger-nominatim-preprocessed-latest.csv.tar.gz
cd ~/comaps
tar -xOzf /home/planet/tiger-nominatim-preprocessed-latest.csv.tar.gz | ~/omim-build-relwithdebinfo/address_parser_tool --output_path=/home/planet/tiger
generate-maps: generate-maps:
if: inputs.run-mapgen if: inputs.jobs == 'maps' || inputs.jobs == 'all-except-upload'
name: Generate Maps name: Generate Maps
runs-on: mapfilemaker runs-on: mapfilemaker
needs: needs:
@@ -528,7 +455,7 @@ jobs:
--data-urlencode 'content=Generator is done!' --data-urlencode 'content=Generator is done!'
upload-maps: upload-maps:
if: inputs.run-upload if: inputs.jobs == 'upload'
name: Upload Maps name: Upload Maps
runs-on: mapfilemaker runs-on: mapfilemaker
container: container:
@@ -540,10 +467,6 @@ jobs:
group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }} group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true cancel-in-progress: true
steps: steps:
- uses: actions/cache@v4
with:
path: "~"
key: cache-${{ github.run_id }}-${{ github.run_attempt }}
- name: Write config file - name: Write config file
run: | run: |
mkdir -p ~/.config/rclone/ mkdir -p ~/.config/rclone/
@@ -575,3 +498,4 @@ jobs:
--data-urlencode topic=codeberg-bot \ --data-urlencode topic=codeberg-bot \
--data-urlencode 'content=Upload is done!' --data-urlencode 'content=Upload is done!'

View File

@@ -1,129 +0,0 @@
name: process_subways
on:
workflow_dispatch: # Manual trigger
env:
PLANET: /home/planet/planet/planet.o5m
TMPDIR: /tmp
HTML_DIR: "/mnt/4tbexternal/osm-planet/subway/validator"
DUMP: "$HTML_DIR"
SKIP_PLANET_UPDATE: "1"
DEBIAN_FRONTEND: nonnteractive
TZ: Etc/UTC
# /var/www/html/subways is mapped as a volume on cdn-fi-1
# as is /tmp/planet
jobs:
clone-repos:
name: Clone Git Repos
runs-on: mapfilemaker
container:
image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes:
- /mnt/4tbexternal:/mnt/4tbexternal
concurrency:
group: ${{ github.workflow }}-process-subways-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- uses: actions/cache@v4
with:
path: "~"
key: cache-${{ github.run_id }}-${{ github.run_attempt }}
- name: Checkout subways repo
shell: bash
run: |
cd ~
git clone --depth 1 --single-branch https://codeberg.org/comaps/subways.git
update-planet-o5m:
name: Update O5M Planet
runs-on: mapfilemaker
container:
image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes:
- /mnt/4tbexternal/:/mnt/4tbexternal/
- /mnt/4tbexternal/osm-planet:/home/planet
concurrency:
group: ${{ github.workflow }}-process-subways-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- name: Check for O5M Planet File
shell: bash
run: |
if [ ! -f /home/planet/planet/planet.o5m ]; then
echo "WARN: No file at /home/planet/planet/planet.o5m"
if [ ! -f /home/planet/planet/planet-latest.osm.pbf ]; then
echo "ERROR: No file at /home/planet/planet/planet-latest.osm.pbf"
ls -al /home/planet/
ls -al /home/planet/planet/
exit 1
fi
echo "Converting planet-latest.osm.pbf to planet.o5m"
cd /home/planet/planet/
osmconvert -v --drop-author --drop-version --hash-memory=4000 planet-latest.osm.pbf -o=planet.o5m
echo "Conversion is done."
fi
- name: Update O5M planet
run: |
echo "Starting..."
cd /home/planet/planet/
rm -f planet-new.o5m
osmupdate -v --drop-author --drop-version --hash-memory=4000 --max-merge=32 --out-o5m planet.o5m planet-new.o5m
mv planet-new.o5m planet.o5m
echo "Done."
- name: Notify Zulip
run: |
curl -X POST https://comaps.zulipchat.com/api/v1/messages \
-u $ZULIP_BOT_EMAIL:$ZULIP_API_KEY \
--data-urlencode type=stream \
--data-urlencode 'to="DevOps"' \
--data-urlencode topic=codeberg-bot \
--data-urlencode 'content=O5M planet update is done!'
update-subways:
if: inputs.run-subways
name: Update Subways
runs-on: mapfilemaker
needs:
- clone-repos
container:
image: codeberg.org/comaps/maps_generator:f6d53d54f794
volumes:
- /mnt/4tbexternal/:/mnt/4tbexternal/
- /mnt/4tbexternal/osm-planet:/home/planet
concurrency:
group: ${{ github.workflow }}-map-generator-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
steps:
- uses: actions/cache@v4
with:
path: "~"
key: cache-${{ github.run_id }}-${{ github.run_attempt }}
- name: Update Subways
shell: bash
run: |
cd ~/comaps/
cp tools/unix/maps/settings.sh.prod tools/unix/maps/settings.sh
./tools/unix/maps/generate_subways.sh
- name: Compare with VK validation
shell: bash
run: |
cd ~/subways
if [ -f "$HTML_DIR/index.html" ]; then
echo "Comparing local validation with VK's validation..."
python3 ./scripts/compare_html_validation.py "$HTML_DIR/index.html" \
--vk-url "https://maps.vk.com/osm/tools/subways/latest/index.html"
else
echo "Local index.html not found at $HTML_DIR/index.html"
exit 1
fi
- name: Notify Zulip
run: |
curl -X POST https://comaps.zulipchat.com/api/v1/messages \
-u $ZULIP_BOT_EMAIL:$ZULIP_API_KEY \
--data-urlencode type=stream \
--data-urlencode 'to="DevOps"' \
--data-urlencode topic=codeberg-bot \
--data-urlencode 'content=Subways are done!'

3
.github/FUNDING.yml vendored
View File

@@ -1,3 +0,0 @@
open_collective: comaps
liberapay: comaps
custom: ["https://comaps.app/donate/"]

View File

@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v6 uses: actions/checkout@v4
with: with:
fetch-depth: 1 fetch-depth: 1
@@ -78,7 +78,7 @@ jobs:
pip install "protobuf<3.21" --break-system-packages pip install "protobuf<3.21" --break-system-packages
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v6 uses: actions/checkout@v4
with: with:
fetch-depth: 200 # enough to get all commits for the current day fetch-depth: 200 # enough to get all commits for the current day
@@ -103,7 +103,7 @@ jobs:
./gradlew -P${{ matrix.arch }} assemble${{ matrix.flavor }} ./gradlew -P${{ matrix.arch }} assemble${{ matrix.flavor }}
- name: Upload ${{ matrix.flavor }} apk - name: Upload ${{ matrix.flavor }} apk
uses: actions/upload-artifact@v6 uses: actions/upload-artifact@v4
with: with:
name: android-${{ matrix.flavor }} name: android-${{ matrix.flavor }}
path: android/app/build/outputs/apk/**/CoMaps-*.apk path: android/app/build/outputs/apk/**/CoMaps-*.apk

View File

@@ -8,14 +8,14 @@ on:
jobs: jobs:
ios-check: ios-check:
name: Build iOS name: Build iOS
runs-on: macos-26 runs-on: macos-15
env: env:
DEVELOPER_DIR: /Applications/Xcode_26.1.app/Contents/Developer DEVELOPER_DIR: /Applications/Xcode_26.app/Contents/Developer
LANG: en_US.UTF-8 # Fastlane complains that the terminal is using ASCII. LANG: en_US.UTF-8 # Fastlane complains that the terminal is using ASCII.
LANGUAGE: en_US.UTF-8 LANGUAGE: en_US.UTF-8
LC_ALL: en_US.UTF-8 LC_ALL: en_US.UTF-8
TEST_RESULTS_BUNDLE_NAME: CoMaps-Test-Results TEST_RESULTS_BUNDLE_NAME: CoMaps-Test-Results
SIMULATOR_DEVICE: 'iPhone 17 Pro Max' SIMULATOR_DEVICE: 'iPhone 16 Pro Max'
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@@ -31,21 +31,18 @@ jobs:
brew install qt \ brew install qt \
optipng optipng
pip3 install "protobuf<3.21" --break-system-packages pip3 install "protobuf<3.21" --break-system-packages
xcodebuild -downloadComponent metalToolchain
xcodebuild -downloadPlatform iOS
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v6 uses: actions/checkout@v4
- name: Parallel submodules checkout - name: Parallel submodules checkout
shell: bash shell: bash
run: git submodule update --depth 1 --init --recursive --jobs=$(($(sysctl -n hw.logicalcpu) * 20)) run: git submodule update --depth 1 --init --recursive --jobs=$(($(sysctl -n hw.logicalcpu) * 20))
- name: Configure repository - name: Configure repository
shell: bash shell: bash
run: ./configure.sh run: ./configure.sh
- name: Configure Xcode cache - name: Configure XCode cache
uses: irgaly/xcode-cache@v1 uses: irgaly/xcode-cache@v1
with: with:
key: xcode-cache-deriveddata-${{ github.workflow }}-${{ matrix.buildType }}-${{ github.sha }} key: xcode-cache-deriveddata-${{ github.workflow }}-${{ matrix.buildType }}-${{ github.sha }}

6
.gitignore vendored
View File

@@ -155,8 +155,6 @@ android/huawei-appgallery.json
android/res/xml/network_security_config.xml android/res/xml/network_security_config.xml
./server/ ./server/
iphone/Maps/app.omaps/ iphone/Maps/app.omaps/
# Generated file
libs/indexer/localized_types_map.cpp
*.li *.li
@@ -190,6 +188,10 @@ tools/python/maps_generator/var/etc/map_generator.ini
tools/python/routing/etc/*.ini tools/python/routing/etc/*.ini
tools/unix/maps/settings.sh tools/unix/maps/settings.sh
# Helpers
/node_modules/
/package-lock.json
# Visual Studio # Visual Studio
.vs .vs

View File

@@ -114,8 +114,35 @@ if (${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo")
add_compile_options(-fno-omit-frame-pointer) add_compile_options(-fno-omit-frame-pointer)
endif() 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}) message(STATUS "Build type: " ${CMAKE_BUILD_TYPE})
if (PLATFORM_LINUX OR PLATFORM_ANDROID)
find_program(LLD_FOUND ld.lld)
if (LLD_FOUND)
message(STATUS "Using ld.lld linker")
set(CMAKE_EXE_LINKER_FLAGS "-fuse-ld=lld")
else()
find_program(GOLD_FOUND ld.gold)
if (GOLD_FOUND)
message(STATUS "Using ld.gold")
set(CMAKE_EXE_LINKER_FLAGS "-fuse-ld=gold")
endif()
endif()
endif()
if (NOT SKIP_TESTS) if (NOT SKIP_TESTS)
enable_testing() enable_testing()
# Enables ctest -T memcheck with valgrind # Enables ctest -T memcheck with valgrind
@@ -195,8 +222,10 @@ if (PLATFORM_DESKTOP AND NOT WITH_SYSTEM_PROVIDED_3PARTY)
include_directories("${PROJECT_BINARY_DIR}/3party/gflags/include") include_directories("${PROJECT_BINARY_DIR}/3party/gflags/include")
endif() endif()
# Fix for #include <boost/regex.hpp> # Android fails to find boost in many cases, this fixes it.
include_directories("${OMIM_ROOT}/3party/boost") if (PLATFORM_ANDROID)
include_directories("${OMIM_ROOT}/3party/boost")
endif()
# Used in qt/ and shaders/ # Used in qt/ and shaders/
find_package(Python3 REQUIRED COMPONENTS Interpreter) find_package(Python3 REQUIRED COMPONENTS Interpreter)

View File

@@ -1,17 +1,15 @@
This file contains a list of people who have contributed to this project. This file contains a list of people who have contributed to this project.
It is not necessarily comprehensive as contributors must manually add themselves. Its not neccesarily comprehensive.
Feel free to add yourself here along with your first contribution! Feel free to add yourself here along with your first contribution!
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
CoMaps contributors: CoMaps contributors:
(in alphabetical order) (in alphabetic order)
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Bastian Greshake Tzovaras Bastian Greshake Tzovaras
clover sage clover sage
Harry Bond <me@hbond.xyz> Harry Bond <me@hbond.xyz>
NoelClick
thesupertechie
vikiawv vikiawv
Yannik Bloscheck Yannik Bloscheck

2
NOTICE
View File

@@ -1,6 +1,6 @@
Copyright 2020 My.com B.V. (Mail.Ru Group) Copyright 2020 My.com B.V. (Mail.Ru Group)
Copyright 2025 Organic Maps Contributors Copyright 2025 Organic Maps Contributors
Copyright 2026 CoMaps Contributors Copyright 2025 CoMaps Contributors
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@@ -1,17 +0,0 @@
## Reporting Vulnerabilities
You can report a security vulnerability by creating an issue or send mail to security@comaps.app
## Verifying Fingerprints
To [verify](https://developer.android.com/studio/command-line/apksigner#usage-verify) the APK, use the following signing certificate fingerprints:
```
SHA-256: 4894e8e6963627ef660031d8593fe77297f835acb4e23810003e926135023b4c
SHA-1: 8b7b5739f917e9f7c681671ced0c9c8562123ade
MD5: 9cce0ffea281dc2f0e0a154d6d2e281e
```
To verify CoMaps via [AppVerifier](https://github.com/soupslurpr/AppVerifier), use the following signing certificate fingerprint:
```
app.comaps
48:94:E8:E6:96:36:27:EF:66:00:31:D8:59:3F:E7:72:97:F8:35:AC:B4:E2:38:10:00:3E:92:61:35:02:3B:4C
```

View File

@@ -254,7 +254,6 @@ android {
androidResources { androidResources {
ignoreAssetsPattern = '!.svn:!.git:!.DS_Store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~' ignoreAssetsPattern = '!.svn:!.git:!.DS_Store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~'
noCompress = ['txt', 'bin', 'html', 'png', 'json', 'mwm', 'ttf', 'sdf', 'ui', 'config', 'csv', 'spv', 'obj'] noCompress = ['txt', 'bin', 'html', 'png', 'json', 'mwm', 'ttf', 'sdf', 'ui', 'config', 'csv', 'spv', 'obj']
// Some languages not supported by Android require to be specified here to be applied
localeFilters += [ localeFilters += [
"af", "af",
"ar", "ar",
@@ -282,7 +281,6 @@ android {
"in", "in",
"it", "it",
"ja", "ja",
"kw",
"ko", "ko",
"lt", "lt",
"lv", "lv",
@@ -353,8 +351,6 @@ dependencies {
implementation libs.androidx.recyclerview implementation libs.androidx.recyclerview
implementation libs.androidx.work.runtime implementation libs.androidx.work.runtime
implementation libs.androidx.lifecycle.process implementation libs.androidx.lifecycle.process
implementation libs.androidx.documentfile
// 1.13 Material library version doesn't render properly alpha properties on map buttons
implementation libs.android.material implementation libs.android.material
// Fix for app/organicmaps/util/FileUploadWorker.java:14: error: cannot access ListenableFuture // Fix for app/organicmaps/util/FileUploadWorker.java:14: error: cannot access ListenableFuture
// https://github.com/organicmaps/organicmaps/issues/6106 // https://github.com/organicmaps/organicmaps/issues/6106
@@ -381,7 +377,6 @@ play {
track.set('production') track.set('production')
defaultToAppBundles.set(true) defaultToAppBundles.set(true)
releaseStatus.set(ReleaseStatus.IN_PROGRESS) releaseStatus.set(ReleaseStatus.IN_PROGRESS)
userFraction.set(0.2d) // Rollout to 20% of users
serviceAccountCredentials.set(file('google-play.json')) serviceAccountCredentials.set(file('google-play.json'))
} }

View File

@@ -1,32 +0,0 @@
Una aplicació de mapes gratuïta i de codi obert dirigida per la comunitat basada en dades d'OpenStreetMap i reforçada amb el compromís amb la transparència, la privadesa i la no ànim de lucre. CoMaps és una derivació/fork d'Organic Maps, que al seu torn és una derivació de Maps.ME.
Llegiu sobre els motius del projecte i la seva direcció a <b><i>codeberg.org/comaps</i></b>.
Uneix-te a la comunitat i ajuda a crear la millor aplicació de mapes
• Utilitza l'aplicació i difon-la
• Dona comentaris i informa de problemes
• Actualitza les dades del mapa a l'aplicació o al lloc web d'OpenStreetMap
‣ <b>Enfocat fora de línia</b>: Planifica i navega pel teu viatge a l'estranger sense necessitat de servei mòbil, cerca punts de referència mentre fas una excursió llunyana, etc. Totes les funcions de l'aplicació estan dissenyades per funcionar fora de línia.
‣ <b>Respecte a la privadesa</b>: L'aplicació està dissenyada tenint en compte la privadesa: no identifica persones, no fa seguiment i no recopila informació personal. Sense anuncis.
‣ <b>Senzill i polit</b>: funcions essencials fàcils d'utilitzar que simplement funcionen.
‣ <b>Estalvia bateria i espai</b>: No consumeix bateria com altres aplicacions de navegació. Els mapes compactes estalvien espai preciós al telèfon.
‣ <b>Gratuït i creat per la comunitat</b>: Gent com tu ha ajudat a crear l'aplicació afegint llocs a OpenStreetMap, provant i donant comentaris sobre les funcions i aportant les seves habilitats de desenvolupament i diners.
‣ <b>Presa de decisions i finances obertes i transparents, sense ànim de lucre i de codi obert.</b>
<b>Característiques principals</b>:
• Mapes detallats descarregables amb llocs que no estan disponibles amb Google Maps
• Mode exterior amb rutes de senderisme destacades, càmpings, fonts d'aigua, pics, corbes de nivell, etc.
• Senders per caminar i carrils bici
• Punts d'interès com restaurants, gasolineres, hotels, botigues, llocs d'interès i molts més
• Cerca per nom, adreça o categoria de punt d'interès
• Navegació amb anuncis de veu per caminar, anar amb bicicleta o conduir
• Marca els teus llocs preferits amb un sol toc
• Articles de la Viquipèdia fora de línia
• Capa i indicacions de trànsit de metro
• Enregistrament de rutes
• Exporta i importa marcadors i rutes en formats KML, KMZ i GPX
• Un mode fosc per utilitzar durant la nit
• Millora les dades del mapa per a tothom mitjançant un editor bàsic integrat
<b>La llibertat és aquí</b>
Descobreix el teu viatge, navega pel món amb la privadesa i la comunitat al capdavant!

View File

@@ -1,6 +1,6 @@
Eine von der Community betriebene, kostenlose Open-Source Karten-App, die auf OpenStreetMap Daten basiert. Transparent und nicht gewinnorientiert. CoMaps ist ein Fork/Abspaltung von Organic Maps, die wiederum ein Fork/Abspaltung von Maps.Me ist. Eine von der Community betriebene, kostenlose Open-Source Karten-App, die auf OpenStreetMap Daten basiert. Transparent und nicht gewinnorientiert. CoMaps ist ein Fork/Abspaltung von Organic Maps, die wiederum ein Fork/Abspaltung von Maps.Me ist.
Lese mehr über die Gründe und Ziele des Projektes unter <b><i>codeberg.org/comaps</i></b> (auf Englisch). Lese mehr über die Gründe und Ziele des Projektes unter <b><i>codeberg.org/comaps</i></b>.
Werde Teil der Community und hilf mit, die beste Karten-App zu entwickeln Werde Teil der Community und hilf mit, die beste Karten-App zu entwickeln
• Nutze die App und erzähle anderen davon • Nutze die App und erzähle anderen davon
• Gib Feedback und melde Probleme • Gib Feedback und melde Probleme
@@ -9,9 +9,9 @@ Werde Teil der Community und hilf mit, die beste Karten-App zu entwickeln
‣ <b>Einfach und ausgereift</b>: Essenzielle, leicht zu bedienende Funktionen, die einfach funktionieren. ‣ <b>Einfach und ausgereift</b>: Essenzielle, leicht zu bedienende Funktionen, die einfach funktionieren.
‣ <b>Offline-orientiert</b>: Plane und navigiere im Ausland ohne Mobilfunkverbindung, finde Wegpunkte auf abgelegenen Wanderungen usw. Alle Funktionen sind für den Offline-Einsatz konzipiert. ‣ <b>Offline-orientiert</b>: Plane und navigiere im Ausland ohne Mobilfunkverbindung, finde Wegpunkte auf abgelegenen Wanderungen usw. Alle Funktionen sind für den Offline-Einsatz konzipiert.
‣ <b>Datenschutzfreundlich</b>: Die App wurde mit Fokus auf Privatsphäre entwickelt keine Personenidentifikation, kein Tracking, keine Erfassung persönlicher Daten, keine Werbung. ‣ <b>Datenschutzfreundlich</b>: Die App wurde mit Fokus auf Privatsphäre entwickelt keine Personenidentifikation, kein Tracking, keine Erfassung persönlicher Daten, keine Werbung.
‣ <b>Spart Akku und Speicherplatz</b>: Verbraucht nicht unnötig viel Akku wie andere Navi-Apps. Kompakte Karten sparen Speicherplatz auf deinem Gerät. ‣ <b>Spart Akku und Speicherplatz</b>: Verbraucht nicht unnötig Akku wie andere Navi-Apps. Kompakte Karten sparen Speicherplatz auf deinem Gerät.
‣ <b>Kostenlos und von der Community entwickelt</b>: Menschen wie du haben geholfen, diese App zu entwickeln durch das Hinzufügen von Orten zu OpenStreetMap, Testen von neuen Funktionen, Softwareentwicklung oder Spenden. ‣ <b>Kostenlos und von der Community entwickelt</b>: Menschen wie du haben geholfen, diese App zu entwickeln durch das Hinzufügen von Orten zu OpenStreetMap, Testen von neuen Funktionen, Softwareentwicklung oder Spenden.
‣ <b>Offen und transparent bei Entscheidungen und Finanzen, gemeinnützig und vollständig Open-Source.</b> ‣ <b>Offen und transparent bei Entscheidungen und Finanzen, gemeinnützig und vollständig Open-Source</b>
<b>Hauptfunktionen</b>: <b>Hauptfunktionen</b>:
• Detaillierte, herunterladbare Karten mit Orten, die bei Google Maps oft fehlen • Detaillierte, herunterladbare Karten mit Orten, die bei Google Maps oft fehlen
@@ -28,5 +28,5 @@ Werde Teil der Community und hilf mit, die beste Karten-App zu entwickeln
• Dunkler Modus für die Nutzung bei Nacht • Dunkler Modus für die Nutzung bei Nacht
• Kartenbearbeitung direkt in der App mit einem einfachen Editor • Kartenbearbeitung direkt in der App mit einem einfachen Editor
<b>Freiheit beginnt hier</b> <b>Entdecke die Unabhängigkeit</b>
Entdecke deine Reise, wobei Datenschutz und Gemeinschaft im Vordergrund stehen! Entdecke deine Reise navigiere in der Welt mit Datenschutz!

View File

@@ -1,9 +1,11 @@
• OSM-Daten vom 6. Januar • OpenStreetMap-Daten vom 16. November
Editor: POI mit mehr als einem Tag, (z.B. Arten von Kunstwerken wie Skulpturen...), mehr POI können als leer/stillgelegt werden Bäume hinzugefügt
Miniatureisenbahnen & Kläranlagen hinzugefügt Kleine Bushaltestellen-Icons die früher angezeigt werden
Material 3-Dialoge & dunklerer Hintergrund im Darkmode Sichtbarkeit von Eingängen reduziert
Fiktive Geschwindigkeitsbegrenzungen für Verbindungsstraßen entfernt Neue POI-Typen hinzugefügt
Versatz der Kameraausschnitt in der Navigation behoben Sandflächen werden auf Karte angezeigt
Weniger empfindliches langes Antippen Option „Geschäft ist leerstehend” zum OSM-Editor hinzugefügt
• Straßenbeschilderung in Europa verbessert
Weitere Details unter codeberg.org/comaps/comaps/releases • Option „Asphaltierte Straßen vermeiden” hinzugefügt
• Icons in den Einstellungen hinzugefügt
Weitere Änderungen in unseren Codeberg-Versionshinweisen!

View File

@@ -1 +1 @@
Leichte Navigation Erlebe mehr von deiner Reise Community-unterstützt Einfache Navigation - Entdecken Sie mehr von Ihrer Reise - Community-Entwickelt

View File

@@ -1,32 +0,0 @@
A community-led free & open source maps app based on OpenStreetMap 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.
Read on about reasons for the project and its direction at <b><i>codeberg.org/comaps</i></b>.
Join the community there and help make the best maps app
• Use the app and spread the word about it
• Give feedback and report issues
• Update map data in the app or on the OpenStreetMap website
‣ <b>Offline-focused</b>: Plan and navigate your trip abroad without the need for cellular service, search waypoints while on a distant hike, etc. All app functions are designed to work offline.
‣ <b>Respecting Privacy</b>: The app is designed with privacy in mind - does not identify people, does not track, and does not collect personal information. Ads-free.
‣ <b>Simple and Polished</b>: essential easy to use features that just work.
‣ <b>Saves Your Battery and Space</b>: Doesnt drain your battery like other navigation apps. Compact maps save precious space on your phone.
‣ <b>Free and Built by the Community</b>: People like you helped build the app by adding places to OpenStreetMap, testing and giving feedback on features and contributing their development skills and money.
‣ <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, sightseeing 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
<b>Freedom Is Here</b>
Discover your journey, navigate the world with privacy and community at the forefront!

View File

@@ -1 +0,0 @@
Easy map navigation - Discover more of your journey - Powered by the community

View File

@@ -1 +0,0 @@
CoMaps - Hike, Bike, Drive Offline with Privacy

View File

@@ -1,9 +1,11 @@
• OpenStreetMap data as of January 6 • OpenStreetMap data as of November 16
Editor: add POI types with more than one OSM tag, e.g. artwork subtypes sculptures, paintings..; more POI types could be marked as vacant/disused Added trees
Added miniature railways and wastewater treatment plants Made bus stop icons smaller and show up earlier
Use Material 3 dialogs and darker background in dark mode Reduce visibility of entrances
Removed fictional speed limits for link roads Added several other POI types
Fixed camera cutout offset in navigation Show sand areas on the map
Less sensitive long tap (full-screen mode) Add business is vacant option to the OSM editor
• Improved road shields in Europe
More details on codeberg.org/comaps/comaps/releases • Avoid paved roads routing option
• Added icons to the settings page
Check our Codeberg release notes for more changes!

View File

@@ -1,32 +0,0 @@
Komunum-gvidata senpaga kaj malfermkoda mapapliko bazita sur OpenStreetMap-datumoj kaj fortigita per komitado al transparencio, privateco kaj ne-lucro. CoMaps estas forko/spin-off de Organic Maps, kiu turne estas forko de Maps.ME.
Legu plu pri la kialoj por la projekto kaj ĝia direkto ĉe <b><i>codeberg.org/comaps</i></b>.
Aliĝu al la komunumo tie kaj helpu fari la plej bonan mapaplikon
• Uzu la aplikon kaj disvastigu la vorton pri ĝi
• Donu rimarkojn kaj raportu problemojn
• Ĝisdatigu mapajn datumojn en la apliko aŭ sur la OpenStreetMap-retejo
‣ <b>Senkonekta-fokusa</b>: Planu kaj navigu vian vojaĝon eksterlande sen bezono de ĉelulara servico, serĉu vojpunktojn dum malproksima promenado, ktp. Ĉiuj funkcioj de la apliko estas dezajnitaj por funkcii senkonekte.
‣ <b>Rispektante Privatecon</b>: La apliko estas dezajnita kun privateco en menso — ne identigas homojn, ne sekvas, kaj ne kolektas personajn informojn. Sen reklamoj.
‣ <b>Simpla kaj Perfekta</b>: esencaj, facile uzeblaj funkcioj kiuj simple funkcias.
‣ <b>Konservas Vian Baterion kaj Spacon</b>: Ne elĉerpas vian baterion kiel aliaj navigaj aplikaĵoj. Kompaktaj mapoj konservas precian spacon sur via telefono.
‣ <b>Sena kaj Konstruita de la Komunumo</b>: Homoj kiel vi helpis konstrui la aplikon per aldonado de lokoj al OpenStreetMap, testado kaj donado de rimarkoj pri funkcioj kaj kontribuado de siaj programadaj kapabloj kaj mono.
‣ <b>Malferma kaj Transparenta Decidado kaj Financoj, Ne-lucra kaj Tute Malfermkoda.</b>
<b>Ĉefaj Funkcioj</b>:
• Elŝuteblaj detalegaj mapoj kun lokoj kiuj ne estas disponeblaj per Google Maps
• Eksteraj modo kun elstarigitaj promenaj vojoj, kampoj, akvofontoj, pintoj, konturlinioj, ktp
• Promenaj vojoj kaj biciklaj vojoj
• Interesaj punktoj kiel restoracioj, benzinstacioj, hoteloj, vendejoj, vidindaĵoj kaj multaj aliaj
• Serĉo laŭ nomo aŭ adreso aŭ laŭ kategorio de interesaj punktoj
• Navigado kun voĉaj anoncoj por promenado, biciklado aŭ veturado
• Marku viajn favorajn lokojn per unu tuŝo
• Senkonektaj Vikipedio-artikoloj
• Metroa transporta tavolo kaj indikoj
• Enregistraĵo de vojoj
• Eksporto kaj importo de markiloj kaj vojoj en KML, KMZ, GPX formatoj
• Malhela modo por uzi nokte
• Plibonigu mapajn datumojn por ĉiuj uzante bazan enkonstruitan redaktilon
<b>Libereco Estas Ĉi Tie</b>
Malkovru vian vojaĝon, navigu la mondon kun privateco kaj komunumo en la antaŭa plano!

View File

@@ -1 +0,0 @@
Facila mapnaviĝado - Malkovru pli de via vojaĝo - Subtenata de la komunumo

View File

@@ -1 +0,0 @@
CoMaps - Migru, Biciklu, Veturigu Eksterrete

View File

@@ -1,9 +1,11 @@
Datos OSM a 06/01 Nuevos datos OSM a 16.11.25
Editor: se añaden tipos de POI con más de una etiqueta, ej. esculturas, pinturas...; se podrán marcar más tipos como en desuso Se añaden árboles
• Se añaden ferrocarriles mini y plantas de tratamiento de aguas • Se reducen los iconos de paradas de autobús y aparecen antes
• Se utilizan diálogos Material 3 y fondo más oscuro en el modo oscuro • Se reduce visibilidad de entradas
• Se eliminan límites de velocidad ficticios para enlaces • Se añaden muchos tipos de puntos de interés
• Se corrige desplazamiento en la navegación • Se muestran las zonas de arena en el mapa
Toque largo menos sensible (en pantalla completa) Se añade la opción «negocio vacío» al editor
• Se mejoran las señales de tráfico en Europa
Más detalles en codeberg.org/comaps/comaps/releases • Nueva opción «evitar caminos asfaltadas»
• Nuevos iconos en la página de configuración
Más detalles en Codeberg

View File

@@ -1,9 +1,11 @@
• Données OpenStreetMap du 6 janvier • Données OpenStreetMap du 16 novembre
Éditeur : support des types de POI avec plus dun tag OSM, par exemple types dœuvres dart sculptures, peintures.. Ajout des arbres
Rendu des rails pour trains miniatures et des stations d'épuration Les icônes des arrêts de bus sont plus petites et apparaissent plus tôt
Utilisation des pop-ups Material 3 et d'un fond plus sombre en thème sombre Réduction de la visibilité des entrées
Suppression des limites de vitesse fictives sur les bretelles de routes Ajout de nouveaux types de POI
Correction des instructions de navigation sur les appareils avec des encoches Affichage des zones de sable
Appui long moins sensible (en mode plein écran) Nouveau bouton pour signaler un commerce vacant
• Amélioration des badges routiers en Europe
Plus de détails sur codeberg.org/comaps/comaps/releases • Ajout d'une option pour éviter les routes pavées
• Ajout d'icônes dans les paramètres
Plus d'informations sur notre Codeberg

View File

@@ -1 +1 @@
CoMaps - Randonnée, Vélo, Conduite hors ligne CoMaps - Rando, vélo, conduite hors ligne & privée

View File

@@ -1,7 +0,0 @@
• OpenStreetMap podaci od 6. siječnja
• Uređivač: dodane točake interesa s više od jedne OSM oznake, npr. podtipovi umjetnina kao skulpture, slike...; više točaka interesa se sada može označiti kao upražnjene/napuštene
• Dodane minijaturne željeznice i postrojenja za pročišćavanje otpadnih voda
• Korištenje Material 3 dijaloga i tamnije pozadine u tamnom načinu rada
• Uklonjena su izmišljena ograničenja brzine za spojne ceste
Više detalja na codeberg.org/comaps/comaps/releases

View File

@@ -0,0 +1,11 @@
• Mappe OSM al 16 Novembre
• Aggiunti alberi
• Fermate bus più piccole e visibili prima
• Entrate rese meno ingombranti
• Aggiunti diversi POI
• Le zone sabbiose sono ora visibili
• Aggiunta l'opzione di POI vacante nell'editor OSM
• Migliorate le insegne stradali in Europa
• Aggiunta opzione per evitare strade pavimentate
• Aggiunte icone nelle impostazioni
Visita Codeberg per ulteriori dettagli

View File

@@ -1,32 +0,0 @@
Bendruomenės vystoma nemokama atvirojo kodo žemėlapių programa, pagrįsta „OpenStreetMap“ duomenimis ir sustiprinta įsipareigojimu užtikrinti skaidrumą, privatumą ir pelno nesiekimą. „CoMaps“ programa yra kilusi iš „Organic Maps“, o pastaroji iš programos „Maps.ME“.
Apie šio projekto kilmę, jos priežastis ir palaikomą kryptį galite paskaityti adresu <b><i>codeberg.org/comaps</i></b>.
Prisijunkite prie bendruomenės ir padėkite sukurti geriausią žemėlapių programą
• Naudokitės programa ir paskleiskite žinią apie ją
• Teikite atsiliepimus ir praneškite apie problemas
• Atnaujinkite žemėlapių duomenis programoje arba „OpenStreetMap“ svetainėje
‣ <b>Skirta naudoti neprisijungus prie interneto</b>: planuokite maršrutus ir keliaukite užsienyje be mobiliojo ryšio, ieškokite kelionės taškų tolimuose žygiuose ir pan. Visos programos funkcijos yra pritaikytos veikti be interneto ryšio.
‣ <b>Gerbia privatumą</b>: programėlė sukurta, teikiant prioritetą privatumui: neidentifikuoja žmonių, neseka ir nerenka asmeninės informacijos. Be reklamų.
‣ <b>Paprasta ir išbaigta</b>: esminės, lengvai naudojamos funkcijos, kurios tiesiog veikia.
‣ <b>Taupo bateriją ir vietą</b>: neišsekina baterijos kaip kitos navigacijos programos. Kompaktiški žemėlapiai tausoja vietą jūsų telefone.
‣ <b>Nemokama ir kuriama bendruomenės</b>: paprasti žmonės kaip jūs padėjo sukurti šią programą, pildydami „OpenStreetMap“ žemėlapį, išbandydami ir pateikdami atsiliepimus apie funkcijas bei prisidėdami savo programavimo įgūdžiais ir pinigais.
‣ <b>Atviras ir skaidrus sprendimų priėmimas ir finansai, ne pelno siekianti ir visiškai atviro kodo programa.</b>
<b>Pagrindinės funkcijos</b>:
• Atsisiunčiami išsamūs žemėlapiai su vietomis, kurių nėra „Google Maps“;
• Žygių pėsčiomis veiksena su pažymėtais pėsčiųjų takais, stovyklavietėmis, vandens šaltiniais, kalnų viršūnėmis, reljefo linijomis ir kt.;
• Pėsčiųjų ir dviračių takai;
• Potencialūs kelionės taškai, kaip antai restoranai, degalinės, viešbučiai, parduotuvės, lankytinos vietos ir daugelis kitų;
• Paieška pagal pavadinimą, adresą arba lankytinos vietos kategoriją;
• Navigacija su balso instrukcijomis pėstiesiems, dviratininkams ir motorinio transporto vairuotojams;
• Mėgstamų vietų įsiminimas vienu bakstelėjimu;
• „Vikipedijos“ straipsniai, prieinami neprisijungus prie interneto;
• Kelionių metro sluoksnis ir maršrutai;
• Trasų įrašymas;
• Žymių ir trasų eksportavimas ir importavimas KML, KMZ, GPX formatais;
• Tamsaus žemėlapio veiksena, skirta naudoti naktį;
• Galimybė papildyti žemėlapio duomenis visiems, naudojantis įtaisytuoju baziniu redaktoriumi.
<b>Laisvė yra čia</b>
Atraskite savo kelionę ir keliaukite po pasaulį, kuriame privatumas ir bendruomenė yra svarbiausia!

View File

@@ -1 +0,0 @@
Paprasta ir patogi navigacija Turiningesnės kelionės Vystoma bendruomenės

View File

@@ -1 +0,0 @@
CoMaps keliaukite atsijungę ir privačiai

View File

@@ -1,9 +1,11 @@
• Dados OSM de 6/1 • Dados OSM de 16/11
Editor: adição de POIs com mais de uma etiqueta OSM, por exemplo esculturas e pinturas; mais tipos de POI podem ser marcados como vagos/desativados Adição de árvores ao mapa
Adição de ferrovias em miniatura e ETEs Ícones de pontos de ônibus menores e exibidos mais cedo
Uso de diálogos Material 3 e fundo mais escuro no modo escuro Visibilidade reduzida das entradas
Remoção de limites de velocidade fictícios para vias de ligação Adição de diversos outros tipos de Pontos de Interesse
Correção de recorte da câmera na navegação Exibição de áreas de areia no mapa
Toque longo menos sensível (modo tela cheia) Adição de opção de "Estabelecimento vazio" ao editor do OSM
• Melhorias nas placas de rodovias na Europa
Mais detalhes em codeberg.org/comaps/comaps/releases • Opção para evitar rotas por estradas pavimentadas
• Adição de ícones nas configurações
Confira as notas de lançamento do Codeberg para mais detalhes!

View File

@@ -1,32 +0,0 @@
Uma aplicação pela comunidade, grátis e open-source, de mapas baseada em dados do OpenStreetMap e reforçada com compromisso para transparência, privacidade e sem fins lucrativos. CoMaps é um fork/spin-off de Organic Maps, que, por sua vez, é um fork de Maps.ME
Leia sobre as razões deste projeto e a sua direção em <b><i>codeberg.org/comaps</i></b>.
Junte-se à comunidade e ajude a fazer a melhor aplicação de mapas
• Use a aplicação e partilhe-a com outros
• Dê feedback e reporte problemas
• Atualize os dados de mapa na aplicação ou no site do OpenStreetMap
‣ <b>Simples e Polida</b>: funcionalidades essenciais fáceis que “somente funcionam”.
‣ <b>Foco Offline</b>: Planeie e navegue as suas viagens no estrangeiro sem dados móveis, procure locais numa caminhada distante, etc. Todas as funções da aplicação foram criadas com intenção de serem usadas sem internet.
‣ <b>Respeita a privacidade</b>: A aplicação foi criada com privacidade em mente — não identifica o utilizador, não rastreia, e não usa a sua informação pessoal. Sem anúncios.
‣ <b>Saves Your Battery and Space</b>: Não esgota a sua bateria ao contrário de outras aplicações. Mapas compactos salvam espaço no seu telemóvel.
‣ <b>Gratuita e Feita pela Comunidade</b>: Pessoas como si ajudam a criar a aplicação ao adicionar locais ao OpenStreetMap, testando e dando opiniões em funcionalidades e contribuindo com dotes de desenvolvimento e dinheiro.
‣ <b>Decisões e Finanças Abertas e Transparentes, Sem fins lucrativos e Open-Source.</b>
<b>Funcionalidades principais</b>:
• Mapas detalhados descarregáveis com locais que não estão disponíveis com o Google Maps
• Modo ao Ar Livre com trilhos de caminhada destacados, acampamentos, fontes de água, cumes, curvas de nível, etc
• Caminhos pedestres e ciclovias
• Pontos de interesse como restaurantes, estações de serviço, hotéis, lojas, atrações e muitos mais
• Pesquise por nome, endereço, ou por categoria de ponto de interesse
• Navegação com anúncios de voz ao caminhar, pedalar ou conduzir
• Marque os seus locais favoritos com um único clique
• Artigos da Wikipédia Offline
• Camada de metro e direções
• Gravação de Percursos
• Exportar e importar marcadores e percursos em formatos KML, KMZ, GPX
• Um modo escuro para usar durante a noite
• Melhore a informação do mapa para todos com um editor básico embebido
<b>A liberdade chegou</b>
Descubra a sua jornada, navegue o mundo com privacidade e a comunidade à frente!

View File

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

View File

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

View File

@@ -1,8 +1,10 @@
• Карты OpenStreetMap от 6 января • Карты OpenStreetMap от 16 ноября
Редактор: возможность добавления POI, определяемых несколькими тегами, например церквей, мечетей, буддистских храмов.. Добавлены деревья и песчаные области
Добавлены миниатюрные железные дороги и очистные сооружения Автобусные остановки показываются раньше, но маленькими иконами
Использование диалогов Material 3 и более тёмного фона в тёмном режиме Входы разделены по типам
Удалены фиктивные ограничения скорости для заездов / съездов с шоссе В OSM редакторе можно отметить место как неиспользуемое
Менее чувствительное длительное нажатие на экран (переход в полноэкранный режим) Улучшения в иконках номеров дорог в Европе
• Возможность избегать дорог с покрытием при построении маршрута
Подробнее на codeberg.org/comaps/comaps/releases • Иконки в экране настроек
На карту добавлены несколько новых типов объектов
Подробнее смотрите на codeberg.org/comaps/comaps/releases

View File

@@ -1,31 +1,31 @@
Brezplačno in odprtokodno zemljevidno orodje, ki ga vodi skupnost, temelji na podatkih OpenStreetMap in je okrepljena s predanostjo transparentnosti, zasebnosti in nepridobitnosti. CoMaps je izpeljanka OrganicMaps, ta pa je izpeljanka Maps.ME. Brezplačno in odprtokodno zemljevidno orodje, ki ga vodi skupnost, temelji na podatkih OpenStreetMap in je okrepljena s predanostjo transparentnosti, zasebnosti in nedobičkonosnosti. CoMaps je izpeljanka OrganicMaps, ta pa je izpeljanka Maps.ME.
Preberite si o razlogih za ta projekt in njegovi usmerjenosti na <b><i>codeberg.org/comaps</i></b>. Preverite si o razlogih za ta projekt in njegovi usmerjenosti na <b><i>codeberg.org/comaps</i></b>.
Pridružite se skupnosti in pomagajte narediti najboljše zemljevidno orodje Pridružite se skupnosti in pomagajte narediti najboljše zemljevidno orodje
• Uporabljajte orodje in širite glas o njem • Uporabljajte orodje in širite glas o njem
• Dajajte povratne informacije in poročajte o napakah • Dajajte povratne informacije in poročajte o napakah
• Posodabljajte podatke zemljevida v tem orodju ali na spletni strani OpenStreetMap • Posodabljajte podatke zemljevida v tem orodju ali na spletni strani OpenStreetMap
‣ <b>Osredotočeno na uporabo brez povezave</b>: Načrtujte in se usmerjajte na vašem potovanju v tujini vrez potrebe po mobilnih podatkih, iščite vmesne točke potovanja ko ste na daljšem pohodu ipd. Vse zmogljivosti orodja so zasnovane za delo brez povezave. ‣ <b>Osredotočeno na uporabo brez povezave</b>: Načrtujte in se usmerjajte na vašem potovanju v tujini vrez potrebe po mobilnih podatkih, iščite vmesne točke potocanja ko ste na daljšem pohodu ipd. Vse zmogljivosti orodja so zasnovane za delo brez povezave.
‣ <b>Spoštovanje zasebnosti</b>: orodje je zasnovano z mislijo na zasebnost ne prepoznava oseb, ne sledi in ne zbira osebnih podatkov. Brez oglasov. ‣ <b>Spoštovanje zasebnosti</b>: orodje je zasnovano z mislijo na zasebnost ne prepoznava oseb, ne sledi in ne zbira osebnih podatkov. Brez oglasov.
‣ <b>Preprosto in dodelano</b>: nujne zmogljivosti, enostavne za uporabo, ki preprosto delujejo. ‣ <b>Preprosto in dodelano</b>: nujne zmogljivosti, enostavne za uporabo, ki preprosto delujejo.
‣ <b>Prihrani vašo baterijo in prostor.</b>: ne izčrpava vaše baterije kakor druga usmerjevalna orodja. Strnjeni zemljevidi prihranijo dragocen prostor na vašem telefonu. ‣ <b>Prihrani vašo baterijo in prostor.</b>: ne izčrpava vaše baterije kakor druga usmerjevalna orodja. Strnjeni zemljevidi prihranijo dragocen prostor na vašem telefonu.
‣ <b>Brezplačno in ustvarjeno v skupnosti</b>: ljudje kot ste vi pomagajo ustvarjati to orodje, tako da dodajajo kraje na OpenStreetMap, preizkušajo in dajejo povratne informacije o zmogljivostih in prispevajo svoje razvijalske sposobnosti in sredstva. ‣ <b>Brezplačno in ustvarjeno v skupnosti</b>: ljudje kot ste vi pomagajo ustvarjati to orodje, tako da dodajajo kraje na OpenStreetMap, preizkušajo in dajejo povratne informacije o zmogljivostih in prispevajo svoje razvijalske sposobnosti in sredstva.
‣ <b>Odprto in transparentno odločanje in finance, nepridobitno in popolnoma odprtokodno.</b> ‣ <b>Odprto in transparentno odločanje in finance, nedobičkonosno in popolnoma odprtokodno.</b>
<b>Glavne zmogljivosti</b>: <b>Glavne zmogljivosti</b>:
• Prenosljivi podrobni zemljevidi s kraji, ki na Googlovih zemljevidih niso na voljo. • Prenosljivi podrobni zemljevidi s kraji, ki na Googlovoh zemljevidih niso na voljo.
• Prikaz za dejavnosti na prostem s poudarjenimi pohodniškimi potmi, tabornimi prostori, vodnimi viri, vrhovi, plastnicami itd. • Prikaz za dejavnosti na prostem s poudarjenimi pohodniškimi potmi, tabornimi prostori, vodnimi viri, vrhovi, plastnicami itd.
• Pešpoti in kolesarke poti • Pešpoti in kolesarke poti
• Kraji zanimanja, npr. restavracije, bencinske črpalke, hoteli, trgovine, znamenitosti in mnogo več • Kraji zanimanja, npr. restavracije, bencinske črpalke, hoteli, trgovine, znamenitosti in mnogo več
• Iščite po imenu, hišnemu naslovu ali po vrsti • Iščite po imenu, hišnemu naslovu ali po vrsti
• Usmerjanje z glasovnimi navodili za hojo, kolesarjenje ali vožnjo avtomobila. • Usmerjanje z glasovnimi obvestili za hojo, kolesarjenje ali vožnjo avtomobila.
• Zaznamujte svoje najljubše kraje s preprostim dotikom • Zaznamujte svoje najljubše kraje s preprostim dotikom
• Wikipedijini članki brez povezave • Wikipedijini članki brez povezave
• Prometna plast podzemne železnice z usmerjanjem • Prometna plast podzemne železnice z usmerjanjem
• Izvozite ali uvozite zaznamke in sledi v oblikah KML, KMZ, GPX • Izvozite ali uvozite zaznamke in sledi v oblikah KML, KMZ, GPX
• Temni prikaz za uporabo ponoči • Temni prikaz za uporabo ponoči
• Izboljšajte podatke zemljevida za vse z uporabo vgrajenega urejevalnika • Izboljšajtw podatke zemljevida za vse z uporabo vgrajenega urejevalnika
<b>Svoboda je tu</b> <b>Svoboda je tu</b>
Odkijte več o vašem potovanju, usmerjajte se po svetu s poudarkom na zasebnosti in skupnostnem delovanju! Odkijte več o vašem potovanju, usmerjajte se po svetu s poudarkom na zasebnosti in skupnostnem delovanju!

View File

@@ -1 +1 @@
Enostavno usmerjanje Odkrijte več o svojem potovanju Podprto v skupnosti Enostavno usmerjanje Odkrij več o svojem potovanju Podprto v skupnosti

View File

@@ -1 +1 @@
CoMaps hodi in vozi brez povezave, zasebno CoMapsHodi, kolesari, vozi brez povezave, zasebno

View File

@@ -0,0 +1,11 @@
• Подaци са OpenStreetMap-а закључно са 16. новембром
• Додате ознаке за дрвеће
• Смањене иконе аутобуских стајалишта и ранији приказ
• Смањена видљивост улаза
• Додато неколико нових типова ознака на мапу
• Приказ пешчаних површина на мапи
• Додата опција „пословни простор је празан“ у OSM едитору
• Побољшани путокази у Европи
• Опција рутирања „избегавај асфалтиране путеве“
• Додате иконе на страници подешавања
Погледајте детаље на Codeberg-у за списак свих промена!

View File

@@ -1 +1 @@
எளிய வழிகாட்டி - பயணத்தை மேலும் கண்டறி - சமூகத்தால் இயக்கப்படுகிறது எளிய வழிகாட்டி - பயணத்தை மேலும் சுவாரசியமாக்க - சமூகத்தால் இயக்கப்படுகிறது

View File

@@ -1 +0,0 @@
இணைவரைபடங்கள் - மலையேறு, வண்டி, தனிமையில் இயக்கு

View File

@@ -1 +1 @@
version: 2025.03.02-7-FDroid+25030207 version: 2025.11.19-2-FDroid+25111902

View File

@@ -3,7 +3,7 @@ Eine von der Community betriebene, kostenlose Open-Source Karten App, die auf Op
Werde Teil der Community und hilf mit, die beste Karten-App zu entwickeln Werde Teil der Community und hilf mit, die beste Karten-App zu entwickeln
• Nutze die App und erzähle anderen davon • Nutze die App und erzähle anderen davon
• Gib Feedback und melde Probleme • Gib Feedback und melde Probleme
• Aktualisiere Kartendaten in der App oder auf der OpenStreetMap-Webseite • Aktualisiere Kartendaten in der App oder auf der OpenStreetMap Website
<i>Dein Feedback und deine 5-Sterne-Bewertung sind die beste Unterstützung für uns!</i> <i>Dein Feedback und deine 5-Sterne-Bewertung sind die beste Unterstützung für uns!</i>
@@ -12,7 +12,7 @@ Werde Teil der Community und hilf mit, die beste Karten-App zu entwickeln
‣ <b>Datenschutz ist uns wichtig!</b>: Die App wurde mit Fokus auf Privatsphäre entwickelt kein Tracking, keine Erfassung persönlicher Daten, keine Werbung. ‣ <b>Datenschutz ist uns wichtig!</b>: Die App wurde mit Fokus auf Privatsphäre entwickelt kein Tracking, keine Erfassung persönlicher Daten, keine Werbung.
‣ <b>Spart Akku und Speicherplatz</b>: Verbraucht nicht unnötig Akku wie andere Navi-Apps. Kompakte Karten sparen Speicherplatz auf Deinem Gerät. ‣ <b>Spart Akku und Speicherplatz</b>: Verbraucht nicht unnötig Akku wie andere Navi-Apps. Kompakte Karten sparen Speicherplatz auf Deinem Gerät.
‣ <b>Kostenlos und von der Community entwickelt</b>: Menschen wie du haben geholfen, die App zu entwickeln durch das Hinzufügen von Orten zu OpenStreetMap, Testen von neuen Funktionen, Softwareentwicklung oder Spenden. ‣ <b>Kostenlos und von der Community entwickelt</b>: Menschen wie du haben geholfen, die App zu entwickeln durch das Hinzufügen von Orten zu OpenStreetMap, Testen von neuen Funktionen, Softwareentwicklung oder Spenden.
‣ <b>Offen und transparent bei Entscheidungen und Finanzen, gemeinnützig und vollständig Open Source.</b> ‣ <b>Offen und transparent bei Entscheidungen und Finanzen, gemeinnützig und vollständig Open Source</b>
<b>Hauptfunktionen</b>: <b>Hauptfunktionen</b>:
• Detaillierte, herunterladbare Karten mit Orten, die bei Google Maps oft fehlen • Detaillierte, herunterladbare Karten mit Orten, die bei Google Maps oft fehlen
@@ -24,13 +24,13 @@ Werde Teil der Community und hilf mit, die beste Karten-App zu entwickeln
• Lesezeichen mit einem einzigen Tippen speichern • Lesezeichen mit einem einzigen Tippen speichern
• Offline verfügbare Wikipedia-Artikel • Offline verfügbare Wikipedia-Artikel
• U- und S-Bahn-Netze • U- und S-Bahn-Netze
• Aufzeichnen von GPS-Tracks • Aufzeichnen von GPS Tracks
• Import und Export von Favoriten und Routen im KML-, KMZ- oder GPX-Format • Import und Export von Favoriten und Routen im KML-, KMZ- oder GPX-Format
• Dunkler Modus für die Nutzung bei Nacht • Dunkler Modus für die Nutzung bei Nacht
• Kartenbearbeitung direkt in der App mit einem einfachen Editor • Kartenbearbeitung direkt in der App mit einem einfachen Editor
• Unterstützung für Android Auto • Unterstützung für Android Auto
Bitte melde Probleme, schlage neue Funktionen vor und werde Teil der Community auf unserer Website: <b><i>comaps.app/de/</i></b> Bitte melde Probleme, schlage neue Funktionen vor und werde Teil der Community auf unserer Website: <b><i>comaps.app</i></b>
<b>Freiheit beginnt hier</b> <b>Entdecke die Unabhängigkeit</b>
Entdecke deine Reise, wobei Datenschutz und Gemeinschaft im Vordergrund stehen! Entdecke deine Reise navigiere in der Welt mit Datenschutz!

View File

@@ -1 +1 @@
Leichte Navigation Erlebe mehr von deiner Reise Community-unterstützt Einfache Navigation - Entdecken Sie mehr von Ihrer Reise - Community-Entwickelt

View File

@@ -68,4 +68,4 @@ Por favor, informa de errores, sugiere ideas y únete a nuestra comunidad en el
<b>La Libertad Está Aquí</b> <b>La Libertad Está Aquí</b>
¡Descubre tu camino, navega el mundo con privacidad y con la comunidad como prioridad! Descubre tu camino, navega el mundo con privacidad y con la comunidad como prioridad.

View File

@@ -1,36 +0,0 @@
Bendruomenės vystoma nemokama atvirojo kodo žemėlapių programa, pagrįsta „OpenStreetMap“ duomenimis ir sustiprinta įsipareigojimu užtikrinti skaidrumą, privatumą ir pelno nesiekimą.
Prisijunkite prie bendruomenės ir padėkite sukurti geriausią žemėlapių programą
• Naudokitės programa ir paskleiskite žinią apie ją
• Teikite atsiliepimus ir praneškite apie problemas
• Atnaujinkite žemėlapių duomenis programoje arba „OpenStreetMap“ svetainėje
<i>Jūsų atsiliepimai ir 5 žvaigždučių vertinimai yra geriausias palaikymas mums!</i>
‣ <b>Paprasta ir išbaigta</b>: esminės, lengvai naudojamos funkcijos, kurios tiesiog veikia.
‣ <b>Skirta naudoti neprisijungus prie interneto</b>: planuokite maršrutus ir keliaukite užsienyje be mobiliojo ryšio, ieškokite kelionės taškų tolimuose žygiuose ir pan. Visos programos funkcijos yra pritaikytos veikti be interneto ryšio.
‣ <b>Gerbia privatumą</b>: programėlė sukurta, teikiant prioritetą privatumui: neidentifikuoja žmonių, neseka ir nerenka asmeninės informacijos. Be reklamų.
‣ <b>Taupo bateriją ir vietą</b>: neišsekina baterijos kaip kitos navigacijos programos. Kompaktiški žemėlapiai tausoja vietą jūsų telefone.
‣ <b>Nemokama ir kuriama bendruomenės</b>: paprasti žmonės kaip jūs padėjo sukurti šią programą, pildydami „OpenStreetMap“ žemėlapį, išbandydami ir pateikdami atsiliepimus apie funkcijas bei prisidėdami savo programavimo įgūdžiais ir pinigais.
‣ <b>Atviras ir skaidrus sprendimų priėmimas ir finansai, ne pelno siekianti ir visiškai atviro kodo programa.</b>
<b>Pagrindinės funkcijos</b>:
• Atsisiunčiami išsamūs žemėlapiai su vietomis, kurių nėra „Google Maps“;
• Žygių pėsčiomis veiksena su pažymėtais pėsčiųjų takais, stovyklavietėmis, vandens šaltiniais, kalnų viršūnėmis, reljefo linijomis ir kt.;
• Pėsčiųjų ir dviračių takai;
• Potencialūs kelionės taškai, kaip antai restoranai, degalinės, viešbučiai, parduotuvės, lankytinos vietos ir daugelis kitų;
• Paieška pagal pavadinimą, adresą arba lankytinos vietos kategoriją;
• Navigacija su balso instrukcijomis pėstiesiems, dviratininkams ir motorinio transporto vairuotojams;
• Mėgstamų vietų įsiminimas vienu bakstelėjimu;
• „Vikipedijos“ straipsniai, prieinami neprisijungus prie interneto;
• Kelionių metro sluoksnis ir maršrutai;
• Trasų įrašymas;
• Žymių ir trasų eksportavimas ir importavimas KML, KMZ, GPX formatais;
• Tamsaus žemėlapio veiksena, skirta naudoti naktį;
• Galimybė papildyti žemėlapio duomenis visiems, naudojantis įtaisytuoju baziniu redaktoriumi;
• „Android Auto“ palaikymas.
Praneškite apie programos problemas, siūlykite idėjas ir prisijunkite prie mūsų bendruomenės svetainėje <b><i>comaps.app</i></b>.
<b>Laisvė yra čia</b>
Atraskite savo kelionę ir keliaukite po pasaulį, kuriame privatumas ir bendruomenė yra svarbiausia!

View File

@@ -1 +0,0 @@
Paprasta ir patogi navigacija Turiningesnės kelionės Vystoma bendruomenės

View File

@@ -1 +0,0 @@
CoMaps naviguokite privačiai

View File

@@ -1,36 +0,0 @@
Aplikacja mapowa tworzona przez społeczność, darmowa i open source, oparta na danych OpenStreetMap, z pełnym naciskiem na transparentność, prywatność i działanie non-profit.
Dołącz do społeczności i pomóż tworzyć najlepszą aplikację mapową
• Korzystaj z aplikacji i polecaj ją innym
• Przekazuj opinie i zgłaszaj problemy
• Aktualizuj dane mapy w aplikacji lub na stronie OpenStreetMap
<i>Twoje opinie i oceny na 5 gwiazdek są dla nas najlepszym wsparciem!</i>
‣ <b>Prosta i dopracowana</b>: najważniejsze, łatwe w użyciu funkcje, które po prostu działają.
‣ <b>Skoncentrowana na trybie offline</b>: planuj i nawiguj za granicą bez sieci komórkowej, wyszukuj punkty na odległych szlakach wszystkie funkcje działają offline.
‣ <b>Z poszanowaniem prywatności</b>: aplikacja nie identyfikuje użytkowników, nie śledzi i nie zbiera danych osobowych. Bez reklam.
‣ <b>Oszczędza baterię i miejsce</b>: nie zużywa baterii jak inne aplikacje nawigacyjne, a kompaktowe mapy oszczędzają miejsce w telefonie.
‣ <b>Darmowa i tworzona przez społeczność</b>: ludzie tacy jak Ty dodają miejsca do OpenStreetMap, testują funkcje, zgłaszają opinie i wspierają projekt.
‣ <b>Otwarte i przejrzyste decyzje i finanse, działanie non-profit, pełne open source.</b>
<b>Główne funkcje</b>:
• Pobierane szczegółowe mapy z miejscami, których nie ma w Google Maps
• Tryb outdoor ze szlakami, biwakami, źródłami wody, szczytami, warstwicami itp.
• Ścieżki piesze i rowerowe
• Punkty zainteresowania: restauracje, stacje paliw, hotele, sklepy, atrakcje i wiele innych
• Wyszukiwanie po nazwie, adresie lub kategorii
• Nawigacja z komunikatami głosowymi dla pieszych, rowerzystów i kierowców
• Dodawanie ulubionych miejsc jednym tapnięciem
• Artykuły Wikipedii dostępne offline
• Warstwa metra i wskazówki dojazdu
• Nagrywanie śladu trasy
• Eksport i import ulubionych miejsc i tras w formatach KML, KMZ, GPX
• Tryb ciemny do używania nocą
• Poprawianie danych mapy za pomocą prostego wbudowanego edytora
• Obsługa Android Auto
Zgłaszaj problemy, proponuj pomysły i dołącz do społeczności na stronie <b><i>comaps.app</i></b>.
<b>Wolność jest tutaj</b>
Odkrywaj swoją drogę i nawiguj po świecie z prywatnością i społecznością na pierwszym miejscu!

View File

@@ -1 +1 @@
Enostavno usmerjanje Odkrijte več o svojem potovanju Podprto v skupnosti Enostavno usmerjanje Odkrij več o svojem potovanju Podprto v skupnosti

View File

@@ -1 +1 @@
CoMaps - Usmerjajte se zasebno CoMaps - Usmerjajte zasebno

View File

@@ -1,36 +0,0 @@
திறந்ததெருவரைபடம் தரவை அடிப்படையாகக் கொண்ட சமூகத்தால் வழிநடத்தப்படும் இலவச & திறந்த மூல வரைபடப் பயன்பாடு, வெளிப்படைத்தன்மை, தனியுரிமை மற்றும் இலாப நோக்கற்ற தன்மை ஆகியவற்றிற்கான அர்ப்பணிப்புடன் வலுப்படுத்தப்பட்டுள்ளது.
சமூகத்தில் சேர்ந்து சிறந்த வரைபடப் பயன்பாட்டை உருவாக்க உதவுங்கள்
• பயன்பாட்டைப் பயன்படுத்தி அதைப் பற்றிய செய்தியைப் பரப்புங்கள்
• கருத்துத் தெரிவிக்கவும் சிக்கல்களைப் புகாரளிக்கவும்
• பயன்பாட்டில் அல்லது OpenStreetMap வலைத்தளத்தில் வரைபடத் தரவைப் புதுப்பிக்கவும்
<i>உங்கள் கருத்து மற்றும் 5-நட்சத்திர மதிப்புரைகள் எங்களுக்குச் சிறந்த ஆதரவாகும்!</i>
‣ <b>எளிமையான மற்றும் மெருகூட்டப்பட்ட</b>: அத்தியாவசியமான பயன்படுத்த எளிதான அம்சங்கள் வேலை செய்கின்றன.
‣ <b>ஆஃப்லைனில் கவனம் செலுத்துகிறது</b>: செல்லுலார் சேவை தேவை இல்லாமல் உங்கள் வெளிநாட்டு பயணத்தைத் திட்டமிட்டு வழிநடத்துங்கள், தொலைதூர நடைபயணத்தின்போது வழிப்புள்ளிகளைத் தேடுங்கள் போன்றவை. அனைத்து பயன்பாட்டு செயல்பாடுகளும் ஆஃப்லைனில் வேலை செய்ய வடிவமைக்கப்பட்டுள்ளன.
‣ <b>தனியுரிமையை மதித்தல்</b>: பயன்பாடு தனியுரிமையை மனதில் கொண்டு வடிவமைக்கப்பட்டுள்ளது - மக்களை அடையாளம் காணாது, கண்காணிக்காது மற்றும் தனிப்பட்ட தகவல்களைச் சேகரிக்காது. விளம்பரங்கள் இல்லாதது.
‣ <b>உங்கள் பேட்டரி மற்றும் இடத்தைச் சேமிக்கிறது</b>: பிற வழிசெலுத்தல் பயன்பாடுகளைப் போல உங்கள் பேட்டரியை வெளியேற்றாது. சிறிய வரைபடங்கள் உங்கள் தொலைபேசியில் விலைமதிப்பற்ற இடத்தைச் சேமிக்கின்றன.
‣ <b>இலவசம் மற்றும் சமூகத்தால் உருவாக்கப்பட்டது</b>: உங்களைப் போன்றவர்கள் OpenStreetMap இல் இடங்களைச் சேர்ப்பதன் மூலமும், அம்சங்கள்குறித்து சோதித்துப் பார்த்துக் கருத்து தெரிவிப்பதன் மூலமும், அவர்களின் மேம்பாட்டுத் திறன்கள் மற்றும் பணத்தை பங்களிப்பதன் மூலமும் பயன்பாட்டை உருவாக்க உதவினார்கள்.
‣ <b>திறந்த மற்றும் வெளிப்படையான முடிவெடுக்கும் மற்றும் நிதி, இலாப நோக்கற்ற மற்றும் முழுமையாகத் திறந்த மூல.</b>
<b>முக்கிய பண்புகள்</b>:
• கூகிள் வரைபடத்தில் கிடைக்காத இடங்களுடன் பதிவிறக்கம் செய்யக்கூடிய விரிவான வரைபடங்கள்
• ஹைகிங் பாதைகள், முகாம் தளங்கள், நீர் ஆதாரங்கள், சிகரங்கள், விளிம்புக் கோடுகள் போன்றவற்றுடன் வெளிப்புற பயன்முறை
• நடைபாதைகள் மற்றும் சைக்கிள் பாதைகள்
• உணவகங்கள், எரிவாயு நிலையங்கள், ஹோட்டல்கள், கடைகள், பார்வையிடல்கள் மற்றும் பல போன்ற ஆர்வமுள்ள இடங்கள்
• பெயர் அல்லது முகவரி அல்லது ஆர்வமுள்ள இட வகைமூலம் தேடுங்கள்
• நடைபயிற்சி, சைக்கிள் ஓட்டுதல் அல்லது வாகனம் ஓட்டுவதற்கான குரல் அறிவிப்புகளுடன் வழிசெலுத்தல்
• உங்களுக்குப் பிடித்த இடங்களை ஒரே தட்டலில் புக்மார்க் செய்யவும்
• ஆஃப்லைன் விக்கிபீடியா கட்டுரைகள்
• சுரங்கப்பாதை போக்குவரத்து அடுக்கு மற்றும் திசைகள்
• பதிவுசெய்தலைக் கண்காணிக்கவும்
• KML, KMZ, GPX வடிவங்களில் புக்மார்க்குகள் மற்றும் தடங்களை ஏற்றுமதி செய்து இறக்குமதி செய்யவும்
• இரவில் பயன்படுத்த ஒரு இருண்ட பயன்முறை
• அடிப்படை உள்ளமைக்கப்பட்ட எடிட்டரைப் பயன்படுத்தி அனைவருக்கும் வரைபடத் தரவை மேம்படுத்தவும்
• ஆண்டாய்டு தானி ஆதரவு
பயன்பாட்டு சிக்கல்களைப் புகாரளிக்கவும், யோசனைகளைப் பரிந்துரைக்கவும் மற்றும் எங்கள் சமூகத்தில் சேரவும் <b><i>comaps.app</i></b> வலைத்தளம்.
<b>சுதந்திரம் இங்கே உள்ளது</b>
உங்கள் பயணத்தைக் கண்டறியவும், தனியுரிமை மற்றும் சமூகத்தை முன்னணியில் வைத்து உலகை வழிநடத்தவும்!

View File

@@ -1 +1 @@
எளிய வழிகாட்டி - பயணத்தை மேலும் கண்டறி - சமூகத்தால் இயக்கப்படுகிறது எளிய வழிகாட்டி - பயணத்தை மேலும் சுவாரசியமாக்க - சமூகத்தால் இயக்கப்படுகிறது

View File

@@ -1 +0,0 @@
இணைவரைபடங்கள் - தனியுரிமை

View File

@@ -18,7 +18,6 @@ import android.location.Location;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
@@ -26,15 +25,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.core.view.ViewCompat; import androidx.core.view.ViewCompat;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.checkbox.MaterialCheckBox;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.progressindicator.LinearProgressIndicator;
import com.google.android.material.textview.MaterialTextView;
import app.organicmaps.base.BaseMwmFragmentActivity; import app.organicmaps.base.BaseMwmFragmentActivity;
import app.organicmaps.dialog.CustomMapServerDialog;
import app.organicmaps.downloader.MapManagerHelper; import app.organicmaps.downloader.MapManagerHelper;
import app.organicmaps.intent.Factory; import app.organicmaps.intent.Factory;
import app.organicmaps.sdk.Framework; import app.organicmaps.sdk.Framework;
@@ -47,7 +38,11 @@ import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.util.UiUtils; import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener; import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.checkbox.MaterialCheckBox;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.progressindicator.LinearProgressIndicator;
import com.google.android.material.textview.MaterialTextView;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@@ -59,7 +54,6 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
private MaterialTextView mTvMessage; private MaterialTextView mTvMessage;
private LinearProgressIndicator mProgress; private LinearProgressIndicator mProgress;
private MaterialButton mBtnDownload; private MaterialButton mBtnDownload;
private MaterialButton mBtnAdvanced;
private MaterialCheckBox mChbDownloadCountry; private MaterialCheckBox mChbDownloadCountry;
private String mCurrentCountry; private String mCurrentCountry;
@@ -273,14 +267,6 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
mProgress = findViewById(R.id.progressbar); mProgress = findViewById(R.id.progressbar);
mBtnDownload = findViewById(R.id.btn_download_resources); mBtnDownload = findViewById(R.id.btn_download_resources);
mChbDownloadCountry = findViewById(R.id.chb_download_country); mChbDownloadCountry = findViewById(R.id.chb_download_country);
mBtnAdvanced = findViewById(R.id.btn_advanced);
mBtnAdvanced.setOnClickListener(v -> {
CustomMapServerDialog.show(this, url -> {
prepareFilesDownload(false);
});
});
mBtnAdvanced.setEnabled(true);
mBtnListeners = new View.OnClickListener[BTN_COUNT]; mBtnListeners = new View.OnClickListener[BTN_COUNT];
mBtnNames = new String[BTN_COUNT]; mBtnNames = new String[BTN_COUNT];
@@ -305,11 +291,6 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
{ {
mBtnDownload.setOnClickListener(mBtnListeners[action]); mBtnDownload.setOnClickListener(mBtnListeners[action]);
mBtnDownload.setText(mBtnNames[action]); mBtnDownload.setText(mBtnNames[action]);
// Allow changing server only when idle or after an error.
boolean advancedEnabled = (action == DOWNLOAD || action == TRY_AGAIN || action == RESUME);
mBtnAdvanced.setEnabled(advancedEnabled);
mBtnAdvanced.setAlpha(advancedEnabled ? 1f : 0.5f);
} }
private void doDownload() private void doDownload()
@@ -378,9 +359,6 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
private void finishFilesDownload(int result) private void finishFilesDownload(int result)
{ {
mBtnAdvanced.setEnabled(true);
mBtnAdvanced.setAlpha(1f);
if (result == ERR_NO_MORE_FILES) if (result == ERR_NO_MORE_FILES)
{ {
// World and WorldCoasts has been downloaded, we should register maps again to correctly add them to the model. // World and WorldCoasts has been downloaded, we should register maps again to correctly add them to the model.
@@ -446,20 +424,16 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
default -> throw new AssertionError("Unexpected result code = " + result); default -> throw new AssertionError("Unexpected result code = " + result);
}; };
mAlertDialog = new MaterialAlertDialogBuilder(this) mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(titleId) .setTitle(titleId)
.setMessage(messageId) .setMessage(messageId)
.setCancelable(true) .setCancelable(true)
.setOnCancelListener((dialog) -> setAction(RESUME)) .setOnCancelListener((dialog) -> setAction(PAUSE))
.setPositiveButton(R.string.try_again, .setPositiveButton(R.string.try_again,
(dialog, which) -> { (dialog, which) -> {
setAction(TRY_AGAIN); setAction(TRY_AGAIN);
onTryAgainClicked(); onTryAgainClicked();
}) })
.setNegativeButton(R.string.cancel,
(dialog, which) -> {
setAction(RESUME);
})
.setOnDismissListener(dialog -> mAlertDialog = null) .setOnDismissListener(dialog -> mAlertDialog = null)
.show(); .show();
} }

View File

@@ -48,6 +48,7 @@ import androidx.core.content.ContextCompat;
import androidx.core.view.ViewCompat; import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat; import androidx.core.view.WindowInsetsCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentFactory;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction; import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
@@ -107,7 +108,6 @@ import app.organicmaps.sdk.routing.RoutingOptions;
import app.organicmaps.sdk.search.SearchEngine; import app.organicmaps.sdk.search.SearchEngine;
import app.organicmaps.sdk.settings.RoadType; import app.organicmaps.sdk.settings.RoadType;
import app.organicmaps.sdk.settings.UnitLocale; import app.organicmaps.sdk.settings.UnitLocale;
import app.organicmaps.sdk.sound.TtsPlayer;
import app.organicmaps.sdk.util.Config; import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.LocationUtils; import app.organicmaps.sdk.util.LocationUtils;
import app.organicmaps.sdk.util.PowerManagment; import app.organicmaps.sdk.util.PowerManagment;
@@ -132,6 +132,8 @@ import app.organicmaps.widget.placepage.PlacePageViewModel;
import com.google.android.material.appbar.MaterialToolbar; import com.google.android.material.appbar.MaterialToolbar;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.textview.MaterialTextView;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Objects; import java.util.Objects;
@@ -431,7 +433,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
} }
dismissLocationErrorDialog(); dismissLocationErrorDialog();
mLocationErrorDialog = new MaterialAlertDialogBuilder(MwmActivity.this) mLocationErrorDialog = new MaterialAlertDialogBuilder(MwmActivity.this, R.style.MwmTheme_AlertDialog)
.setMessage(R.string.unknown_current_position) .setMessage(R.string.unknown_current_position)
.setCancelable(true) .setCancelable(true)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@@ -654,7 +656,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
else else
{ {
dismissAlertDialog(); dismissAlertDialog();
mAlertDialog = new MaterialAlertDialogBuilder(this) mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.message_invalid_feature_position) .setTitle(R.string.message_invalid_feature_position)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
.setOnDismissListener(dialog -> mAlertDialog = null) .setOnDismissListener(dialog -> mAlertDialog = null)
@@ -711,6 +713,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
if (!TextUtils.isEmpty(appName)) if (!TextUtils.isEmpty(appName))
{ {
setTitle(appName); setTitle(appName);
((MaterialTextView) mPointChooser.findViewById(R.id.title)).setText(appName);
} }
} }
@@ -1153,7 +1156,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
if (type == IsolinesState.EXPIREDDATA) if (type == IsolinesState.EXPIREDDATA)
{ {
mAlertDialog = new MaterialAlertDialogBuilder(this) mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.downloader_update_maps) .setTitle(R.string.downloader_update_maps)
.setMessage(R.string.isolines_activation_error_dialog) .setMessage(R.string.isolines_activation_error_dialog)
.setPositiveButton( .setPositiveButton(
@@ -1772,7 +1775,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
{ {
dismissAlertDialog(); dismissAlertDialog();
mAlertDialog = mAlertDialog =
new MaterialAlertDialogBuilder(this) new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.unable_to_calc_alert_title) .setTitle(R.string.unable_to_calc_alert_title)
.setMessage(R.string.unable_to_calc_alert_subtitle) .setMessage(R.string.unable_to_calc_alert_subtitle)
.setPositiveButton(R.string.settings, .setPositiveButton(R.string.settings,
@@ -1795,7 +1798,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
builder.append(getString(resId)).append("\n\n"); builder.append(getString(resId)).append("\n\n");
dismissAlertDialog(); dismissAlertDialog();
mAlertDialog = new MaterialAlertDialogBuilder(this) mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.dialog_routing_disclaimer_title) .setTitle(R.string.dialog_routing_disclaimer_title)
.setMessage(builder.toString()) .setMessage(builder.toString())
.setCancelable(false) .setCancelable(false)
@@ -1811,26 +1814,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
return false; return false;
} }
private void deliverTtsMessage()
{
if (Config.isTtsMessageDelivered())
return;
String languageDisplayName = TtsPlayer.INSTANCE.getLanguageDisplayName();
if (languageDisplayName != null)
{
String navigationStartMessage = getResources().getString(R.string.navigation_start_tts_message);
navigationStartMessage += languageDisplayName;
Toast.makeText(this, navigationStartMessage, Toast.LENGTH_LONG).show();
}
else
Toast.makeText(this, getResources().getString(R.string.navigation_start_tts_disabled_message), Toast.LENGTH_LONG)
.show();
Config.setTtsMessageDelivered();
}
private boolean showStartPointNotice() private boolean showStartPointNotice()
{ {
final RoutingController controller = RoutingController.get(); final RoutingController controller = RoutingController.get();
@@ -1844,7 +1827,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
return true; return true;
final MapObject endPoint = Objects.requireNonNull(controller.getEndPoint()); final MapObject endPoint = Objects.requireNonNull(controller.getEndPoint());
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this) final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.p2p_only_from_current) .setTitle(R.string.p2p_only_from_current)
.setMessage(R.string.p2p_reroute_from_current) .setMessage(R.string.p2p_reroute_from_current)
.setCancelable(false) .setCancelable(false)
@@ -2038,7 +2021,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
{ {
mPreciseLocationDialogShown = true; mPreciseLocationDialogShown = true;
final MaterialAlertDialogBuilder builder = final MaterialAlertDialogBuilder builder =
new MaterialAlertDialogBuilder(this) new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle("" + getString(R.string.limited_accuracy)) .setTitle("" + getString(R.string.limited_accuracy))
.setMessage(R.string.precise_location_is_disabled_long_text) .setMessage(R.string.precise_location_is_disabled_long_text)
.setNegativeButton(R.string.close, (dialog, which) -> dialog.dismiss()) .setNegativeButton(R.string.close, (dialog, which) -> dialog.dismiss())
@@ -2072,7 +2055,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
return; return;
} }
mLocationErrorDialog = new MaterialAlertDialogBuilder(this) mLocationErrorDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.enable_location_services) .setTitle(R.string.enable_location_services)
.setMessage(R.string.location_is_disabled_long_text) .setMessage(R.string.location_is_disabled_long_text)
.setOnDismissListener(dialog -> mLocationErrorDialog = null) .setOnDismissListener(dialog -> mLocationErrorDialog = null)
@@ -2165,7 +2148,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
return; return;
} }
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this) final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.enable_location_services) .setTitle(R.string.enable_location_services)
.setMessage(R.string.location_is_disabled_long_text) .setMessage(R.string.location_is_disabled_long_text)
.setOnDismissListener(dialog -> mLocationErrorDialog = null) .setOnDismissListener(dialog -> mLocationErrorDialog = null)
@@ -2207,8 +2190,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
if (!showRoutingDisclaimer()) if (!showRoutingDisclaimer())
return; return;
deliverTtsMessage();
closeFloatingPanels(); closeFloatingPanels();
setFullscreen(false); setFullscreen(false);
RoutingController.get().start(); RoutingController.get().start();
@@ -2251,7 +2232,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
dismissAlertDialog(); dismissAlertDialog();
final MaterialAlertDialogBuilder builder = final MaterialAlertDialogBuilder builder =
new MaterialAlertDialogBuilder(this) new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.current_location_unknown_error_title) .setTitle(R.string.current_location_unknown_error_title)
.setCancelable(true) .setCancelable(true)
.setMessage(R.string.power_save_dialog_summary) .setMessage(R.string.power_save_dialog_summary)
@@ -2276,7 +2257,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
{ {
dismissAlertDialog(); dismissAlertDialog();
mAlertDialog = mAlertDialog =
new MaterialAlertDialogBuilder(this) new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.load_kmz_title) .setTitle(R.string.load_kmz_title)
.setMessage(getString(R.string.unknown_file_type, uri)) .setMessage(getString(R.string.unknown_file_type, uri))
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@@ -2293,7 +2274,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
{ {
dismissAlertDialog(); dismissAlertDialog();
mAlertDialog = mAlertDialog =
new MaterialAlertDialogBuilder(this) new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.load_kmz_title) .setTitle(R.string.load_kmz_title)
.setMessage(getString(R.string.failed_to_open_file, uri, error)) .setMessage(getString(R.string.failed_to_open_file, uri, error))
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@@ -2315,7 +2296,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
public void onBookmarksFileImportFailed() public void onBookmarksFileImportFailed()
{ {
dismissAlertDialog(); dismissAlertDialog();
mAlertDialog = new MaterialAlertDialogBuilder(this) mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.load_kmz_title) .setTitle(R.string.load_kmz_title)
.setMessage(R.string.load_kmz_failed) .setMessage(R.string.load_kmz_failed)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@@ -2576,7 +2557,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
private void reportUnsupported() private void reportUnsupported()
{ {
new MaterialAlertDialogBuilder(this) new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setMessage(R.string.unsupported_phone) .setMessage(R.string.unsupported_phone)
.setCancelable(false) .setCancelable(false)
.setPositiveButton(R.string.close, (dlg, which) -> this.moveTaskToBack(true)) .setPositiveButton(R.string.close, (dlg, which) -> this.moveTaskToBack(true))

View File

@@ -120,7 +120,7 @@ public class SplashActivity extends AppCompatActivity
private void showFatalErrorDialog(@StringRes int titleId, @StringRes int messageId, Exception error) private void showFatalErrorDialog(@StringRes int titleId, @StringRes int messageId, Exception error)
{ {
mCanceled = true; mCanceled = true;
new MaterialAlertDialogBuilder(this, R.style.MwmTheme_M3_AlertDialog) new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(titleId) .setTitle(titleId)
.setMessage(messageId) .setMessage(messageId)
.setPositiveButton( .setPositiveButton(

View File

@@ -60,14 +60,14 @@ public enum BookmarksSharingHelper
case BookmarkSharingResult.SUCCESS -> case BookmarkSharingResult.SUCCESS ->
SharingUtils.shareBookmarkFile(context, launcher, result.getSharingPath(), result.getMimeType()); SharingUtils.shareBookmarkFile(context, launcher, result.getSharingPath(), result.getMimeType());
case BookmarkSharingResult.EMPTY_CATEGORY -> case BookmarkSharingResult.EMPTY_CATEGORY ->
new MaterialAlertDialogBuilder(context) new MaterialAlertDialogBuilder(context, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.bookmarks_error_title_share_empty) .setTitle(R.string.bookmarks_error_title_share_empty)
.setMessage(R.string.bookmarks_error_message_share_empty) .setMessage(R.string.bookmarks_error_message_share_empty)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
.show(); .show();
case BookmarkSharingResult.ARCHIVE_ERROR, BookmarkSharingResult.FILE_ERROR -> case BookmarkSharingResult.ARCHIVE_ERROR, BookmarkSharingResult.FILE_ERROR ->
{ {
new MaterialAlertDialogBuilder(context) new MaterialAlertDialogBuilder(context, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.dialog_routing_system_error) .setTitle(R.string.dialog_routing_system_error)
.setMessage(R.string.bookmarks_error_message_share_general) .setMessage(R.string.bookmarks_error_message_share_general)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)

View File

@@ -42,7 +42,6 @@ public class ChooseBookmarkCategoryFragment
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{ {
View root = inflater.inflate(R.layout.choose_bookmark_category_fragment, container, false); View root = inflater.inflate(R.layout.choose_bookmark_category_fragment, container, false);
getDialog().getWindow().setBackgroundDrawableResource(android.R.color.transparent);
mRecycler = root.findViewById(R.id.recycler); mRecycler = root.findViewById(R.id.recycler);
mRecycler.setLayoutManager(new LinearLayoutManager(requireActivity())); mRecycler.setLayoutManager(new LinearLayoutManager(requireActivity()));
return root; return root;

View File

@@ -77,7 +77,6 @@ public class ChooseBookmarksSortingTypeFragment
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
{ {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
getDialog().getWindow().setBackgroundDrawableResource(android.R.color.transparent);
final Bundle args = getArguments(); final Bundle args = getArguments();
if (args == null) if (args == null)

View File

@@ -114,7 +114,6 @@ public final class CarAppSession extends Session implements DefaultLifecycleObse
public void onCreate(@NonNull LifecycleOwner owner) public void onCreate(@NonNull LifecycleOwner owner)
{ {
Logger.d(TAG); Logger.d(TAG);
Framework.nativeSetCarScreenMode(true);
mSensorsManager = new CarSensorsManager(getCarContext()); mSensorsManager = new CarSensorsManager(getCarContext());
mDisplayManager = MwmApplication.from(getCarContext()).getDisplayManager(); mDisplayManager = MwmApplication.from(getCarContext()).getDisplayManager();
mDisplayManager.addListener(DisplayType.Car, this); mDisplayManager.addListener(DisplayType.Car, this);
@@ -160,7 +159,6 @@ public final class CarAppSession extends Session implements DefaultLifecycleObse
public void onDestroy(@NonNull LifecycleOwner owner) public void onDestroy(@NonNull LifecycleOwner owner)
{ {
mDisplayManager.removeListener(DisplayType.Car); mDisplayManager.removeListener(DisplayType.Car);
Framework.nativeSetCarScreenMode(false);
} }
private void init() private void init()

View File

@@ -177,7 +177,7 @@ public final class UiHelpers
{ {
case LocationState.PENDING_POSITION, LocationState.NOT_FOLLOW_NO_POSITION -> case LocationState.PENDING_POSITION, LocationState.NOT_FOLLOW_NO_POSITION ->
drawableRes = R.drawable.ic_location_off; drawableRes = R.drawable.ic_location_off;
case LocationState.NOT_FOLLOW -> drawableRes = R.drawable.ic_location_crosshair; case LocationState.NOT_FOLLOW -> drawableRes = R.drawable.ic_not_follow;
case LocationState.FOLLOW -> case LocationState.FOLLOW ->
{ {
drawableRes = R.drawable.ic_follow; drawableRes = R.drawable.ic_follow;

View File

@@ -1,86 +0,0 @@
package app.organicmaps.dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.PreferenceManager;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
import app.organicmaps.R;
import app.organicmaps.sdk.Framework;
public final class CustomMapServerDialog
{
public interface OnUrlAppliedListener
{
void onUrlApplied(@NonNull String url);
}
private CustomMapServerDialog() {}
public static void show(@NonNull Context context,
@Nullable OnUrlAppliedListener listener)
{
View dialogView = LayoutInflater.from(context)
.inflate(R.layout.dialog_custom_map_server, null);
TextInputLayout til = dialogView.findViewById(R.id.til_custom_map_server);
TextInputEditText edit = dialogView.findViewById(R.id.edit_custom_map_server);
SharedPreferences prefs =
PreferenceManager.getDefaultSharedPreferences(context);
String current = prefs.getString(context.getString(R.string.pref_custom_map_download_url), "");
edit.setText(current);
MaterialAlertDialogBuilder builder =
new MaterialAlertDialogBuilder(context)
.setTitle(R.string.download_resources_custom_url_title)
.setMessage(R.string.download_resources_custom_url_message)
.setView(dialogView)
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.save, null);
AlertDialog dialog = builder.create();
dialog.setOnShowListener(dlg -> {
Button ok = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
ok.setOnClickListener(v -> {
String url = edit.getText() != null ? edit.getText().toString().trim() : "";
if (!url.isEmpty()
&& !url.startsWith("http://")
&& !url.startsWith("https://"))
{
til.setError(context.getString(R.string.download_resources_custom_url_error_scheme));
return;
}
til.setError(null);
String normalizedUrl = Framework.normalizeServerUrl(url);
prefs.edit()
.putString(context.getString(R.string.pref_custom_map_download_url), normalizedUrl)
.apply();
// Apply to native
Framework.applyCustomMapDownloadUrl(context, normalizedUrl);
if (listener != null)
listener.onUrlApplied(normalizedUrl);
dialog.dismiss();
});
});
dialog.show();
}
}

View File

@@ -113,7 +113,7 @@ public class EditTextDialogFragment extends BaseMwmDialogFragment
negativeButtonText = args.getString(ARG_NEGATIVE_BUTTON); negativeButtonText = args.getString(ARG_NEGATIVE_BUTTON);
} }
AlertDialog editTextDialog = new MaterialAlertDialogBuilder(requireActivity()) AlertDialog editTextDialog = new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setView(buildView()) .setView(buildView())
.setNegativeButton(negativeButtonText, null) .setNegativeButton(negativeButtonText, null)
.setPositiveButton(positiveButtonText, null) .setPositiveButton(positiveButtonText, null)
@@ -152,7 +152,7 @@ public class EditTextDialogFragment extends BaseMwmDialogFragment
if (mInputValidator != null) if (mInputValidator != null)
{ {
final String maybeError = mInputValidator.validate(activity, input); final String maybeError = mInputValidator.validate(activity, input);
mEtInputLayout.setError(maybeError); mEtInputLayout.getEditText().setError(maybeError);
mEtInputLayout.requestFocus(); mEtInputLayout.requestFocus();
return maybeError == null; return maybeError == null;
} }

View File

@@ -119,7 +119,7 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
{ {
if (RoutingController.get().isNavigating()) if (RoutingController.get().isNavigating())
{ {
new MaterialAlertDialogBuilder(adapter.mActivity) new MaterialAlertDialogBuilder(adapter.mActivity, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.downloader_delete_map) .setTitle(R.string.downloader_delete_map)
.setMessage(R.string.downloader_delete_map_while_routing_dialog) .setMessage(R.string.downloader_delete_map_while_routing_dialog)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@@ -133,7 +133,7 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
return; return;
} }
new MaterialAlertDialogBuilder(adapter.mActivity) new MaterialAlertDialogBuilder(adapter.mActivity, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.downloader_delete_map) .setTitle(R.string.downloader_delete_map)
.setMessage(R.string.downloader_delete_map_dialog) .setMessage(R.string.downloader_delete_map_dialog)
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)

View File

@@ -49,7 +49,7 @@ public class MapManagerHelper
return; return;
} }
final AlertDialog dlg = new MaterialAlertDialogBuilder(activity) final AlertDialog dlg = new MaterialAlertDialogBuilder(activity, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.country_status_download_failed) .setTitle(R.string.country_status_download_failed)
.setMessage(getErrorCodeStrRes(errorData.errorCode)) .setMessage(getErrorCodeStrRes(errorData.errorCode))
.setNegativeButton(R.string.cancel, .setNegativeButton(R.string.cancel,
@@ -72,7 +72,7 @@ public class MapManagerHelper
private static void notifyNoSpaceInternal(Activity activity) private static void notifyNoSpaceInternal(Activity activity)
{ {
new MaterialAlertDialogBuilder(activity) new MaterialAlertDialogBuilder(activity, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.downloader_no_space_title) .setTitle(R.string.downloader_no_space_title)
.setMessage(R.string.downloader_no_space_message) .setMessage(R.string.downloader_no_space_message)
.setPositiveButton(android.R.string.ok, null) .setPositiveButton(android.R.string.ok, null)
@@ -123,7 +123,7 @@ public class MapManagerHelper
return false; return false;
} }
new MaterialAlertDialogBuilder(activity) new MaterialAlertDialogBuilder(activity, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.download_over_mobile_header) .setTitle(R.string.download_over_mobile_header)
.setMessage(R.string.download_over_mobile_message) .setMessage(R.string.download_over_mobile_message)
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)

View File

@@ -1,7 +1,5 @@
package app.organicmaps.editor; package app.organicmaps.editor;
import static android.view.View.INVISIBLE;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
@@ -15,13 +13,14 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.AutoCompleteTextView; import android.widget.AutoCompleteTextView;
import android.widget.GridLayout; import android.widget.GridLayout;
import android.widget.Toast;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
import androidx.annotation.DrawableRes; import androidx.annotation.DrawableRes;
import androidx.annotation.IdRes; import androidx.annotation.IdRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.appcompat.widget.SwitchCompat;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R; import app.organicmaps.R;
@@ -43,9 +42,9 @@ import app.organicmaps.util.Graphics;
import app.organicmaps.util.InputUtils; import app.organicmaps.util.InputUtils;
import app.organicmaps.util.UiUtils; import app.organicmaps.util.UiUtils;
import com.google.android.material.button.MaterialButton; import com.google.android.material.button.MaterialButton;
import com.google.android.material.card.MaterialCardView;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.imageview.ShapeableImageView; import com.google.android.material.imageview.ShapeableImageView;
import com.google.android.material.materialswitch.MaterialSwitch;
import com.google.android.material.textfield.TextInputEditText; import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout; import com.google.android.material.textfield.TextInputLayout;
import com.google.android.material.textview.MaterialTextView; import com.google.android.material.textview.MaterialTextView;
@@ -116,9 +115,9 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
private MaterialTextView mPhone; private MaterialTextView mPhone;
private MaterialButton mEditPhoneLink; private MaterialButton mEditPhoneLink;
private MaterialTextView mCuisine; private MaterialTextView mCuisine;
private MaterialSwitch mWifi; private SwitchCompat mWifi;
private MaterialTextView mSelfService; private MaterialTextView mSelfService;
private MaterialSwitch mOutdoorSeating; private SwitchCompat mOutdoorSeating;
// Default Metadata entries. // Default Metadata entries.
private static final class MetadataEntry private static final class MetadataEntry
@@ -196,8 +195,10 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
{ {
final Context context = mInputBuildingLevels.getContext(); final Context context = mInputBuildingLevels.getContext();
final boolean isValid = Editor.nativeIsLevelValid(s.toString()); final boolean isValid = Editor.nativeIsLevelValid(s.toString());
mInputBuildingLevels.setError(isValid ? null : context.getString(R.string.error_enter_correct_storey_number, UiUtils.setInputError(mInputBuildingLevels,
Editor.nativeGetMaxEditableBuildingLevels())); isValid ? null
: context.getString(R.string.error_enter_correct_storey_number,
Editor.nativeGetMaxEditableBuildingLevels()));
} }
}); });
@@ -352,7 +353,8 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
{ {
hasChargeSockets = hasChargeSockets || (type == Metadata.MetadataType.FMD_CHARGE_SOCKETS.toInt()); hasChargeSockets = hasChargeSockets || (type == Metadata.MetadataType.FMD_CHARGE_SOCKETS.toInt());
} }
UiUtils.showIf(hasChargeSockets, mCardChargingStation); // Hide socket until https://codeberg.org/comaps/comaps/issues/2368 is fixed
//UiUtils.showIf(hasChargeSockets, mCardChargingStation);
setCardVisibility(mCardDetails, mDetailsBlocks, editableDetails); setCardVisibility(mCardDetails, mDetailsBlocks, editableDetails);
setCardVisibility(mCardSocialMedia, mSocialMediaBlocks, editableDetails); setCardVisibility(mCardSocialMedia, mSocialMediaBlocks, editableDetails);
@@ -394,18 +396,16 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
typeBtns.removeAllViews(); typeBtns.removeAllViews();
List<String> SOCKET_TYPES = Arrays.stream(getResources().getStringArray(R.array.charge_socket_types)).toList(); List<String> SOCKET_TYPES = Arrays.stream(getResources().getStringArray(R.array.charge_socket_types)).toList();
for (String socketType : SOCKET_TYPES) for (String socket : SOCKET_TYPES)
{ {
ChargeSocketDescriptor socket = new ChargeSocketDescriptor(socketType,0,0);
MaterialButton btn = (MaterialButton) inflater.inflate(R.layout.button_socket_type, typeBtns, false); MaterialButton btn = (MaterialButton) inflater.inflate(R.layout.button_socket_type, typeBtns, false);
btn.setTag(R.id.socket_type, socket.type()); btn.setTag(R.id.socket_type, socket);
// load SVG icon converted into VectorDrawable in res/drawable // load SVG icon converted into VectorDrawable in res/drawable
@SuppressLint("DiscouragedApi") @SuppressLint("DiscouragedApi")
int resIconId = int resIconId =
getResources().getIdentifier("ic_charge_socket_" + socket.visualType(), "drawable", requireContext().getPackageName()); getResources().getIdentifier("ic_charge_socket_" + socket, "drawable", requireContext().getPackageName());
if (resIconId != 0) if (resIconId != 0)
{ {
btn.setIcon(getResources().getDrawable(resIconId)); btn.setIcon(getResources().getDrawable(resIconId));
@@ -413,7 +413,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
@SuppressLint("DiscouragedApi") @SuppressLint("DiscouragedApi")
int resTypeId = int resTypeId =
getResources().getIdentifier("charge_socket_" + socket.visualType(), "string", requireContext().getPackageName()); getResources().getIdentifier("charge_socket_" + socket, "string", requireContext().getPackageName());
if (resTypeId != 0) if (resTypeId != 0)
{ {
btn.setText(getResources().getString(resTypeId)); btn.setText(getResources().getString(resTypeId));
@@ -493,7 +493,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
} }
}); });
return new MaterialAlertDialogBuilder(requireActivity()) return new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setTitle(R.string.editor_socket) .setTitle(R.string.editor_socket)
.setView(dialogView) .setView(dialogView)
.setPositiveButton(R.string.save, .setPositiveButton(R.string.save,
@@ -545,7 +545,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
updateChargeSockets(socketIndex, socket); updateChargeSockets(socketIndex, socket);
}) })
.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss()); .setNegativeButton(R.string.cancel, (dialog, which) -> { dialog.dismiss(); });
} }
// Helper method for validation logic // Helper method for validation logic
@@ -601,7 +601,8 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
GridLayout socketsGrid = mChargeSockets.findViewById(R.id.socket_grid_editor); GridLayout socketsGrid = mChargeSockets.findViewById(R.id.socket_grid_editor);
socketsGrid.removeAllViews(); socketsGrid.removeAllViews();
for (int i = 0; i < sockets.length; i++) { for (int i = 0; i < sockets.length; i++)
{
final int currentIndex = i; final int currentIndex = i;
ChargeSocketDescriptor socket = sockets[i]; ChargeSocketDescriptor socket = sockets[i];
@@ -612,42 +613,45 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
MaterialTextView power = itemView.findViewById(R.id.socket_power); MaterialTextView power = itemView.findViewById(R.id.socket_power);
MaterialTextView count = itemView.findViewById(R.id.socket_count); MaterialTextView count = itemView.findViewById(R.id.socket_count);
// load SVG icon converted into VectorDrawable in res/drawable // load SVG icon converted into VectorDrawable in res/drawable
@SuppressLint("DiscouragedApi") @SuppressLint("DiscouragedApi")
int resIconId = getResources().getIdentifier("ic_charge_socket_" + socket.visualType(), "drawable", int resIconId = getResources().getIdentifier("ic_charge_socket_" + socket.type(), "drawable",
requireContext().getPackageName()); requireContext().getPackageName());
if (resIconId != 0) { if (resIconId != 0)
{
icon.setImageResource(resIconId); icon.setImageResource(resIconId);
} }
@SuppressLint("DiscouragedApi") @SuppressLint("DiscouragedApi")
int resTypeId = int resTypeId =
getResources().getIdentifier("charge_socket_" + socket.visualType(), "string", requireContext().getPackageName()); getResources().getIdentifier("charge_socket_" + socket.type(), "string", requireContext().getPackageName());
if (resTypeId != 0) { if (resTypeId != 0)
{
type.setText(resTypeId); type.setText(resTypeId);
} }
if (socket.power() != 0) { if (socket.power() != 0)
{
DecimalFormat df = new DecimalFormat("#.##"); DecimalFormat df = new DecimalFormat("#.##");
power.setText(getString(R.string.kw_label, df.format(socket.power()))); power.setText(getString(R.string.kw_label, df.format(socket.power())));
} }
else if (socket.ignorePower()) {
power.setVisibility(INVISIBLE);
}
if (socket.count() != 0) if (socket.count() != 0)
{ {
count.setText(getString(R.string.count_label, socket.count())); count.setText(getString(R.string.count_label, socket.count()));
} }
itemView.setOnClickListener(v -> buildChargeSocketDialog(currentIndex, socket.type(), socket.count(), socket.power()).show()); itemView.setOnClickListener(v -> {
buildChargeSocketDialog(currentIndex, socket.type(), socket.count(), socket.power()).show();
});
socketsGrid.addView(itemView); socketsGrid.addView(itemView);
} }
// add a 'new item' button at the end, to create new sockets // add a 'new item' button at the end, to create new sockets
View btnNewItemView = inflater.inflate(R.layout.button_new_item, socketsGrid, false); View btnNewItemView = inflater.inflate(R.layout.button_new_item, socketsGrid, false);
btnNewItemView.setOnClickListener(v -> buildChargeSocketDialog(-1, "unknown", -1, -1).show()); btnNewItemView.setOnClickListener(v -> {
buildChargeSocketDialog(-1, "unknown", -1, -1).show();
});
socketsGrid.addView(btnNewItemView); socketsGrid.addView(btnNewItemView);
} }
@@ -946,7 +950,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
mDisused.setVisibility(Editor.nativeCanMarkPlaceAsDisused() ? View.VISIBLE : View.GONE); mDisused.setVisibility(Editor.nativeCanMarkPlaceAsDisused() ? View.VISIBLE : View.GONE);
if (Editor.nativeAreSomeFeatureChangesUploaded()) if (Editor.nativeIsMapObjectUploaded())
{ {
mReset.setText(R.string.editor_place_doesnt_exist); mReset.setText(R.string.editor_place_doesnt_exist);
return; return;
@@ -964,7 +968,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
private void reset() private void reset()
{ {
if (Editor.nativeAreSomeFeatureChangesUploaded()) if (Editor.nativeIsMapObjectUploaded())
{ {
placeDoesntExist(); placeDoesntExist();
return; return;
@@ -997,7 +1001,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
message = R.string.editor_reset_edits_message; message = R.string.editor_reset_edits_message;
} }
new MaterialAlertDialogBuilder(requireActivity()) new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setTitle(message) .setTitle(message)
.setPositiveButton(title, .setPositiveButton(title,
(dialog, which) -> { (dialog, which) -> {
@@ -1020,7 +1024,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
private void placeDisused() private void placeDisused()
{ {
new MaterialAlertDialogBuilder(requireActivity()) new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setTitle(R.string.editor_mark_business_vacant_title) .setTitle(R.string.editor_mark_business_vacant_title)
.setMessage(R.string.editor_mark_business_vacant_description) .setMessage(R.string.editor_mark_business_vacant_description)
.setPositiveButton(R.string.editor_submit, (dlg, which) -> { .setPositiveButton(R.string.editor_submit, (dlg, which) -> {

View File

@@ -237,7 +237,6 @@ public class EditorHostFragment
for (LocalizedName name : sNames) for (LocalizedName name : sNames)
languages.add(name.lang); languages.add(name.lang);
args.putStringArrayList(LanguagesFragment.EXISTING_LOCALIZED_NAMES, languages); args.putStringArrayList(LanguagesFragment.EXISTING_LOCALIZED_NAMES, languages);
args.putBoolean(LanguagesFragment.INCLUDE_LOCAL_LANGUAGE, false);
editWithFragment(Mode.LANGUAGE, R.string.choose_language, args, LanguagesFragment.class, false); editWithFragment(Mode.LANGUAGE, R.string.choose_language, args, LanguagesFragment.class, false);
} }
@@ -353,7 +352,7 @@ public class EditorHostFragment
private void processNoFeatures() private void processNoFeatures()
{ {
new MaterialAlertDialogBuilder(requireActivity()) new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setTitle(R.string.downloader_no_space_title) .setTitle(R.string.downloader_no_space_title)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
.show(); .show();
@@ -387,7 +386,7 @@ public class EditorHostFragment
private void showNoobDialog() private void showNoobDialog()
{ {
new MaterialAlertDialogBuilder(requireActivity()) new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setTitle(R.string.editor_share_to_all_dialog_title) .setTitle(R.string.editor_share_to_all_dialog_title)
.setMessage(getString(R.string.editor_share_to_all_dialog_message_1) + " " .setMessage(getString(R.string.editor_share_to_all_dialog_message_1) + " "
+ getString(R.string.editor_share_to_all_dialog_message_2)) + getString(R.string.editor_share_to_all_dialog_message_2))

View File

@@ -1,20 +1,16 @@
package app.organicmaps.editor; package app.organicmaps.editor;
import android.content.res.ColorStateList;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.editor.data.FeatureCategory; import app.organicmaps.sdk.editor.data.FeatureCategory;
import app.organicmaps.sdk.util.StringUtils; import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.util.UiUtils; import app.organicmaps.util.UiUtils;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.textfield.TextInputEditText; import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textview.MaterialTextView; import com.google.android.material.textview.MaterialTextView;
@@ -123,7 +119,7 @@ public class FeatureCategoryAdapter extends RecyclerView.Adapter<RecyclerView.Vi
protected static class FooterViewHolder extends RecyclerView.ViewHolder protected static class FooterViewHolder extends RecyclerView.ViewHolder
{ {
private final TextInputEditText mNoteEditText; private final TextInputEditText mNoteEditText;
private final MaterialButton mSendNoteButton; private final View mSendNoteButton;
FooterViewHolder(@NonNull View itemView, @NonNull FooterListener listener) FooterViewHolder(@NonNull View itemView, @NonNull FooterListener listener)
{ {
@@ -133,29 +129,6 @@ public class FeatureCategoryAdapter extends RecyclerView.Adapter<RecyclerView.Vi
mNoteEditText = itemView.findViewById(R.id.note_edit_text); mNoteEditText = itemView.findViewById(R.id.note_edit_text);
mSendNoteButton = itemView.findViewById(R.id.send_note_button); mSendNoteButton = itemView.findViewById(R.id.send_note_button);
mSendNoteButton.setOnClickListener(v -> listener.onSendNoteClicked()); mSendNoteButton.setOnClickListener(v -> listener.onSendNoteClicked());
final ColorStateList bgButtonColor = new ColorStateList(
new int[][]{
new int[]{android.R.attr.state_enabled}, // enabled
new int[]{-android.R.attr.state_enabled} // disabled
},
new int[]{
ContextCompat.getColor(
mSendNoteButton.getContext(), R.color.base_accent),
ContextCompat.getColor(mSendNoteButton.getContext(), R.color.button_accent_disabled)
});
final ColorStateList textButtonColor = new ColorStateList(
new int[][]{
new int[]{android.R.attr.state_enabled}, // enabled
new int[]{-android.R.attr.state_enabled} // disabled
},
new int[]{
ContextCompat.getColor(
mSendNoteButton.getContext(),
UiUtils.getStyledResourceId(mSendNoteButton.getContext(), android.R.attr.textColorPrimaryInverse)),
ContextCompat.getColor(mSendNoteButton.getContext(), R.color.button_accent_text_disabled)
});
mSendNoteButton.setBackgroundTintList(bgButtonColor);
mSendNoteButton.setTextColor(textButtonColor);
mNoteEditText.addTextChangedListener(new StringUtils.SimpleTextWatcher() { mNoteEditText.addTextChangedListener(new StringUtils.SimpleTextWatcher() {
@Override @Override
public void onTextChanged(CharSequence s, int start, int before, int count) public void onTextChanged(CharSequence s, int start, int before, int count)

View File

@@ -155,7 +155,7 @@ public class FeatureCategoryFragment
// Duplicate of showNoobDialog() // Duplicate of showNoobDialog()
private void showNoteConfirmationDialog(double lat, double lon, String noteText) private void showNoteConfirmationDialog(double lat, double lon, String noteText)
{ {
new MaterialAlertDialogBuilder(requireActivity()) new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setTitle(R.string.editor_share_to_all_dialog_title) .setTitle(R.string.editor_share_to_all_dialog_title)
.setMessage(getString(R.string.editor_share_to_all_dialog_message_1) + " " .setMessage(getString(R.string.editor_share_to_all_dialog_message_1) + " "
+ getString(R.string.editor_share_to_all_dialog_message_2)) + getString(R.string.editor_share_to_all_dialog_message_2))

View File

@@ -158,7 +158,7 @@ public class FromToTimePicker
.setTitleText(title) .setTitleText(title)
.setTimeFormat(mIs24HourFormat ? TimeFormat.CLOCK_24H : TimeFormat.CLOCK_12H) .setTimeFormat(mIs24HourFormat ? TimeFormat.CLOCK_24H : TimeFormat.CLOCK_12H)
.setInputMode(mInputMode) .setInputMode(mInputMode)
.setTheme(R.style.MwmTheme_MaterialTimePicker) .setTheme(R.style.MwmMain_MaterialTimePicker)
.setHour((int) time.hours) .setHour((int) time.hours)
.setMinute((int) time.minutes); .setMinute((int) time.minutes);

View File

@@ -1,15 +1,11 @@
package app.organicmaps.editor; package app.organicmaps.editor;
import static app.organicmaps.sdk.editor.data.Language.DEFAULT_LANG_CODE;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.os.ConfigurationCompat; import androidx.core.os.ConfigurationCompat;
import androidx.core.os.LocaleListCompat; import androidx.core.os.LocaleListCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import app.organicmaps.R;
import app.organicmaps.base.BaseMwmRecyclerFragment; import app.organicmaps.base.BaseMwmRecyclerFragment;
import app.organicmaps.sdk.editor.Editor; import app.organicmaps.sdk.editor.Editor;
import app.organicmaps.sdk.editor.data.Language; import app.organicmaps.sdk.editor.data.Language;
@@ -19,13 +15,11 @@ import java.util.Comparator;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Objects;
import java.util.Set; import java.util.Set;
public class LanguagesFragment extends BaseMwmRecyclerFragment<LanguagesAdapter> public class LanguagesFragment extends BaseMwmRecyclerFragment<LanguagesAdapter>
{ {
final static String EXISTING_LOCALIZED_NAMES = "ExistingLocalizedNames"; final static String EXISTING_LOCALIZED_NAMES = "ExistingLocalizedNames";
final static String INCLUDE_LOCAL_LANGUAGE = "IncludeLocalLanguage";
public interface Listener public interface Listener
{ {
@@ -39,8 +33,6 @@ public class LanguagesFragment extends BaseMwmRecyclerFragment<LanguagesAdapter>
protected LanguagesAdapter createAdapter() protected LanguagesAdapter createAdapter()
{ {
Bundle args = getArguments(); Bundle args = getArguments();
boolean includeLocalLanguage =
args != null ? args.getBoolean(INCLUDE_LOCAL_LANGUAGE) : true;
Set<String> existingLanguages = Set<String> existingLanguages =
args != null ? new HashSet<>(args.getStringArrayList(EXISTING_LOCALIZED_NAMES)) : new HashSet<>(); args != null ? new HashSet<>(args.getStringArrayList(EXISTING_LOCALIZED_NAMES)) : new HashSet<>();
@@ -48,9 +40,7 @@ public class LanguagesFragment extends BaseMwmRecyclerFragment<LanguagesAdapter>
LocaleListCompat systemLocales = ConfigurationCompat.getLocales(config); LocaleListCompat systemLocales = ConfigurationCompat.getLocales(config);
List<Language> languages = new ArrayList<>(); List<Language> languages = new ArrayList<>();
List<Language> systemLanguages = new ArrayList<>(systemLocales.size()); List<Language> systemLanguages = new ArrayList<>();
for (int i = 0; i < systemLocales.size(); i++)
systemLanguages.add(null);
for (Language lang : Editor.nativeGetSupportedLanguages(false)) for (Language lang : Editor.nativeGetSupportedLanguages(false))
{ {
@@ -59,10 +49,7 @@ public class LanguagesFragment extends BaseMwmRecyclerFragment<LanguagesAdapter>
{ {
Locale locale = systemLocales.get(i); Locale locale = systemLocales.get(i);
if (locale != null && locale.getLanguage().equals(lang.code)) if (locale != null && locale.getLanguage().equals(lang.code))
{ systemLanguages.add(lang);
systemLanguages.add(i, lang);
break;
}
} }
if (existingLanguages.contains(lang.code) || systemLanguages.contains(lang)) if (existingLanguages.contains(lang.code) || systemLanguages.contains(lang))
@@ -73,13 +60,7 @@ public class LanguagesFragment extends BaseMwmRecyclerFragment<LanguagesAdapter>
Collections.sort(languages, Comparator.comparing(lhs -> lhs.name)); Collections.sort(languages, Comparator.comparing(lhs -> lhs.name));
languages.addAll(0, systemLanguages.stream().filter(Objects::nonNull).toList()); languages.addAll(0, systemLanguages);
if (includeLocalLanguage) {
String localLanguageLabel = getString(R.string.pref_maplanguage_local);
Language localLanguage = new Language(DEFAULT_LANG_CODE, localLanguageLabel);
languages.add(0, localLanguage);
}
return new LanguagesAdapter(this, languages.toArray(new Language[languages.size()])); return new LanguagesAdapter(this, languages.toArray(new Language[languages.size()]));
} }

View File

@@ -79,7 +79,7 @@ public class OsmLoginFragment extends BaseMwmToolbarFragment
private void onAuthFail() private void onAuthFail()
{ {
new MaterialAlertDialogBuilder(requireActivity()) new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setTitle(R.string.editor_login_error_dialog) .setTitle(R.string.editor_login_error_dialog)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
.show(); .show();

View File

@@ -6,6 +6,7 @@ import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ProgressBar;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat; import androidx.core.view.ViewCompat;
@@ -22,7 +23,6 @@ import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils; import app.organicmaps.util.WindowInsetUtils;
import app.organicmaps.widget.StackedButtonDialogFragment; import app.organicmaps.widget.StackedButtonDialogFragment;
import com.google.android.material.imageview.ShapeableImageView; import com.google.android.material.imageview.ShapeableImageView;
import com.google.android.material.progressindicator.CircularProgressIndicator;
import com.google.android.material.textview.MaterialTextView; import com.google.android.material.textview.MaterialTextView;
import java.text.NumberFormat; import java.text.NumberFormat;
@@ -50,7 +50,7 @@ public class ProfileFragment extends BaseMwmToolbarFragment
private MaterialTextView mEditsSent; private MaterialTextView mEditsSent;
private MaterialTextView mProfileName; private MaterialTextView mProfileName;
private ShapeableImageView mProfileImage; private ShapeableImageView mProfileImage;
private CircularProgressIndicator mProfileInfoLoading; private ProgressBar mProfileInfoLoading;
@Nullable @Nullable
@Override @Override

View File

@@ -11,6 +11,7 @@ import android.widget.LinearLayout;
import androidx.annotation.IdRes; import androidx.annotation.IdRes;
import androidx.annotation.IntRange; import androidx.annotation.IntRange;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.widget.SwitchCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
@@ -24,7 +25,6 @@ import app.organicmaps.sdk.util.Utils;
import app.organicmaps.util.UiUtils; import app.organicmaps.util.UiUtils;
import com.google.android.material.button.MaterialButton; import com.google.android.material.button.MaterialButton;
import com.google.android.material.checkbox.MaterialCheckBox; import com.google.android.material.checkbox.MaterialCheckBox;
import com.google.android.material.materialswitch.MaterialSwitch;
import com.google.android.material.textview.MaterialTextView; import com.google.android.material.textview.MaterialTextView;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@@ -195,7 +195,7 @@ class SimpleTimetableAdapter extends RecyclerView.Adapter<SimpleTimetableAdapter
SparseArray<MaterialCheckBox> days = new SparseArray<>(7); SparseArray<MaterialCheckBox> days = new SparseArray<>(7);
View allday; View allday;
MaterialSwitch swAllday; SwitchCompat swAllday;
View schedule; View schedule;
View openClose; View openClose;
View open; View open;

View File

@@ -66,7 +66,7 @@ public class FaqFragment extends BaseMwmFragment
FloatingActionButton feedbackFab = root.findViewById(R.id.feedback_fab); FloatingActionButton feedbackFab = root.findViewById(R.id.feedback_fab);
feedbackFab.setOnClickListener( feedbackFab.setOnClickListener(
v v
-> new MaterialAlertDialogBuilder(requireActivity()) -> new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setTitle(R.string.feedback) .setTitle(R.string.feedback)
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)
.setItems(new CharSequence[] {getString(R.string.feedback_general), getString(R.string.report_a_bug)}, .setItems(new CharSequence[] {getString(R.string.feedback_general), getString(R.string.report_a_bug)},

View File

@@ -2,12 +2,14 @@ package app.organicmaps.maplayer;
import android.content.Context; import android.content.Context;
import android.view.View; import android.view.View;
import androidx.annotation.AttrRes;
import androidx.annotation.DrawableRes; import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.adapter.OnItemClickListener; import app.organicmaps.adapter.OnItemClickListener;
import app.organicmaps.sdk.maplayer.Mode; import app.organicmaps.sdk.maplayer.Mode;
import app.organicmaps.util.ThemeUtils;
public class LayerBottomSheetItem public class LayerBottomSheetItem
{ {
@@ -35,25 +37,27 @@ public class LayerBottomSheetItem
@DrawableRes @DrawableRes
int drawableResId = 0; int drawableResId = 0;
@StringRes @StringRes
int buttonTextResource = switch (mode) { int buttonTextResource = R.string.layers_title;
case OUTDOORS -> { switch (mode)
drawableResId = R.drawable.ic_layers_outdoors; {
yield R.string.button_layer_outdoor; case OUTDOORS:
} drawableResId = R.drawable.ic_layers_outdoors;
case SUBWAY -> { buttonTextResource = R.string.button_layer_outdoor;
drawableResId = R.drawable.ic_layers_subway; break;
yield R.string.subway; case SUBWAY:
} drawableResId = R.drawable.ic_layers_subway;
case ISOLINES -> { buttonTextResource = R.string.subway;
drawableResId = R.drawable.ic_layers_isoline; break;
yield R.string.button_layer_isolines; case ISOLINES:
} drawableResId = R.drawable.ic_layers_isoline;
case TRAFFIC -> { buttonTextResource = R.string.button_layer_isolines;
drawableResId = R.drawable.ic_layers_traffic; break;
yield R.string.button_layer_traffic; case TRAFFIC:
} drawableResId = R.drawable.ic_layers_traffic;
}; buttonTextResource = R.string.button_layer_traffic;
return new LayerBottomSheetItem(drawableResId, buttonTextResource, mode, layerItemClickListener); break;
}
return new LayerBottomSheetItem(drawableResId, buttonTextResource, mode, layerItemClickListener);
} }
@NonNull @NonNull

View File

@@ -107,7 +107,7 @@ public class TrafficButtonController implements TrafficManager.TrafficCallback
if (mDialog != null && mDialog.isShowing()) if (mDialog != null && mDialog.isShowing())
return; return;
mDialog = new MaterialAlertDialogBuilder(mActivity) mDialog = new MaterialAlertDialogBuilder(mActivity, R.style.MwmTheme_AlertDialog)
.setMessage(R.string.common_check_internet_connection_dialog) .setMessage(R.string.common_check_internet_connection_dialog)
.setPositiveButton(R.string.ok, (dialog, which) -> TrafficManager.INSTANCE.setEnabled(false)) .setPositiveButton(R.string.ok, (dialog, which) -> TrafficManager.INSTANCE.setEnabled(false))
.setCancelable(true) .setCancelable(true)

View File

@@ -56,7 +56,7 @@ abstract class BaseRoutingErrorDialogFragment extends BaseMwmDialogFragment
public Dialog onCreateDialog(Bundle savedInstanceState) public Dialog onCreateDialog(Bundle savedInstanceState)
{ {
parseArguments(); parseArguments();
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireActivity()) MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setCancelable(true) .setCancelable(true)
.setNegativeButton(android.R.string.cancel, null); .setNegativeButton(android.R.string.cancel, null);
beforeDialogCreated(builder); beforeDialogCreated(builder);

View File

@@ -98,11 +98,6 @@ public class NavigationController implements TrafficManager.TrafficCallback, Nav
mSpeedLimit = topFrame.findViewById(R.id.nav_speed_limit); mSpeedLimit = topFrame.findViewById(R.id.nav_speed_limit);
mCurrentSpeed = topFrame.findViewById(R.id.nav_current_speed); mCurrentSpeed = topFrame.findViewById(R.id.nav_current_speed);
View mTopbar = topFrame.findViewById(R.id.statutbar);
ViewCompat.setOnApplyWindowInsetsListener(mTopbar,(v, windowInsets) -> {
UiUtils.setViewNavigationTopInsetsMargin(v, windowInsets);
return windowInsets;
});
// Show a blank view below the navbar to hide the menu content // Show a blank view below the navbar to hide the menu content
final View navigationBarBackground = mFrame.findViewById(R.id.nav_bottom_sheet_nav_bar); final View navigationBarBackground = mFrame.findViewById(R.id.nav_bottom_sheet_nav_bar);
final View nextTurnContainer = mFrame.findViewById(R.id.nav_next_turn_container); final View nextTurnContainer = mFrame.findViewById(R.id.nav_next_turn_container);

View File

@@ -5,8 +5,10 @@ import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.StyleRes;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import app.organicmaps.base.BaseMwmFragmentActivity; import app.organicmaps.base.BaseMwmFragmentActivity;
import app.organicmaps.util.ThemeUtils;
public class SearchActivity extends BaseMwmFragmentActivity public class SearchActivity extends BaseMwmFragmentActivity
{ {

View File

@@ -6,10 +6,12 @@ import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.XmlRes; import androidx.annotation.XmlRes;
import androidx.core.content.ContextCompat;
import androidx.core.view.ViewCompat; import androidx.core.view.ViewCompat;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceFragmentCompat;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils.ScrollableContentInsetsListener; import app.organicmaps.util.WindowInsetUtils.ScrollableContentInsetsListener;
@@ -42,6 +44,7 @@ abstract class BaseXmlSettingsFragment extends PreferenceFragmentCompat
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
{ {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
view.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.bg_cards));
RecyclerView recyclerView = getListView(); RecyclerView recyclerView = getListView();
ViewCompat.setOnApplyWindowInsetsListener(recyclerView, new ScrollableContentInsetsListener(recyclerView)); ViewCompat.setOnApplyWindowInsetsListener(recyclerView, new ScrollableContentInsetsListener(recyclerView));
} }

View File

@@ -8,9 +8,7 @@ import android.view.ViewGroup;
import android.widget.CompoundButton; import android.widget.CompoundButton;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.widget.SwitchCompat;
import com.google.android.material.materialswitch.MaterialSwitch;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.base.BaseMwmToolbarFragment; import app.organicmaps.base.BaseMwmToolbarFragment;
import app.organicmaps.sdk.routing.RoutingController; import app.organicmaps.sdk.routing.RoutingController;
@@ -90,34 +88,34 @@ public class DrivingOptionsFragment extends BaseMwmToolbarFragment
private void initViews(@NonNull View root) private void initViews(@NonNull View root)
{ {
MaterialSwitch tollsBtn = root.findViewById(R.id.avoid_tolls_btn); SwitchCompat tollsBtn = root.findViewById(R.id.avoid_tolls_btn);
tollsBtn.setChecked(RoutingOptions.hasOption(RoadType.Toll)); tollsBtn.setChecked(RoutingOptions.hasOption(RoadType.Toll));
CompoundButton.OnCheckedChangeListener tollBtnListener = new ToggleRoutingOptionListener(RoadType.Toll, root); CompoundButton.OnCheckedChangeListener tollBtnListener = new ToggleRoutingOptionListener(RoadType.Toll, root);
tollsBtn.setOnCheckedChangeListener(tollBtnListener); tollsBtn.setOnCheckedChangeListener(tollBtnListener);
MaterialSwitch motorwaysBtn = root.findViewById(R.id.avoid_motorways_btn); SwitchCompat motorwaysBtn = root.findViewById(R.id.avoid_motorways_btn);
motorwaysBtn.setChecked(RoutingOptions.hasOption(RoadType.Motorway)); motorwaysBtn.setChecked(RoutingOptions.hasOption(RoadType.Motorway));
CompoundButton.OnCheckedChangeListener motorwayBtnListener = CompoundButton.OnCheckedChangeListener motorwayBtnListener =
new ToggleRoutingOptionListener(RoadType.Motorway, root); new ToggleRoutingOptionListener(RoadType.Motorway, root);
motorwaysBtn.setOnCheckedChangeListener(motorwayBtnListener); motorwaysBtn.setOnCheckedChangeListener(motorwayBtnListener);
MaterialSwitch ferriesBtn = root.findViewById(R.id.avoid_ferries_btn); SwitchCompat ferriesBtn = root.findViewById(R.id.avoid_ferries_btn);
ferriesBtn.setChecked(RoutingOptions.hasOption(RoadType.Ferry)); ferriesBtn.setChecked(RoutingOptions.hasOption(RoadType.Ferry));
CompoundButton.OnCheckedChangeListener ferryBtnListener = new ToggleRoutingOptionListener(RoadType.Ferry, root); CompoundButton.OnCheckedChangeListener ferryBtnListener = new ToggleRoutingOptionListener(RoadType.Ferry, root);
ferriesBtn.setOnCheckedChangeListener(ferryBtnListener); ferriesBtn.setOnCheckedChangeListener(ferryBtnListener);
MaterialSwitch dirtyRoadsBtn = root.findViewById(R.id.avoid_dirty_roads_btn); SwitchCompat dirtyRoadsBtn = root.findViewById(R.id.avoid_dirty_roads_btn);
dirtyRoadsBtn.setChecked(RoutingOptions.hasOption(RoadType.Dirty)); dirtyRoadsBtn.setChecked(RoutingOptions.hasOption(RoadType.Dirty));
dirtyRoadsBtn.setEnabled(!RoutingOptions.hasOption(RoadType.Paved) || RoutingOptions.hasOption(RoadType.Dirty)); dirtyRoadsBtn.setEnabled(!RoutingOptions.hasOption(RoadType.Paved) || RoutingOptions.hasOption(RoadType.Dirty));
CompoundButton.OnCheckedChangeListener dirtyBtnListener = new ToggleRoutingOptionListener(RoadType.Dirty, root); CompoundButton.OnCheckedChangeListener dirtyBtnListener = new ToggleRoutingOptionListener(RoadType.Dirty, root);
dirtyRoadsBtn.setOnCheckedChangeListener(dirtyBtnListener); dirtyRoadsBtn.setOnCheckedChangeListener(dirtyBtnListener);
MaterialSwitch stepsBtn = root.findViewById(R.id.avoid_steps_btn); SwitchCompat stepsBtn = root.findViewById(R.id.avoid_steps_btn);
stepsBtn.setChecked(RoutingOptions.hasOption(RoadType.Steps)); stepsBtn.setChecked(RoutingOptions.hasOption(RoadType.Steps));
CompoundButton.OnCheckedChangeListener stepsBtnListener = new ToggleRoutingOptionListener(RoadType.Steps, root); CompoundButton.OnCheckedChangeListener stepsBtnListener = new ToggleRoutingOptionListener(RoadType.Steps, root);
stepsBtn.setOnCheckedChangeListener(stepsBtnListener); stepsBtn.setOnCheckedChangeListener(stepsBtnListener);
MaterialSwitch pavedBtn = root.findViewById(R.id.avoid_paved_roads_btn); SwitchCompat pavedBtn = root.findViewById(R.id.avoid_paved_roads_btn);
pavedBtn.setChecked(RoutingOptions.hasOption(RoadType.Paved)); pavedBtn.setChecked(RoutingOptions.hasOption(RoadType.Paved));
pavedBtn.setEnabled(!RoutingOptions.hasOption(RoadType.Dirty) || RoutingOptions.hasOption(RoadType.Paved)); pavedBtn.setEnabled(!RoutingOptions.hasOption(RoadType.Dirty) || RoutingOptions.hasOption(RoadType.Paved));
CompoundButton.OnCheckedChangeListener pavedBtnListener = new ToggleRoutingOptionListener(RoadType.Paved, root); CompoundButton.OnCheckedChangeListener pavedBtnListener = new ToggleRoutingOptionListener(RoadType.Paved, root);
@@ -146,8 +144,8 @@ public class DrivingOptionsFragment extends BaseMwmToolbarFragment
else else
RoutingOptions.removeOption(mRoadType); RoutingOptions.removeOption(mRoadType);
MaterialSwitch dirtyRoadsBtn = mRoot.findViewById(R.id.avoid_dirty_roads_btn); SwitchCompat dirtyRoadsBtn = mRoot.findViewById(R.id.avoid_dirty_roads_btn);
MaterialSwitch pavedBtn = mRoot.findViewById(R.id.avoid_paved_roads_btn); SwitchCompat pavedBtn = mRoot.findViewById(R.id.avoid_paved_roads_btn);
if (mRoadType == RoadType.Dirty) if (mRoadType == RoadType.Dirty)
{ {
pavedBtn.setEnabled(!isChecked); pavedBtn.setEnabled(!isChecked);

View File

@@ -1,27 +1,19 @@
package app.organicmaps.settings; package app.organicmaps.settings;
import static app.organicmaps.leftbutton.LeftButtonsHolder.DISABLE_BUTTON_CODE; import static app.organicmaps.leftbutton.LeftButtonsHolder.DISABLE_BUTTON_CODE;
import static app.organicmaps.sdk.editor.data.Language.DEFAULT_LANG_CODE;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.preference.ListPreference; import androidx.preference.ListPreference;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceManager;
import androidx.preference.TwoStatePreference; import androidx.preference.TwoStatePreference;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.dialog.CustomMapServerDialog;
import app.organicmaps.downloader.OnmapDownloader; import app.organicmaps.downloader.OnmapDownloader;
import app.organicmaps.editor.LanguagesFragment; import app.organicmaps.editor.LanguagesFragment;
import app.organicmaps.editor.ProfileActivity; import app.organicmaps.editor.ProfileActivity;
@@ -43,7 +35,7 @@ import app.organicmaps.sdk.util.SharedPropertiesUtils;
import app.organicmaps.sdk.util.log.LogsManager; import app.organicmaps.sdk.util.log.LogsManager;
import app.organicmaps.util.ThemeSwitcher; import app.organicmaps.util.ThemeSwitcher;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@@ -81,7 +73,6 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment implements La
initScreenSleepEnabledPrefsCallbacks(); initScreenSleepEnabledPrefsCallbacks();
initShowOnLockScreenPrefsCallbacks(); initShowOnLockScreenPrefsCallbacks();
initLeftButtonPrefs(); initLeftButtonPrefs();
initCustomMapDownloadUrlPrefsCallbacks();
} }
private void initLeftButtonPrefs() private void initLeftButtonPrefs()
@@ -141,13 +132,8 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment implements La
private void updateMapLanguageCodeSummary() private void updateMapLanguageCodeSummary()
{ {
final Preference pref = getPreference(getString(R.string.pref_map_locale)); final Preference pref = getPreference(getString(R.string.pref_map_locale));
String mapLanguageCode = MapLanguageCode.getMapLanguageCode(); Locale locale = new Locale(MapLanguageCode.getMapLanguageCode());
if (mapLanguageCode.equals(DEFAULT_LANG_CODE)) { pref.setSummary(locale.getDisplayLanguage());
pref.setSummary(R.string.pref_maplanguage_local);
} else {
Locale locale = new Locale(mapLanguageCode);
pref.setSummary(locale.getDisplayLanguage());
}
} }
private void updateRoutingSettingsPrefsSummary() private void updateRoutingSettingsPrefsSummary()
@@ -500,7 +486,7 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment implements La
pref.setOnPreferenceClickListener(preference -> { pref.setOnPreferenceClickListener(preference -> {
if (MapManager.nativeIsDownloading()) if (MapManager.nativeIsDownloading())
{ {
new MaterialAlertDialogBuilder(requireActivity()) new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setTitle(R.string.downloading_is_active) .setTitle(R.string.downloading_is_active)
.setMessage(R.string.cant_change_this_setting) .setMessage(R.string.cant_change_this_setting)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@@ -549,34 +535,6 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment implements La
}); });
} }
private void initCustomMapDownloadUrlPrefsCallbacks()
{
Preference customUrlPref = getPreference(getString(R.string.pref_custom_map_download_url));
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(requireContext());
String current = prefs.getString(getString(R.string.pref_custom_map_download_url), "");
String normalizedUrl = Framework.normalizeServerUrl(current);
// Initial summary
customUrlPref.setSummary(normalizedUrl.isEmpty()
? getString(R.string.download_resources_custom_url_summary_none)
: normalizedUrl);
// Sync native
Framework.applyCustomMapDownloadUrl(requireContext(), normalizedUrl);
// Show dialog
customUrlPref.setOnPreferenceClickListener(preference -> {
CustomMapServerDialog.show(requireContext(), url -> {
preference.setSummary(url.isEmpty()
? getString(R.string.download_resources_custom_url_summary_none)
: url);
});
return true;
});
}
private void removePreference(@NonNull String categoryKey, @NonNull Preference preference) private void removePreference(@NonNull String categoryKey, @NonNull Preference preference)
{ {
final PreferenceCategory category = getPreference(categoryKey); final PreferenceCategory category = getPreference(categoryKey);

View File

@@ -97,7 +97,7 @@ public class StoragePathFragment extends BaseSettingsFragment
final String oldPath = storages.get(currentIndex).mPath; final String oldPath = storages.get(currentIndex).mPath;
final String newPath = storages.get(newIndex).mPath; final String newPath = storages.get(newIndex).mPath;
new MaterialAlertDialogBuilder(requireActivity()) new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setCancelable(false) .setCancelable(false)
.setTitle(R.string.move_maps) .setTitle(R.string.move_maps)
.setPositiveButton(R.string.ok, (dlg, which) -> moveStorage(newPath, oldPath)) .setPositiveButton(R.string.ok, (dlg, which) -> moveStorage(newPath, oldPath))
@@ -133,7 +133,7 @@ public class StoragePathFragment extends BaseSettingsFragment
if (!result) if (!result)
{ {
new MaterialAlertDialogBuilder(requireActivity()) new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setTitle(R.string.move_maps_error) .setTitle(R.string.move_maps_error)
.setPositiveButton( .setPositiveButton(
R.string.report_a_bug, R.string.report_a_bug,

View File

@@ -90,7 +90,8 @@ public enum ThemeSwitcher
{ {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
uiModeManager.setApplicationNightMode(UiModeManager.MODE_NIGHT_YES); uiModeManager.setApplicationNightMode(UiModeManager.MODE_NIGHT_YES);
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES); else
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
if (RoutingController.get().isVehicleNavigation()) if (RoutingController.get().isVehicleNavigation())
style = MapStyle.VehicleDark; style = MapStyle.VehicleDark;
@@ -103,7 +104,8 @@ public enum ThemeSwitcher
{ {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
uiModeManager.setApplicationNightMode(UiModeManager.MODE_NIGHT_NO); uiModeManager.setApplicationNightMode(UiModeManager.MODE_NIGHT_NO);
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); else
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
if (RoutingController.get().isVehicleNavigation()) if (RoutingController.get().isVehicleNavigation())
style = MapStyle.VehicleClear; style = MapStyle.VehicleClear;

View File

@@ -24,6 +24,7 @@ import androidx.annotation.ColorInt;
import androidx.annotation.IdRes; import androidx.annotation.IdRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.core.content.ContextCompat;
import androidx.core.content.res.ResourcesCompat; import androidx.core.content.res.ResourcesCompat;
import androidx.core.graphics.Insets; import androidx.core.graphics.Insets;
import androidx.core.view.WindowCompat; import androidx.core.view.WindowCompat;
@@ -195,7 +196,7 @@ public final class UiUtils
public static void showHomeUpButton(MaterialToolbar toolbar) public static void showHomeUpButton(MaterialToolbar toolbar)
{ {
toolbar.setNavigationIcon( toolbar.setNavigationIcon(
UiUtils.getStyledResourceId(toolbar.getContext(), androidx.appcompat.R.attr.homeAsUpIndicator)); ThemeUtils.getResource(toolbar.getContext(), androidx.appcompat.R.attr.homeAsUpIndicator));
} }
// this method returns the total height of the display (in pixels) including notch and other touchable areas // this method returns the total height of the display (in pixels) including notch and other touchable areas
@@ -208,7 +209,15 @@ public final class UiUtils
} }
public static void setInputError(@NonNull TextInputLayout layout, @StringRes int error) public static void setInputError(@NonNull TextInputLayout layout, @StringRes int error)
{ {
layout.setError(error == 0 ? null : layout.getContext().getString(error)); setInputError(layout, error == 0 ? null : layout.getContext().getString(error));
}
public static void setInputError(@NonNull TextInputLayout layout, String error)
{
layout.getEditText().setError(error);
layout.getEditText().setTextColor(error == null
? ThemeUtils.getColor(layout.getContext(), android.R.attr.textColorPrimary)
: ContextCompat.getColor(layout.getContext(), R.color.base_red));
} }
public static void setFullscreen(@NonNull Activity activity, boolean fullscreen) public static void setFullscreen(@NonNull Activity activity, boolean fullscreen)
@@ -272,14 +281,6 @@ public final class UiUtils
view.setPadding(systemInsets.left, systemInsets.top, systemInsets.right, view.getPaddingBottom()); view.setPadding(systemInsets.left, systemInsets.top, systemInsets.right, view.getPaddingBottom());
} }
public static void setViewNavigationTopInsetsMargin(View view, WindowInsetsCompat windowInsets)
{
final Insets systemInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
lp.topMargin = systemInsets.top;
view.setLayoutParams(lp);
}
public static void setupNavigationIcon(@NonNull MaterialToolbar toolbar, @NonNull View.OnClickListener listener) public static void setupNavigationIcon(@NonNull MaterialToolbar toolbar, @NonNull View.OnClickListener listener)
{ {
View customNavigationButton = toolbar.findViewById(R.id.back); View customNavigationButton = toolbar.findViewById(R.id.back);

View File

@@ -3,6 +3,7 @@ package app.organicmaps.widget;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;

View File

@@ -7,6 +7,7 @@ import androidx.annotation.DrawableRes;
import androidx.appcompat.content.res.AppCompatResources; import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.widget.AppCompatRadioButton; import androidx.appcompat.widget.AppCompatRadioButton;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.util.ThemeUtils;
public class RoutingToolbarButton extends AppCompatRadioButton public class RoutingToolbarButton extends AppCompatRadioButton
{ {

View File

@@ -61,7 +61,6 @@ public class StackedButtonsDialog extends AppCompatDialog implements View.OnClic
setCancelable(mCancelable); setCancelable(mCancelable);
setOnCancelListener(mCancelListener); setOnCancelListener(mCancelListener);
setContentView(R.layout.dialog_stacked_buttons); setContentView(R.layout.dialog_stacked_buttons);
getWindow().setBackgroundDrawableResource(android.R.color.transparent);
TextView title = findViewById(R.id.tv__title); TextView title = findViewById(R.id.tv__title);
UiUtils.setTextAndHideIfEmpty(title, mTitle); UiUtils.setTextAndHideIfEmpty(title, mTitle);

View File

@@ -67,7 +67,7 @@ public class MyPositionButton
{ {
case LocationState.PENDING_POSITION -> R.drawable.ic_menu_location_pending; case LocationState.PENDING_POSITION -> R.drawable.ic_menu_location_pending;
case LocationState.NOT_FOLLOW_NO_POSITION -> R.drawable.ic_location_off; case LocationState.NOT_FOLLOW_NO_POSITION -> R.drawable.ic_location_off;
case LocationState.NOT_FOLLOW -> R.drawable.ic_location_crosshair; case LocationState.NOT_FOLLOW -> R.drawable.ic_not_follow;
case LocationState.FOLLOW -> R.drawable.ic_follow; case LocationState.FOLLOW -> R.drawable.ic_follow;
case LocationState.FOLLOW_AND_ROTATE -> R.drawable.ic_follow_and_rotate; case LocationState.FOLLOW_AND_ROTATE -> R.drawable.ic_follow_and_rotate;
default -> throw new IllegalArgumentException("Invalid button mode: " + mode); default -> throw new IllegalArgumentException("Invalid button mode: " + mode);

View File

@@ -47,7 +47,7 @@ public class BookmarkColorDialogFragment extends BaseMwmDialogFragment
mIconResId = getArguments().getInt(ICON_RES); mIconResId = getArguments().getInt(ICON_RES);
} }
return new MaterialAlertDialogBuilder(requireActivity()) return new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setView(buildView()) .setView(buildView())
.setTitle(R.string.choose_color) .setTitle(R.string.choose_color)
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)

View File

@@ -464,7 +464,7 @@ public class PlacePageController
mAlertDialog.show(); mAlertDialog.show();
return; return;
} }
mAlertDialog = new MaterialAlertDialogBuilder(requireContext()) mAlertDialog = new MaterialAlertDialogBuilder(requireContext(), R.style.MwmTheme_AlertDialog)
.setTitle(requireContext().getString(R.string.delete_track_dialog_title, mMapObject.getTitle())) .setTitle(requireContext().getString(R.string.delete_track_dialog_title, mMapObject.getTitle()))
.setCancelable(true) .setCancelable(true)
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)

View File

@@ -32,6 +32,7 @@ import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.Observer; import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import app.organicmaps.BuildConfig;
import app.organicmaps.MwmActivity; import app.organicmaps.MwmActivity;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; import app.organicmaps.R;
@@ -56,6 +57,7 @@ import app.organicmaps.sdk.downloader.MapManager;
import app.organicmaps.sdk.editor.Editor; import app.organicmaps.sdk.editor.Editor;
import app.organicmaps.sdk.editor.OhState; import app.organicmaps.sdk.editor.OhState;
import app.organicmaps.sdk.editor.OpeningHours; import app.organicmaps.sdk.editor.OpeningHours;
import app.organicmaps.sdk.editor.data.HoursMinutes;
import app.organicmaps.sdk.editor.data.Timetable; import app.organicmaps.sdk.editor.data.Timetable;
import app.organicmaps.sdk.location.LocationListener; import app.organicmaps.sdk.location.LocationListener;
import app.organicmaps.sdk.location.SensorListener; import app.organicmaps.sdk.location.SensorListener;
@@ -154,7 +156,6 @@ public class PlacePageView extends Fragment
private MaterialTextView mTvLastChecked; private MaterialTextView mTvLastChecked;
private View mEditPlace; private View mEditPlace;
private View mAddPlace; private View mAddPlace;
private View mMapTooOld;
private View mEditTopSpace; private View mEditTopSpace;
private ShapeableImageView mColorIcon; private ShapeableImageView mColorIcon;
private MaterialTextView mTvCategory; private MaterialTextView mTvCategory;
@@ -319,7 +320,6 @@ public class PlacePageView extends Fragment
mTvLastChecked = mFrame.findViewById(R.id.place_page_last_checked); mTvLastChecked = mFrame.findViewById(R.id.place_page_last_checked);
mEditPlace = mFrame.findViewById(R.id.ll__place_editor); mEditPlace = mFrame.findViewById(R.id.ll__place_editor);
mAddPlace = mFrame.findViewById(R.id.ll__place_add); mAddPlace = mFrame.findViewById(R.id.ll__place_add);
mMapTooOld = mFrame.findViewById(R.id.cv__map_too_old);
mEditTopSpace = mFrame.findViewById(R.id.edit_top_space); mEditTopSpace = mFrame.findViewById(R.id.edit_top_space);
latlon.setOnLongClickListener(this); latlon.setOnLongClickListener(this);
address.setOnLongClickListener(this); address.setOnLongClickListener(this);
@@ -428,9 +428,8 @@ public class PlacePageView extends Fragment
private void updateBookmarkView() private void updateBookmarkView()
{ {
boolean enabled = mMapObject.isBookmark() || mMapObject.isTrack();
updateViewFragment(PlacePageBookmarkFragment.class, BOOKMARK_FRAGMENT_TAG, R.id.place_page_bookmark_fragment, updateViewFragment(PlacePageBookmarkFragment.class, BOOKMARK_FRAGMENT_TAG, R.id.place_page_bookmark_fragment,
enabled); mMapObject.isBookmark());
} }
private void updateTrackView() private void updateTrackView()
@@ -687,84 +686,39 @@ public class PlacePageView extends Fragment
if (RoutingController.get().isNavigating() || RoutingController.get().isPlanning()) if (RoutingController.get().isNavigating() || RoutingController.get().isPlanning())
{ {
UiUtils.hide(mEditPlace, mAddPlace, mEditTopSpace, mMapTooOld); UiUtils.hide(mEditPlace, mAddPlace, mEditTopSpace);
} }
else else
{ {
UiUtils.showIf(Editor.nativeShouldShowEditPlace(), mEditPlace); UiUtils.showIf(Editor.nativeShouldShowEditPlace(), mEditPlace);
UiUtils.showIf(Editor.nativeShouldShowAddPlace(), mAddPlace); UiUtils.showIf(Editor.nativeShouldShowAddPlace(), mAddPlace);
UiUtils.hide(mMapTooOld);
MaterialButton mTvEditPlace = mEditPlace.findViewById(R.id.mb__place_editor); MaterialButton mTvEditPlace = mEditPlace.findViewById(R.id.mb__place_editor);
MaterialButton mTvAddPlace = mAddPlace.findViewById(R.id.mb__place_add); MaterialButton mTvAddPlace = mAddPlace.findViewById(R.id.mb__place_add);
mTvEditPlace.setOnClickListener(this);
boolean shouldEnableEditPlace = Editor.nativeShouldEnableEditPlace(); mTvAddPlace.setOnClickListener(this);
mTvEditPlace.setEnabled(Editor.nativeShouldEnableEditPlace());
if (shouldEnableEditPlace) mTvAddPlace.setEnabled(Editor.nativeShouldEnableAddPlace());
{ final int editTextButtonColor =
mTvEditPlace.setEnabled(true); Editor.nativeShouldEnableEditPlace()
mTvAddPlace.setEnabled(true);
mTvEditPlace.setOnClickListener(this);
mTvAddPlace.setOnClickListener(this);
}
else
{
String countryId = MapManager.nativeGetSelectedCountry();
if (countryId != null && MapManager.nativeIsMapTooOldToEdit(countryId))
{
// map editing is disabled because the map is too old
mTvEditPlace.setEnabled(true);
mTvAddPlace.setEnabled(true);
mTvEditPlace.setOnClickListener((v) -> {
Utils.showSnackbar(v.getContext(), v.getRootView(), R.string.place_page_too_old_to_edit);
});
mTvAddPlace.setOnClickListener((v) -> {
Utils.showSnackbar(v.getContext(), v.getRootView(), R.string.place_page_too_old_to_edit);
});
CountryItem map = CountryItem.fill(countryId);
if (map.status == CountryItem.STATUS_UPDATABLE || map.status == CountryItem.STATUS_DONE
|| map.status == CountryItem.STATUS_FAILED)
{
UiUtils.show(mMapTooOld);
boolean canUpdateMap = map.status != CountryItem.STATUS_DONE;
MaterialButton mTvUpdateTooOldMap = mMapTooOld.findViewById(R.id.mb__update_too_old_map);
UiUtils.showIf(canUpdateMap, mTvUpdateTooOldMap);
MaterialTextView mapTooOldDescription = mMapTooOld.findViewById(R.id.tv__map_too_old_description);
if (canUpdateMap)
{
mapTooOldDescription.setText(R.string.place_page_map_too_old_description);
mTvUpdateTooOldMap.setOnClickListener((v) -> {
MapManagerHelper.warn3gAndDownload(requireActivity(), map.id, null);
UiUtils.hide(mMapTooOld);
});
}
else
mapTooOldDescription.setText(R.string.place_page_app_too_old_description);
}
}
else
{
// map editing is disabled for other reasons
mTvEditPlace.setEnabled(false);
mTvAddPlace.setEnabled(false);
}
}
final int editButtonColor =
shouldEnableEditPlace
? ContextCompat.getColor( ? ContextCompat.getColor(
getContext(), getContext(),
UiUtils.getStyledResourceId(getContext(), com.google.android.material.R.attr.colorSecondary)) UiUtils.getStyledResourceId(getContext(), com.google.android.material.R.attr.colorSecondary))
: ContextCompat.getColor(getContext(), R.color.button_accent_text_disabled); : ContextCompat.getColor(getContext(), R.color.button_accent_text_disabled);
final ColorStateList editStrokeButtonColor = new ColorStateList(
mTvEditPlace.setTextColor(editButtonColor); new int[][]{
mTvAddPlace.setTextColor(editButtonColor); new int[]{android.R.attr.state_enabled}, // enabled
mTvEditPlace.setStrokeColor(ColorStateList.valueOf(editButtonColor)); new int[]{-android.R.attr.state_enabled} // disabled
mTvAddPlace.setStrokeColor(ColorStateList.valueOf(editButtonColor)); },
new int[]{
ContextCompat.getColor(
getContext(),
UiUtils.getStyledResourceId(getContext(), com.google.android.material.R.attr.colorSecondary)),
ContextCompat.getColor(getContext(), R.color.button_accent_text_disabled)
});
mTvEditPlace.setTextColor(editTextButtonColor);
mTvAddPlace.setTextColor(editTextButtonColor);
mTvEditPlace.setStrokeColor(editStrokeButtonColor);
mTvAddPlace.setStrokeColor(editStrokeButtonColor);
UiUtils.showIf( UiUtils.showIf(
UiUtils.isVisible(mEditPlace) || UiUtils.isVisible(mAddPlace), UiUtils.isVisible(mEditPlace) || UiUtils.isVisible(mAddPlace),
mEditTopSpace); mEditTopSpace);

View File

@@ -23,7 +23,6 @@ import app.organicmaps.R;
import app.organicmaps.sdk.bookmarks.data.Bookmark; import app.organicmaps.sdk.bookmarks.data.Bookmark;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager; import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.sdk.bookmarks.data.MapObject; import app.organicmaps.sdk.bookmarks.data.MapObject;
import app.organicmaps.sdk.bookmarks.data.Track;
import app.organicmaps.sdk.util.StringUtils; import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.util.UiUtils; import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
@@ -42,7 +41,6 @@ public class PlacePageBookmarkFragment extends Fragment implements View.OnClickL
private PlacePageViewModel mViewModel; private PlacePageViewModel mViewModel;
private Bookmark currentBookmark; private Bookmark currentBookmark;
private Track currentTrack;
@Nullable @Nullable
@Override @Override
@@ -90,15 +88,7 @@ public class PlacePageBookmarkFragment extends Fragment implements View.OnClickL
private void updateBookmarkDetails() private void updateBookmarkDetails()
{ {
String notes = null; final String notes = currentBookmark.getBookmarkDescription();
if (currentBookmark != null)
{
notes = currentBookmark.getBookmarkDescription();
}
if (currentTrack != null)
{
notes = currentTrack.getTrackDescription();
}
if (TextUtils.isEmpty(notes)) if (TextUtils.isEmpty(notes))
{ {
UiUtils.hide(mTvBookmarkNote); UiUtils.hide(mTvBookmarkNote);
@@ -130,16 +120,8 @@ public class PlacePageBookmarkFragment extends Fragment implements View.OnClickL
public void onClick(View v) public void onClick(View v)
{ {
final FragmentActivity activity = requireActivity(); final FragmentActivity activity = requireActivity();
if (currentBookmark != null) EditBookmarkFragment.editBookmark(currentBookmark.getCategoryId(), currentBookmark.getBookmarkId(), activity,
{ getChildFragmentManager(), PlacePageBookmarkFragment.this);
EditBookmarkFragment.editBookmark(currentBookmark.getCategoryId(), currentBookmark.getBookmarkId(), activity,
getChildFragmentManager(), PlacePageBookmarkFragment.this);
}
else if (currentTrack != null)
{
EditBookmarkFragment.editBookmark(currentTrack.getCategoryId(), currentTrack.getTrackId(), activity,
getChildFragmentManager(), PlacePageBookmarkFragment.this);
}
} }
@Override @Override
@@ -170,11 +152,6 @@ public class PlacePageBookmarkFragment extends Fragment implements View.OnClickL
currentBookmark = (Bookmark) mapObject; currentBookmark = (Bookmark) mapObject;
updateBookmarkDetails(); updateBookmarkDetails();
} }
if (mapObject != null && mapObject.isTrack())
{
currentTrack = (Track) mapObject;
updateBookmarkDetails();
}
} }
@Override @Override

View File

@@ -1,13 +1,13 @@
package app.organicmaps.widget.placepage.sections; package app.organicmaps.widget.placepage.sections;
import static android.view.View.INVISIBLE;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.GridLayout; import android.widget.GridLayout;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
@@ -21,6 +21,7 @@ import app.organicmaps.R;
import app.organicmaps.sdk.Framework; import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.bookmarks.data.ChargeSocketDescriptor; import app.organicmaps.sdk.bookmarks.data.ChargeSocketDescriptor;
import app.organicmaps.sdk.bookmarks.data.MapObject; import app.organicmaps.sdk.bookmarks.data.MapObject;
import app.organicmaps.sdk.bookmarks.data.Metadata;
import app.organicmaps.widget.placepage.PlacePageViewModel; import app.organicmaps.widget.placepage.PlacePageViewModel;
import java.text.DecimalFormat; import java.text.DecimalFormat;
@@ -88,7 +89,7 @@ public class PlacePageChargeSocketsFragment extends Fragment implements Observer
// load SVG icon converted into VectorDrawable in res/drawable // load SVG icon converted into VectorDrawable in res/drawable
@SuppressLint("DiscouragedApi") @SuppressLint("DiscouragedApi")
int resIconId = getResources().getIdentifier("ic_charge_socket_" + socket.visualType(), "drawable", int resIconId = getResources().getIdentifier("ic_charge_socket_" + socket.type(), "drawable",
requireContext().getPackageName()); requireContext().getPackageName());
if (resIconId != 0) if (resIconId != 0)
{ {
@@ -97,7 +98,7 @@ public class PlacePageChargeSocketsFragment extends Fragment implements Observer
@SuppressLint("DiscouragedApi") @SuppressLint("DiscouragedApi")
int resTypeId = int resTypeId =
getResources().getIdentifier("charge_socket_" + socket.visualType(), "string", requireContext().getPackageName()); getResources().getIdentifier("charge_socket_" + socket.type(), "string", requireContext().getPackageName());
if (resTypeId != 0) if (resTypeId != 0)
{ {
type.setText(resTypeId); type.setText(resTypeId);
@@ -108,9 +109,6 @@ public class PlacePageChargeSocketsFragment extends Fragment implements Observer
DecimalFormat df = new DecimalFormat("#.##"); DecimalFormat df = new DecimalFormat("#.##");
power.setText(getString(R.string.kw_label, df.format(socket.power()))); power.setText(getString(R.string.kw_label, df.format(socket.power())));
} }
else if (socket.ignorePower()) {
power.setVisibility(INVISIBLE);
}
if (socket.count() != 0) if (socket.count() != 0)
{ {

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2021 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!-- Material3 alternative to textColorHighlight for dark theme -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:alpha="@dimen/material_emphasis_medium" android:color="@color/m3_sys_color_dark_primary" />
</selector>

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2021 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<!-- Material3 alternative to textColorHighlight for light theme -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:alpha="@dimen/material_emphasis_medium" android:color="?attr/colorOnPrimaryContainer" />
</selector>

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