Merge commit '07cd1ec4f5' into traffic
# Conflicts: # libs/indexer/ftypes_matcher.hpp Bug: boost/regex.hpp may not be found Workaround: remove `if` in CMakeLists.txt:226, leave `include_directories`
@@ -5,10 +5,10 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
description: 'Which job(s) to run right now?'
|
description: 'Which job(s) to run right now?'
|
||||||
required: true
|
required: true
|
||||||
default: 'all'
|
default: 'all-except-upload'
|
||||||
type: choice
|
type: choice
|
||||||
options:
|
options:
|
||||||
- all
|
- all-except-upload
|
||||||
- copy-coasts
|
- copy-coasts
|
||||||
- planet
|
- planet
|
||||||
- wiki
|
- wiki
|
||||||
@@ -16,30 +16,82 @@ on:
|
|||||||
- subways
|
- subways
|
||||||
- tiger
|
- tiger
|
||||||
- maps
|
- maps
|
||||||
|
- upload
|
||||||
|
map-generator-continue:
|
||||||
|
description: 'Continue previous map generation?'
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
type: boolean
|
||||||
|
map-generator-countries:
|
||||||
|
description: 'Generate specific MWMs? (i.e. "US_New York_*, foo")'
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
reset:
|
||||||
|
description: 'Reset part of the system?'
|
||||||
|
required: false
|
||||||
|
default: 'no'
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- 'no'
|
||||||
|
- wiki-ratelimit
|
||||||
|
|
||||||
|
## RCLONE_CONF is multi-line text containing keys and credentials for us2,ru1,fi1,de1 servers
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
RCLONE_CONF: ${{ secrets.RCLONE_CONF }}
|
||||||
WIKIMEDIA_USERNAME: ${{ secrets.WIKIMEDIA_USERNAME }}
|
WIKIMEDIA_USERNAME: ${{ secrets.WIKIMEDIA_USERNAME }}
|
||||||
WIKIMEDIA_PASSWORD: ${{ secrets.WIKIMEDIA_PASSWORD }}
|
WIKIMEDIA_PASSWORD: ${{ secrets.WIKIMEDIA_PASSWORD }}
|
||||||
S3_KEY_ID: ${{ secrets.S3_KEY_ID }}
|
ZULIP_BOT_EMAIL: ${{ secrets.ZULIP_BOT_EMAIL }}
|
||||||
S3_SECRET_KEY: ${{ secrets.S3_SECRET_KEY }}
|
ZULIP_API_KEY: ${{ secrets.ZULIP_API_KEY }}
|
||||||
S3_ENDPOINT: ${{ secrets.S3_ENDPOINT }}
|
MWMCONTINUE: ${{ inputs.map-generator-continue }}
|
||||||
S3_BUCKET: ${{ secrets.S3_BUCKET }}
|
MWMCOUNTRIES: ${{ inputs.map-generator-countries }}
|
||||||
SFTP_USER: ${{ secrets.SFTP_USER }}
|
|
||||||
SFTP_PASSWORD: ${{ secrets.SFTP_PASSWORD }}
|
|
||||||
SFTP_HOST: ${{ secrets.SFTP_HOST }}
|
|
||||||
SFTP_PATH: ${{ secrets.SFTP_PATH }}
|
|
||||||
DEBIAN_FRONTEND: noninteractive
|
DEBIAN_FRONTEND: noninteractive
|
||||||
TZ: Etc/UTC
|
TZ: Etc/UTC
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
copy-coasts:
|
clone-repos:
|
||||||
if: inputs.jobs == 'copy-coasts' || inputs.jobs == 'all'
|
name: Clone Git Repos
|
||||||
name: Copy Previously Generated Coasts
|
|
||||||
runs-on: mapfilemaker
|
runs-on: mapfilemaker
|
||||||
container:
|
container:
|
||||||
image: ubuntu:latest
|
image: codeberg.org/comaps/maps_generator:f6d53d54f794
|
||||||
volumes:
|
volumes:
|
||||||
- /media/4tbexternal:/media/4tbexternal
|
- /mnt/4tbexternal:/mnt/4tbexternal
|
||||||
|
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: Checkout main repo
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "Cloning $FORGEJO_SERVER_URL/$FORGEJO_REPOSITORY branch $FORGEJO_REF_NAME"
|
||||||
|
cd ~
|
||||||
|
git clone --recurse-submodules --shallow-submodules -b $FORGEJO_REF_NAME --single-branch $FORGEJO_SERVER_URL/$FORGEJO_REPOSITORY.git comaps
|
||||||
|
- name: Checkout wikiparser repo
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cd ~
|
||||||
|
git clone https://codeberg.org/comaps/wikiparser.git
|
||||||
|
- name: Checkout subways repo
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cd ~
|
||||||
|
git clone https://codeberg.org/comaps/subways.git
|
||||||
|
|
||||||
|
copy-coasts:
|
||||||
|
if: inputs.jobs == 'copy-coasts' || inputs.jobs == 'all-except-upload'
|
||||||
|
name: Copy Previously Generated Coasts
|
||||||
|
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:
|
concurrency:
|
||||||
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
|
||||||
@@ -47,336 +99,403 @@ jobs:
|
|||||||
- name: Copy Coasts
|
- name: Copy Coasts
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
if [ -f /media/4tbexternal/osm-maps/*/intermediate_data/WorldCoasts.geom ]; then
|
echo "WorldCoasts available:"
|
||||||
cp /media/4tbexternal/osm-maps/*/intermediate_data/WorldCoasts.geom /media/4tbexternal/osm-planet/latest_coasts.geom
|
ls -al /mnt/4tbexternal/osm-maps/*/intermediate_data/WorldCoasts.*
|
||||||
cp /media/4tbexternal/osm-maps/*/intermediate_data/WorldCoasts.rawgeom /media/4tbexternal/osm-planet/latest_coasts.rawgeom
|
|
||||||
|
if [ -f /mnt/4tbexternal/osm-maps/*/intermediate_data/WorldCoasts.geom ]; then
|
||||||
|
|
||||||
|
echo "Before:"
|
||||||
|
ls -al /home/planet/latest_coasts*
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
echo "After:"
|
||||||
|
ls -al /home/planet/latest_coasts*
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
echo "No WorldCoasts found."
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
update-planet:
|
update-planet:
|
||||||
if: inputs.jobs == 'planet' || inputs.jobs == 'all'
|
if: inputs.jobs == 'planet' || inputs.jobs == 'all-except-upload'
|
||||||
name: Update Planet
|
name: Update Planet
|
||||||
runs-on: mapfilemaker
|
runs-on: mapfilemaker
|
||||||
|
needs:
|
||||||
|
- clone-repos
|
||||||
container:
|
container:
|
||||||
image: ubuntu:latest
|
image: codeberg.org/comaps/maps_generator:f6d53d54f794
|
||||||
volumes:
|
volumes:
|
||||||
- /media/4tbexternal:/media/4tbexternal
|
- /mnt/4tbexternal/:/mnt/4tbexternal/
|
||||||
|
- /mnt/4tbexternal/osm-planet:/home/planet
|
||||||
concurrency:
|
concurrency:
|
||||||
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: Install dependencies
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
apt-get update -y
|
|
||||||
apt-get install -y pyosmium osmium-tool python3-venv python3-pip wget2
|
|
||||||
rm -f /usr/lib/python*/EXTERNALLY-MANAGED
|
|
||||||
pip3 install "protobuf<4"
|
|
||||||
- name: Download Planet File if Absent
|
- name: Download Planet File if Absent
|
||||||
shell: bash
|
shell: bash
|
||||||
|
# TODO: replace wget2 with curl -Z
|
||||||
run: |
|
run: |
|
||||||
if [ ! -d /media/4tbexternal/osm-planet/planet/ ]; then
|
if [ ! -d /home/planet/planet/ ]; then
|
||||||
mkdir -p /media/4tbexternal/osm-planet/planet/
|
mkdir -p /home/planet/planet/
|
||||||
fi
|
fi
|
||||||
if [ ! -f /media/4tbexternal/osm-planet/planet/planet-latest.osm.pbf ]; then
|
if [ ! -f /home/planet/planet/planet-latest.osm.pbf ]; then
|
||||||
cd /media/4tbexternal/osm-planet/planet/
|
cd /home/planet/planet/
|
||||||
wget2 --verbose --progress=bar --continue --debug https://ftpmirror.your.org/pub/openstreetmap/pbf/planet-latest.osm.pbf
|
wget2 --verbose --progress=bar --continue https://ftpmirror.your.org/pub/openstreetmap/pbf/planet-latest.osm.pbf
|
||||||
|
else
|
||||||
|
echo "planet-latest.osm.pbf was found, raw download not required."
|
||||||
fi
|
fi
|
||||||
- name: Update Planet
|
- name: Update Planet
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
cd /media/4tbexternal/osm-planet/planet/
|
cd /home/planet/planet/
|
||||||
pyosmium-up-to-date planet-latest.osm.pbf -o planet-latest-new.osm.pbf -vv --size 16384
|
rm -f planet-latest-new.osm.pbf
|
||||||
|
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
|
- name: Converting planet-latest.osm.pbf to planet.o5m
|
||||||
run: /root/OM/osmctools/osmconvert planet-latest.osm.pbf -o=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
|
||||||
|
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=Planet update is done!'
|
||||||
|
|
||||||
wiki-update:
|
wiki-update:
|
||||||
if: inputs.jobs == 'wiki' || inputs.jobs == 'all'
|
if: inputs.jobs == 'wiki' || inputs.jobs == 'all-except-upload'
|
||||||
name: Update Wikipedia
|
name: Update Wikipedia
|
||||||
runs-on: mapfilemaker
|
runs-on: mapfilemaker
|
||||||
|
needs:
|
||||||
|
- clone-repos
|
||||||
container:
|
container:
|
||||||
image: ubuntu:latest
|
image: codeberg.org/comaps/maps_generator:f6d53d54f794
|
||||||
volumes:
|
volumes:
|
||||||
- /media/4tbexternal:/media/4tbexternal
|
- /mnt/4tbexternal/:/mnt/4tbexternal/
|
||||||
|
- /mnt/4tbexternal/osm-planet:/home/planet
|
||||||
concurrency:
|
concurrency:
|
||||||
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: Install dependencies
|
- uses: actions/cache@v4
|
||||||
shell: bash
|
with:
|
||||||
run: |
|
path: "~"
|
||||||
apt-get update -y
|
key: cache-${{ github.run_id }}-${{ github.run_attempt }}
|
||||||
apt-get install -y jq curl wget2 rustc cargo git ca-certificates
|
|
||||||
- name: Clone wikiparser if necessary
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
if [ ! -d /media/4tbexternal/wikiparser ]; then
|
|
||||||
cd /media/4tbexternal
|
|
||||||
git clone https://codeberg.org/comaps/wikiparser.git
|
|
||||||
fi
|
|
||||||
- name: Check for planet file
|
- name: Check for planet file
|
||||||
shell: bash
|
shell: bash
|
||||||
|
# TODO: remove debug output
|
||||||
run: |
|
run: |
|
||||||
if [ ! -f /media/4tbexternal/osm-planet/planet/planet-latest.osm.pbf ]; then
|
if [ ! -f /home/planet/planet/planet-latest.osm.pbf ]; then
|
||||||
echo "ERROR: No file at /media/4tbexternal/osm-planet/planet/planet-latest.osm.pbf"
|
echo "ERROR: No file at /home/planet/planet/planet-latest.osm.pbf"
|
||||||
ls -al /media/4tbexternal/
|
ls -al /home/planet/
|
||||||
ls -al /media/4tbexternal/osm-planet/
|
ls -al /home/planet/planet/
|
||||||
ls -al /media/4tbexternal/osm-planet/planet/
|
exit 1
|
||||||
|
fi
|
||||||
|
- name: Only get new dumps once per 30 days
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
if [[ '${{ inputs.reset }}' == 'wiki-ratelimit' ]]; then
|
||||||
|
echo "Bypassing wiki rate limit upon request."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
datediff() {
|
||||||
|
d1=$(date -d "$1" +%s)
|
||||||
|
d2=$(date -d "$2" +%s)
|
||||||
|
echo $(( (d1 - d2) / 86400 ))
|
||||||
|
}
|
||||||
|
RECENTDUMPDATE=$(find /home/planet/wikipedia/dumps/ -mindepth 1 -maxdepth 1 -iname "2*" -type d | sort -n -r | head -1 | cut -d/ -f6)
|
||||||
|
TODAY=$(date +%Y%m%d)
|
||||||
|
DATEDIFF=$(datediff $TODAY $RECENTDUMPDATE)
|
||||||
|
if [ $DATEDIFF -lt 30 ]; then
|
||||||
|
echo "ERROR: The most recent wiki dump is from $RECENTDUMPDATE, $DATEDIFF days ago. Wikimedia limits users to 15 snapshot requests per month."
|
||||||
|
echo "Set the 'reset' option to 'wiki-ratelimit' to bypass this."
|
||||||
|
ls -al /home/planet/wikipedia/dumps/
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
- name: Update Wikipedia from Enterprise API
|
- name: Update Wikipedia from Enterprise API
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
mkdir -p /media/4tbexternal/osm-planet/wikipedia/dumps
|
#todo: curl in download.sh can fail when rate limited and even save error messages to the output. need to validate.
|
||||||
mkdir -p /media/4tbexternal/osm-planet/wikipedia/build
|
#downloading all languages can also trigger rate limits or fail as well. needs work.
|
||||||
cd /media/4tbexternal/wikiparser
|
#also: a failure to download means a failure to build, and could result in no wiki descriptions etc.
|
||||||
|
#also-also: do we want to remove old wiki data in planet between builds? pastk: no need, its being updated / augmented
|
||||||
|
mkdir -p /home/planet/wikipedia/dumps
|
||||||
|
mkdir -p /home/planet/wikipedia/build
|
||||||
|
cd ~/wikiparser
|
||||||
ls -al
|
ls -al
|
||||||
echo "Downloading ..."
|
echo "Downloading ..."
|
||||||
./download.sh /media/4tbexternal/osm-planet/wikipedia/dumps
|
./download.sh /home/planet/wikipedia/dumps
|
||||||
|
ls -al /home/planet/wikipedia/dumps/*
|
||||||
echo "Running ..."
|
echo "Running ..."
|
||||||
./run.sh /media/4tbexternal/osm-planet/wikipedia/build \
|
./run.sh /home/planet/wikipedia/build \
|
||||||
/media/4tbexternal/osm-planet/planet/planet-latest.osm.pbf \
|
/home/planet/planet/planet-latest.osm.pbf \
|
||||||
/media/4tbexternal/osm-planet/wikipedia/dumps/latest/*.tar.gz
|
/home/planet/wikipedia/dumps/latest/*.tar.gz
|
||||||
echo "DONE"
|
echo "DONE"
|
||||||
|
- name: Check that the latest dumps are present, recent, and not super tiny
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
FAILCHECK=0
|
||||||
|
|
||||||
|
# Check all .tar.gz files in /home/planet/wikipedia/dumps/latest/
|
||||||
|
for file in /home/planet/wikipedia/dumps/latest/*.tar.gz; do
|
||||||
|
# Check if file exists (handles case where glob doesn't match)
|
||||||
|
[ -e "$file" ] || continue
|
||||||
|
|
||||||
|
# Get file size in MB and modification time in days
|
||||||
|
size_mb=$(stat -f%z "$file" 2>/dev/null | awk '{print int($1/1024/1024)}' || stat -c%s "$file" | awk
|
||||||
|
'{print int($1/1024/1024)}')
|
||||||
|
days_old=$(find "$file" -mtime -7 | wc -l)
|
||||||
|
|
||||||
|
# Verify conditions
|
||||||
|
if [ "$size_mb" -lt 100 ]; then
|
||||||
|
echo "FAIL: $file is only ${size_mb}MB (< 100MB)"
|
||||||
|
FAILCHECK=1
|
||||||
|
elif [ "$days_old" -eq 0 ]; then
|
||||||
|
echo "FAIL: $file is older than 7 days"
|
||||||
|
ls -al $file
|
||||||
|
FAILCHECK=1
|
||||||
|
else
|
||||||
|
echo "PASS: $file (${size_mb}MB, modified within 7 days)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
exit $FAILCHECK
|
||||||
|
- 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=Wiki update is done!'
|
||||||
|
|
||||||
update-isolines:
|
update-isolines:
|
||||||
if: inputs.jobs == 'isolines' || inputs.jobs == 'all'
|
if: inputs.jobs == 'isolines' || inputs.jobs == 'all-except-upload'
|
||||||
name: Update Isolines
|
name: Update Isolines
|
||||||
runs-on: mapfilemaker
|
runs-on: mapfilemaker
|
||||||
|
needs:
|
||||||
|
- clone-repos
|
||||||
container:
|
container:
|
||||||
image: ubuntu:latest
|
image: codeberg.org/comaps/maps_generator:f6d53d54f794
|
||||||
volumes:
|
volumes:
|
||||||
- /media/4tbexternal:/media/4tbexternal
|
- /mnt/4tbexternal/:/mnt/4tbexternal/
|
||||||
|
- /mnt/4tbexternal/osm-planet:/home/planet
|
||||||
concurrency:
|
concurrency:
|
||||||
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: Install dependencies
|
- uses: actions/cache@v4
|
||||||
shell: bash
|
with:
|
||||||
run: |
|
path: "~"
|
||||||
apt-get update -qq \
|
key: cache-${{ github.run_id }}-${{ github.run_attempt }}
|
||||||
&& apt-get install -y --no-install-recommends \
|
# TODO: we only need to update these if our SRTM or countries change
|
||||||
curl \
|
# TODO: after update, verify that sizable files exist: /home/planet/isolines/*.isolines
|
||||||
osmctools \
|
|
||||||
rclone \
|
|
||||||
git \
|
|
||||||
ca-certificates \
|
|
||||||
openssh-client \
|
|
||||||
sshpass \
|
|
||||||
vim \
|
|
||||||
wget \
|
|
||||||
build-essential \
|
|
||||||
clang \
|
|
||||||
cmake \
|
|
||||||
python3 \
|
|
||||||
python3-pip \
|
|
||||||
python3.12-venv \
|
|
||||||
qt6-base-dev \
|
|
||||||
qt6-positioning-dev \
|
|
||||||
libc++-dev \
|
|
||||||
libfreetype-dev \
|
|
||||||
libglvnd-dev \
|
|
||||||
libgl1-mesa-dev \
|
|
||||||
libharfbuzz-dev \
|
|
||||||
libicu-dev \
|
|
||||||
libqt6svg6-dev \
|
|
||||||
libqt6positioning6-plugins \
|
|
||||||
libqt6positioning6 \
|
|
||||||
libsqlite3-dev \
|
|
||||||
libxrandr-dev \
|
|
||||||
libxinerama-dev \
|
|
||||||
libxcursor-dev \
|
|
||||||
libxi-dev \
|
|
||||||
zlib1g-dev
|
|
||||||
rm -f /usr/lib/python*/EXTERNALLY-MANAGED
|
|
||||||
pip3 install "protobuf<4"
|
|
||||||
- name: Clone main repo if necessary
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
if [ ! -d /media/4tbexternal/comaps-init ]; then
|
|
||||||
apt-get update -qq && apt-get install -y --no-install-recommends git
|
|
||||||
cd /media/4tbexternal
|
|
||||||
git clone --recurse-submodules --shallow-submodules -b rebase-generator-pastk-wb251014 --single-branch https://codeberg.org/comaps/comaps.git comaps-init
|
|
||||||
fi
|
|
||||||
- name: Update Isolines
|
- name: Update Isolines
|
||||||
shell: bash
|
shell: bash
|
||||||
|
# TODO: preserve previous isolines version?
|
||||||
|
# TODO: cleanup the tmp-tiles dir after completion
|
||||||
run: |
|
run: |
|
||||||
cd /media/4tbexternal/comaps-init/
|
cd ~/comaps/
|
||||||
./tools/unix/build_omim.sh -R topography_generator_tool
|
./tools/unix/build_omim.sh -p ~ -R topography_generator_tool
|
||||||
rm -rf ../osm-planet/isolines/
|
rm -rf /home/planet/isolines/
|
||||||
mkdir ../osm-planet/isolines/
|
mkdir /home/planet/isolines/
|
||||||
../omim-build-relwithdebinfo/topography_generator_tool \
|
~/omim-build-relwithdebinfo/topography_generator_tool \
|
||||||
--profiles_path=./data/conf/isolines/isolines-profiles.json \
|
--profiles_path=./data/conf/isolines/isolines-profiles.json \
|
||||||
--countries_to_generate_path=./data/conf/isolines/countries-to-generate.json \
|
--countries_to_generate_path=./data/conf/isolines/countries-to-generate.json \
|
||||||
--tiles_isolines_out_dir=../osm-planet/isolines/tmp-tiles/ \
|
--tiles_isolines_out_dir=/home/planet/isolines/tmp-tiles/ \
|
||||||
--countries_isolines_out_dir=../osm-planet/isolines/ \
|
--countries_isolines_out_dir=/home/planet/isolines/ \
|
||||||
--data_dir=./data/ \
|
--data_dir=./data/ \
|
||||||
--srtm_path=../osm-planet/SRTM-patched-europe/ \
|
--srtm_path=/home/planet/SRTM-patched-europe/ \
|
||||||
--threads=22
|
--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-subways:
|
update-subways:
|
||||||
if: inputs.jobs == 'subways' || inputs.jobs == 'all'
|
if: inputs.jobs == 'subways' || inputs.jobs == 'all-except-upload'
|
||||||
name: Update Subways
|
name: Update Subways
|
||||||
runs-on: mapfilemaker
|
runs-on: mapfilemaker
|
||||||
|
needs:
|
||||||
|
- clone-repos
|
||||||
container:
|
container:
|
||||||
image: ubuntu:latest
|
image: codeberg.org/comaps/maps_generator:f6d53d54f794
|
||||||
volumes:
|
volumes:
|
||||||
- /media/4tbexternal:/media/4tbexternal
|
- /mnt/4tbexternal/:/mnt/4tbexternal/
|
||||||
|
- /mnt/4tbexternal/osm-planet:/home/planet
|
||||||
concurrency:
|
concurrency:
|
||||||
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: Install dependencies
|
- uses: actions/cache@v4
|
||||||
shell: bash
|
with:
|
||||||
run: |
|
path: "~"
|
||||||
apt-get update -qq && apt-get install -y --no-install-recommends curl osmctools osmium-tool python3-venv ca-certificates git python3-pip
|
key: cache-${{ github.run_id }}-${{ github.run_attempt }}
|
||||||
rm -f /usr/lib/python*/EXTERNALLY-MANAGED
|
|
||||||
pip3 install "protobuf<4"
|
|
||||||
- name: Clone subways if necessary
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
if [ ! -d /media/4tbexternal/subways ]; then
|
|
||||||
cd /media/4tbexternal
|
|
||||||
git clone https://codeberg.org/comaps/subways.git
|
|
||||||
fi
|
|
||||||
- name: Clone main repo if necessary
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
if [ ! -d /media/4tbexternal/comaps-init ]; then
|
|
||||||
cd /media/4tbexternal
|
|
||||||
git clone --recurse-submodules --shallow-submodules -b rebase-generator-pastk-wb251014 --single-branch https://codeberg.org/comaps/comaps.git comaps-init
|
|
||||||
fi
|
|
||||||
- name: Update Subways
|
- name: Update Subways
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
cd /media/4tbexternal/comaps-init/
|
cd ~/comaps/
|
||||||
cp tools/unix/maps/settings.sh.prod tools/unix/maps/settings.sh
|
cp tools/unix/maps/settings.sh.prod tools/unix/maps/settings.sh
|
||||||
./tools/unix/maps/generate_subways.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:
|
update-tiger:
|
||||||
if: inputs.jobs == 'tiger' || inputs.jobs == 'all'
|
if: inputs.jobs == 'tiger' || inputs.jobs == 'all-except-upload'
|
||||||
name: Update TIGER
|
name: Update TIGER
|
||||||
runs-on: mapfilemaker
|
runs-on: mapfilemaker
|
||||||
|
needs:
|
||||||
|
- clone-repos
|
||||||
container:
|
container:
|
||||||
image: ubuntu:latest
|
image: codeberg.org/comaps/maps_generator:f6d53d54f794
|
||||||
volumes:
|
volumes:
|
||||||
- /media/4tbexternal:/media/4tbexternal
|
- /mnt/4tbexternal/:/mnt/4tbexternal/
|
||||||
|
- /mnt/4tbexternal/osm-planet:/home/planet
|
||||||
concurrency:
|
concurrency:
|
||||||
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: Install dependencies
|
- uses: actions/cache@v4
|
||||||
shell: bash
|
with:
|
||||||
run: |
|
path: "~"
|
||||||
apt-get update -qq && apt-get install -y --no-install-recommends \
|
key: cache-${{ github.run_id }}-${{ github.run_attempt }}
|
||||||
build-essential \
|
|
||||||
clang \
|
|
||||||
cmake \
|
|
||||||
ninja-build \
|
|
||||||
ca-certificates \
|
|
||||||
git \
|
|
||||||
wget2
|
|
||||||
- name: Clone main repo if necessary
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
if [ ! -d /media/4tbexternal/comaps-init ]; then
|
|
||||||
cd /media/4tbexternal
|
|
||||||
git clone --recurse-submodules --shallow-submodules -b rebase-generator-pastk-wb251014 --single-branch https://codeberg.org/comaps/comaps.git comaps-init
|
|
||||||
fi
|
|
||||||
- name: Build address_parser
|
- name: Build address_parser
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
cd /media/4tbexternal/comaps-init
|
cd ~/comaps
|
||||||
rm -rf ../omim-build-relwithdebinfo/CMakeCache.txt
|
#rm -rf ~/omim-build-relwithdebinfo/CMakeCache.txt
|
||||||
rm -rf ../omim-build-relwithdebinfo/CMakeFiles
|
#rm -rf ~/omim-build-relwithdebinfo/CMakeFiles
|
||||||
./tools/unix/build_omim.sh -R address_parser_tool
|
./tools/unix/build_omim.sh -p ~ -R address_parser_tool
|
||||||
- name: Update TIGER from Nominatim
|
- name: Update TIGER from Nominatim
|
||||||
shell: bash
|
shell: bash
|
||||||
|
# TODO: use curl instead of wget2
|
||||||
run: |
|
run: |
|
||||||
cd /media/4tbexternal/osm-planet/
|
# 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
|
wget2 https://nominatim.org/data/tiger-nominatim-preprocessed-latest.csv.tar.gz
|
||||||
tar -xOzf tiger-nominatim-preprocessed-latest.csv.tar.gz | /media/4tbexternal/omim-build-relwithdebinfo/address_parser_tool --output_path=./tiger
|
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.jobs == 'maps' || inputs.jobs == 'all'
|
if: inputs.jobs == 'maps' || inputs.jobs == 'all-except-upload'
|
||||||
name: Generate Maps
|
name: Generate Maps
|
||||||
runs-on: mapfilemaker
|
runs-on: mapfilemaker
|
||||||
|
needs:
|
||||||
|
- clone-repos
|
||||||
|
timeout-minutes: 40320
|
||||||
container:
|
container:
|
||||||
image: ubuntu:latest
|
image: codeberg.org/comaps/maps_generator:f6d53d54f794
|
||||||
volumes:
|
volumes:
|
||||||
- /media/4tbexternal:/media/4tbexternal
|
- /mnt/4tbexternal/:/mnt/4tbexternal/
|
||||||
|
- /mnt/4tbexternal/osm-planet:/home/planet
|
||||||
options: --ulimit nofile=262144:262144
|
options: --ulimit nofile=262144:262144
|
||||||
concurrency:
|
concurrency:
|
||||||
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: Install dependencies
|
- uses: actions/cache@v4
|
||||||
shell: bash
|
with:
|
||||||
run: |
|
path: "~"
|
||||||
apt-get update -qq \
|
key: cache-${{ github.run_id }}-${{ github.run_attempt }}
|
||||||
&& apt-get install -y --no-install-recommends \
|
|
||||||
curl \
|
|
||||||
osmctools \
|
|
||||||
rclone \
|
|
||||||
git \
|
|
||||||
ca-certificates \
|
|
||||||
openssh-client \
|
|
||||||
sshpass \
|
|
||||||
vim \
|
|
||||||
wget \
|
|
||||||
build-essential \
|
|
||||||
clang \
|
|
||||||
cmake \
|
|
||||||
ninja-build \
|
|
||||||
python3 \
|
|
||||||
python3-pip \
|
|
||||||
python3.12-venv \
|
|
||||||
qt6-base-dev \
|
|
||||||
qt6-positioning-dev \
|
|
||||||
libc++-dev \
|
|
||||||
libfreetype-dev \
|
|
||||||
libglvnd-dev \
|
|
||||||
libgl1-mesa-dev \
|
|
||||||
libharfbuzz-dev \
|
|
||||||
libicu-dev \
|
|
||||||
libqt6svg6-dev \
|
|
||||||
libqt6positioning6-plugins \
|
|
||||||
libqt6positioning6 \
|
|
||||||
libsqlite3-dev \
|
|
||||||
libxrandr-dev \
|
|
||||||
libxinerama-dev \
|
|
||||||
libxcursor-dev \
|
|
||||||
libxi-dev \
|
|
||||||
zlib1g-dev
|
|
||||||
- name: Clone repo if necessary
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
if [ ! -d /media/4tbexternal/comaps-init ]; then
|
|
||||||
cd /media/4tbexternal
|
|
||||||
git clone --recurse-submodules --shallow-submodules -b rebase-generator-pastk-wb251014 --single-branch https://codeberg.org/comaps/comaps.git comaps-init
|
|
||||||
fi
|
|
||||||
- name: Make output folders if necessary
|
- name: Make output folders if necessary
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
if [ ! -d /media/4tbexternal/osm-maps ]; then
|
if [ ! -d /mnt/4tbexternal/osm-maps ]; then
|
||||||
mkdir -p /media/4tbexternal/osm-maps
|
mkdir -p /mnt/4tbexternal/osm-maps
|
||||||
fi
|
fi
|
||||||
- name: Get SRTM if necessary
|
- name: Get SRTM if necessary
|
||||||
|
# TODO: it should be a separate step like Wiki or isolines
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
if [ ! -d /media/4tbexternal/osm-planet/SRTM-patched-europe/ ]; then
|
if [ ! -d /home/planet/SRTM-patched-europe/ ]; then
|
||||||
echo "ERROR: NO SRTM"
|
echo "ERROR: NO SRTM"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
- name: Symlink paths for repo scripts
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
mkdir -p /root/OM
|
|
||||||
ln -s /media/4tbexternal/comaps-init /root/OM/organicmaps
|
|
||||||
ln -s /media/4tbexternal/osm-planet /home/planet
|
|
||||||
ln -s /media/4tbexternal/osm-maps /root/OM/maps_build
|
|
||||||
- name: Run docker_maps_generator.sh
|
- name: Run docker_maps_generator.sh
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
cd /root/OM/organicmaps
|
cd ~/comaps
|
||||||
./tools/unix/docker_maps_generator.sh
|
bash ./tools/unix/maps/docker_maps_generator.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=Generator is done!'
|
||||||
|
|
||||||
|
upload-maps:
|
||||||
|
if: inputs.jobs == 'upload'
|
||||||
|
name: Upload Maps
|
||||||
|
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 }}-map-generator-${{ github.event.pull_request.number || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
steps:
|
||||||
|
- name: Write config file
|
||||||
|
run: |
|
||||||
|
mkdir -p ~/.config/rclone/
|
||||||
|
echo "${{ secrets.RCLONE_CONF }}" > ~/.config/rclone/rclone.conf
|
||||||
|
- name: Upload map files to CDNs
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
shopt -s nullglob
|
||||||
|
buildfolder=$(find /mnt/4tbexternal/osm-maps/ -mindepth 1 -maxdepth 1 -iname "2*" -type d | sort -n -r | head -1 | cut -d/ -f5)
|
||||||
|
builddate=$(find /mnt/4tbexternal/osm-maps/*/ -mindepth 1 -maxdepth 1 -iname "2*" -type d | sort -n -r | head -1 | cut -d/ -f6)
|
||||||
|
mwmfiles=( /mnt/4tbexternal/osm-maps/$buildfolder/$builddate/*.mwm )
|
||||||
|
|
||||||
|
if (( ${#mwmfiles[@]} )); then
|
||||||
|
echo "<$(date +%T)> Uploading maps from $buildfolder/$builddate..."
|
||||||
|
cd ~/comaps/tools/unix/maps
|
||||||
|
./upload_to_cdn.sh /mnt/4tbexternal/osm-maps/$buildfolder/$builddate
|
||||||
|
echo "<$(date +%T)> Finished uploading maps from $buildfolder/$builddate."
|
||||||
|
else
|
||||||
|
echo "<$(date +%T)> No MWM files in /mnt/4tbexternal/osm-maps/$buildfolder/$builddate/*.mwm, not uploading maps."
|
||||||
|
echo "<$(date +%T)> Found top level: $(ls -alt /mnt/4tbexternal/osm-maps/*)"
|
||||||
|
echo "<$(date +%T)> Found second level: $(ls -alt /mnt/4tbexternal/osm-maps/$buildfolder/*)"
|
||||||
|
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=Upload is done!'
|
||||||
|
|
||||||
|
|
||||||
1
.gitignore
vendored
@@ -9,6 +9,7 @@ Makefile.Release
|
|||||||
object_script.*.Debug
|
object_script.*.Debug
|
||||||
object_script.*.Release
|
object_script.*.Release
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
|
*.local.*
|
||||||
|
|
||||||
stxxl.errlog
|
stxxl.errlog
|
||||||
stxxl.log
|
stxxl.log
|
||||||
|
|||||||
@@ -175,10 +175,10 @@ if (NOT PLATFORM_IPHONE AND NOT PLATFORM_ANDROID)
|
|||||||
find_package(Qt6 COMPONENTS REQUIRED ${qt_components} PATHS $ENV{QT_PATH} /opt/homebrew/opt/qt@6 /usr/local/opt/qt@6 /usr/lib/x86_64-linux-gnu/qt6)
|
find_package(Qt6 COMPONENTS REQUIRED ${qt_components} PATHS $ENV{QT_PATH} /opt/homebrew/opt/qt@6 /usr/local/opt/qt@6 /usr/lib/x86_64-linux-gnu/qt6)
|
||||||
|
|
||||||
set(MINIMUM_REQUIRED_QT_VERSION 6.4.0)
|
set(MINIMUM_REQUIRED_QT_VERSION 6.4.0)
|
||||||
if (Qt6Widgets_VERSION VERSION_LESS ${MINIMUM_REQUIRED_QT_VERSION})
|
if (Qt6_VERSION VERSION_LESS ${MINIMUM_REQUIRED_QT_VERSION})
|
||||||
message(FATAL_ERROR "Unsupported Qt version: ${Qt6Widgets_VERSION}, the minimum required is ${MINIMUM_REQUIRED_QT_VERSION}")
|
message(FATAL_ERROR "Unsupported Qt version: ${Qt6_VERSION}, the minimum required is ${MINIMUM_REQUIRED_QT_VERSION}")
|
||||||
else()
|
else()
|
||||||
message(STATUS "Found Qt version: ${Qt6Widgets_VERSION}")
|
message(STATUS "Found Qt version: ${Qt6_VERSION}")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -222,6 +222,11 @@ 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()
|
||||||
|
|
||||||
|
# Android fails to find boost in many cases, this fixes it.
|
||||||
|
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)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
En fællesskabdrevet og åben source kortapp, baseret på kortdata fra OpenStreetMap og styrket i forpligtelsen til værdierne gennemsigtighed, privatlivets fred, og non-profit. CoMaps udspringer af Organic Maps, som selv udsprang af Maps.ME.
|
||||||
|
|
||||||
|
Læs mere om grundlaget for projektet og dets udviklingsretnign på <b><i>codeberg.org/comaps</i></b>.
|
||||||
|
Slut dig til fælleskabet og hjælp til med at bygge den bedste kortapp i verden.
|
||||||
|
• Brug appen og fortæl andre om den
|
||||||
|
• Giv feedback anmeld fejl
|
||||||
|
• Opdater kortdata i appen eller på OpenStreetMap-hjemmesiden.
|
||||||
|
|
||||||
|
‣ <b>Offlinefokuseret</b>: Planlæg din rute og find vej i udlandet uden brug af mobildata, søg og find afsidesliggende mål på en afsidesliggende vandretur, mm. Alle funktioner er designet til at fungere uden internetforbindelse.
|
||||||
|
‣ <b>Respekt for privatlivets fred</b>: Appen er designet med henblik på at respektere dit privatliv – den identificerer dig ikke, indeholder ingen sporingsmekanismer, og insamler ingen personlig information. Appen er reklamefri.
|
||||||
|
‣ <b>Enkel og elegant</b>: de essentielle funktioner er nemme at bruge, og de virker bare.
|
||||||
|
‣ <b>Sparer på batteriet og på lagerpladsen</b>: Dræner ikke dit batteri hurtigt, som andre kortapps. De kompakte kortfiler minimerer varigt lagerpladsforbrug.
|
||||||
|
‣ <b>Gratis og bygget i fællesskab</b>: Folk som dig har hjulpet med denne app ved at tilføje steder til OpenStreetMap, ved at teste appens funktioner og give feedback på dem og ved at bidrage til udviklingen af appen med deres tid og penge.
|
||||||
|
‣ <b>Åben og gennemsigtig beslutningstagningsproces og finanser, non-profit, og fuldt ud åben source.</b>
|
||||||
|
|
||||||
|
<b>Hovedfunktioner</b>
|
||||||
|
• Hent detaljerede kort, der indeholder steder som ikke findes i mange kommericelle kort.
|
||||||
|
• En frilufts-tilstand med markede vandrestier, teltpladser, kilder, bjerg- og bakketoppe, højdekonturlinjer, mm.
|
||||||
|
• Gangstier og cykelstier
|
||||||
|
• Steder, der kan besøges, som f.eks. restauranter, tankstationer, hoteller, butikker, seværdigheder og mange andre.
|
||||||
|
• Søg efter stednavn, adresse, eller type af sted.
|
||||||
|
• Gem dine yndlingssteder som bogmærker med et enkelt tryk.
|
||||||
|
• iCloud synkronisering af bogmærker og optagede spor.
|
||||||
|
• Offline artikler fra Wikipedia.
|
||||||
|
• Metro-lag med navigation.
|
||||||
|
• Optagelse af spor.
|
||||||
|
• Eksport og import af bogmærker og spor i formaterne KML, KMZ og GPX.
|
||||||
|
• Mørk tilstand til brug om natten.
|
||||||
|
• Mulighed for at forbedre kortet vha. en indbygget editor.
|
||||||
|
• CarPlay understøttes.
|
||||||
|
|
||||||
|
<b>Friheden er ankommet</b>
|
||||||
|
Opdag din rejse, find vej i verden med privatliv og fællesskab i førersædet!
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
• OpenStreetMap-Daten vom 4. November
|
• OpenStreetMap-Daten vom 16. November
|
||||||
• Aktualisierte Karten-Icons, inkl. Farben für Unterhaltungs-, Sport- & andere Unternehmen
|
• Bäume hinzugefügt
|
||||||
• Informationen zu Steckdosen an EV-Ladestationen
|
• Kleine Bushaltestellen-Icons die früher angezeigt werden
|
||||||
• Symbole für Sportzentren, Veranstaltungsorte, Massagesalons, Gästehäuser und einige stillgelegte Unternehmen
|
• Sichtbarkeit von Eingängen reduziert
|
||||||
• Verbesserungen bei der Suche
|
• Neue POI-Typen hinzugefügt
|
||||||
• Behebung eines Absturzes bei der Suche
|
• Sandflächen werden auf Karte angezeigt
|
||||||
• Verbesserte Sprachführung während der Navigation
|
• Option „Geschäft ist leerstehend” zum OSM-Editor hinzugefügt
|
||||||
Weitere Änderungen finden in unseren Codeberg-Versionshinweisen!
|
• Straßenbeschilderung in Europa verbessert
|
||||||
|
• Option „Asphaltierte Straßen vermeiden” hinzugefügt
|
||||||
|
• Icons in den Einstellungen hinzugefügt
|
||||||
|
Weitere Änderungen in unseren Codeberg-Versionshinweisen!
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 628 KiB After Width: | Height: | Size: 636 KiB |
|
Before Width: | Height: | Size: 532 KiB After Width: | Height: | Size: 407 KiB |
|
Before Width: | Height: | Size: 391 KiB After Width: | Height: | Size: 155 KiB |
|
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 454 KiB |
|
Before Width: | Height: | Size: 268 KiB After Width: | Height: | Size: 451 KiB |
|
Before Width: | Height: | Size: 263 KiB After Width: | Height: | Size: 357 KiB |
@@ -1,8 +1,11 @@
|
|||||||
• OpenStreetMap data as of November 4
|
• OpenStreetMap data as of November 16
|
||||||
• Recategorized map icons including some new colors for entertainment, sports and other businesses
|
• Added trees
|
||||||
• Display info about available sockets on charging stations
|
• Made bus stop icons smaller and show up earlier
|
||||||
• Added bandstands, backless benches and loungers
|
• Reduce visibility of entrances
|
||||||
• New icons for different sport centres, event venues, massage salons, guest houses and some disused businesses
|
• Added several other POI types
|
||||||
• Multiple search improvements and crash fix
|
• Show sand areas on the map
|
||||||
• Improved voice guidance during navigation
|
• Add business is vacant option to the OSM editor
|
||||||
|
• Improved road shields in Europe
|
||||||
|
• Avoid paved roads routing option
|
||||||
|
• Added icons to the settings page
|
||||||
Check our Codeberg release notes for more changes!
|
Check our Codeberg release notes for more changes!
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
• Datos OSM del 04/11
|
• Nuevos datos OSM a 16.11.25
|
||||||
• Iconos del mapa recategorizados, incluyendo nuevos colores
|
• Se añaden árboles
|
||||||
• Visualización de información sobre enchufes disponibles en estaciones de recarga
|
• Se reducen los iconos de paradas de autobús y aparecen antes
|
||||||
• Adición de iconos para diferentes centros deportivos, lugares de eventos, salones de masajes, posadas y algunos establecimientos comerciales desactivados
|
• Se reduce visibilidad de entradas
|
||||||
• Varias mejoras y correcciones de errores en la búsqueda
|
• Se añaden muchos tipos de puntos de interés
|
||||||
• Mejora en la orientación por voz durante la navegación
|
• Se muestran las zonas de arena en el mapa
|
||||||
|
• Se añade la opción «negocio vacío» al editor
|
||||||
|
• Se mejoran las señales de tráfico en Europa
|
||||||
|
• Nueva opción «evitar caminos asfaltadas»
|
||||||
|
• Nuevos iconos en la página de configuración
|
||||||
Más detalles en Codeberg
|
Más detalles en Codeberg
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 655 KiB After Width: | Height: | Size: 605 KiB |
|
Before Width: | Height: | Size: 532 KiB After Width: | Height: | Size: 407 KiB |
|
Before Width: | Height: | Size: 391 KiB After Width: | Height: | Size: 164 KiB |
|
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 452 KiB |
|
Before Width: | Height: | Size: 254 KiB After Width: | Height: | Size: 460 KiB |
|
Before Width: | Height: | Size: 263 KiB After Width: | Height: | Size: 355 KiB |
@@ -1,8 +1,11 @@
|
|||||||
• Données OpenStreetMap au 4 novembre
|
• Données OpenStreetMap du 16 novembre
|
||||||
• Recatégorisation des icônes sur la carte avec ajout de nouvelles couleurs pour certains types de lieux
|
• Ajout des arbres
|
||||||
• Affichage des prises sur les bornes électriques
|
• Les icônes des arrêts de bus sont plus petites et apparaissent plus tôt
|
||||||
• Ajout d'icônes pour les centres sportifs, salles d'événements, salon de massage et autres lieux
|
• Réduction de la visibilité des entrées
|
||||||
• Multiple améliorations dans la recherche
|
• Ajout de nouveaux types de POI
|
||||||
• Correction d'un plantage dans la recherche
|
• Affichage des zones de sable
|
||||||
• Amélioration de la synthèse vocale durant la navigation
|
• Nouveau bouton pour signaler un commerce vacant
|
||||||
|
• Amélioration des badges routiers en Europe
|
||||||
|
• Ajout d'une option pour éviter les routes pavées
|
||||||
|
• Ajout d'icônes dans les paramètres
|
||||||
Plus d'informations sur notre Codeberg
|
Plus d'informations sur notre Codeberg
|
||||||
|
|||||||
11
android/app/src/fdroid/play/listings/it-IT/release-notes.txt
Normal 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
|
||||||
@@ -1,7 +1,11 @@
|
|||||||
• Dados OSM de 04/11
|
• Dados OSM de 16/11
|
||||||
• Ícones do mapa recategorizados, incluindo novas cores
|
• Adição de árvores ao mapa
|
||||||
• Exibição de informações sobre tomadas disponíveis em eletropostos
|
• Ícones de pontos de ônibus menores e exibidos mais cedo
|
||||||
• Adição de ícones para diferentes centros esportivos, locais de eventos, salões de massagem, pousadas e alguns estabelecimentos comerciais desativados
|
• Visibilidade reduzida das entradas
|
||||||
• Diversas melhorias e correção de erro na busca
|
• Adição de diversos outros tipos de Pontos de Interesse
|
||||||
• Melhoria na orientação por voz durante a navegação
|
• Exibição de áreas de areia no mapa
|
||||||
Confira nossas notas de lançamento no Codeberg para mais detalhes!
|
• Adição de opção de "Estabelecimento vazio" ao editor do OSM
|
||||||
|
• Melhorias nas placas de rodovias na Europa
|
||||||
|
• 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!
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
• Карты OpenStreetMap от 4 ноября
|
• Карты OpenStreetMap от 16 ноября
|
||||||
• Обновлены цвета иконок на карте, добавлены новые цвета для развлечений, спорта, некоторых бизнесов
|
• Добавлены деревья и песчаные области
|
||||||
• На зарядных станциях показываются имеющиеся типы разъёмов
|
• Автобусные остановки показываются раньше, но маленькими иконами
|
||||||
• Добавлены эстрады, скамейки без спинок и лежаки
|
• Входы разделены по типам
|
||||||
• Новые иконки для разных спорт центров, массажных салонов, гостевых домов, некоторых закрытых бизнесов
|
• В OSM редакторе можно отметить место как неиспользуемое
|
||||||
• Несколько улучшений и исправлений в поиске
|
• Улучшения в иконках номеров дорог в Европе
|
||||||
• Улучшены голосовые подсказки при навигации
|
• Возможность избегать дорог с покрытием при построении маршрута
|
||||||
|
• Иконки в экране настроек
|
||||||
|
• На карту добавлены несколько новых типов объектов
|
||||||
Подробнее смотрите на codeberg.org/comaps/comaps/releases
|
Подробнее смотрите на codeberg.org/comaps/comaps/releases
|
||||||
|
|||||||
31
android/app/src/fdroid/play/listings/sl/full-description.txt
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
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.
|
||||||
|
|
||||||
|
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
|
||||||
|
• Uporabljajte orodje in širite glas o njem
|
||||||
|
• Dajajte povratne informacije in poročajte o napakah
|
||||||
|
• 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 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>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>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, nedobičkonosno in popolnoma odprtokodno.</b>
|
||||||
|
|
||||||
|
<b>Glavne zmogljivosti</b>:
|
||||||
|
• 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.
|
||||||
|
• Pešpoti in kolesarke poti
|
||||||
|
• Kraji zanimanja, npr. restavracije, bencinske črpalke, hoteli, trgovine, znamenitosti in mnogo več
|
||||||
|
• Iščite po imenu, hišnemu naslovu ali po vrsti
|
||||||
|
• Usmerjanje z glasovnimi obvestili za hojo, kolesarjenje ali vožnjo avtomobila.
|
||||||
|
• Zaznamujte svoje najljubše kraje s preprostim dotikom
|
||||||
|
• Wikipedijini članki brez povezave
|
||||||
|
• Prometna plast podzemne železnice z usmerjanjem
|
||||||
|
• Izvozite ali uvozite zaznamke in sledi v oblikah KML, KMZ, GPX
|
||||||
|
• Temni prikaz za uporabo ponoči
|
||||||
|
• Izboljšajtw podatke zemljevida za vse z uporabo vgrajenega urejevalnika
|
||||||
|
|
||||||
|
<b>Svoboda je tu</b>
|
||||||
|
Odkijte več o vašem potovanju, usmerjajte se po svetu s poudarkom na zasebnosti in skupnostnem delovanju!
|
||||||
11
android/app/src/fdroid/play/listings/sr/release-notes.txt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
• Подaци са OpenStreetMap-а закључно са 16. новембром
|
||||||
|
• Додате ознаке за дрвеће
|
||||||
|
• Смањене иконе аутобуских стајалишта и ранији приказ
|
||||||
|
• Смањена видљивост улаза
|
||||||
|
• Додато неколико нових типова ознака на мапу
|
||||||
|
• Приказ пешчаних површина на мапи
|
||||||
|
• Додата опција „пословни простор је празан“ у OSM едитору
|
||||||
|
• Побољшани путокази у Европи
|
||||||
|
• Опција рутирања „избегавај асфалтиране путеве“
|
||||||
|
• Додате иконе на страници подешавања
|
||||||
|
Погледајте детаље на Codeberg-у за списак свих промена!
|
||||||
1
android/app/src/fdroid/play/listings/sv-SE/title.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Comaps- Vandra, Cykla, Kör Offline, Privat
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
OpenStreetMap தரவை அடிப்படையாகக் கொண்ட சமூகம் தலைமையிலான இலவச மற்றும் திறந்த மூல வரைபட பயன்பாடு மற்றும் வெளிப்படைத்தன்மை, தனியுரிமை மற்றும் இலாப நோக்கற்றது ஆகியவற்றுக்கான அர்ப்பணிப்புடன் வலுவூட்டப்பட்டது. CoMaps என்பது ஆர்கானிக் மேப்சின் ஃபோர்க்/ச்பின்-ஆஃப் ஆகும், இது Maps.ME இன் ஃபோர்க் ஆகும்.
|
||||||
|
|
||||||
|
திட்டத்திற்கான காரணங்கள் மற்றும் அதன் திசையை <b><i>codeberg.org/comaps</i></b> இல் படிக்கவும்.
|
||||||
|
அங்குள்ள சமூகத்தில் சேர்ந்து சிறந்த வரைபட பயன்பாட்டை உருவாக்க உதவுங்கள்
|
||||||
|
• பயன்பாட்டைப் பயன்படுத்தி, அதைப் பற்றிய தகவலைப் பரப்புங்கள்
|
||||||
|
• கருத்துக்களை வழங்கவும் மற்றும் சிக்கல்களைப் புகாரளிக்கவும்
|
||||||
|
• பயன்பாட்டில் அல்லது OpenStreetMap இணையதளத்தில் வரைபடத் தரவைப் புதுப்பிக்கவும்
|
||||||
|
|
||||||
|
‣ <b>ஆஃப்லைனில் கவனம் செலுத்தப்பட்டது</b>: செல்லுலார் சேவையின் தேவையின்றி உங்களின் வெளிநாட்டுப் பயணத்தைத் திட்டமிட்டு வழிநடத்துங்கள், தொலைதூர பயணத்தில் இருக்கும் போது வழிப் புள்ளிகளைத் தேடுங்கள்.
|
||||||
|
‣ <b>தனியுரிமைக்கு மதிப்பளித்தல்</b>: பயன்பாடு தனியுரிமையை மனதில் கொண்டு வடிவமைக்கப்பட்டுள்ளது - நபர்களை அடையாளம் காணாது, கண்காணிக்காது மற்றும் தனிப்பட்ட தகவல்களைச் சேகரிக்காது. விளம்பரங்கள் இல்லாதது.
|
||||||
|
‣ <b>எளிமையான மற்றும் மெருகூட்டப்பட்டது</b>: செயல்படும் நற்பொருத்தங்கள் பயன்படுத்த எளிதானது.
|
||||||
|
‣ <b>உங்கள் பேட்டரி மற்றும் இடத்தைச் சேமிக்கிறது</b>: மற்ற வழிசெலுத்தல் பயன்பாடுகளைப் போல உங்கள் பேட்டரியை வெளியேற்றாது. சிறிய வரைபடங்கள் உங்கள் தொலைபேசியில் விலைமதிப்பற்ற இடத்தை சேமிக்கின்றன.
|
||||||
|
‣ <b>இலவசம் மற்றும் சமூகத்தால் உருவாக்கப்பட்டது</b>: OpenStreetMap இல் இடங்களைச் சேர்ப்பதன் மூலமும், சோதனை செய்து, அம்சங்களைப் பற்றிய கருத்துக்களை வழங்குவதன் மூலமும், அவர்களின் மேம்பாட்டுத் திறன்களையும் பணத்தையும் பங்களிப்பதன் மூலமும் உங்களைப் போன்றவர்கள் பயன்பாட்டை உருவாக்க உதவியுள்ளனர்.
|
||||||
|
‣ <b>திறந்த மற்றும் வெளிப்படையான முடிவெடுக்கும் மற்றும் நிதியியல், இலாப நோக்கற்ற மற்றும் முழு திறந்த மூல.</b>
|
||||||
|
|
||||||
|
<b>முக்கிய அம்சங்கள்</b>:
|
||||||
|
• கூகுள் மேப்சில் இல்லாத இடங்களுடன் தரவிறக்கம் செய்யக்கூடிய விரிவான வரைபடங்கள்
|
||||||
|
• ஐகிங் பாதைகள், முகாம்கள், நீர் ஆதாரங்கள், சிகரங்கள், விளிம்பு கோடுகள் போன்றவற்றைக் கொண்ட வெளிப்புறப் பயன்முறை
|
||||||
|
• நடைபாதைகள் மற்றும் சைக்கிள் பாதைகள்
|
||||||
|
• உணவகங்கள், எரிவாயு நிலையங்கள், ஓட்டல்கள், கடைகள், சுற்றிப்பார்க்கும் இடங்கள் மற்றும் பல போன்ற ஆர்வமுள்ள இடங்கள்
|
||||||
|
• பெயர் அல்லது முகவரி அல்லது ஆர்வமுள்ள வகை மூலம் தேடவும்
|
||||||
|
• நடைபயிற்சி, சைக்கிள் ஓட்டுதல் அல்லது வண்டி ஓட்டுவதற்கான குரல் அறிவிப்புகளுடன் வழிசெலுத்தல்
|
||||||
|
• ஒரே தட்டினால் உங்களுக்குப் பிடித்த இடங்களை புத்தகக்குறி செய்யவும்
|
||||||
|
• இணைப்பில்லாத விக்கிபீடியா கட்டுரைகள்
|
||||||
|
• சுரங்கப்பாதை போக்குவரத்து அடுக்கு மற்றும் திசைகள்
|
||||||
|
• ட்ராக் ரெக்கார்டிங்
|
||||||
|
• KML, KMZ, GPX வடிவங்களில் புக்மார்க்குகள் மற்றும் டிராக்குகளை ஏற்றுமதி மற்றும் இறக்குமதி செய்யுங்கள்
|
||||||
|
• இரவில் பயன்படுத்த ஒரு இருண்ட பயன்முறை
|
||||||
|
• அடிப்படை உள்ளமைக்கப்பட்ட எடிட்டரைப் பயன்படுத்தி அனைவருக்கும் வரைபடத் தரவை மேம்படுத்தவும்
|
||||||
|
|
||||||
|
<b>சுதந்திரம் இங்கே உள்ளது</b>
|
||||||
|
உங்கள் பயணத்தைக் கண்டறியவும், தனியுரிமை மற்றும் சமூகத்தை முன்னணியில் கொண்டு உலகிற்கு செல்லவும்!
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
எளிய வழிகாட்டி - பயணத்தை மேலும் சுவாரசியமாக்க - சமூகத்தால் இயக்கப்படுகிறது
|
||||||
1
android/app/src/google/play/listings/sv-SE/title.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Comaps- Navigera Privat
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
எளிய வழிகாட்டி - பயணத்தை மேலும் சுவாரசியமாக்க - சமூகத்தால் இயக்கப்படுகிறது
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
package app.organicmaps.background;
|
package app.organicmaps.background;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.Build;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.work.Constraints;
|
import androidx.work.Constraints;
|
||||||
import androidx.work.ExistingWorkPolicy;
|
import androidx.work.ExistingWorkPolicy;
|
||||||
import androidx.work.NetworkType;
|
import androidx.work.NetworkType;
|
||||||
import androidx.work.OneTimeWorkRequest;
|
import androidx.work.OneTimeWorkRequest;
|
||||||
|
import androidx.work.OutOfQuotaPolicy;
|
||||||
import androidx.work.WorkManager;
|
import androidx.work.WorkManager;
|
||||||
import androidx.work.Worker;
|
import androidx.work.Worker;
|
||||||
import androidx.work.WorkerParameters;
|
import androidx.work.WorkerParameters;
|
||||||
@@ -35,7 +37,11 @@ public class OsmUploadWork extends Worker
|
|||||||
if (Editor.nativeHasSomethingToUpload() && OsmOAuth.isAuthorized())
|
if (Editor.nativeHasSomethingToUpload() && OsmOAuth.isAuthorized())
|
||||||
{
|
{
|
||||||
final Constraints c = new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build();
|
final Constraints c = new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build();
|
||||||
final OneTimeWorkRequest wr = new OneTimeWorkRequest.Builder(OsmUploadWork.class).setConstraints(c).build();
|
OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest.Builder(OsmUploadWork.class).setConstraints(c);
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
|
builder.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST);
|
||||||
|
}
|
||||||
|
final OneTimeWorkRequest wr = builder.build();
|
||||||
WorkManager.getInstance(context).beginUniqueWork("UploadOsmChanges", ExistingWorkPolicy.KEEP, wr).enqueue();
|
WorkManager.getInstance(context).beginUniqueWork("UploadOsmChanges", ExistingWorkPolicy.KEEP, wr).enqueue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,9 +18,7 @@ import androidx.fragment.app.FragmentManager;
|
|||||||
import app.organicmaps.MwmApplication;
|
import app.organicmaps.MwmApplication;
|
||||||
import app.organicmaps.R;
|
import app.organicmaps.R;
|
||||||
import app.organicmaps.SplashActivity;
|
import app.organicmaps.SplashActivity;
|
||||||
import app.organicmaps.sdk.util.Config;
|
|
||||||
import app.organicmaps.sdk.util.log.Logger;
|
import app.organicmaps.sdk.util.log.Logger;
|
||||||
import app.organicmaps.util.RtlUtils;
|
|
||||||
import com.google.android.material.appbar.MaterialToolbar;
|
import com.google.android.material.appbar.MaterialToolbar;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@@ -42,7 +40,6 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity
|
|||||||
{
|
{
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
EdgeToEdge.enable(this, SystemBarStyle.dark(Color.TRANSPARENT));
|
EdgeToEdge.enable(this, SystemBarStyle.dark(Color.TRANSPARENT));
|
||||||
RtlUtils.manageRtl(this);
|
|
||||||
if (!MwmApplication.from(this).getOrganicMaps().arePlatformAndCoreInitialized())
|
if (!MwmApplication.from(this).getOrganicMaps().arePlatformAndCoreInitialized())
|
||||||
{
|
{
|
||||||
final Intent intent = Objects.requireNonNull(getIntent());
|
final Intent intent = Objects.requireNonNull(getIntent());
|
||||||
|
|||||||
@@ -32,7 +32,8 @@ public class DrivingOptionsScreen extends BaseMapScreen
|
|||||||
new DrivingOption(RoadType.Dirty, R.string.avoid_unpaved),
|
new DrivingOption(RoadType.Dirty, R.string.avoid_unpaved),
|
||||||
new DrivingOption(RoadType.Ferry, R.string.avoid_ferry),
|
new DrivingOption(RoadType.Ferry, R.string.avoid_ferry),
|
||||||
new DrivingOption(RoadType.Motorway, R.string.avoid_motorways),
|
new DrivingOption(RoadType.Motorway, R.string.avoid_motorways),
|
||||||
new DrivingOption(RoadType.Steps, R.string.avoid_steps)};
|
new DrivingOption(RoadType.Steps, R.string.avoid_steps),
|
||||||
|
new DrivingOption(RoadType.Paved, R.string.avoid_paved)};
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private final Map<RoadType, Boolean> mInitialDrivingOptionsState = new HashMap<>();
|
private final Map<RoadType, Boolean> mInitialDrivingOptionsState = new HashMap<>();
|
||||||
|
|||||||
@@ -357,7 +357,7 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
|
|||||||
|
|
||||||
private MenuBottomSheetItem getCancelMenuItem()
|
private MenuBottomSheetItem getCancelMenuItem()
|
||||||
{
|
{
|
||||||
return new MenuBottomSheetItem(R.string.cancel, R.drawable.ic_cancel, () -> onCancelActionSelected(mSelectedItem));
|
return new MenuBottomSheetItem(R.string.cancel, R.drawable.ic_close, () -> onCancelActionSelected(mSelectedItem));
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ItemViewHolder extends BaseInnerViewHolder<CountryItem>
|
private class ItemViewHolder extends BaseInnerViewHolder<CountryItem>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import android.location.Location;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.view.ViewCompat;
|
import androidx.core.view.ViewCompat;
|
||||||
import app.organicmaps.MwmActivity;
|
import app.organicmaps.MwmActivity;
|
||||||
@@ -26,6 +27,10 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
|
|||||||
{
|
{
|
||||||
private static boolean sAutodownloadLocked;
|
private static boolean sAutodownloadLocked;
|
||||||
|
|
||||||
|
private static final int HIDE_THRESHOLD = 2;
|
||||||
|
// Default bundles (e.g., world/coasts). Used to approximate “user-downloaded” count.
|
||||||
|
private static final int DEFAULT_MAP_BASELINE = 2;
|
||||||
|
|
||||||
private final MwmActivity mActivity;
|
private final MwmActivity mActivity;
|
||||||
private final View mFrame;
|
private final View mFrame;
|
||||||
private final MaterialTextView mParent;
|
private final MaterialTextView mParent;
|
||||||
@@ -33,6 +38,7 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
|
|||||||
private final MaterialTextView mSize;
|
private final MaterialTextView mSize;
|
||||||
private final WheelProgressView mProgress;
|
private final WheelProgressView mProgress;
|
||||||
private final MaterialButton mButton;
|
private final MaterialButton mButton;
|
||||||
|
private final View mOfflineExplanation;
|
||||||
|
|
||||||
private int mStorageSubscriptionSlot;
|
private int mStorageSubscriptionSlot;
|
||||||
|
|
||||||
@@ -43,8 +49,10 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
|
|||||||
@Override
|
@Override
|
||||||
public void onStatusChanged(List<MapManager.StorageCallbackData> data)
|
public void onStatusChanged(List<MapManager.StorageCallbackData> data)
|
||||||
{
|
{
|
||||||
if (mCurrentCountry == null)
|
if (mCurrentCountry == null) {
|
||||||
|
updateOfflineExplanationVisibility();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (MapManager.StorageCallbackData item : data)
|
for (MapManager.StorageCallbackData item : data)
|
||||||
{
|
{
|
||||||
@@ -58,7 +66,7 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
|
|||||||
{
|
{
|
||||||
mCurrentCountry.update();
|
mCurrentCountry.update();
|
||||||
updateProgressState(false);
|
updateProgressState(false);
|
||||||
|
updateOfflineExplanationVisibility();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,6 +109,12 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
|
|||||||
return enqueued || progress || applying;
|
return enqueued || progress || applying;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateOfflineExplanationVisibility() {
|
||||||
|
if (mOfflineExplanation == null) return;
|
||||||
|
// hide once threshold reached; safe to call repeatedly.
|
||||||
|
app.organicmaps.util.UiUtils.showIf(MapManager.nativeGetDownloadedCount() < (DEFAULT_MAP_BASELINE + HIDE_THRESHOLD), mOfflineExplanation);
|
||||||
|
}
|
||||||
|
|
||||||
private void updateProgressState(boolean shouldAutoDownload)
|
private void updateProgressState(boolean shouldAutoDownload)
|
||||||
{
|
{
|
||||||
updateStateInternal(shouldAutoDownload);
|
updateStateInternal(shouldAutoDownload);
|
||||||
@@ -108,6 +122,8 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
|
|||||||
|
|
||||||
private void updateStateInternal(boolean shouldAutoDownload)
|
private void updateStateInternal(boolean shouldAutoDownload)
|
||||||
{
|
{
|
||||||
|
updateOfflineExplanationVisibility();
|
||||||
|
|
||||||
boolean showFrame =
|
boolean showFrame =
|
||||||
(mCurrentCountry != null && !mCurrentCountry.present && !RoutingController.get().isNavigating());
|
(mCurrentCountry != null && !mCurrentCountry.present && !RoutingController.get().isNavigating());
|
||||||
if (showFrame)
|
if (showFrame)
|
||||||
@@ -191,6 +207,9 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
|
|||||||
mProgress = controls.findViewById(R.id.wheel_downloader_progress);
|
mProgress = controls.findViewById(R.id.wheel_downloader_progress);
|
||||||
mButton = controls.findViewById(R.id.downloader_button);
|
mButton = controls.findViewById(R.id.downloader_button);
|
||||||
|
|
||||||
|
mOfflineExplanation = mFrame.findViewById(R.id.offline_explanation);
|
||||||
|
updateOfflineExplanationVisibility();
|
||||||
|
|
||||||
mProgress.setOnClickListener(v -> {
|
mProgress.setOnClickListener(v -> {
|
||||||
if (mCurrentCountry == null)
|
if (mCurrentCountry == null)
|
||||||
return;
|
return;
|
||||||
@@ -247,6 +266,7 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
|
|||||||
|
|
||||||
public void onResume()
|
public void onResume()
|
||||||
{
|
{
|
||||||
|
updateOfflineExplanationVisibility();
|
||||||
if (mStorageSubscriptionSlot == 0)
|
if (mStorageSubscriptionSlot == 0)
|
||||||
{
|
{
|
||||||
mStorageSubscriptionSlot = MapManager.nativeSubscribe(mStorageCallback);
|
mStorageSubscriptionSlot = MapManager.nativeSubscribe(mStorageCallback);
|
||||||
|
|||||||
@@ -153,6 +153,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
|
|||||||
private final Map<Metadata.MetadataType, View> mDetailsBlocks = new HashMap<>();
|
private final Map<Metadata.MetadataType, View> mDetailsBlocks = new HashMap<>();
|
||||||
private final Map<Metadata.MetadataType, View> mSocialMediaBlocks = new HashMap<>();
|
private final Map<Metadata.MetadataType, View> mSocialMediaBlocks = new HashMap<>();
|
||||||
private MaterialButton mReset;
|
private MaterialButton mReset;
|
||||||
|
private MaterialButton mDisused;
|
||||||
|
|
||||||
private EditorHostFragment mParent;
|
private EditorHostFragment mParent;
|
||||||
|
|
||||||
@@ -827,6 +828,8 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
|
|||||||
osmInfo.setMovementMethod(LinkMovementMethod.getInstance());
|
osmInfo.setMovementMethod(LinkMovementMethod.getInstance());
|
||||||
mReset = view.findViewById(R.id.reset);
|
mReset = view.findViewById(R.id.reset);
|
||||||
mReset.setOnClickListener(this);
|
mReset.setOnClickListener(this);
|
||||||
|
mDisused = view.findViewById(R.id.disused);
|
||||||
|
mDisused.setOnClickListener(this);
|
||||||
|
|
||||||
mDetailsBlocks.put(Metadata.MetadataType.FMD_OPEN_HOURS, blockOpeningHours);
|
mDetailsBlocks.put(Metadata.MetadataType.FMD_OPEN_HOURS, blockOpeningHours);
|
||||||
mDetailsBlocks.put(Metadata.MetadataType.FMD_PHONE_NUMBER, blockPhone);
|
mDetailsBlocks.put(Metadata.MetadataType.FMD_PHONE_NUMBER, blockPhone);
|
||||||
@@ -894,6 +897,8 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
|
|||||||
mParent.addLanguage();
|
mParent.addLanguage();
|
||||||
else if (id == R.id.reset)
|
else if (id == R.id.reset)
|
||||||
reset();
|
reset();
|
||||||
|
else if (id == R.id.disused)
|
||||||
|
placeDisused();
|
||||||
else if (id == R.id.block_outdoor_seating)
|
else if (id == R.id.block_outdoor_seating)
|
||||||
mOutdoorSeating.toggle();
|
mOutdoorSeating.toggle();
|
||||||
}
|
}
|
||||||
@@ -939,9 +944,12 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
|
|||||||
if (mParent.addingNewObject())
|
if (mParent.addingNewObject())
|
||||||
{
|
{
|
||||||
UiUtils.hide(mReset);
|
UiUtils.hide(mReset);
|
||||||
|
UiUtils.hide(mDisused);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mDisused.setVisibility(Editor.nativeCanMarkPlaceAsDisused() ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
if (Editor.nativeIsMapObjectUploaded())
|
if (Editor.nativeIsMapObjectUploaded())
|
||||||
{
|
{
|
||||||
mReset.setText(R.string.editor_place_doesnt_exist);
|
mReset.setText(R.string.editor_place_doesnt_exist);
|
||||||
@@ -1014,6 +1022,19 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
|
|||||||
dialogFragment.setTextSaveListener(this::commitPlaceDoesntExists);
|
dialogFragment.setTextSaveListener(this::commitPlaceDoesntExists);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void placeDisused()
|
||||||
|
{
|
||||||
|
new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
|
||||||
|
.setTitle(R.string.editor_mark_business_vacant_title)
|
||||||
|
.setMessage(R.string.editor_mark_business_vacant_description)
|
||||||
|
.setPositiveButton(R.string.editor_submit, (dlg, which) -> {
|
||||||
|
Editor.nativeMarkPlaceAsDisused();
|
||||||
|
mParent.processEditedFeatures();
|
||||||
|
})
|
||||||
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
private void commitPlaceDoesntExists(@NonNull String text)
|
private void commitPlaceDoesntExists(@NonNull String text)
|
||||||
{
|
{
|
||||||
Editor.nativePlaceDoesNotExist(text);
|
Editor.nativePlaceDoesNotExist(text);
|
||||||
|
|||||||
@@ -358,7 +358,7 @@ public class EditorHostFragment
|
|||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processEditedFeatures()
|
public void processEditedFeatures()
|
||||||
{
|
{
|
||||||
if (OsmOAuth.isAuthorized())
|
if (OsmOAuth.isAuthorized())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
package app.organicmaps.editor;
|
package app.organicmaps.editor;
|
||||||
|
|
||||||
|
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.LocaleListCompat;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import app.organicmaps.base.BaseMwmRecyclerFragment;
|
import app.organicmaps.base.BaseMwmRecyclerFragment;
|
||||||
import app.organicmaps.sdk.editor.Editor;
|
import app.organicmaps.sdk.editor.Editor;
|
||||||
@@ -11,6 +14,7 @@ import java.util.Collections;
|
|||||||
import java.util.Comparator;
|
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.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class LanguagesFragment extends BaseMwmRecyclerFragment<LanguagesAdapter>
|
public class LanguagesFragment extends BaseMwmRecyclerFragment<LanguagesAdapter>
|
||||||
@@ -32,10 +36,23 @@ public class LanguagesFragment extends BaseMwmRecyclerFragment<LanguagesAdapter>
|
|||||||
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<>();
|
||||||
|
|
||||||
|
Configuration config = requireContext().getResources().getConfiguration();
|
||||||
|
LocaleListCompat systemLocales = ConfigurationCompat.getLocales(config);
|
||||||
|
|
||||||
List<Language> languages = new ArrayList<>();
|
List<Language> languages = new ArrayList<>();
|
||||||
|
List<Language> systemLanguages = new ArrayList<>();
|
||||||
|
|
||||||
for (Language lang : Editor.nativeGetSupportedLanguages(false))
|
for (Language lang : Editor.nativeGetSupportedLanguages(false))
|
||||||
{
|
{
|
||||||
if (existingLanguages.contains(lang.code))
|
// Separately extract system languages
|
||||||
|
for (int i = 0; i < systemLocales.size(); i++)
|
||||||
|
{
|
||||||
|
Locale locale = systemLocales.get(i);
|
||||||
|
if (locale != null && locale.getLanguage().equals(lang.code))
|
||||||
|
systemLanguages.add(lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existingLanguages.contains(lang.code) || systemLanguages.contains(lang))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
languages.add(lang);
|
languages.add(lang);
|
||||||
@@ -43,6 +60,8 @@ 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);
|
||||||
|
|
||||||
return new LanguagesAdapter(this, languages.toArray(new Language[languages.size()]));
|
return new LanguagesAdapter(this, languages.toArray(new Language[languages.size()]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package app.organicmaps.editor;
|
package app.organicmaps.editor;
|
||||||
|
|
||||||
|
import android.content.res.ColorStateList;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -11,6 +12,7 @@ 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.appcompat.widget.SwitchCompat;
|
||||||
|
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;
|
||||||
import app.organicmaps.R;
|
import app.organicmaps.R;
|
||||||
@@ -381,6 +383,29 @@ class SimpleTimetableAdapter extends RecyclerView.Adapter<SimpleTimetableAdapter
|
|||||||
final boolean enable = mComplementItem != null && mComplementItem.weekdays.length != 0;
|
final boolean enable = mComplementItem != null && mComplementItem.weekdays.length != 0;
|
||||||
final String text = mFragment.getString(R.string.editor_time_add);
|
final String text = mFragment.getString(R.string.editor_time_add);
|
||||||
mAdd.setEnabled(enable);
|
mAdd.setEnabled(enable);
|
||||||
|
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(
|
||||||
|
mAdd.getContext(), R.color.base_accent),
|
||||||
|
ContextCompat.getColor(mAdd.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(
|
||||||
|
mAdd.getContext(),
|
||||||
|
UiUtils.getStyledResourceId(mAdd.getContext(), android.R.attr.textColorPrimaryInverse)),
|
||||||
|
ContextCompat.getColor(mAdd.getContext(), R.color.button_accent_text_disabled)
|
||||||
|
});
|
||||||
|
mAdd.setBackgroundTintList(bgButtonColor);
|
||||||
|
mAdd.setTextColor(textButtonColor);
|
||||||
mAdd.setText(enable ? text + " (" + TimeFormatUtils.formatWeekdays(mComplementItem) + ")" : text);
|
mAdd.setText(enable ? text + " (" + TimeFormatUtils.formatWeekdays(mComplementItem) + ")" : text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ import app.organicmaps.util.UiUtils;
|
|||||||
|
|
||||||
class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.SearchDataViewHolder>
|
class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.SearchDataViewHolder>
|
||||||
{
|
{
|
||||||
|
private static final int SHORT_HORIZON_CLOSE_MIN = 60;
|
||||||
|
private static final int SHORT_HORIZON_OPEN_MIN = 15;
|
||||||
|
|
||||||
private final SearchFragment mSearchFragment;
|
private final SearchFragment mSearchFragment;
|
||||||
@Nullable
|
@Nullable
|
||||||
private SearchResult[] mResults;
|
private SearchResult[] mResults;
|
||||||
@@ -149,41 +152,32 @@ class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.SearchDataViewHol
|
|||||||
{
|
{
|
||||||
final Resources resources = mSearchFragment.getResources();
|
final Resources resources = mSearchFragment.getResources();
|
||||||
|
|
||||||
switch (result.description.openNow)
|
if (result.description.openNow != SearchResult.OPEN_NOW_YES && result.description.openNow != SearchResult.OPEN_NOW_NO)
|
||||||
{
|
{
|
||||||
case SearchResult.OPEN_NOW_YES ->
|
// Hide if unknown opening hours state
|
||||||
{
|
UiUtils.hide(mOpen);
|
||||||
if (result.description.minutesUntilClosed < 60) // less than 1 hour
|
return;
|
||||||
{
|
}
|
||||||
final String time = result.description.minutesUntilClosed + " " + resources.getString(R.string.minute);
|
|
||||||
final String string = resources.getString(R.string.closes_in, time);
|
|
||||||
|
|
||||||
UiUtils.setTextAndShow(mOpen, string);
|
final boolean isOpen = result.description.openNow == SearchResult.OPEN_NOW_YES;
|
||||||
|
final int minsToNextState = isOpen ? result.description.minutesUntilClosed : result.description.minutesUntilOpen;
|
||||||
|
|
||||||
|
final boolean shortHorizonClosing = isOpen && minsToNextState >= 0 && minsToNextState <= SHORT_HORIZON_CLOSE_MIN;
|
||||||
|
final boolean shortHorizonOpening = !isOpen && minsToNextState >= 0 && minsToNextState <= SHORT_HORIZON_OPEN_MIN;
|
||||||
|
|
||||||
|
if (shortHorizonClosing || shortHorizonOpening)
|
||||||
|
{
|
||||||
|
final String minsToChangeStr = resources.getQuantityString(
|
||||||
|
R.plurals.minutes_short, Math.max(minsToNextState, 1), Math.max(minsToNextState, 1));
|
||||||
|
final String nextChangeFormatted = resources.getString(isOpen ? R.string.closes_in : R.string.opens_in, minsToChangeStr);
|
||||||
|
|
||||||
|
UiUtils.setTextAndShow(mOpen, nextChangeFormatted);
|
||||||
mOpen.setTextColor(ContextCompat.getColor(mSearchFragment.getContext(), R.color.base_yellow));
|
mOpen.setTextColor(ContextCompat.getColor(mSearchFragment.getContext(), R.color.base_yellow));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UiUtils.setTextAndShow(mOpen, resources.getString(R.string.editor_time_open));
|
UiUtils.setTextAndShow(mOpen, isOpen ? resources.getString(R.string.editor_time_open) : resources.getString(R.string.closed));
|
||||||
mOpen.setTextColor(ContextCompat.getColor(mSearchFragment.getContext(), R.color.base_green));
|
mOpen.setTextColor(ContextCompat.getColor(mSearchFragment.getContext(), isOpen ? R.color.base_green : R.color.base_red));
|
||||||
}
|
|
||||||
}
|
|
||||||
case SearchResult.OPEN_NOW_NO ->
|
|
||||||
{
|
|
||||||
if (result.description.minutesUntilOpen < 60) // less than 1 hour
|
|
||||||
{
|
|
||||||
final String time = result.description.minutesUntilOpen + " " + resources.getString(R.string.minute);
|
|
||||||
final String string = resources.getString(R.string.opens_in, time);
|
|
||||||
|
|
||||||
UiUtils.setTextAndShow(mOpen, string);
|
|
||||||
mOpen.setTextColor(ContextCompat.getColor(mSearchFragment.getContext(), R.color.base_red));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UiUtils.setTextAndShow(mOpen, resources.getString(R.string.closed));
|
|
||||||
mOpen.setTextColor(ContextCompat.getColor(mSearchFragment.getContext(), R.color.base_red));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default -> UiUtils.hide(mOpen);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,28 +90,36 @@ public class DrivingOptionsFragment extends BaseMwmToolbarFragment
|
|||||||
{
|
{
|
||||||
SwitchCompat 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);
|
CompoundButton.OnCheckedChangeListener tollBtnListener = new ToggleRoutingOptionListener(RoadType.Toll, root);
|
||||||
tollsBtn.setOnCheckedChangeListener(tollBtnListener);
|
tollsBtn.setOnCheckedChangeListener(tollBtnListener);
|
||||||
|
|
||||||
SwitchCompat 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 = new ToggleRoutingOptionListener(RoadType.Motorway);
|
CompoundButton.OnCheckedChangeListener motorwayBtnListener =
|
||||||
|
new ToggleRoutingOptionListener(RoadType.Motorway, root);
|
||||||
motorwaysBtn.setOnCheckedChangeListener(motorwayBtnListener);
|
motorwaysBtn.setOnCheckedChangeListener(motorwayBtnListener);
|
||||||
|
|
||||||
SwitchCompat 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);
|
CompoundButton.OnCheckedChangeListener ferryBtnListener = new ToggleRoutingOptionListener(RoadType.Ferry, root);
|
||||||
ferriesBtn.setOnCheckedChangeListener(ferryBtnListener);
|
ferriesBtn.setOnCheckedChangeListener(ferryBtnListener);
|
||||||
|
|
||||||
SwitchCompat 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));
|
||||||
CompoundButton.OnCheckedChangeListener dirtyBtnListener = new ToggleRoutingOptionListener(RoadType.Dirty);
|
dirtyRoadsBtn.setEnabled(!RoutingOptions.hasOption(RoadType.Paved) || RoutingOptions.hasOption(RoadType.Dirty));
|
||||||
|
CompoundButton.OnCheckedChangeListener dirtyBtnListener = new ToggleRoutingOptionListener(RoadType.Dirty, root);
|
||||||
dirtyRoadsBtn.setOnCheckedChangeListener(dirtyBtnListener);
|
dirtyRoadsBtn.setOnCheckedChangeListener(dirtyBtnListener);
|
||||||
|
|
||||||
SwitchCompat 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);
|
CompoundButton.OnCheckedChangeListener stepsBtnListener = new ToggleRoutingOptionListener(RoadType.Steps, root);
|
||||||
stepsBtn.setOnCheckedChangeListener(stepsBtnListener);
|
stepsBtn.setOnCheckedChangeListener(stepsBtnListener);
|
||||||
|
|
||||||
|
SwitchCompat pavedBtn = root.findViewById(R.id.avoid_paved_roads_btn);
|
||||||
|
pavedBtn.setChecked(RoutingOptions.hasOption(RoadType.Paved));
|
||||||
|
pavedBtn.setEnabled(!RoutingOptions.hasOption(RoadType.Dirty) || RoutingOptions.hasOption(RoadType.Paved));
|
||||||
|
CompoundButton.OnCheckedChangeListener pavedBtnListener = new ToggleRoutingOptionListener(RoadType.Paved, root);
|
||||||
|
pavedBtn.setOnCheckedChangeListener(pavedBtnListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ToggleRoutingOptionListener implements CompoundButton.OnCheckedChangeListener
|
private static class ToggleRoutingOptionListener implements CompoundButton.OnCheckedChangeListener
|
||||||
@@ -119,9 +127,13 @@ public class DrivingOptionsFragment extends BaseMwmToolbarFragment
|
|||||||
@NonNull
|
@NonNull
|
||||||
private final RoadType mRoadType;
|
private final RoadType mRoadType;
|
||||||
|
|
||||||
private ToggleRoutingOptionListener(@NonNull RoadType roadType)
|
@NonNull
|
||||||
|
private final View mRoot;
|
||||||
|
|
||||||
|
private ToggleRoutingOptionListener(@NonNull RoadType roadType, @NonNull View root)
|
||||||
{
|
{
|
||||||
mRoadType = roadType;
|
mRoadType = roadType;
|
||||||
|
mRoot = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -131,6 +143,27 @@ public class DrivingOptionsFragment extends BaseMwmToolbarFragment
|
|||||||
RoutingOptions.addOption(mRoadType);
|
RoutingOptions.addOption(mRoadType);
|
||||||
else
|
else
|
||||||
RoutingOptions.removeOption(mRoadType);
|
RoutingOptions.removeOption(mRoadType);
|
||||||
|
|
||||||
|
SwitchCompat dirtyRoadsBtn = mRoot.findViewById(R.id.avoid_dirty_roads_btn);
|
||||||
|
SwitchCompat pavedBtn = mRoot.findViewById(R.id.avoid_paved_roads_btn);
|
||||||
|
if (mRoadType == RoadType.Dirty)
|
||||||
|
{
|
||||||
|
pavedBtn.setEnabled(!isChecked);
|
||||||
|
if (isChecked)
|
||||||
|
{
|
||||||
|
pavedBtn.setChecked(false);
|
||||||
|
dirtyRoadsBtn.setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mRoadType == RoadType.Paved)
|
||||||
|
{
|
||||||
|
dirtyRoadsBtn.setEnabled(!isChecked);
|
||||||
|
if (isChecked)
|
||||||
|
{
|
||||||
|
dirtyRoadsBtn.setChecked(false);
|
||||||
|
pavedBtn.setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
package app.organicmaps.util;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.view.View;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.core.text.TextUtilsCompat;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
public class RtlUtils
|
|
||||||
{
|
|
||||||
private final static List<String> rtlLocalesWithTranslation = Arrays.asList("ar", "fa");
|
|
||||||
|
|
||||||
public static void manageRtl(@NonNull final Activity activity)
|
|
||||||
{
|
|
||||||
final String currentLanguage = Locale.getDefault().getLanguage();
|
|
||||||
final boolean isRTL =
|
|
||||||
TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL;
|
|
||||||
if (isRTL && rtlLocalesWithTranslation.contains(currentLanguage))
|
|
||||||
activity.getWindow().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
|
|
||||||
else
|
|
||||||
activity.getWindow().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package app.organicmaps.widget.placepage;
|
||||||
|
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.format.TextStyle;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public class OpenStateTextFormatter
|
||||||
|
{
|
||||||
|
private OpenStateTextFormatter() {}
|
||||||
|
|
||||||
|
static String formatHoursMinutes(int hour, int minute, boolean use24h)
|
||||||
|
{
|
||||||
|
if (use24h)
|
||||||
|
return String.format(Locale.ROOT, "%02d:%02d", hour, minute);
|
||||||
|
|
||||||
|
int h = hour % 12;
|
||||||
|
if (h == 0) h = 12;
|
||||||
|
String ampm = (hour < 12) ? "AM" : "PM";
|
||||||
|
return String.format(Locale.ROOT, "%d:%02d %s", h, minute, ampm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isSameLocalDate(ZonedDateTime a, ZonedDateTime b)
|
||||||
|
{
|
||||||
|
return a.toLocalDate().isEqual(b.toLocalDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
static String dayShort(ZonedDateTime t, Locale locale)
|
||||||
|
{
|
||||||
|
return t.getDayOfWeek().getDisplayName(TextStyle.SHORT, locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
static String buildAtLabel(
|
||||||
|
boolean opens,
|
||||||
|
boolean isToday,
|
||||||
|
String dayShort,
|
||||||
|
String time,
|
||||||
|
String opensAtLocalized,
|
||||||
|
String closesAtLocalized,
|
||||||
|
String opensDayAtLocalized,
|
||||||
|
String closesDayAtLocalized
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (isToday)
|
||||||
|
return opens ? String.format(Locale.ROOT, opensAtLocalized, time) // Opens at %s
|
||||||
|
: String.format(Locale.ROOT, closesAtLocalized, time); // Closes at %s
|
||||||
|
return opens ? String.format(Locale.ROOT, opensDayAtLocalized, dayShort, time) // Opens %s at %s
|
||||||
|
: String.format(Locale.ROOT, closesDayAtLocalized, dayShort, time); // Closes %s at %s
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,6 +31,8 @@ import androidx.fragment.app.FragmentFactory;
|
|||||||
import androidx.fragment.app.FragmentManager;
|
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;
|
||||||
@@ -85,9 +87,11 @@ import com.google.android.material.textview.MaterialTextView;
|
|||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.format.TextStyle;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
public class PlacePageView extends Fragment
|
public class PlacePageView extends Fragment
|
||||||
implements View.OnClickListener, View.OnLongClickListener, LocationListener, SensorListener, Observer<MapObject>,
|
implements View.OnClickListener, View.OnLongClickListener, LocationListener, SensorListener, Observer<MapObject>,
|
||||||
@@ -105,6 +109,9 @@ public class PlacePageView extends Fragment
|
|||||||
private static final String LINKS_FRAGMENT_TAG = "LINKS_FRAGMENT_TAG";
|
private static final String LINKS_FRAGMENT_TAG = "LINKS_FRAGMENT_TAG";
|
||||||
private static final String TRACK_SHARE_MENU_ID = "TRACK_SHARE_MENU_ID";
|
private static final String TRACK_SHARE_MENU_ID = "TRACK_SHARE_MENU_ID";
|
||||||
|
|
||||||
|
private static final int SHORT_HORIZON_CLOSE_MIN = 60;
|
||||||
|
private static final int SHORT_HORIZON_OPEN_MIN = 15;
|
||||||
|
|
||||||
private static final List<CoordinatesFormat> visibleCoordsFormat =
|
private static final List<CoordinatesFormat> visibleCoordsFormat =
|
||||||
Arrays.asList(CoordinatesFormat.LatLonDMS, CoordinatesFormat.LatLonDecimal, CoordinatesFormat.OLCFull,
|
Arrays.asList(CoordinatesFormat.LatLonDMS, CoordinatesFormat.LatLonDecimal, CoordinatesFormat.OLCFull,
|
||||||
CoordinatesFormat.UTM, CoordinatesFormat.MGRS, CoordinatesFormat.OSMLink);
|
CoordinatesFormat.UTM, CoordinatesFormat.MGRS, CoordinatesFormat.OSMLink);
|
||||||
@@ -797,8 +804,13 @@ public class PlacePageView extends Fragment
|
|||||||
final String ohStr = mMapObject.getMetadata(Metadata.MetadataType.FMD_OPEN_HOURS);
|
final String ohStr = mMapObject.getMetadata(Metadata.MetadataType.FMD_OPEN_HOURS);
|
||||||
final Timetable[] timetables = OpeningHours.nativeTimetablesFromString(ohStr);
|
final Timetable[] timetables = OpeningHours.nativeTimetablesFromString(ohStr);
|
||||||
|
|
||||||
if (timetables != null && timetables.length != 0)
|
// No valid timetable
|
||||||
|
if (timetables == null || timetables.length == 0)
|
||||||
{
|
{
|
||||||
|
UiUtils.hide(mTvOpenState);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final Context context = requireContext();
|
final Context context = requireContext();
|
||||||
final OhState poiState = OpeningHours.nativeCurrentState(timetables);
|
final OhState poiState = OpeningHours.nativeCurrentState(timetables);
|
||||||
|
|
||||||
@@ -820,34 +832,99 @@ public class PlacePageView extends Fragment
|
|||||||
final SpannableStringBuilder openStateString = new SpannableStringBuilder();
|
final SpannableStringBuilder openStateString = new SpannableStringBuilder();
|
||||||
final boolean isOpen = (poiState.state == OhState.State.Open); // False == Closed due to early exit for Unknown
|
final boolean isOpen = (poiState.state == OhState.State.Open); // False == Closed due to early exit for Unknown
|
||||||
final long nextStateTime = isOpen ? poiState.nextTimeClosed : poiState.nextTimeOpen; // Unix time (seconds)
|
final long nextStateTime = isOpen ? poiState.nextTimeClosed : poiState.nextTimeOpen; // Unix time (seconds)
|
||||||
final int minsToNextState = (int) ((nextStateTime - (System.currentTimeMillis() / 1000)) / 60);
|
|
||||||
|
|
||||||
if (minsToNextState <= 60) // POI opens/closes in 60 mins
|
ZonedDateTime nextChangeLocal = null;
|
||||||
|
boolean hasFiniteNextChange = false;
|
||||||
|
|
||||||
|
final long nowSec = System.currentTimeMillis() / 1000;
|
||||||
|
final int minsToNextState = (int) ((nextStateTime - nowSec) / 60);
|
||||||
|
|
||||||
|
// Try to resolve a finite next-change time; handle 24/7 case
|
||||||
|
final boolean looksLike247 = "24/7".equals(ohStr.trim());
|
||||||
|
final int ONE_WEEK_MIN = 7 * 24 * 60;
|
||||||
|
final boolean noRealNextChange = looksLike247 || minsToNextState >= ONE_WEEK_MIN;
|
||||||
|
|
||||||
|
if (!noRealNextChange)
|
||||||
{
|
{
|
||||||
final String minsToChangeStr = minsToNextState + " " + getString(R.string.minute);
|
try
|
||||||
final String nextChangeFormatted = getString(isOpen ? R.string.closes_in : R.string.opens_in, minsToChangeStr);
|
{
|
||||||
final ForegroundColorSpan nextChangeColor = isOpen ? colorYellow : colorRed;
|
if (nextStateTime > 0 && nextStateTime < Long.MAX_VALUE / 2)
|
||||||
// TODO: We should check closed/open time for specific feature's timezone.
|
{
|
||||||
ZonedDateTime time = ZonedDateTime.ofInstant(Instant.ofEpochSecond(nextStateTime), ZoneId.systemDefault());
|
// NOTE: Timezone is currently device timezone. TODO: use feature-specific timezone.
|
||||||
String localizedTime =
|
nextChangeLocal = ZonedDateTime.ofInstant(
|
||||||
new HoursMinutes(time.getHour(), time.getMinute(), DateUtils.is24HourFormat(context)).toString();
|
Instant.ofEpochSecond(nextStateTime), ZoneId.systemDefault()
|
||||||
|
);
|
||||||
openStateString.append(nextChangeFormatted, nextChangeColor, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
hasFiniteNextChange = true;
|
||||||
.append(" • ") // Add spacer
|
|
||||||
.append(getString(R.string.at, localizedTime));
|
|
||||||
}
|
}
|
||||||
else if (isOpen)
|
}
|
||||||
|
catch (Throwable ignored) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasFiniteNextChange) // No valid next change
|
||||||
|
{
|
||||||
|
if (isOpen)
|
||||||
openStateString.append(getString(R.string.open_now), colorGreen, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
openStateString.append(getString(R.string.open_now), colorGreen, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
// TODO: Add "Closes at 18:00" etc
|
else
|
||||||
else // Closed
|
|
||||||
openStateString.append(getString(R.string.closed_now), colorRed, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
openStateString.append(getString(R.string.closed_now), colorRed, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
// TODO: Add "Opens at 18:00" etc
|
|
||||||
|
|
||||||
UiUtils.setTextAndHideIfEmpty(mTvOpenState, openStateString);
|
UiUtils.setTextAndHideIfEmpty(mTvOpenState, openStateString);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// No valid timetable
|
|
||||||
UiUtils.hide(mTvOpenState);
|
String localizedTimeString = OpenStateTextFormatter.formatHoursMinutes(
|
||||||
|
nextChangeLocal.getHour(), nextChangeLocal.getMinute(), DateUtils.is24HourFormat(context));
|
||||||
|
|
||||||
|
final boolean shortHorizonClosing = isOpen && minsToNextState >= 0 && minsToNextState <= SHORT_HORIZON_CLOSE_MIN;
|
||||||
|
final boolean shortHorizonOpening = !isOpen && minsToNextState >= 0 && minsToNextState <= SHORT_HORIZON_OPEN_MIN;
|
||||||
|
|
||||||
|
if (shortHorizonClosing || shortHorizonOpening) // POI Opens/Closes in 60 mins • at 18:00
|
||||||
|
{
|
||||||
|
final String minsToChangeStr = getResources().getQuantityString(
|
||||||
|
R.plurals.minutes_short, Math.max(minsToNextState, 1), Math.max(minsToNextState, 1));
|
||||||
|
final String nextChangeFormatted = getString(isOpen ? R.string.closes_in : R.string.opens_in, minsToChangeStr);
|
||||||
|
|
||||||
|
openStateString.append(nextChangeFormatted, colorYellow, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||||
|
.append(" • ") // Add spacer
|
||||||
|
.append(getString(R.string.at, localizedTimeString));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
final String opensAtStr = getString(R.string.opens_at); // "Opens at %s"
|
||||||
|
final String closesAtStr = getString(R.string.closes_at); // "Closes at %s"
|
||||||
|
final String opensDayAtStr = getString(R.string.opens_day_at); // "Opens %1$s at %2$s"
|
||||||
|
final String closesDayAtStr = getString(R.string.closes_day_at); // "Closes %1$s at %2$s"
|
||||||
|
|
||||||
|
final boolean isToday =
|
||||||
|
OpenStateTextFormatter.isSameLocalDate(nextChangeLocal, ZonedDateTime.now(nextChangeLocal.getZone()));
|
||||||
|
// Full weekday name per design feedback.
|
||||||
|
final String dayName =
|
||||||
|
nextChangeLocal.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.getDefault());
|
||||||
|
|
||||||
|
if (isOpen) // > 60 minutes OR negative (safety). Show “Open now • Closes at 18:00”
|
||||||
|
{
|
||||||
|
openStateString.append(getString(R.string.open_now), colorGreen, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
|
||||||
|
final String atLabel =
|
||||||
|
OpenStateTextFormatter.buildAtLabel(false, isToday, dayName, localizedTimeString,
|
||||||
|
opensAtStr, closesAtStr, opensDayAtStr, closesDayAtStr);
|
||||||
|
|
||||||
|
if (!TextUtils.isEmpty(atLabel))
|
||||||
|
openStateString.append(" • ").append(atLabel);
|
||||||
|
}
|
||||||
|
else // Closed
|
||||||
|
{
|
||||||
|
openStateString.append(getString(R.string.closed_now), colorRed, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
|
||||||
|
final String atLabel =
|
||||||
|
OpenStateTextFormatter.buildAtLabel(true, isToday, dayName, localizedTimeString,
|
||||||
|
opensAtStr, closesAtStr, opensDayAtStr, closesDayAtStr);
|
||||||
|
|
||||||
|
if (!TextUtils.isEmpty(atLabel))
|
||||||
|
openStateString.append(" • ").append(atLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UiUtils.setTextAndHideIfEmpty(mTvOpenState, openStateString);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addPlace()
|
private void addPlace()
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#717065" />
|
<solid android:color="#51585E" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#717065" />
|
<solid android:color="#51585E" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#7F5933" />
|
<solid android:color="#802D19" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#BB9342" />
|
<solid android:color="#8C491C" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#7F5933" />
|
<solid android:color="#802D19" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#8C5F93" />
|
<solid android:color="#6B425C" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#717065" />
|
<solid android:color="#574469" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#C15746" />
|
<solid android:color="#983E44" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#664E42" />
|
<solid android:color="#614A43" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#BB9342" />
|
<solid android:color="#8C491C" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#2E89B0" />
|
<solid android:color="#20607C" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#C15746" />
|
<solid android:color="#983E44" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#717065" />
|
<solid android:color="#51585E" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#717065" />
|
<solid android:color="#51585E" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#717065" />
|
<solid android:color="#51585E" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#717065" />
|
<solid android:color="#51585E" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#8C5F93" />
|
<solid android:color="#6B425C" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#8C5F93" />
|
<solid android:color="#6B425C" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#7F5933" />
|
<solid android:color="#51585E" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#7F5933" />
|
<solid android:color="#6E4426" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#717065" />
|
<solid android:color="#51585E" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
10
android/app/src/main/res/drawable/ic_browse_activity.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:pathData="M80,360v-160q0,-33 23.5,-56.5T160,120h640q33,0 56.5,23.5T880,200v160h-80v-160L160,200v160L80,360ZM160,720q-33,0 -56.5,-23.5T80,640v-200h80v200h640v-200h80v200q0,33 -23.5,56.5T800,720L160,720ZM40,840v-80h880v80L40,840ZM480,420ZM80,440v-80h240q11,0 21,6t15,16l47,93 123,-215q5,-9 14,-14.5t20,-5.5q11,0 21,5.5t15,16.5l49,98h235v80L620,440q-11,0 -21,-5.5T584,418l-26,-53 -123,215q-5,10 -15,15t-21,5q-11,0 -20.5,-6T364,578l-69,-138L80,440Z"
|
||||||
|
android:fillColor="#fff"/>
|
||||||
|
</vector>
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="960"
|
|
||||||
android:viewportHeight="960">
|
|
||||||
<path
|
|
||||||
android:fillColor="@android:color/white"
|
|
||||||
android:pathData="M480,536L284,732Q273,743 256,743Q239,743 228,732Q217,721 217,704Q217,687 228,676L424,480L228,284Q217,273 217,256Q217,239 228,228Q239,217 256,217Q273,217 284,228L480,424L676,228Q687,217 704,217Q721,217 732,228Q743,239 743,256Q743,273 732,284L536,480L732,676Q743,687 743,704Q743,721 732,732Q721,743 704,743Q687,743 676,732L480,536Z"/>
|
|
||||||
</vector>
|
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#9C6136" />
|
<solid android:color="#EB785D" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#9C6136" />
|
<solid android:color="#EB785D" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#747E86" />
|
<solid android:color="#AA96BC" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<size
|
<size
|
||||||
android:width="40dp"
|
android:width="40dp"
|
||||||
android:height="40dp" />
|
android:height="40dp" />
|
||||||
<solid android:color="#9C6136" />
|
<solid android:color="#747E86" />
|
||||||
</shape>
|
</shape>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:viewportHeight="24" android:viewportWidth="24"
|
android:width="24dp"
|
||||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
android:height="24dp"
|
||||||
<path android:fillColor="@android:color/white" android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
|
android:tint="#FFFFFF"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M480,536L284,732Q273,743 256,743Q239,743 228,732Q217,721 217,704Q217,687 228,676L424,480L228,284Q217,273 217,256Q217,239 228,228Q239,217 256,217Q273,217 284,228L480,424L676,228Q687,217 704,217Q721,217 732,228Q743,239 743,256Q743,273 732,284L536,480L732,676Q743,687 743,704Q743,721 732,732Q721,743 704,743Q687,743 676,732L480,536Z"/>
|
||||||
</vector>
|
</vector>
|
||||||
|
|||||||
10
android/app/src/main/res/drawable/ic_dark_mode.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:pathData="M480,840q-150,0 -255,-105T120,480q0,-150 105,-255t255,-105q14,0 27.5,1t26.5,3q-41,29 -65.5,75.5T444,300q0,90 63,153t153,63q55,0 101,-24.5t75,-65.5q2,13 3,26.5t1,27.5q0,150 -105,255T480,840ZM480,760q88,0 158,-48.5T740,585q-20,5 -40,8t-40,3q-123,0 -209.5,-86.5T364,300q0,-20 3,-40t8,-40q-78,32 -126.5,102T200,480q0,116 82,198t198,82ZM470,490Z"
|
||||||
|
android:fillColor="#fff"/>
|
||||||
|
</vector>
|
||||||
10
android/app/src/main/res/drawable/ic_download_st.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:pathData="M19,9h-4v-6h-6v6h-4l7,7 7,-7ZM5,18v2h14v-2h-14Z"
|
||||||
|
android:fillColor="#FFF"/>
|
||||||
|
</vector>
|
||||||
10
android/app/src/main/res/drawable/ic_eco.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:pathData="M216,784q-45,-45 -70.5,-104T120,558q0,-63 24,-124.5T222,318q35,-35 86.5,-60t122,-39.5Q501,204 591.5,201t202.5,7q8,106 5,195t-16.5,160.5q-13.5,71.5 -38,125T684,778q-53,53 -112.5,77.5T450,880q-65,0 -127,-25.5T216,784ZM328,768q29,17 59.5,24.5T450,800q46,0 91,-18.5t86,-59.5q18,-18 36.5,-50.5t32,-85Q709,534 716,459.5t2,-177.5q-49,-2 -110.5,-1.5T485,290q-61,9 -116,29t-90,55q-45,45 -62,89t-17,85q0,59 22.5,103.5T262,714q42,-80 111,-153.5T534,440q-72,63 -125.5,142.5T328,768ZM328,768ZM328,768Z"
|
||||||
|
android:fillColor="#fff"/>
|
||||||
|
</vector>
|
||||||
10
android/app/src/main/res/drawable/ic_instant_mix.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:pathData="M200,800v-280h-80v-80h240v80h-80v280h-80ZM200,360v-200h80v200h-80ZM360,360v-80h80v-120h80v120h80v80L360,360ZM440,800v-360h80v360h-80ZM680,800v-120h-80v-80h240v80h-80v120h-80ZM680,520v-360h80v360h-80Z"
|
||||||
|
android:fillColor="#fff"/>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:pathData="M280,920q-33,0 -56.5,-23.5T200,840v-720q0,-33 23.5,-56.5T280,40h400q33,0 56.5,23.5T760,120v124q18,7 29,22t11,34v80q0,19 -11,34t-29,22v404q0,33 -23.5,56.5T680,920L280,920ZM280,840h400v-720L280,120v720ZM280,840v-720,720ZM394,640h172q14,0 24,-10t10,-24v-132q0,-14 -10,-24t-24,-10h-6v-40q0,-33 -23.5,-56.5T480,320q-33,0 -56.5,23.5T400,400v40h-6q-14,0 -24,10t-10,24v132q0,14 10,24t24,10ZM440,440v-40q0,-17 11.5,-28.5T480,360q17,0 28.5,11.5T520,400v40h-80Z"
|
||||||
|
android:fillColor="#fff"/>
|
||||||
|
</vector>
|
||||||
10
android/app/src/main/res/drawable/ic_network_manage.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:pathData="M339,698q22,-22 49.5,-36t58.5,-19q-5,19 -8,38t-3,39q0,24 3.5,47t11.5,44L339,698ZM254,614 L170,528q62,-62 142,-95t168,-33q49,0 96,10.5t90,30.5q-44,8 -81.5,29T517,522q-9,-1 -18.5,-1.5T480,520q-64,0 -122.5,24.5T254,614ZM84,444 L0,360q95,-97 219.5,-148.5T480,160q136,0 260.5,51.5T960,360l-84,84q-79,-79 -181.5,-121.5T480,280q-112,0 -214.5,42.5T84,444ZM760,520 L772,580q12,5 22.5,10.5T816,604l58,-18 40,68 -46,40q2,12 2,26t-2,26l46,40 -40,68 -58,-18q-11,8 -21.5,13.5T772,860l-12,60h-80l-12,-60q-12,-5 -22.5,-10.5T624,836l-58,18 -40,-68 46,-40q-2,-12 -2,-26t2,-26l-46,-40 40,-68 58,18q11,-8 21.5,-13.5T668,580l12,-60h80ZM720,640q-33,0 -56.5,23.5T640,720q0,33 23.5,56.5T720,800q33,0 56.5,-23.5T800,720q0,-33 -23.5,-56.5T720,640Z"
|
||||||
|
android:fillColor="#fff"/>
|
||||||
|
</vector>
|
||||||
10
android/app/src/main/res/drawable/ic_profile.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:pathData="M480,480q-66,0 -113,-47t-47,-113q0,-66 47,-113t113,-47q66,0 113,47t47,113q0,66 -47,113t-113,47ZM160,800v-112q0,-34 17.5,-62.5T224,582q62,-31 126,-46.5T480,520q66,0 130,15.5T736,582q29,15 46.5,43.5T800,688v112L160,800ZM240,720h480v-32q0,-11 -5.5,-20T700,654q-54,-27 -109,-40.5T480,600q-56,0 -111,13.5T260,654q-9,5 -14.5,14t-5.5,20v32ZM480,400q33,0 56.5,-23.5T560,320q0,-33 -23.5,-56.5T480,240q-33,0 -56.5,23.5T400,320q0,33 23.5,56.5T480,400ZM480,320ZM480,720Z"
|
||||||
|
android:fillColor="#fff"/>
|
||||||
|
</vector>
|
||||||
10
android/app/src/main/res/drawable/ic_record_voice_over.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:pathData="m798,638 l-62,-62q44,-41 69,-97t25,-119q0,-63 -25,-118t-69,-96l62,-64q56,53 89,125t33,153q0,81 -33,153t-89,125ZM670,510l-64,-64q18,-17 29,-38.5t11,-47.5q0,-26 -11,-47.5T606,274l64,-64q32,29 50,67.5t18,82.5q0,44 -18,82.5T670,510ZM360,520q-66,0 -113,-47t-47,-113q0,-66 47,-113t113,-47q66,0 113,47t47,113q0,66 -47,113t-113,47ZM40,840v-112q0,-33 17,-62t47,-44q51,-26 115,-44t141,-18q77,0 141,18t115,44q30,15 47,44t17,62v112L40,840ZM120,760h480v-32q0,-11 -5.5,-20T580,694q-36,-18 -92.5,-36T360,640q-71,0 -127.5,18T140,694q-9,5 -14.5,14t-5.5,20v32ZM360,440q33,0 56.5,-23.5T440,360q0,-33 -23.5,-56.5T360,280q-33,0 -56.5,23.5T280,360q0,33 23.5,56.5T360,440ZM360,360ZM360,760Z"
|
||||||
|
android:fillColor="#fff"/>
|
||||||
|
</vector>
|
||||||
10
android/app/src/main/res/drawable/ic_sd_card.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:pathData="M360,440h80v-160h-80v160ZM480,440h80v-160h-80v160ZM600,440h80v-160h-80v160ZM240,880q-33,0 -56.5,-23.5T160,800v-480l240,-240h320q33,0 56.5,23.5T800,160v640q0,33 -23.5,56.5T720,880L240,880ZM240,800h480v-640L434,160L240,354v446ZM240,800h480,-480Z"
|
||||||
|
android:fillColor="#fff"/>
|
||||||
|
</vector>
|
||||||
10
android/app/src/main/res/drawable/ic_search_recent_st.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="?colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M13.26,3C8.17,2.86 4,6.95 4,12L2.21,12c-0.45,0 -0.67,0.54 -0.35,0.85l2.79,2.8c0.2,0.2 0.51,0.2 0.71,0l2.79,-2.8c0.31,-0.31 0.09,-0.85 -0.36,-0.85L6,12c0,-3.9 3.18,-7.05 7.1,-7 3.72,0.05 6.85,3.18 6.9,6.9 0.05,3.91 -3.1,7.1 -7,7.1 -1.61,0 -3.1,-0.55 -4.28,-1.48 -0.4,-0.31 -0.96,-0.28 -1.32,0.08 -0.42,0.42 -0.39,1.13 0.08,1.49C9,20.29 10.91,21 13,21c5.05,0 9.14,-4.17 9,-9.26 -0.13,-4.69 -4.05,-8.61 -8.74,-8.74zM12.75,8c-0.41,0 -0.75,0.34 -0.75,0.75v3.68c0,0.35 0.19,0.68 0.49,0.86l3.12,1.85c0.36,0.21 0.82,0.09 1.03,-0.26 0.21,-0.36 0.09,-0.82 -0.26,-1.03l-2.88,-1.71v-3.4c0,-0.4 -0.34,-0.74 -0.75,-0.74z"/>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:pathData="M480,560q-33,0 -56.5,-23.5T400,480q0,-33 23.5,-56.5T480,400q33,0 56.5,23.5T560,480q0,33 -23.5,56.5T480,560ZM480,840q-139,0 -241,-91.5T122,520h82q14,104 92.5,172T480,760q117,0 198.5,-81.5T760,480q0,-117 -81.5,-198.5T480,200q-69,0 -129,32t-101,88h110v80L120,400v-240h80v94q51,-64 124.5,-99T480,120q75,0 140.5,28.5t114,77q48.5,48.5 77,114T840,480q0,75 -28.5,140.5t-77,114q-48.5,48.5 -114,77T480,840Z"
|
||||||
|
android:fillColor="#fff"/>
|
||||||
|
</vector>
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:pathData="M2,20h20v-4h-20v4ZM4,17h2v2h-2v-2ZM2,4v4h20v-4h-20ZM6,7h-2v-2h2v2ZM2,14h20v-4h-20v4ZM4,11h2v2h-2v-2Z"
|
|
||||||
android:fillColor="#FFF"/>
|
|
||||||
</vector>
|
|
||||||
10
android/app/src/main/res/drawable/ic_straighten.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:pathData="M160,720q-33,0 -56.5,-23.5T80,640v-320q0,-33 23.5,-56.5T160,240h640q33,0 56.5,23.5T880,320v320q0,33 -23.5,56.5T800,720L160,720ZM160,640h640v-320L680,320v160h-80v-160h-80v160h-80v-160h-80v160h-80v-160L160,320v320ZM280,480h80,-80ZM440,480h80,-80ZM600,480h80,-80ZM480,480Z"
|
||||||
|
android:fillColor="#fff"/>
|
||||||
|
</vector>
|
||||||
10
android/app/src/main/res/drawable/ic_text_fields.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:pathData="M280,800v-520L80,280v-120h520v120L400,280v520L280,800ZM640,800v-320L520,480v-120h360v120L760,480v320L640,800Z"
|
||||||
|
android:fillColor="#fff"/>
|
||||||
|
</vector>
|
||||||
10
android/app/src/main/res/drawable/ic_three_d_rotation.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:pathData="M480,880q-83,0 -156,-31.5T197,763q-54,-54 -85.5,-127T80,480h80q0,115 72.5,203T418,794l-58,-58 56,-56L598,862q-29,10 -58.5,14T480,880ZM500,600v-240h120q17,0 28.5,11.5T660,400v160q0,17 -11.5,28.5T620,600L500,600ZM300,600v-60h100v-40h-60v-40h60v-40L300,420v-60h120q17,0 28.5,11.5T460,400v160q0,17 -11.5,28.5T420,600L300,600ZM560,540h40v-120h-40v120ZM800,480q0,-115 -72.5,-203T542,166l58,58 -56,56 -182,-182q29,-10 58.5,-14t59.5,-4q83,0 156,31.5T763,197q54,54 85.5,127T880,480h-80Z"
|
||||||
|
android:fillColor="#fff"/>
|
||||||
|
</vector>
|
||||||
10
android/app/src/main/res/drawable/ic_translate.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:pathData="m476,880 l182,-480h84L924,880h-84l-43,-122L603,758L560,880h-84ZM160,760l-56,-56 202,-202q-35,-35 -63.5,-80T190,320h84q20,39 40,68t48,58q33,-33 68.5,-92.5T484,240L40,240v-80h280v-80h80v80h280v80L564,240q-21,72 -63,148t-83,116l96,98 -30,82 -122,-125 -202,201ZM628,688h144l-72,-204 -72,204Z"
|
||||||
|
android:fillColor="#fff"/>
|
||||||
|
</vector>
|
||||||
10
android/app/src/main/res/drawable/ic_translate_indic.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:pathData="m476,880 l182,-480h84L924,880h-84l-43,-122L603,758L560,880h-84ZM628,688h144l-72,-204 -72,204ZM254,640q-66,0 -123.5,-38.5T44,498l72,-36q21,42 58,70t79,28q38,0 62.5,-23.5T340,480q0,-33 -23.5,-56.5T260,400h-60v-80h60q25,0 42.5,-17.5T320,260q0,-25 -17,-42.5T261,200q-23,0 -41,15t-32,33l-63,-49q26,-32 60,-55.5t77,-23.5q57,0 97.5,40.5T400,259q0,27 -10,52.5T361,357q10,10 18.5,20.5T396,400h124v-200h-80v-80h240v80h-80v116l-61,164L420,480v4q0,63 -46,109.5T254,640Z"
|
||||||
|
android:fillColor="#fff"/>
|
||||||
|
</vector>
|
||||||
@@ -3,7 +3,13 @@
|
|||||||
android:height="20dp"
|
android:height="20dp"
|
||||||
android:viewportWidth="960"
|
android:viewportWidth="960"
|
||||||
android:viewportHeight="960">
|
android:viewportHeight="960">
|
||||||
|
<group
|
||||||
|
android:pivotX="370"
|
||||||
|
android:pivotY="480"
|
||||||
|
android:scaleX="2.2"
|
||||||
|
android:scaleY="1.7">
|
||||||
<path
|
<path
|
||||||
android:pathData="M420,652q-8,0 -14,-5.5t-6,-14.5v-304q0,-9 6,-14.5t14,-5.5q2,0 14,6l145,145q5,5 7,10t2,11q0,6 -2,11t-7,10L434,646q-3,3 -6.5,4.5T420,652Z"
|
android:pathData="M640,760 L200,480l440,-280v560Z"
|
||||||
android:fillColor="#1f1f1f"/>
|
android:fillColor="#FFFFFF"/>
|
||||||
|
</group>
|
||||||
</vector>
|
</vector>
|
||||||
|
|||||||
10
android/app/src/main/res/drawable/ic_wifi_find.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?colorControlNormal">
|
||||||
|
<path
|
||||||
|
android:pathData="M480,840 L0,359q93,-93 215.5,-146T480,160q142,0 264.5,53T960,359l-56,57q-81,-81 -190,-128.5T480,240q-103,0 -195,32.5T117,363l419,420 -56,57ZM864,800L761,698q-18,11 -38,16.5t-43,5.5q-68,0 -114,-46t-46,-114q0,-68 46,-114t114,-46q68,0 114,46t46,114q0,23 -5.5,43T818,641l102,103 -56,56ZM680,640q34,0 57,-23t23,-57q0,-34 -23,-57t-57,-23q-34,0 -57,23t-23,57q0,34 23,57t57,23ZM480,783Z"
|
||||||
|
android:fillColor="#fff"/>
|
||||||
|
</vector>
|
||||||
@@ -26,6 +26,11 @@
|
|||||||
android:clipChildren="false"
|
android:clipChildren="false"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
tools:ignore="UselessParent">
|
tools:ignore="UselessParent">
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/offline_explanation"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -47,6 +52,7 @@
|
|||||||
android:layout_height="2dp"
|
android:layout_height="2dp"
|
||||||
android:layout_marginTop="@dimen/margin_quarter"
|
android:layout_marginTop="@dimen/margin_quarter"
|
||||||
android:layout_marginBottom="@dimen/margin_quarter"/>
|
android:layout_marginBottom="@dimen/margin_quarter"/>
|
||||||
|
</LinearLayout>
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
android:id="@+id/downloader_parent"
|
android:id="@+id/downloader_parent"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|||||||
@@ -3,8 +3,7 @@
|
|||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/feedback_fab"
|
android:id="@+id/feedback_fab"
|
||||||
style="MwmWidget.M3.FAB.Primary"
|
style="@style/MwmWidget.M3.FAB.Primary"
|
||||||
app:shapeAppearance="@style/ShapeAppearanceOverlay.Material3.FloatingActionButton"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:contentDescription="@string/feedback"
|
android:contentDescription="@string/feedback"
|
||||||
|
|||||||
@@ -22,8 +22,8 @@
|
|||||||
android:clipChildren="false">
|
android:clipChildren="false">
|
||||||
<com.google.android.material.imageview.ShapeableImageView
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
android:id="@+id/floating_triangle"
|
android:id="@+id/floating_triangle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="@dimen/margin_half"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="@dimen/margin_half"
|
||||||
android:elevation="@dimen/margin_eighth"
|
android:elevation="@dimen/margin_eighth"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
app:tint="@android:color/white"
|
app:tint="@android:color/white"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:background="?attr/cardBackground"
|
android:background="?attr/cardBackground"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -20,8 +21,15 @@
|
|||||||
android:minHeight="@dimen/height_block_base"
|
android:minHeight="@dimen/height_block_base"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingEnd="@dimen/margin_base"
|
android:paddingEnd="@dimen/margin_half"
|
||||||
android:paddingStart="@dimen/margin_base">
|
android:paddingStart="@dimen/margin_base">
|
||||||
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginEnd="@dimen/margin_base_plus"
|
||||||
|
android:layout_marginTop="@dimen/margin_half_plus"
|
||||||
|
app:srcCompat="@drawable/ic_avoid_tolls_disabled"
|
||||||
|
app:tint="?iconTint" />
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
android:text="@string/avoid_tolls"
|
android:text="@string/avoid_tolls"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
@@ -36,14 +44,20 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:padding="@dimen/margin_half_double_plus"/>
|
android:padding="@dimen/margin_half_double_plus"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
<include layout="@layout/item_divider"/>
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:minHeight="@dimen/height_block_base"
|
android:minHeight="@dimen/height_block_base"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingEnd="@dimen/margin_base"
|
android:paddingEnd="@dimen/margin_half"
|
||||||
android:paddingStart="@dimen/margin_base">
|
android:paddingStart="@dimen/margin_base">
|
||||||
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginEnd="@dimen/margin_base_plus"
|
||||||
|
android:layout_marginTop="@dimen/margin_half_plus"
|
||||||
|
app:srcCompat="@drawable/ic_avoid_unpaved_disabled"
|
||||||
|
app:tint="?iconTint" />
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
android:text="@string/avoid_unpaved"
|
android:text="@string/avoid_unpaved"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
@@ -58,14 +72,48 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:padding="@dimen/margin_half_double_plus"/>
|
android:padding="@dimen/margin_half_double_plus"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
<include layout="@layout/item_divider"/>
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:minHeight="@dimen/height_block_base"
|
android:minHeight="@dimen/height_block_base"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingEnd="@dimen/margin_base"
|
android:paddingEnd="@dimen/margin_half"
|
||||||
android:paddingStart="@dimen/margin_base">
|
android:paddingStart="@dimen/margin_base">
|
||||||
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginEnd="@dimen/margin_base_plus"
|
||||||
|
android:layout_marginTop="@dimen/margin_half_plus"
|
||||||
|
app:srcCompat="@drawable/ic_avoid_paved_disabled"
|
||||||
|
app:tint="?iconTint" />
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:text="@string/avoid_paved"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"/>
|
||||||
|
<androidx.appcompat.widget.SwitchCompat
|
||||||
|
android:id="@+id/avoid_paved_roads_btn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:padding="@dimen/margin_half_double_plus"/>
|
||||||
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:minHeight="@dimen/height_block_base"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingEnd="@dimen/margin_half"
|
||||||
|
android:paddingStart="@dimen/margin_base">
|
||||||
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginEnd="@dimen/margin_base_plus"
|
||||||
|
android:layout_marginTop="@dimen/margin_half_plus"
|
||||||
|
app:srcCompat="@drawable/ic_avoid_ferry_disabled"
|
||||||
|
app:tint="?iconTint" />
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
android:text="@string/avoid_ferry"
|
android:text="@string/avoid_ferry"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
@@ -80,14 +128,20 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:padding="@dimen/margin_half_double_plus"/>
|
android:padding="@dimen/margin_half_double_plus"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
<include layout="@layout/item_divider"/>
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:minHeight="@dimen/height_block_base"
|
android:minHeight="@dimen/height_block_base"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingEnd="@dimen/margin_base"
|
android:paddingEnd="@dimen/margin_half"
|
||||||
android:paddingStart="@dimen/margin_base">
|
android:paddingStart="@dimen/margin_base">
|
||||||
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginEnd="@dimen/margin_base_plus"
|
||||||
|
android:layout_marginTop="@dimen/margin_half_plus"
|
||||||
|
app:srcCompat="@drawable/ic_avoid_motorways_disabled"
|
||||||
|
app:tint="?iconTint" />
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
android:text="@string/avoid_motorways"
|
android:text="@string/avoid_motorways"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
@@ -102,14 +156,20 @@
|
|||||||
android:padding="@dimen/margin_half_double_plus"
|
android:padding="@dimen/margin_half_double_plus"
|
||||||
android:layout_height="match_parent"/>
|
android:layout_height="match_parent"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
<include layout="@layout/item_divider"/>
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:minHeight="@dimen/height_block_base"
|
android:minHeight="@dimen/height_block_base"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingEnd="@dimen/margin_base"
|
android:paddingEnd="@dimen/margin_half"
|
||||||
android:paddingStart="@dimen/margin_base">
|
android:paddingStart="@dimen/margin_base">
|
||||||
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginEnd="@dimen/margin_base_plus"
|
||||||
|
android:layout_marginTop="@dimen/margin_half_plus"
|
||||||
|
app:srcCompat="@drawable/ic_avoid_steps_disabled"
|
||||||
|
app:tint="?iconTint" />
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
android:text="@string/avoid_steps"
|
android:text="@string/avoid_steps"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
|||||||
@@ -394,7 +394,8 @@
|
|||||||
|
|
||||||
<com.google.android.material.card.MaterialCardView
|
<com.google.android.material.card.MaterialCardView
|
||||||
android:id="@+id/cv__more"
|
android:id="@+id/cv__more"
|
||||||
style="@style/MwmWidget.Editor.CardView">
|
style="@style/MwmWidget.Editor.CardView"
|
||||||
|
android:layout_marginBottom="@dimen/margin_base">
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -421,6 +422,17 @@
|
|||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/disused"
|
||||||
|
style="@style/MwmWidget.M3.Button.Secondary"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_marginBottom="@dimen/margin_quarter"
|
||||||
|
app:backgroundTint="?cardBackground"
|
||||||
|
android:textColor="@color/base_red"
|
||||||
|
app:strokeColor="@color/base_red"
|
||||||
|
android:text="@string/editor_business_vacant_button"/>
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/reset"
|
android:id="@+id/reset"
|
||||||
style="@style/MwmWidget.M3.Button.Secondary"
|
style="@style/MwmWidget.M3.Button.Secondary"
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
android:id="@+id/empty_opening_hours"
|
android:id="@+id/empty_opening_hours"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerVertical="true"
|
android:layout_marginTop="@dimen/margin_base"
|
||||||
android:layout_marginStart="@dimen/editor_margin_timetable_left"
|
android:layout_marginStart="@dimen/editor_margin_timetable_left"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:visibility="gone">
|
tools:visibility="gone">
|
||||||
@@ -57,10 +57,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
style="@style/Widget.Material3.Button.TextButton"
|
style="@style/Widget.Material3.Button.TextButton"
|
||||||
android:layout_below="@id/opening_hours"
|
android:layout_below="@id/opening_hours"
|
||||||
android:layout_marginStart="@dimen/editor_margin_timetable_left"
|
android:layout_marginTop="@dimen/margin_base"
|
||||||
android:layout_marginTop="@dimen/margin_base_plus"
|
android:gravity="center_horizontal"
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:minHeight="@dimen/height_block_base"
|
|
||||||
android:text="@string/edit_opening_hours"
|
android:text="@string/edit_opening_hours"
|
||||||
android:textColor="?colorSecondary"
|
android:textColor="?colorSecondary"
|
||||||
android:textAppearance="@style/MwmTextAppearance.Body1" />
|
android:textAppearance="@style/MwmTextAppearance.Body1" />
|
||||||
|
|||||||
@@ -28,12 +28,12 @@
|
|||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/delete_icon"
|
app:layout_constraintEnd_toStartOf="@+id/delete_icon"
|
||||||
app:layout_constraintStart_toEndOf="@+id/phone_icon"
|
app:layout_constraintStart_toEndOf="@+id/phone_icon"
|
||||||
|
app:hintEnabled="false"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:id="@+id/input"
|
android:id="@+id/input"
|
||||||
style="@style/MwmWidget.Editor.FieldLayout.EditText"
|
style="@style/MwmWidget.Editor.FieldLayout.EditText"
|
||||||
tools:hint="Hint"
|
android:hint="@string/phone_format"
|
||||||
tools:text="Input"
|
|
||||||
android:inputType="phone"/>
|
android:inputType="phone"/>
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
|||||||