Compare commits

..

25 Commits

Author SHA1 Message Date
Viktor Govako
e7987a14c0 [generator][tests] Added ScopedDirCleanup helper.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-12-05 19:12:47 +07:00
Kiryl Kaveryn
0c079f5120 [drape] Enable visibleViewport tracking for add place mode
It allows to dynamically update the crosshair position when the place page is dismissed.

Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
2025-12-05 19:12:47 +07:00
Andrei Shkrob
723b84ca5a [map] Remove osm_opening_hours.hpp
Signed-off-by: Andrei Shkrob <github@shkrob.dev>
2025-12-05 19:12:47 +07:00
Viktor Govako
b4093e554d [map] Updated wiki loader.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-12-05 19:12:47 +07:00
Viktor Govako
5ab07ea610 [map] Removed Framework::m_popularityLoader.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-12-05 19:12:47 +07:00
renderexpert
3faf052b32 Fix issue after clang-format
Signed-off-by: renderexpert <expert@renderconsulting.co.uk>
2025-12-05 19:12:47 +07:00
Viktor Govako
6259e396f4 Redundant includes.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-12-05 19:12:47 +07:00
Viktor Govako
c968d79f4f [drape] Refactor VisualParams.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-12-05 19:12:44 +07:00
Viktor Govako
4cb6e65e81 [desktop] Show geometry type in context menu.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-12-05 19:08:18 +07:00
Viktor Govako
a962c61978 [desktop] Cancel downloading.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-12-05 19:08:18 +07:00
Kiryl Kaveryn
6cf791580f [map] Remove DeactivateMapSelection on Save osm edits
The call of `DeactivateMapSelection` is redundant because it try to close the current PP. It produces buggy behaviour on iOS the PP is closed and does not have time to open.
The PP should be only be updated using the `ActivateMapSelection`

Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
2025-12-05 19:08:18 +07:00
Viktor Govako
d1f817c3e6 [drape] Refactor UpdateVisualScale.
Signed-off-by: Viktor Govako <viktor.govako@gmail.com>
2025-12-05 19:08:18 +07:00
Jean-Baptiste
2762bd50ae [android] Rework shape of zoom buttons
Signed-off-by: Jean-Baptiste <jeanbaptiste.charron@outlook.fr>
2025-12-05 16:04:10 +07:00
Leonardo Bishop
2b137a8d12 [drape] Base zoom level on distance to next turn
This commit changes the auto zoom level behaviour during navigation
to be based off the distance to the next turn, rather than naively
coupling it to the current speed. This will improve the navigation
experience during driving.

Signed-off-by: Leonardo Bishop <me@leonardobishop.net>
2025-12-05 16:04:10 +07:00
x7z4w
12ac8e8814 [search] Remove stop words
Signed-off-by: x7z4w <x7z4w@noreply.codeberg.org>
2025-12-05 16:04:10 +07:00
gekeleda
5ab43dd67e Add Toast message at navigation start
Signed-off-by: gekeleda <git@davidgekeler.eu>
2025-12-05 15:50:48 +07:00
gekeleda
2847345324 [android] Update TtsPlayer documentation, prefer en.US default locale over installed TTS locales
Signed-off-by: gekeleda <git@davidgekeler.eu>
2025-12-05 15:50:48 +07:00
gekeleda
c9b3778ecc [android] Consider all langs available in TTS engine
Signed-off-by: gekeleda <git@davidgekeler.eu>
2025-12-05 15:50:48 +07:00
gekeleda
593561bc06 [android] Improve TTS selection logging
Signed-off-by: gekeleda <git@davidgekeler.eu>
2025-12-05 15:50:48 +07:00
gekeleda
1cfbc1a8be [android] Consider all system langs for TTS
Signed-off-by: gekeleda <git@davidgekeler.eu>
2025-12-05 15:50:48 +07:00
gekeleda
ba997f6c05 [android] Fix avg speed display edge case, simplify code
Signed-off-by: gekeleda <git@davidgekeler.eu>
2025-12-05 15:49:00 +07:00
David Gekeler
9c9e8dac63 [android] Clarify speed average behaviour in absence of location updates
Signed-off-by: David Gekeler <git@davidgekeler.eu>
2025-12-05 15:48:58 +07:00
David Gekeler
75c151bbbe [android] Fix formatting
Signed-off-by: David Gekeler <git@davidgekeler.eu>
2025-12-05 15:48:56 +07:00
David Gekeler
f960b3959f [android] Add average speed calculation and change speed view to display it
Signed-off-by: David Gekeler <git@davidgekeler.eu>
2025-12-05 15:48:53 +07:00
Konstantin Pastbin
24c9802a2a [planet] Update map data to 251203
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
2025-12-05 12:53:12 +07:00
829 changed files with 10590 additions and 22775 deletions

View File

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

View File

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

View File

@@ -105,17 +105,17 @@ jobs:
run: |
echo "Cloning $FORGEJO_SERVER_URL/$FORGEJO_REPOSITORY branch $FORGEJO_REF_NAME"
cd ~
git clone --depth 1 --recurse-submodules --shallow-submodules -b $FORGEJO_REF_NAME --single-branch $FORGEJO_SERVER_URL/$FORGEJO_REPOSITORY.git comaps
git clone --recurse-submodules --shallow-submodules -b $FORGEJO_REF_NAME --single-branch $FORGEJO_SERVER_URL/$FORGEJO_REPOSITORY.git comaps
- name: Checkout wikiparser repo
shell: bash
run: |
cd ~
git clone --depth 1 --single-branch https://codeberg.org/comaps/wikiparser.git
git clone https://codeberg.org/comaps/wikiparser.git
- name: Checkout subways repo
shell: bash
run: |
cd ~
git clone --depth 1 --single-branch https://codeberg.org/comaps/subways.git
git clone https://codeberg.org/comaps/subways.git
copy-coasts:
# if: inputs.run-copy-coasts

View File

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

View File

@@ -2,5 +2,3 @@
480fa6c2fcf53be296504ac6ba8e6b3d70f92b42
a6ede2b1466f0c9d8a443600ef337ba6b5832e58
1377b81bf1cac72bb6da192da7fed6696d5d5281
05ba3afa979104bb33e5f41ede1d43e1ba30a63c
732210b9a24a95d798d092eb3455456a79d4c702

3
.github/FUNDING.yml vendored
View File

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

View File

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

View File

@@ -35,7 +35,7 @@ jobs:
xcodebuild -downloadPlatform iOS
- name: Checkout sources
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Parallel submodules checkout
shell: bash

2
.gitignore vendored
View File

@@ -155,8 +155,6 @@ android/huawei-appgallery.json
android/res/xml/network_security_config.xml
./server/
iphone/Maps/app.omaps/
# Generated file
libs/indexer/localized_types_map.cpp
*.li

View File

@@ -1,83 +0,0 @@
///////////////////////// ankerl::unordered_dense::{map, set} /////////////////////////
// A fast & densely stored hashmap and hashset based on robin-hood backward shift deletion.
// Version 4.8.1
// https://github.com/martinus/unordered_dense
//
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 Martin Leitner-Ankerl <martin.ankerl@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#ifndef ANKERL_STL_H
#define ANKERL_STL_H
#include <array> // for array
#include <cstdint> // for uint64_t, uint32_t, std::uint8_t, UINT64_C
#include <cstring> // for size_t, memcpy, memset
#include <functional> // for equal_to, hash
#include <initializer_list> // for initializer_list
#include <iterator> // for pair, distance
#include <limits> // for numeric_limits
#include <memory> // for allocator, allocator_traits, shared_ptr
#include <optional> // for optional
#include <stdexcept> // for out_of_range
#include <string> // for basic_string
#include <string_view> // for basic_string_view, hash
#include <tuple> // for forward_as_tuple
#include <type_traits> // for enable_if_t, declval, conditional_t, ena...
#include <utility> // for forward, exchange, pair, as_const, piece...
#include <vector> // for vector
// <memory_resource> includes <mutex>, which fails to compile if
// targeting GCC >= 13 with the (rewritten) win32 thread model, and
// targeting Windows earlier than Vista (0x600). GCC predefines
// _REENTRANT when using the 'posix' model, and doesn't when using the
// 'win32' model.
#if defined __MINGW64__ && defined __GNUC__ && __GNUC__ >= 13 && !defined _REENTRANT
// _WIN32_WINNT is guaranteed to be defined here because of the
// <cstdint> inclusion above.
# ifndef _WIN32_WINNT
# error "_WIN32_WINNT not defined"
# endif
# if _WIN32_WINNT < 0x600
# define ANKERL_MEMORY_RESOURCE_IS_BAD() 1 // NOLINT(cppcoreguidelines-macro-usage)
# endif
#endif
#ifndef ANKERL_MEMORY_RESOURCE_IS_BAD
# define ANKERL_MEMORY_RESOURCE_IS_BAD() 0 // NOLINT(cppcoreguidelines-macro-usage)
#endif
#if defined(__has_include) && !defined(ANKERL_UNORDERED_DENSE_DISABLE_PMR)
# if __has_include(<memory_resource>) && !ANKERL_MEMORY_RESOURCE_IS_BAD()
# define ANKERL_UNORDERED_DENSE_PMR std::pmr // NOLINT(cppcoreguidelines-macro-usage)
# include <memory_resource> // for polymorphic_allocator
# elif __has_include(<experimental/memory_resource>)
# define ANKERL_UNORDERED_DENSE_PMR std::experimental::pmr // NOLINT(cppcoreguidelines-macro-usage)
# include <experimental/memory_resource> // for polymorphic_allocator
# endif
#endif
#if defined(_MSC_VER) && defined(_M_X64)
# include <intrin.h>
# pragma intrinsic(_umul128)
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -116,6 +116,20 @@ endif()
message(STATUS "Build type: " ${CMAKE_BUILD_TYPE})
if (PLATFORM_LINUX OR PLATFORM_ANDROID)
find_program(LLD_FOUND ld.lld)
if (LLD_FOUND)
message(STATUS "Using ld.lld linker")
set(CMAKE_EXE_LINKER_FLAGS "-fuse-ld=lld")
else()
find_program(GOLD_FOUND ld.gold)
if (GOLD_FOUND)
message(STATUS "Using ld.gold")
set(CMAKE_EXE_LINKER_FLAGS "-fuse-ld=gold")
endif()
endif()
endif()
if (NOT SKIP_TESTS)
enable_testing()
# Enables ctest -T memcheck with valgrind

View File

@@ -10,7 +10,6 @@ CoMaps contributors:
Bastian Greshake Tzovaras
clover sage
Harry Bond <me@hbond.xyz>
NoelClick
thesupertechie
vikiawv
Yannik Bloscheck

2
NOTICE
View File

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

View File

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

View File

@@ -254,20 +254,18 @@ android {
androidResources {
ignoreAssetsPattern = '!.svn:!.git:!.DS_Store:!*.scc:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*~'
noCompress = ['txt', 'bin', 'html', 'png', 'json', 'mwm', 'ttf', 'sdf', 'ui', 'config', 'csv', 'spv', 'obj']
// Some languages not supported by Android require to be specified here to be applied
localeFilters += [
"en",
"af",
"ar",
"az",
"be",
"bg",
"bn",
"ca",
"cs",
"da",
"de",
"el",
"en",
"en-rGB",
"es",
"es-rMX",
@@ -277,38 +275,28 @@ android {
"fi",
"fr",
"fr-rCA",
"gl",
"gsw",
"he",
"iw",
"hi",
"hu",
"id",
"in",
"is",
"it",
"iw",
"ja",
"kw",
"ko",
"lt",
"lv",
"mr",
"mt",
"nb",
"nb-rNO",
"nl",
"pl",
"pt",
"pt-rBR",
"ro",
"ru",
"sl",
"sk",
"sr-rCyrl",
"sr-rLatn",
"sr",
"sv",
"sw",
"ta",
"th",
"tr",
"uk",
@@ -363,8 +351,6 @@ dependencies {
implementation libs.androidx.recyclerview
implementation libs.androidx.work.runtime
implementation libs.androidx.lifecycle.process
implementation libs.androidx.documentfile
// 1.13 Material library version doesn't render properly alpha properties on map buttons
implementation libs.android.material
// Fix for app/organicmaps/util/FileUploadWorker.java:14: error: cannot access ListenableFuture
// https://github.com/organicmaps/organicmaps/issues/6106

View File

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

View File

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

View File

@@ -1,9 +0,0 @@
• OSM-Daten vom 6. Januar
• Editor: POI mit mehr als einem Tag, (z.B. Arten von Kunstwerken wie Skulpturen...), mehr POI können als leer/stillgelegt werden
• Miniatureisenbahnen & Kläranlagen hinzugefügt
• Material 3-Dialoge & dunklerer Hintergrund im Darkmode
• Fiktive Geschwindigkeitsbegrenzungen für Verbindungsstraßen entfernt
• Versatz der Kameraausschnitt in der Navigation behoben
• Weniger empfindliches langes Antippen
Weitere Details unter codeberg.org/comaps/comaps/releases

View File

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

View File

@@ -1,32 +0,0 @@
A community-led free & open source maps app based on OpenStreetMap data and reinforced with commitment to transparency, privacy and being not-for-profit. CoMaps is a fork/spin-off of Organic Maps, which in turn is a fork of Maps.ME.
Read on about reasons for the project and its direction at <b><i>codeberg.org/comaps</i></b>.
Join the community there and help make the best maps app
• Use the app and spread the word about it
• Give feedback and report issues
• Update map data in the app or on the OpenStreetMap website
‣ <b>Offline-focused</b>: Plan and navigate your trip abroad without the need for cellular service, search waypoints while on a distant hike, etc. All app functions are designed to work offline.
‣ <b>Respecting Privacy</b>: The app is designed with privacy in mind - does not identify people, does not track, and does not collect personal information. Ads-free.
‣ <b>Simple and Polished</b>: essential easy to use features that just work.
‣ <b>Saves Your Battery and Space</b>: Doesnt drain your battery like other navigation apps. Compact maps save precious space on your phone.
‣ <b>Free and Built by the Community</b>: People like you helped build the app by adding places to OpenStreetMap, testing and giving feedback on features and contributing their development skills and money.
‣ <b>Open and Transparent Decision-making and Financials, Not-for-profit and Fully Open Source.</b>
<b>Main Features</b>:
• Downloadable detailed maps with places which are not available with Google Maps
• Outdoor mode with highlighted hiking trails, campsites, water sources, peaks, contour lines, etc
• Walking paths and cycleways
• Points of interest like restaurants, gas stations, hotels, shops, sightseeing and many more
• Search by name or an address or by point of interest category
• Navigation with voice announcements for walking, cycling, or driving
• Bookmark your favorite places with a single tap
• Offline Wikipedia articles
• Subway transit layer and directions
• Track recording
• Export and import bookmarks and tracks in KML, KMZ, GPX formats
• A dark mode to use during the night
• Improve map data for everyone using a basic built-in editor
<b>Freedom Is Here</b>
Discover your journey, navigate the world with privacy and community at the forefront!

View File

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

View File

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

View File

@@ -1,9 +1,13 @@
OpenStreetMap data as of January 6
Editor: add POI types with more than one OSM tag, e.g. artwork subtypes sculptures, paintings..; more POI types could be marked as vacant/disused
• Added miniature railways and wastewater treatment plants
• Use Material 3 dialogs and darker background in dark mode
• Removed fictional speed limits for link roads
• Fixed camera cutout offset in navigation
• Less sensitive long tap (full-screen mode)
Fixed voice directions pronouncing weird symbols in the beginning
OpenStreetMap data as of November 23
More details on codeberg.org/comaps/comaps/releases
Changes in the previous release:
• Added trees
• Made bus stop icons smaller and show up earlier
• Reduce visibility of entrances
• Added several other POI types
• Show sand areas on the map
• 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

View File

@@ -1,9 +0,0 @@
• Datos OSM a 06/01
• Editor: se añaden tipos de POI con más de una etiqueta, ej. esculturas, pinturas...; se podrán marcar más tipos como en desuso
• Se añaden ferrocarriles mini y plantas de tratamiento de aguas
• Se utilizan diálogos Material 3 y fondo más oscuro en el modo oscuro
• Se eliminan límites de velocidad ficticios para enlaces
• Se corrige desplazamiento en la navegación
• Toque largo menos sensible (en pantalla completa)
Más detalles en codeberg.org/comaps/comaps/releases

View File

@@ -1,9 +0,0 @@
• Données OpenStreetMap du 6 janvier
• Éditeur : support des types de POI avec plus dun tag OSM, par exemple types dœuvres dart sculptures, peintures..
• Rendu des rails pour trains miniatures et des stations d'épuration
• Utilisation des pop-ups Material 3 et d'un fond plus sombre en thème sombre
• Suppression des limites de vitesse fictives sur les bretelles de routes
• Correction des instructions de navigation sur les appareils avec des encoches
• Appui long moins sensible (en mode plein écran)
Plus de détails sur codeberg.org/comaps/comaps/releases

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,9 +0,0 @@
• Dados OSM de 6/1
• Editor: adição de POIs com mais de uma etiqueta OSM, por exemplo esculturas e pinturas; mais tipos de POI podem ser marcados como vagos/desativados
• Adição de ferrovias em miniatura e ETEs
• Uso de diálogos Material 3 e fundo mais escuro no modo escuro
• Remoção de limites de velocidade fictícios para vias de ligação
• Correção de recorte da câmera na navegação
• Toque longo menos sensível (modo tela cheia)
Mais detalhes em codeberg.org/comaps/comaps/releases

View File

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

View File

@@ -1,31 +1,31 @@
Brezplačno in odprtokodno zemljevidno orodje, ki ga vodi skupnost, temelji na podatkih OpenStreetMap in je okrepljena s predanostjo transparentnosti, zasebnosti in nepridobitnosti. CoMaps je izpeljanka OrganicMaps, ta pa je izpeljanka Maps.ME.
Brezplačno in odprtokodno zemljevidno orodje, ki ga vodi skupnost, temelji na podatkih OpenStreetMap in je okrepljena s predanostjo transparentnosti, zasebnosti in nedobičkonosnosti. CoMaps je izpeljanka OrganicMaps, ta pa je izpeljanka Maps.ME.
Preberite si o razlogih za ta projekt in njegovi usmerjenosti na <b><i>codeberg.org/comaps</i></b>.
Preverite si o razlogih za ta projekt in njegovi usmerjenosti na <b><i>codeberg.org/comaps</i></b>.
Pridružite se skupnosti in pomagajte narediti najboljše zemljevidno orodje
• 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 potovanja ko ste na daljšem pohodu ipd. Vse zmogljivosti orodja so zasnovane za delo brez povezave.
‣ <b>Osredotočeno na uporabo brez povezave</b>: Načrtujte in se usmerjajte na vašem potovanju v tujini vrez potrebe po mobilnih podatkih, iščite vmesne točke potocanja ko ste na daljšem pohodu ipd. Vse zmogljivosti orodja so zasnovane za delo brez povezave.
‣ <b>Spoštovanje zasebnosti</b>: orodje je zasnovano z mislijo na zasebnost ne prepoznava oseb, ne sledi in ne zbira osebnih podatkov. Brez oglasov.
‣ <b>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, nepridobitno in popolnoma odprtokodno.</b>
‣ <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 Googlovih zemljevidih niso na voljo.
• Prenosljivi podrobni zemljevidi s kraji, ki na Googlovoh zemljevidih niso na voljo.
• Prikaz za dejavnosti na prostem s poudarjenimi pohodniškimi potmi, tabornimi prostori, vodnimi viri, vrhovi, plastnicami itd.
• 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 navodili za hojo, kolesarjenje ali vožnjo avtomobila.
• Usmerjanje z glasovnimi obvestili za hojo, kolesarjenje ali vožnjo avtomobila.
• Zaznamujte svoje najljubše kraje s preprostim dotikom
• 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šajte podatke zemljevida za vse z uporabo vgrajenega urejevalnika
• 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!

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -28,6 +28,7 @@ import com.github.mikephil.charting.formatter.IAxisValueFormatter;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
import com.google.android.material.textview.MaterialTextView;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

View File

@@ -26,7 +26,6 @@ import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.core.view.ViewCompat;
import app.organicmaps.base.BaseMwmFragmentActivity;
import app.organicmaps.dialog.CustomMapServerDialog;
import app.organicmaps.downloader.MapManagerHelper;
import app.organicmaps.intent.Factory;
import app.organicmaps.sdk.Framework;
@@ -55,7 +54,6 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
private MaterialTextView mTvMessage;
private LinearProgressIndicator mProgress;
private MaterialButton mBtnDownload;
private MaterialButton mBtnAdvanced;
private MaterialCheckBox mChbDownloadCountry;
private String mCurrentCountry;
@@ -255,7 +253,7 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
mProgress.setMax(bytes);
// Start progress at 1% according to M3 guidelines
mProgress.setProgressCompat(bytes / 100, true);
mProgress.setProgressCompat(bytes/100, true);
}
else
finishFilesDownload(bytes);
@@ -269,11 +267,6 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
mProgress = findViewById(R.id.progressbar);
mBtnDownload = findViewById(R.id.btn_download_resources);
mChbDownloadCountry = findViewById(R.id.chb_download_country);
mBtnAdvanced = findViewById(R.id.btn_advanced);
mBtnAdvanced.setOnClickListener(
v -> { CustomMapServerDialog.show(this, url -> { prepareFilesDownload(false); }); });
mBtnAdvanced.setEnabled(true);
mBtnListeners = new View.OnClickListener[BTN_COUNT];
mBtnNames = new String[BTN_COUNT];
@@ -298,11 +291,6 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
{
mBtnDownload.setOnClickListener(mBtnListeners[action]);
mBtnDownload.setText(mBtnNames[action]);
// Allow changing server only when idle or after an error.
boolean advancedEnabled = (action == DOWNLOAD || action == TRY_AGAIN || action == RESUME);
mBtnAdvanced.setEnabled(advancedEnabled);
mBtnAdvanced.setAlpha(advancedEnabled ? 1f : 0.5f);
}
private void doDownload()
@@ -371,9 +359,6 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
private void finishFilesDownload(int result)
{
mBtnAdvanced.setEnabled(true);
mBtnAdvanced.setAlpha(1f);
if (result == ERR_NO_MORE_FILES)
{
// World and WorldCoasts has been downloaded, we should register maps again to correctly add them to the model.
@@ -387,7 +372,7 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
mTvMessage.setText(getString(R.string.downloading_country_can_proceed, item.name, fileSizeString));
mProgress.setMax((int) item.totalSize);
// Start progress at 1% according to M3 guidelines
mProgress.setProgressCompat((int) (item.totalSize / 100), true);
mProgress.setProgressCompat((int) (item.totalSize/100), true);
mCountryDownloadListenerSlot = MapManager.nativeSubscribe(mCountryDownloadListener);
MapManagerHelper.startDownload(mCurrentCountry);
@@ -439,18 +424,17 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
default -> throw new AssertionError("Unexpected result code = " + result);
};
mAlertDialog = new MaterialAlertDialogBuilder(this)
.setTitle(titleId)
.setMessage(messageId)
.setCancelable(true)
.setOnCancelListener((dialog) -> setAction(RESUME))
.setPositiveButton(R.string.try_again,
(dialog, which) -> {
setAction(TRY_AGAIN);
onTryAgainClicked();
})
.setNegativeButton(R.string.cancel, (dialog, which) -> { setAction(RESUME); })
.setOnDismissListener(dialog -> mAlertDialog = null)
.show();
mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(titleId)
.setMessage(messageId)
.setCancelable(true)
.setOnCancelListener((dialog) -> setAction(PAUSE))
.setPositiveButton(R.string.try_again,
(dialog, which) -> {
setAction(TRY_AGAIN);
onTryAgainClicked();
})
.setOnDismissListener(dialog -> mAlertDialog = null)
.show();
}
}

View File

@@ -132,6 +132,8 @@ import app.organicmaps.widget.placepage.PlacePageViewModel;
import com.google.android.material.appbar.MaterialToolbar;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.textview.MaterialTextView;
import java.util.ArrayList;
import java.util.Objects;
@@ -431,7 +433,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
}
dismissLocationErrorDialog();
mLocationErrorDialog = new MaterialAlertDialogBuilder(MwmActivity.this)
mLocationErrorDialog = new MaterialAlertDialogBuilder(MwmActivity.this, R.style.MwmTheme_AlertDialog)
.setMessage(R.string.unknown_current_position)
.setCancelable(true)
.setPositiveButton(R.string.ok, null)
@@ -654,7 +656,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
else
{
dismissAlertDialog();
mAlertDialog = new MaterialAlertDialogBuilder(this)
mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.message_invalid_feature_position)
.setPositiveButton(R.string.ok, null)
.setOnDismissListener(dialog -> mAlertDialog = null)
@@ -711,6 +713,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
if (!TextUtils.isEmpty(appName))
{
setTitle(appName);
((MaterialTextView) mPointChooser.findViewById(R.id.title)).setText(appName);
}
}
@@ -1153,7 +1156,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
if (type == IsolinesState.EXPIREDDATA)
{
mAlertDialog = new MaterialAlertDialogBuilder(this)
mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.downloader_update_maps)
.setMessage(R.string.isolines_activation_error_dialog)
.setPositiveButton(
@@ -1772,7 +1775,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
{
dismissAlertDialog();
mAlertDialog =
new MaterialAlertDialogBuilder(this)
new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.unable_to_calc_alert_title)
.setMessage(R.string.unable_to_calc_alert_subtitle)
.setPositiveButton(R.string.settings,
@@ -1795,7 +1798,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
builder.append(getString(resId)).append("\n\n");
dismissAlertDialog();
mAlertDialog = new MaterialAlertDialogBuilder(this)
mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.dialog_routing_disclaimer_title)
.setMessage(builder.toString())
.setCancelable(false)
@@ -1811,22 +1814,13 @@ public class MwmActivity extends BaseMwmFragmentActivity
return false;
}
private void deliverTtsMessage()
{
if (Config.isTtsMessageDelivered())
private void deliverTtsMessage() {
if(Config.isTtsMessageDelivered())
return;
String languageDisplayName = TtsPlayer.INSTANCE.getLanguageDisplayName();
if (languageDisplayName != null)
{
String navigationStartMessage = getResources().getString(R.string.navigation_start_tts_message);
navigationStartMessage += languageDisplayName;
Toast.makeText(this, navigationStartMessage, Toast.LENGTH_LONG).show();
}
else
Toast.makeText(this, getResources().getString(R.string.navigation_start_tts_disabled_message), Toast.LENGTH_LONG)
.show();
String navigationStartMessage = getResources().getString(R.string.navigation_start_tts_message);
navigationStartMessage += TtsPlayer.INSTANCE.getLanguageDisplayName();
Toast.makeText(this, navigationStartMessage, Toast.LENGTH_LONG).show();
Config.setTtsMessageDelivered();
}
@@ -1844,7 +1838,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
return true;
final MapObject endPoint = Objects.requireNonNull(controller.getEndPoint());
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this)
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.p2p_only_from_current)
.setMessage(R.string.p2p_reroute_from_current)
.setCancelable(false)
@@ -2038,7 +2032,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
{
mPreciseLocationDialogShown = true;
final MaterialAlertDialogBuilder builder =
new MaterialAlertDialogBuilder(this)
new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle("" + getString(R.string.limited_accuracy))
.setMessage(R.string.precise_location_is_disabled_long_text)
.setNegativeButton(R.string.close, (dialog, which) -> dialog.dismiss())
@@ -2072,7 +2066,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
return;
}
mLocationErrorDialog = new MaterialAlertDialogBuilder(this)
mLocationErrorDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.enable_location_services)
.setMessage(R.string.location_is_disabled_long_text)
.setOnDismissListener(dialog -> mLocationErrorDialog = null)
@@ -2165,7 +2159,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
return;
}
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this)
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.enable_location_services)
.setMessage(R.string.location_is_disabled_long_text)
.setOnDismissListener(dialog -> mLocationErrorDialog = null)
@@ -2251,7 +2245,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
dismissAlertDialog();
final MaterialAlertDialogBuilder builder =
new MaterialAlertDialogBuilder(this)
new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.current_location_unknown_error_title)
.setCancelable(true)
.setMessage(R.string.power_save_dialog_summary)
@@ -2276,7 +2270,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
{
dismissAlertDialog();
mAlertDialog =
new MaterialAlertDialogBuilder(this)
new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.load_kmz_title)
.setMessage(getString(R.string.unknown_file_type, uri))
.setPositiveButton(R.string.ok, null)
@@ -2293,7 +2287,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
{
dismissAlertDialog();
mAlertDialog =
new MaterialAlertDialogBuilder(this)
new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.load_kmz_title)
.setMessage(getString(R.string.failed_to_open_file, uri, error))
.setPositiveButton(R.string.ok, null)
@@ -2315,7 +2309,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
public void onBookmarksFileImportFailed()
{
dismissAlertDialog();
mAlertDialog = new MaterialAlertDialogBuilder(this)
mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.load_kmz_title)
.setMessage(R.string.load_kmz_failed)
.setPositiveButton(R.string.ok, null)
@@ -2576,7 +2570,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
private void reportUnsupported()
{
new MaterialAlertDialogBuilder(this)
new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setMessage(R.string.unsupported_phone)
.setCancelable(false)
.setPositiveButton(R.string.close, (dlg, which) -> this.moveTaskToBack(true))

View File

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

View File

@@ -38,9 +38,8 @@ public class OsmUploadWork extends Worker
{
final Constraints c = new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).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);
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();

View File

@@ -17,6 +17,7 @@ import androidx.annotation.NonNull;
import androidx.documentfile.provider.DocumentFile;
import app.organicmaps.R;
import app.organicmaps.sdk.util.log.Logger;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;

View File

@@ -10,6 +10,7 @@ import androidx.fragment.app.DialogFragment;
public class BaseMwmDialogFragment extends DialogFragment
{
protected int getStyle()
{
return STYLE_NORMAL;

View File

@@ -282,13 +282,11 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
{
if (isEmptySearchResults())
{
requirePlaceholder().setContent(R.string.search_not_found, R.string.search_not_found_query,
R.drawable.ic_search_fail);
requirePlaceholder().setContent(R.string.search_not_found, R.string.search_not_found_query, R.drawable.ic_search_fail);
}
else if (isEmpty())
{
requirePlaceholder().setContent(R.string.bookmarks_empty_list_title, R.string.bookmarks_empty_list_message,
R.drawable.ic_bookmarks);
requirePlaceholder().setContent(R.string.bookmarks_empty_list_title, R.string.bookmarks_empty_list_message, R.drawable.ic_bookmarks);
}
boolean isEmptyRecycler = isEmpty() || isEmptySearchResults();

View File

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

View File

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

View File

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

View File

@@ -23,6 +23,7 @@ import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.widget.recycler.RecyclerClickListener;
import app.organicmaps.widget.recycler.RecyclerLongClickListener;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.checkbox.MaterialCheckBox;
import com.google.android.material.imageview.ShapeableImageView;
@@ -457,12 +458,10 @@ public class Holders
String formattedDesc = desc.replace("\n", "<br>");
Spanned spannedDesc = Utils.fromHtml(formattedDesc);
if (!TextUtils.isEmpty(spannedDesc))
{
if (!TextUtils.isEmpty(spannedDesc)) {
mDescText.setText(spannedDesc);
}
else
{
else {
mDescText.setText(R.string.list_description_empty);
}
}

View File

@@ -50,8 +50,8 @@ public final class IntentUtils
}
// https://developer.android.com/reference/androidx/car/app/CarContext#startCarApp(android.content.Intent)
private static void processNavigationIntent(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer,
@NonNull Intent intent)
private static void processNavigationIntent(@NonNull CarContext carContext,
@NonNull Renderer surfaceRenderer, @NonNull Intent intent)
{
// TODO (AndrewShkrob): This logic will need to be revised when we introduce support for adding stops during
// navigation or route planning. Skip navigation intents during navigation

View File

@@ -31,7 +31,7 @@ public final class RoutingHelpers
default -> Distance.UNIT_METERS;
};
return Distance.create(distance.mDistance, displayUnit);
return Distance.create(distance.mDistance, displayUnit);
}
@NonNull
@@ -52,7 +52,7 @@ public final class RoutingHelpers
default -> LaneDirection.SHAPE_UNKNOWN;
};
return LaneDirection.create(shape, isRecommended);
return LaneDirection.create(shape, isRecommended);
}
@NonNull
@@ -77,7 +77,7 @@ public final class RoutingHelpers
case EXIT_HIGHWAY_TO_LEFT -> Maneuver.TYPE_OFF_RAMP_SLIGHT_LEFT;
case EXIT_HIGHWAY_TO_RIGHT -> Maneuver.TYPE_OFF_RAMP_SLIGHT_RIGHT;
};
final Maneuver.Builder builder = new Maneuver.Builder(maneuverType);
final Maneuver.Builder builder = new Maneuver.Builder(maneuverType);
if (maneuverType == Maneuver.TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW)
builder.setRoundaboutExitNumber(roundaboutExitNum > 0 ? roundaboutExitNum : 1);
builder.setIcon(new CarIcon.Builder(createManeuverIcon(context, carDirection, roundaboutExitNum)).build());
@@ -85,8 +85,7 @@ public final class RoutingHelpers
}
@NonNull
private static IconCompat createManeuverIcon(@NonNull final CarContext context, @NonNull CarDirection carDirection,
int roundaboutExitNum)
private static IconCompat createManeuverIcon(@NonNull final CarContext context, @NonNull CarDirection carDirection, int roundaboutExitNum)
{
if (!CarDirection.isRoundAbout(carDirection) || roundaboutExitNum == 0)
{

View File

@@ -39,7 +39,8 @@ public final class UiHelpers
}
@NonNull
public static ActionStrip createMapActionStrip(@NonNull CarContext context, @NonNull Renderer surfaceRenderer)
public static ActionStrip createMapActionStrip(@NonNull CarContext context,
@NonNull Renderer surfaceRenderer)
{
final CarIcon iconPlus = new CarIcon.Builder(IconCompat.createWithResource(context, R.drawable.ic_plus)).build();
final CarIcon iconMinus = new CarIcon.Builder(IconCompat.createWithResource(context, R.drawable.ic_minus)).build();
@@ -58,13 +59,15 @@ public final class UiHelpers
}
@NonNull
public static MapController createMapController(@NonNull CarContext context, @NonNull Renderer surfaceRenderer)
public static MapController createMapController(@NonNull CarContext context,
@NonNull Renderer surfaceRenderer)
{
return new MapController.Builder().setMapActionStrip(createMapActionStrip(context, surfaceRenderer)).build();
}
@NonNull
public static Action createSettingsAction(@NonNull BaseMapScreen mapScreen, @NonNull Renderer surfaceRenderer)
public static Action createSettingsAction(@NonNull BaseMapScreen mapScreen,
@NonNull Renderer surfaceRenderer)
{
return createSettingsAction(mapScreen, surfaceRenderer, null);
}
@@ -78,7 +81,8 @@ public final class UiHelpers
}
@NonNull
private static Action createSettingsAction(@NonNull BaseMapScreen mapScreen, @NonNull Renderer surfaceRenderer,
private static Action createSettingsAction(@NonNull BaseMapScreen mapScreen,
@NonNull Renderer surfaceRenderer,
@Nullable OnScreenResultListener onScreenResultListener)
{
final CarContext context = mapScreen.getCarContext();
@@ -119,7 +123,8 @@ public final class UiHelpers
return null;
final Row.Builder builder = new Row.Builder();
builder.setImage(new CarIcon.Builder(IconCompat.createWithResource(context, R.drawable.ic_opening_hours)).build());
builder.setImage(
new CarIcon.Builder(IconCompat.createWithResource(context, R.drawable.ic_opening_hours)).build());
if (isEmptyTT)
builder.setTitle(ohStr);

View File

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

View File

@@ -113,7 +113,7 @@ public class EditTextDialogFragment extends BaseMwmDialogFragment
negativeButtonText = args.getString(ARG_NEGATIVE_BUTTON);
}
AlertDialog editTextDialog = new MaterialAlertDialogBuilder(requireActivity())
AlertDialog editTextDialog = new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setView(buildView())
.setNegativeButton(negativeButtonText, null)
.setPositiveButton(positiveButtonText, null)
@@ -125,8 +125,7 @@ public class EditTextDialogFragment extends BaseMwmDialogFragment
positiveButton.setOnClickListener(view -> {
final String result = mEtInput.getText().toString();
if (validateInput(requireActivity(), result))
{
if (validateInput(requireActivity(), result)) {
processInput(result);
editTextDialog.dismiss();
}
@@ -153,7 +152,7 @@ public class EditTextDialogFragment extends BaseMwmDialogFragment
if (mInputValidator != null)
{
final String maybeError = mInputValidator.validate(activity, input);
mEtInputLayout.setError(maybeError);
mEtInputLayout.getEditText().setError(maybeError);
mEtInputLayout.requestFocus();
return maybeError == null;
}

View File

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

View File

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

View File

@@ -4,6 +4,7 @@ import android.location.Location;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import app.organicmaps.MwmActivity;
@@ -48,8 +49,7 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
@Override
public void onStatusChanged(List<MapManager.StorageCallbackData> data)
{
if (mCurrentCountry == null)
{
if (mCurrentCountry == null) {
updateOfflineExplanationVisibility();
return;
}
@@ -109,13 +109,10 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
return enqueued || progress || applying;
}
private void updateOfflineExplanationVisibility()
{
if (mOfflineExplanation == null)
return;
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);
app.organicmaps.util.UiUtils.showIf(MapManager.nativeGetDownloadedCount() < (DEFAULT_MAP_BASELINE + HIDE_THRESHOLD), mOfflineExplanation);
}
private void updateProgressState(boolean shouldAutoDownload)

View File

@@ -15,6 +15,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.AutoCompleteTextView;
import android.widget.GridLayout;
import androidx.annotation.CallSuper;
import androidx.annotation.DrawableRes;
import androidx.annotation.IdRes;
@@ -195,9 +196,10 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
{
final Context context = mInputBuildingLevels.getContext();
final boolean isValid = Editor.nativeIsLevelValid(s.toString());
mInputBuildingLevels.setError(isValid ? null
: context.getString(R.string.error_enter_correct_storey_number,
Editor.nativeGetMaxEditableBuildingLevels()));
UiUtils.setInputError(mInputBuildingLevels,
isValid ? null
: context.getString(R.string.error_enter_correct_storey_number,
Editor.nativeGetMaxEditableBuildingLevels()));
}
});
@@ -396,7 +398,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
List<String> SOCKET_TYPES = Arrays.stream(getResources().getStringArray(R.array.charge_socket_types)).toList();
for (String socketType : SOCKET_TYPES)
{
ChargeSocketDescriptor socket = new ChargeSocketDescriptor(socketType, 0, 0);
ChargeSocketDescriptor socket = new ChargeSocketDescriptor(socketType,0,0);
MaterialButton btn = (MaterialButton) inflater.inflate(R.layout.button_socket_type, typeBtns, false);
@@ -404,16 +406,16 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
// load SVG icon converted into VectorDrawable in res/drawable
@SuppressLint("DiscouragedApi")
int resIconId = getResources().getIdentifier("ic_charge_socket_" + socket.visualType(), "drawable",
requireContext().getPackageName());
int resIconId =
getResources().getIdentifier("ic_charge_socket_" + socket.visualType(), "drawable", requireContext().getPackageName());
if (resIconId != 0)
{
btn.setIcon(getResources().getDrawable(resIconId));
}
@SuppressLint("DiscouragedApi")
int resTypeId = getResources().getIdentifier("charge_socket_" + socket.visualType(), "string",
requireContext().getPackageName());
int resTypeId =
getResources().getIdentifier("charge_socket_" + socket.visualType(), "string", requireContext().getPackageName());
if (resTypeId != 0)
{
btn.setText(getResources().getString(resTypeId));
@@ -461,16 +463,13 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
// Add a TextWatcher to validate on text change
countView.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after)
{}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{}
public void onTextChanged(CharSequence s, int start, int before, int count) {}
@Override
public void afterTextChanged(Editable s)
{
public void afterTextChanged(Editable s) {
validatePositiveField(s.toString(), countInputLayout);
}
});
@@ -485,99 +484,88 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
// Add a TextWatcher to validate on text change
powerView.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after)
{}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{}
public void onTextChanged(CharSequence s, int start, int before, int count) {}
@Override
public void afterTextChanged(Editable s)
{
public void afterTextChanged(Editable s) {
validatePositiveField(s.toString(), powerInputLayout);
}
});
return new MaterialAlertDialogBuilder(requireActivity())
return new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setTitle(R.string.editor_socket)
.setView(dialogView)
.setPositiveButton(
R.string.save,
(dialog, which) -> {
String socketType = "";
for (MaterialButton b : buttonList)
{
if (b.isChecked())
{
socketType = b.getTag(R.id.socket_type).toString();
break;
}
}
.setPositiveButton(R.string.save,
(dialog, which) -> {
String socketType = "";
for (MaterialButton b : buttonList)
{
if (b.isChecked())
{
socketType = b.getTag(R.id.socket_type).toString();
break;
}
}
int countValue = 0; // 0 means 'unknown count'
try
{
countValue = Integer.parseInt(countView.getText().toString());
}
catch (NumberFormatException ignored)
{
Logger.w(CHARGE_SOCKETS_TAG, "Invalid count value for socket:" + countView.getText().toString());
}
int countValue = 0; // 0 means 'unknown count'
try
{
countValue = Integer.parseInt(countView.getText().toString());
}
catch (NumberFormatException ignored)
{
Logger.w(CHARGE_SOCKETS_TAG, "Invalid count value for socket:" + countView.getText().toString());
}
if (countValue < 0)
{
countValue = 0;
Logger.w(CHARGE_SOCKETS_TAG, "Invalid count value for socket:" + countView.getText().toString());
}
if (countValue < 0)
{
countValue = 0;
Logger.w(CHARGE_SOCKETS_TAG, "Invalid count value for socket:" + countView.getText().toString());
}
double powerValue = 0; // 0 means 'unknown power'
try
{
powerValue = Double.parseDouble(powerView.getText().toString());
}
catch (NumberFormatException ignored)
{
Logger.w(CHARGE_SOCKETS_TAG, "Invalid power value for socket:" + powerView.getText().toString());
}
double powerValue = 0; // 0 means 'unknown power'
try
{
powerValue = Double.parseDouble(powerView.getText().toString());
}
catch (NumberFormatException ignored)
{
Logger.w(CHARGE_SOCKETS_TAG, "Invalid power value for socket:" + powerView.getText().toString());
}
if (powerValue < 0)
{
powerValue = 0;
Logger.w(CHARGE_SOCKETS_TAG, "Invalid power value for socket:" + powerView.getText().toString());
}
if (powerValue < 0)
{
powerValue = 0;
Logger.w(CHARGE_SOCKETS_TAG, "Invalid power value for socket:" + powerView.getText().toString());
}
ChargeSocketDescriptor socket = new ChargeSocketDescriptor(socketType, countValue, powerValue);
ChargeSocketDescriptor socket =
new ChargeSocketDescriptor(socketType, countValue, powerValue);
updateChargeSockets(socketIndex, socket);
})
updateChargeSockets(socketIndex, socket);
})
.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
}
// Helper method for validation logic
private boolean validatePositiveField(String text, TextInputLayout layout)
{
if (text.isEmpty())
{
private boolean validatePositiveField(String text, TextInputLayout layout) {
if (text.isEmpty()) {
layout.setError(null); // No error if empty (assuming 0 is the default)
return true;
}
try
{
try {
double value = Double.parseDouble(text);
if (value < 0)
{
if (value < 0) {
layout.setError(getString(R.string.error_value_must_be_positive));
return false;
} else {
layout.setError(null);
return true;
}
else
{
layout.setError(null);
return true;
}
}
catch (NumberFormatException e)
{
} catch (NumberFormatException e) {
layout.setError(getString(R.string.error_invalid_number));
return false;
}
@@ -597,8 +585,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
{
sockets[socketIndex] = socket;
}
else
{
else {
List<ChargeSocketDescriptor> list = new ArrayList<>(Arrays.asList(sockets));
list.add(socket);
sockets = list.toArray(new ChargeSocketDescriptor[0]);
@@ -616,8 +603,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
GridLayout socketsGrid = mChargeSockets.findViewById(R.id.socket_grid_editor);
socketsGrid.removeAllViews();
for (int i = 0; i < sockets.length; i++)
{
for (int i = 0; i < sockets.length; i++) {
final int currentIndex = i;
ChargeSocketDescriptor socket = sockets[i];
@@ -628,30 +614,27 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
MaterialTextView power = itemView.findViewById(R.id.socket_power);
MaterialTextView count = itemView.findViewById(R.id.socket_count);
// load SVG icon converted into VectorDrawable in res/drawable
@SuppressLint("DiscouragedApi")
int resIconId = getResources().getIdentifier("ic_charge_socket_" + socket.visualType(), "drawable",
requireContext().getPackageName());
if (resIconId != 0)
{
requireContext().getPackageName());
if (resIconId != 0) {
icon.setImageResource(resIconId);
}
@SuppressLint("DiscouragedApi")
int resTypeId = getResources().getIdentifier("charge_socket_" + socket.visualType(), "string",
requireContext().getPackageName());
if (resTypeId != 0)
{
int resTypeId =
getResources().getIdentifier("charge_socket_" + socket.visualType(), "string", requireContext().getPackageName());
if (resTypeId != 0) {
type.setText(resTypeId);
}
if (socket.power() != 0)
{
if (socket.power() != 0) {
DecimalFormat df = new DecimalFormat("#.##");
power.setText(getString(R.string.kw_label, df.format(socket.power())));
}
else if (socket.ignorePower())
{
else if (socket.ignorePower()) {
power.setVisibility(INVISIBLE);
}
@@ -660,8 +643,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
count.setText(getString(R.string.count_label, socket.count()));
}
itemView.setOnClickListener(
v -> buildChargeSocketDialog(currentIndex, socket.type(), socket.count(), socket.power()).show());
itemView.setOnClickListener(v -> buildChargeSocketDialog(currentIndex, socket.type(), socket.count(), socket.power()).show());
socketsGrid.addView(itemView);
}
@@ -807,8 +789,9 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
View lineContactBlock =
initBlock(view, Metadata.MetadataType.FMD_CONTACT_LINE, R.id.block_line, R.drawable.ic_line_white,
R.string.editor_line_social_network, InputType.TYPE_TEXT_VARIATION_URI);
View blueskyContactBlock = initBlock(view, Metadata.MetadataType.FMD_CONTACT_BLUESKY, R.id.block_bluesky,
R.drawable.ic_bluesky, R.string.bluesky, InputType.TYPE_TEXT_VARIATION_URI);
View blueskyContactBlock =
initBlock(view, Metadata.MetadataType.FMD_CONTACT_BLUESKY, R.id.block_bluesky, R.drawable.ic_bluesky,
R.string.bluesky, InputType.TYPE_TEXT_VARIATION_URI);
View operatorBlock = initBlock(view, Metadata.MetadataType.FMD_OPERATOR, R.id.block_operator,
R.drawable.ic_operator, R.string.editor_operator, 0);
@@ -965,7 +948,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
mDisused.setVisibility(Editor.nativeCanMarkPlaceAsDisused() ? View.VISIBLE : View.GONE);
if (Editor.nativeAreSomeFeatureChangesUploaded())
if (Editor.nativeIsMapObjectUploaded())
{
mReset.setText(R.string.editor_place_doesnt_exist);
return;
@@ -983,7 +966,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
private void reset()
{
if (Editor.nativeAreSomeFeatureChangesUploaded())
if (Editor.nativeIsMapObjectUploaded())
{
placeDoesntExist();
return;
@@ -1016,7 +999,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
message = R.string.editor_reset_edits_message;
}
new MaterialAlertDialogBuilder(requireActivity())
new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setTitle(message)
.setPositiveButton(title,
(dialog, which) -> {
@@ -1039,16 +1022,15 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
private void placeDisused()
{
new MaterialAlertDialogBuilder(requireActivity())
.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();
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)

View File

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

View File

@@ -13,6 +13,7 @@ import app.organicmaps.R;
import app.organicmaps.sdk.editor.data.FeatureCategory;
import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.util.UiUtils;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textview.MaterialTextView;
@@ -68,7 +69,8 @@ public class FeatureCategoryAdapter extends RecyclerView.Adapter<RecyclerView.Vi
}
case TYPE_FOOTER ->
{
return new FooterViewHolder(inflater.inflate(R.layout.item_feature_category_footer, parent, false), mFragment);
return new FooterViewHolder(inflater.inflate(R.layout.item_feature_category_footer, parent, false),
mFragment);
}
default -> throw new IllegalArgumentException("Unsupported viewType: " + viewType);
}
@@ -132,21 +134,26 @@ public class FeatureCategoryAdapter extends RecyclerView.Adapter<RecyclerView.Vi
mSendNoteButton = itemView.findViewById(R.id.send_note_button);
mSendNoteButton.setOnClickListener(v -> listener.onSendNoteClicked());
final ColorStateList bgButtonColor = new ColorStateList(
new int[][] {
new int[] {android.R.attr.state_enabled}, // enabled
new int[] {-android.R.attr.state_enabled} // disabled
},
new int[] {ContextCompat.getColor(mSendNoteButton.getContext(), R.color.base_accent),
ContextCompat.getColor(mSendNoteButton.getContext(), R.color.button_accent_disabled)});
new int[][]{
new int[]{android.R.attr.state_enabled}, // enabled
new int[]{-android.R.attr.state_enabled} // disabled
},
new int[]{
ContextCompat.getColor(
mSendNoteButton.getContext(), R.color.base_accent),
ContextCompat.getColor(mSendNoteButton.getContext(), R.color.button_accent_disabled)
});
final ColorStateList textButtonColor = new ColorStateList(
new int[][] {
new int[] {android.R.attr.state_enabled}, // enabled
new int[] {-android.R.attr.state_enabled} // disabled
},
new int[] {ContextCompat.getColor(mSendNoteButton.getContext(),
UiUtils.getStyledResourceId(mSendNoteButton.getContext(),
android.R.attr.textColorPrimaryInverse)),
ContextCompat.getColor(mSendNoteButton.getContext(), R.color.button_accent_text_disabled)});
new int[][]{
new int[]{android.R.attr.state_enabled}, // enabled
new int[]{-android.R.attr.state_enabled} // disabled
},
new int[]{
ContextCompat.getColor(
mSendNoteButton.getContext(),
UiUtils.getStyledResourceId(mSendNoteButton.getContext(), android.R.attr.textColorPrimaryInverse)),
ContextCompat.getColor(mSendNoteButton.getContext(), R.color.button_accent_text_disabled)
});
mSendNoteButton.setBackgroundTintList(bgButtonColor);
mSendNoteButton.setTextColor(textButtonColor);
mNoteEditText.addTextChangedListener(new StringUtils.SimpleTextWatcher() {

View File

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

View File

@@ -2,16 +2,19 @@ package app.organicmaps.editor;
import android.content.res.Configuration;
import android.content.res.Resources;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import com.google.android.material.timepicker.MaterialTimePicker;
import com.google.android.material.timepicker.TimeFormat;
import app.organicmaps.R;
import app.organicmaps.sdk.editor.data.HoursMinutes;
import app.organicmaps.sdk.util.DateUtils;
import com.google.android.material.timepicker.MaterialTimePicker;
import com.google.android.material.timepicker.TimeFormat;
public class FromToTimePicker
{
@@ -29,11 +32,18 @@ public class FromToTimePicker
private boolean mIsFromTimePicked;
private int mInputMode;
public static void pickTime(@NonNull Fragment fragment, @NonNull FromToTimePicker.OnPickListener listener,
@NonNull HoursMinutes fromTime, @NonNull HoursMinutes toTime, int id,
public static void pickTime(@NonNull Fragment fragment,
@NonNull FromToTimePicker.OnPickListener listener,
@NonNull HoursMinutes fromTime,
@NonNull HoursMinutes toTime,
int id,
boolean startWithToTime)
{
FromToTimePicker timePicker = new FromToTimePicker(fragment, listener, fromTime, toTime, id);
FromToTimePicker timePicker = new FromToTimePicker(fragment,
listener,
fromTime,
toTime,
id);
if (startWithToTime)
timePicker.showToTimePicker();
@@ -41,8 +51,11 @@ public class FromToTimePicker
timePicker.showFromTimePicker();
}
private FromToTimePicker(@NonNull Fragment fragment, @NonNull FromToTimePicker.OnPickListener listener,
@NonNull HoursMinutes fromTime, @NonNull HoursMinutes toTime, int id)
private FromToTimePicker(@NonNull Fragment fragment,
@NonNull FromToTimePicker.OnPickListener listener,
@NonNull HoursMinutes fromTime,
@NonNull HoursMinutes toTime,
int id)
{
mActivity = fragment.requireActivity();
mFragmentManager = fragment.getChildFragmentManager();
@@ -87,12 +100,15 @@ public class FromToTimePicker
private MaterialTimePicker buildFromTimePicker()
{
MaterialTimePicker timePicker = buildTimePicker(mFromTime, mResources.getString(R.string.editor_time_from),
mResources.getString(R.string.next_button), null);
MaterialTimePicker timePicker = buildTimePicker(mFromTime,
mResources.getString(R.string.editor_time_from),
mResources.getString(R.string.next_button),
null);
timePicker.addOnNegativeButtonClickListener(view -> finishTimePicking(false));
timePicker.addOnPositiveButtonClickListener(view -> {
timePicker.addOnPositiveButtonClickListener(view ->
{
mIsFromTimePicked = true;
saveState(timePicker, true);
mFromTimePicker = null;
@@ -106,10 +122,13 @@ public class FromToTimePicker
private MaterialTimePicker buildToTimePicker()
{
MaterialTimePicker timePicker = buildTimePicker(mToTime, mResources.getString(R.string.editor_time_to), null,
MaterialTimePicker timePicker = buildTimePicker(mToTime,
mResources.getString(R.string.editor_time_to),
null,
mResources.getString(R.string.back));
timePicker.addOnNegativeButtonClickListener(view -> {
timePicker.addOnNegativeButtonClickListener(view ->
{
saveState(timePicker, false);
mToTimePicker = null;
if (mIsFromTimePicked)
@@ -118,7 +137,8 @@ public class FromToTimePicker
finishTimePicking(false);
});
timePicker.addOnPositiveButtonClickListener(view -> {
timePicker.addOnPositiveButtonClickListener(view ->
{
saveState(timePicker, false);
finishTimePicking(true);
});
@@ -129,18 +149,18 @@ public class FromToTimePicker
}
@NonNull
private MaterialTimePicker buildTimePicker(@NonNull HoursMinutes time, @NonNull String title,
private MaterialTimePicker buildTimePicker(@NonNull HoursMinutes time,
@NonNull String title,
@Nullable String positiveButtonTextOverride,
@Nullable String negativeButtonTextOverride)
{
MaterialTimePicker.Builder builder =
new MaterialTimePicker.Builder()
.setTitleText(title)
.setTimeFormat(mIs24HourFormat ? TimeFormat.CLOCK_24H : TimeFormat.CLOCK_12H)
.setInputMode(mInputMode)
.setTheme(R.style.MwmTheme_MaterialTimePicker)
.setHour((int) time.hours)
.setMinute((int) time.minutes);
MaterialTimePicker.Builder builder = new MaterialTimePicker.Builder()
.setTitleText(title)
.setTimeFormat(mIs24HourFormat ? TimeFormat.CLOCK_24H : TimeFormat.CLOCK_12H)
.setInputMode(mInputMode)
.setTheme(R.style.MwmTheme_MaterialTimePicker)
.setHour((int) time.hours)
.setMinute((int) time.minutes);
if (positiveButtonTextOverride != null)
builder.setPositiveButtonText(positiveButtonTextOverride);

View File

@@ -1,14 +1,11 @@
package app.organicmaps.editor;
import static app.organicmaps.sdk.editor.data.Language.DEFAULT_LANG_CODE;
import android.content.res.Configuration;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.core.os.ConfigurationCompat;
import androidx.core.os.LocaleListCompat;
import androidx.fragment.app.Fragment;
import app.organicmaps.R;
import app.organicmaps.base.BaseMwmRecyclerFragment;
import app.organicmaps.sdk.editor.Editor;
import app.organicmaps.sdk.editor.data.Language;
@@ -24,7 +21,6 @@ import java.util.Set;
public class LanguagesFragment extends BaseMwmRecyclerFragment<LanguagesAdapter>
{
final static String EXISTING_LOCALIZED_NAMES = "ExistingLocalizedNames";
final static String INCLUDE_LOCAL_LANGUAGE = "IncludeLocalLanguage";
public interface Listener
{
@@ -38,7 +34,6 @@ public class LanguagesFragment extends BaseMwmRecyclerFragment<LanguagesAdapter>
protected LanguagesAdapter createAdapter()
{
Bundle args = getArguments();
boolean includeLocalLanguage = args != null ? args.getBoolean(INCLUDE_LOCAL_LANGUAGE) : true;
Set<String> existingLanguages =
args != null ? new HashSet<>(args.getStringArrayList(EXISTING_LOCALIZED_NAMES)) : new HashSet<>();
@@ -73,13 +68,6 @@ public class LanguagesFragment extends BaseMwmRecyclerFragment<LanguagesAdapter>
languages.addAll(0, systemLanguages.stream().filter(Objects::nonNull).toList());
if (includeLocalLanguage)
{
String localLanguageLabel = getString(R.string.pref_maplanguage_local);
Language localLanguage = new Language(DEFAULT_LANG_CODE, localLanguageLabel);
languages.add(0, localLanguage);
}
return new LanguagesAdapter(this, languages.toArray(new Language[languages.size()]));
}

View File

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

View File

@@ -7,6 +7,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import androidx.annotation.IdRes;
import androidx.annotation.IntRange;
import androidx.annotation.Nullable;
@@ -121,14 +122,20 @@ class SimpleTimetableAdapter extends RecyclerView.Adapter<SimpleTimetableAdapter
notifyItemChanged(getItemCount() - 1);
}
private void pickTime(int position, @IntRange(from = ID_OPENING_TIME, to = ID_CLOSED_SPAN) int id,
private void pickTime(int position,
@IntRange(from = ID_OPENING_TIME, to = ID_CLOSED_SPAN) int id,
boolean startWithToTime)
{
final Timetable data = mItems.get(position);
mPickingPosition = position;
FromToTimePicker.pickTime(mFragment, this, data.workingTimespan.start, data.workingTimespan.end, id,
startWithToTime);
FromToTimePicker.pickTime(mFragment,
this,
data.workingTimespan.start,
data.workingTimespan.end,
id,
startWithToTime);
}
@Override
@@ -377,21 +384,26 @@ class SimpleTimetableAdapter extends RecyclerView.Adapter<SimpleTimetableAdapter
final String text = mFragment.getString(R.string.editor_time_add);
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)});
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)});
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);

View File

@@ -9,8 +9,8 @@ import androidx.annotation.Nullable;
import app.organicmaps.R;
import app.organicmaps.base.BaseMwmRecyclerFragment;
public class SimpleTimetableFragment
extends BaseMwmRecyclerFragment<SimpleTimetableAdapter> implements TimetableProvider
public class SimpleTimetableFragment extends BaseMwmRecyclerFragment<SimpleTimetableAdapter>
implements TimetableProvider
{
private SimpleTimetableAdapter mAdapter;
@Nullable

View File

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

View File

@@ -35,30 +35,25 @@ public class LayerBottomSheetItem
@DrawableRes
int drawableResId = 0;
@StringRes
int buttonTextResource = switch (mode)
{
case OUTDOORS ->
{
drawableResId = R.drawable.ic_layers_outdoors;
yield R.string.button_layer_outdoor;
}
case SUBWAY ->
{
drawableResId = R.drawable.ic_layers_subway;
yield R.string.subway;
}
case ISOLINES ->
{
drawableResId = R.drawable.ic_layers_isoline;
yield R.string.button_layer_isolines;
}
case TRAFFIC ->
{
drawableResId = R.drawable.ic_layers_traffic;
yield R.string.button_layer_traffic;
}
int buttonTextResource = switch (mode) {
case OUTDOORS -> {
drawableResId = R.drawable.ic_layers_outdoors;
yield R.string.button_layer_outdoor;
}
case SUBWAY -> {
drawableResId = R.drawable.ic_layers_subway;
yield R.string.subway;
}
case ISOLINES -> {
drawableResId = R.drawable.ic_layers_isoline;
yield R.string.button_layer_isolines;
}
case TRAFFIC -> {
drawableResId = R.drawable.ic_layers_traffic;
yield R.string.button_layer_traffic;
}
};
return new LayerBottomSheetItem(drawableResId, buttonTextResource, mode, layerItemClickListener);
return new LayerBottomSheetItem(drawableResId, buttonTextResource, mode, layerItemClickListener);
}
@NonNull

View File

@@ -5,9 +5,11 @@ import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.textview.MaterialTextView;
import app.organicmaps.R;
import app.organicmaps.adapter.OnItemClickListener;
import com.google.android.material.textview.MaterialTextView;
class LayerHolder extends RecyclerView.ViewHolder
{

View File

@@ -395,7 +395,7 @@ public class MapButtonsController extends Fragment
0;
// Allow offset tolerance for zoom buttons
};
showButton(getViewTopOffset(translation, button) >= toleranceOffset, entry.getKey());
showButton(getViewTopOffset(translation, button) >= toleranceOffset, entry.getKey());
}
}
}

View File

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

View File

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

View File

@@ -18,6 +18,7 @@ import app.organicmaps.R;
import app.organicmaps.maplayer.MapButtonsViewModel;
import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.Router;
import app.organicmaps.sdk.location.LocationHelper;
import app.organicmaps.sdk.maplayer.traffic.TrafficManager;
import app.organicmaps.sdk.routing.CarDirection;
import app.organicmaps.sdk.routing.RoutingController;
@@ -98,11 +99,6 @@ public class NavigationController implements TrafficManager.TrafficCallback, Nav
mSpeedLimit = topFrame.findViewById(R.id.nav_speed_limit);
mCurrentSpeed = topFrame.findViewById(R.id.nav_current_speed);
View mTopbar = topFrame.findViewById(R.id.statutbar);
ViewCompat.setOnApplyWindowInsetsListener(mTopbar, (v, windowInsets) -> {
UiUtils.setViewNavigationTopInsetsMargin(v, windowInsets);
return windowInsets;
});
// Show a blank view below the navbar to hide the menu content
final View navigationBarBackground = mFrame.findViewById(R.id.nav_bottom_sheet_nav_bar);
final View nextTurnContainer = mFrame.findViewById(R.id.nav_next_turn_container);
@@ -272,16 +268,18 @@ public class NavigationController implements TrafficManager.TrafficCallback, Nav
private void updateSpeedWidgets(@NonNull final RoutingInfo info)
{
final Location location = MwmApplication.from(mFrame.getContext()).getLocationHelper().getSavedLocation();
final LocationHelper locationHelper = MwmApplication.from(mFrame.getContext()).getLocationHelper();
final Location location = locationHelper.getSavedLocation();
if (location == null)
{
mSpeedLimit.setSpeedLimit(-1, false);
mCurrentSpeed.setCurrentSpeed(-1);
return;
}
final double currentAvgSpeed = locationHelper.getAverageSpeed();
final int fSpeedLimit = StringUtils.nativeFormatSpeed(info.speedLimitMps);
final boolean speedLimitExceeded = fSpeedLimit < StringUtils.nativeFormatSpeed(location.getSpeed());
final boolean speedLimitExceeded = fSpeedLimit < StringUtils.nativeFormatSpeed(currentAvgSpeed);
mSpeedLimit.setSpeedLimit(fSpeedLimit, speedLimitExceeded);
mCurrentSpeed.setCurrentSpeed(location.getSpeed());
mCurrentSpeed.setCurrentSpeed(currentAvgSpeed);
}
}

View File

@@ -43,6 +43,7 @@ import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.widget.recycler.DotDividerItemDecoration;
import app.organicmaps.widget.recycler.MultilineLayoutManager;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.imageview.ShapeableImageView;
import com.google.android.material.textview.MaterialTextView;
@@ -122,9 +123,9 @@ final class RoutingBottomMenuController implements View.OnClickListener
@NonNull View timeElevationLine, @NonNull View transitFrame,
@NonNull MaterialTextView error, @NonNull MaterialButton start,
@NonNull ShapeableImageView altitudeChart, @NonNull MaterialTextView time,
@NonNull MaterialTextView altitudeDifference,
@NonNull MaterialTextView timeVehicle, @Nullable MaterialTextView arrival,
@NonNull View actionFrame, @Nullable RoutingBottomMenuListener listener)
@NonNull MaterialTextView altitudeDifference, @NonNull MaterialTextView timeVehicle,
@Nullable MaterialTextView arrival, @NonNull View actionFrame,
@Nullable RoutingBottomMenuListener listener)
{
mContext = context;
mAltitudeChartFrame = altitudeChartFrame;

View File

@@ -12,6 +12,9 @@ import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import com.google.android.material.textview.MaterialTextView;
import app.organicmaps.MwmApplication;
import app.organicmaps.R;
import app.organicmaps.sdk.Framework;
@@ -26,7 +29,6 @@ import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener;
import app.organicmaps.widget.RoutingToolbarButton;
import app.organicmaps.widget.ToolbarController;
import app.organicmaps.widget.WheelProgressView;
import com.google.android.material.textview.MaterialTextView;
public class RoutingPlanController extends ToolbarController
{
@@ -262,7 +264,7 @@ public class RoutingPlanController extends ToolbarController
default -> throw new IllegalArgumentException("unknown router: " + router);
};
RoutingToolbarButton button = mRouterTypes.findViewById(mRouterTypes.getCheckedRadioButtonId());
RoutingToolbarButton button = mRouterTypes.findViewById(mRouterTypes.getCheckedRadioButtonId());
button.progress();
updateProgressLabels();

View File

@@ -14,10 +14,12 @@ import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.textview.MaterialTextView;
import app.organicmaps.R;
import app.organicmaps.sdk.search.DisplayedCategories;
import app.organicmaps.sdk.util.Language;
import com.google.android.material.textview.MaterialTextView;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Locale;

View File

@@ -10,12 +10,14 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.textview.MaterialTextView;
import app.organicmaps.R;
import app.organicmaps.sdk.search.SearchResult;
import app.organicmaps.util.Graphics;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.util.UiUtils;
import com.google.android.material.textview.MaterialTextView;
class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.SearchDataViewHolder>
{
@@ -150,8 +152,7 @@ class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.SearchDataViewHol
{
final Resources resources = mSearchFragment.getResources();
if (result.description.openNow != SearchResult.OPEN_NOW_YES
&& result.description.openNow != SearchResult.OPEN_NOW_NO)
if (result.description.openNow != SearchResult.OPEN_NOW_YES && result.description.openNow != SearchResult.OPEN_NOW_NO)
{
// Hide if unknown opening hours state
UiUtils.hide(mOpen);
@@ -168,18 +169,15 @@ class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.SearchDataViewHol
{
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);
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));
}
else
{
UiUtils.setTextAndShow(
mOpen, isOpen ? resources.getString(R.string.editor_time_open) : resources.getString(R.string.closed));
mOpen.setTextColor(
ContextCompat.getColor(mSearchFragment.getContext(), isOpen ? R.color.base_green : R.color.base_red));
UiUtils.setTextAndShow(mOpen, isOpen ? resources.getString(R.string.editor_time_open) : resources.getString(R.string.closed));
mOpen.setTextColor(ContextCompat.getColor(mSearchFragment.getContext(), isOpen ? R.color.base_green : R.color.base_red));
}
}

View File

@@ -273,8 +273,7 @@ public class SearchFragment extends BaseMwmFragment implements SearchListener, C
RecyclerView mResults = mResultsFrame.findViewById(R.id.recycler);
setRecyclerScrollListener(mResults);
mResultsPlaceholder = mResultsFrame.findViewById(R.id.placeholder);
mResultsPlaceholder.setContent(R.string.search_not_found, R.string.search_not_found_query,
R.drawable.ic_search_fail);
mResultsPlaceholder.setContent(R.string.search_not_found, R.string.search_not_found_query, R.drawable.ic_search_fail);
mSearchAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver()
{

View File

@@ -5,13 +5,15 @@ import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.textview.MaterialTextView;
import app.organicmaps.MwmApplication;
import app.organicmaps.R;
import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.search.SearchRecents;
import app.organicmaps.util.Graphics;
import app.organicmaps.widget.SearchToolbarController;
import com.google.android.material.textview.MaterialTextView;
class SearchHistoryAdapter extends RecyclerView.Adapter<SearchHistoryAdapter.ViewHolder>
{

View File

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

View File

@@ -8,12 +8,14 @@ import android.view.ViewGroup;
import android.widget.CompoundButton;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.materialswitch.MaterialSwitch;
import app.organicmaps.R;
import app.organicmaps.base.BaseMwmToolbarFragment;
import app.organicmaps.sdk.routing.RoutingController;
import app.organicmaps.sdk.routing.RoutingOptions;
import app.organicmaps.sdk.settings.RoadType;
import com.google.android.material.materialswitch.MaterialSwitch;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;

View File

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

View File

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

View File

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

View File

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

View File

@@ -53,7 +53,7 @@ public class MenuBottomSheetFragment extends BottomSheetDialogFragment
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState)
{
return new BottomSheetDialog(requireContext(), R.style.MwmTheme_BottomSheetDialog) {
return new BottomSheetDialog(requireContext(), getTheme()) {
@Override
public void onAttachedToWindow()
{

View File

@@ -8,165 +8,165 @@ import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public abstract class BaseSignView extends View
{
private float mBorderWidthRatio = 0.1f;
protected void setBorderWidthRatio(float ratio)
{
mBorderWidthRatio = ratio;
}
private float mBorderInsetRatio = 0f;
protected void setBorderInsetRatio(float ratio)
{
mBorderInsetRatio = ratio;
}
// colors
protected int mBackgroundColor;
protected int mBorderColor;
protected int mAlertColor;
protected int mTextColor;
protected int mTextAlertColor;
// paints
protected final Paint mBackgroundPaint;
protected final Paint mBorderPaint;
protected final Paint mTextPaint;
// geometry
protected float mWidth;
protected float mHeight;
protected float mRadius;
protected float mBorderWidth;
protected float mBorderRadius;
public BaseSignView(Context ctx, @Nullable AttributeSet attrs)
{
super(ctx, attrs);
mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBorderPaint.setStyle(Paint.Style.STROKE);
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
}
protected void setColors(int backgroundColor, int borderColor, int alertColor, int textColor, int textAlertColor)
{
mBackgroundColor = backgroundColor;
mBorderColor = borderColor;
mAlertColor = alertColor;
mTextColor = textColor;
mTextAlertColor = textAlertColor;
mBackgroundPaint.setColor(mBackgroundColor);
mBorderPaint.setColor(mBorderColor);
mTextPaint.setColor(mTextColor);
}
@Override
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight)
{
super.onSizeChanged(width, height, oldWidth, oldHeight);
final float paddingX = getPaddingLeft() + getPaddingRight();
final float paddingY = getPaddingTop() + getPaddingBottom();
mWidth = width - paddingX;
mHeight = height - paddingY;
mRadius = Math.min(mWidth, mHeight) / 2f;
mBorderWidth = mRadius * mBorderWidthRatio;
// subtract half the stroke PLUS the extra inset
final float gap = mRadius * mBorderInsetRatio;
mBorderRadius = mRadius - (mBorderWidth / 2f) - gap;
configureTextSize();
}
@Override
protected void onDraw(@NonNull Canvas canvas)
{
super.onDraw(canvas);
final String str = getValueString();
if (str == null)
return;
final float cx = mWidth / 2f;
final float cy = mHeight / 2f;
// background & border
boolean alert = isAlert();
mBackgroundPaint.setColor(alert ? mAlertColor : mBackgroundColor);
canvas.drawCircle(cx, cy, mRadius, mBackgroundPaint);
if (!alert)
{
mBorderPaint.setStrokeWidth(mBorderWidth);
mBorderPaint.setColor(mBorderColor);
canvas.drawCircle(cx, cy, mBorderRadius, mBorderPaint);
private float mBorderWidthRatio = 0.1f;
protected void setBorderWidthRatio(float ratio) {
mBorderWidthRatio = ratio;
}
// text
mTextPaint.setColor(alert ? mTextAlertColor : mTextColor);
drawValueString(canvas, cx, cy, str);
}
@Override
public boolean onTouchEvent(@NonNull MotionEvent e)
{
final float cx = mWidth / 2f, cy = mHeight / 2f;
final float dx = e.getX() - cx, dy = e.getY() - cy;
if ((dx * dx) + (dy * dy) <= (mRadius * mRadius))
{
performClick();
return true;
private float mBorderInsetRatio = 0f;
protected void setBorderInsetRatio(float ratio) {
mBorderInsetRatio = ratio;
}
return false;
}
@Override
public boolean performClick()
{
super.performClick();
return false;
}
// colors
protected int mBackgroundColor;
protected int mBorderColor;
protected int mAlertColor;
protected int mTextColor;
protected int mTextAlertColor;
private void drawValueString(Canvas c, float cx, float cy, String str)
{
Rect b = new Rect();
mTextPaint.getTextBounds(str, 0, str.length(), b);
final float y = cy - b.exactCenterY();
c.drawText(str, cx, y, mTextPaint);
}
// paints
protected final Paint mBackgroundPaint;
protected final Paint mBorderPaint;
protected final Paint mTextPaint;
void configureTextSize()
{
String text = getValueString();
if (text == null)
return;
final float textRadius = mBorderRadius - mBorderWidth;
final float maxTextSize = 2f * textRadius;
final float maxTextSize2 = maxTextSize * maxTextSize;
float lo = 0f, hi = maxTextSize, sz = maxTextSize;
Rect b = new Rect();
while (lo <= hi)
// geometry
protected float mWidth;
protected float mHeight;
protected float mRadius;
protected float mBorderWidth;
protected float mBorderRadius;
public BaseSignView(Context ctx, @Nullable AttributeSet attrs)
{
sz = (lo + hi) / 2f;
mTextPaint.setTextSize(sz);
mTextPaint.getTextBounds(text, 0, text.length(), b);
float area = b.width() * b.width() + b.height() * b.height();
if (area <= maxTextSize2)
lo = sz + 1f;
else
hi = sz - 1f;
super(ctx, attrs);
mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBorderPaint.setStyle(Paint.Style.STROKE);
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setTextAlign(Paint.Align.CENTER);
mTextPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
}
mTextPaint.setTextSize(Math.max(1f, sz));
}
/** child must return the string to draw, or null if nothing */
@Nullable
protected abstract String getValueString();
protected void setColors(int backgroundColor,
int borderColor,
int alertColor,
int textColor,
int textAlertColor)
{
mBackgroundColor = backgroundColor;
mBorderColor = borderColor;
mAlertColor = alertColor;
mTextColor = textColor;
mTextAlertColor = textAlertColor;
/** child decides if this is in “alert” state */
protected abstract boolean isAlert();
mBackgroundPaint.setColor(mBackgroundColor);
mBorderPaint.setColor(mBorderColor);
mTextPaint.setColor(mTextColor);
}
@Override
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
super.onSizeChanged(width, height, oldWidth, oldHeight);
final float paddingX = getPaddingLeft() + getPaddingRight();
final float paddingY = getPaddingTop() + getPaddingBottom();
mWidth = width - paddingX;
mHeight = height - paddingY;
mRadius = Math.min(mWidth, mHeight) / 2f;
mBorderWidth = mRadius * mBorderWidthRatio;
// subtract half the stroke PLUS the extra inset
final float gap = mRadius * mBorderInsetRatio;
mBorderRadius = mRadius - (mBorderWidth / 2f) - gap;
configureTextSize();
}
@Override
protected void onDraw(@NonNull Canvas canvas)
{
super.onDraw(canvas);
final String str = getValueString();
if (str == null) return;
final float cx = mWidth / 2f;
final float cy = mHeight / 2f;
// background & border
boolean alert = isAlert();
mBackgroundPaint.setColor(alert ? mAlertColor : mBackgroundColor);
canvas.drawCircle(cx, cy, mRadius, mBackgroundPaint);
if (!alert)
{
mBorderPaint.setStrokeWidth(mBorderWidth);
mBorderPaint.setColor(mBorderColor);
canvas.drawCircle(cx, cy, mBorderRadius, mBorderPaint);
}
// text
mTextPaint.setColor(alert ? mTextAlertColor : mTextColor);
drawValueString(canvas, cx, cy, str);
}
@Override
public boolean onTouchEvent(@NonNull MotionEvent e)
{
final float cx = mWidth / 2f, cy = mHeight / 2f;
final float dx = e.getX() - cx, dy = e.getY() - cy;
if ((dx * dx) + (dy * dy) <= (mRadius * mRadius))
{
performClick();
return true;
}
return false;
}
@Override
public boolean performClick()
{
super.performClick();
return false;
}
private void drawValueString(Canvas c, float cx, float cy, String str)
{
Rect b = new Rect();
mTextPaint.getTextBounds(str, 0, str.length(), b);
final float y = cy - b.exactCenterY();
c.drawText(str, cx, y, mTextPaint);
}
void configureTextSize()
{
String text = getValueString();
if (text == null) return;
final float textRadius = mBorderRadius - mBorderWidth;
final float maxTextSize = 2f * textRadius;
final float maxTextSize2 = maxTextSize * maxTextSize;
float lo = 0f, hi = maxTextSize, sz = maxTextSize;
Rect b = new Rect();
while (lo <= hi)
{
sz = (lo + hi) / 2f;
mTextPaint.setTextSize(sz);
mTextPaint.getTextBounds(text, 0, text.length(), b);
float area = b.width()*b.width() + b.height()*b.height();
if (area <= maxTextSize2)
lo = sz + 1f;
else
hi = sz - 1f;
}
mTextPaint.setTextSize(Math.max(1f, sz));
}
/** child must return the string to draw, or null if nothing */
@Nullable
protected abstract String getValueString();
/** child decides if this is in “alert” state */
protected abstract boolean isAlert();
}

View File

@@ -4,7 +4,9 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Pair;
import androidx.annotation.Nullable;
import app.organicmaps.R;
import app.organicmaps.sdk.util.StringUtils;
@@ -20,18 +22,18 @@ public class CurrentSpeedView extends BaseSignView
setBorderWidthRatio(0.1f);
setBorderInsetRatio(0.05f);
try (TypedArray a = ctx.getTheme().obtainStyledAttributes(
attrs, R.styleable.CurrentSpeedView /* reuse same attrs or define new */, 0, 0))
try (TypedArray a = ctx.getTheme()
.obtainStyledAttributes(attrs, R.styleable.CurrentSpeedView /* reuse same attrs or define new */ , 0, 0))
{
int bg = a.getColor(R.styleable.CurrentSpeedView_currentSpeedBackgroundColor, DefaultValues.BACKGROUND_COLOR);
int bd = a.getColor(R.styleable.CurrentSpeedView_currentSpeedBorderColor, DefaultValues.BORDER_COLOR);
int tc = a.getColor(R.styleable.CurrentSpeedView_currentSpeedTextColor, DefaultValues.TEXT_COLOR);
int bg = a.getColor(R.styleable.CurrentSpeedView_currentSpeedBackgroundColor, DefaultValues.BACKGROUND_COLOR);
int bd = a.getColor(R.styleable.CurrentSpeedView_currentSpeedBorderColor, DefaultValues.BORDER_COLOR);
int tc = a.getColor(R.styleable.CurrentSpeedView_currentSpeedTextColor, DefaultValues.TEXT_COLOR);
setColors(bg, bd, 0, tc, 0);
if (isInEditMode())
{
mSpeedMps = a.getInt(R.styleable.CurrentSpeedView_currentSpeedEditModeCurrentSpeed, 50);
mSpeedStr = Integer.toString((int) mSpeedMps);
mSpeedMps = a.getInt(R.styleable.CurrentSpeedView_currentSpeedEditModeCurrentSpeed, 50);
mSpeedStr = Integer.toString((int)mSpeedMps);
}
}
}
@@ -45,7 +47,7 @@ public class CurrentSpeedView extends BaseSignView
}
else
{
Pair<String, String> su = StringUtils.nativeFormatSpeedAndUnits(mps);
Pair<String,String> su = StringUtils.nativeFormatSpeedAndUnits(mps);
mSpeedStr = su.first;
}
requestLayout();
@@ -68,8 +70,8 @@ public class CurrentSpeedView extends BaseSignView
private interface DefaultValues
{
int BACKGROUND_COLOR = 0xFFFFFFFF;
int BORDER_COLOR = 0xFF000000;
int TEXT_COLOR = 0xFF000000;
int BACKGROUND_COLOR = 0xFFFFFFFF;
int BORDER_COLOR = 0xFF000000;
int TEXT_COLOR = 0xFF000000;
}
}

View File

@@ -12,11 +12,13 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.core.content.ContextCompat;
import app.organicmaps.R;
import app.organicmaps.util.UiUtils;
import com.google.android.material.imageview.ShapeableImageView;
import com.google.android.material.textview.MaterialTextView;
import app.organicmaps.R;
import app.organicmaps.util.UiUtils;
public class PlaceholderView extends LinearLayout
{
@SuppressWarnings("NullableProblems")

View File

@@ -5,14 +5,16 @@ import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import androidx.annotation.Nullable;
import app.organicmaps.R;
public class SpeedLimitView extends BaseSignView
{
private int mSpeedLimit = -1;
private boolean mAlert = false;
private String mSpeedStr = "-1";
private int mSpeedLimit = -1;
private boolean mAlert = false;
private String mSpeedStr = "-1";
private final int unlimitedBorderColor;
private final int unlimitedStripeColor;
@@ -25,22 +27,15 @@ public class SpeedLimitView extends BaseSignView
try (TypedArray styleAttrs = ctx.getTheme().obtainStyledAttributes(attrs, R.styleable.SpeedLimitView, 0, 0))
{
final int bgColor =
styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitBackgroundColor, DefaultValues.BACKGROUND_COLOR);
final int borderColor =
styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitBorderColor, DefaultValues.BORDER_COLOR);
final int alertColor =
styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitAlertColor, DefaultValues.ALERT_COLOR);
final int textColor =
styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitTextColor, DefaultValues.TEXT_COLOR);
final int txtAlertColor =
styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitTextAlertColor, DefaultValues.TEXT_ALERT_COLOR);
final int bgColor = styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitBackgroundColor, DefaultValues.BACKGROUND_COLOR);
final int borderColor = styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitBorderColor, DefaultValues.BORDER_COLOR);
final int alertColor = styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitAlertColor, DefaultValues.ALERT_COLOR);
final int textColor = styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitTextColor, DefaultValues.TEXT_COLOR);
final int txtAlertColor = styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitTextAlertColor, DefaultValues.TEXT_ALERT_COLOR);
setColors(bgColor, borderColor, alertColor, textColor, txtAlertColor);
unlimitedBorderColor = styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitUnlimitedBorderColor,
DefaultValues.UNLIMITED_BORDER_COLOR);
unlimitedStripeColor = styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitUnlimitedStripeColor,
DefaultValues.UNLIMITED_STRIPE_COLOR);
unlimitedBorderColor = styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitUnlimitedBorderColor, DefaultValues.UNLIMITED_BORDER_COLOR);
unlimitedStripeColor = styleAttrs.getColor(R.styleable.SpeedLimitView_speedLimitUnlimitedStripeColor, DefaultValues.UNLIMITED_STRIPE_COLOR);
if (isInEditMode())
{
@@ -56,7 +51,7 @@ public class SpeedLimitView extends BaseSignView
if (mSpeedLimit != limit)
{
mSpeedLimit = limit;
mSpeedStr = Integer.toString(limit);
mSpeedStr = Integer.toString(limit);
requestLayout();
}
mAlert = alert;
@@ -80,7 +75,7 @@ public class SpeedLimitView extends BaseSignView
@Override
protected void onDraw(Canvas canvas)
{
final float cx = mWidth / 2f, cy = mHeight / 2f;
final float cx = mWidth/2f, cy = mHeight/2f;
if (mSpeedLimit == 0) // 0 means unlimited speed (maxspeed=none)
{
@@ -110,7 +105,7 @@ public class SpeedLimitView extends BaseSignView
stripe.setStrokeWidth(mBorderWidth * 0.4f);
final float radius = mRadius * 0.8f; // Shorten to 80% of full radius
final float diag = (float) (1 / Math.sqrt(2)); // 45 degrees
final float diag = (float) (1/Math.sqrt(2)); // 45 degrees
final float dx = -diag, dy = +diag;
final float px = -dy, py = +dx; // Perpendicular
final float step = radius * 0.15f; // Spacing
@@ -127,13 +122,14 @@ public class SpeedLimitView extends BaseSignView
}
}
private interface DefaultValues
{
int BACKGROUND_COLOR = 0xFFFFFFFF;
int BORDER_COLOR = 0xFFFF0000;
int ALERT_COLOR = 0xFFFF0000;
int TEXT_COLOR = 0xFF000000;
int TEXT_ALERT_COLOR = 0xFFFFFFFF;
int BACKGROUND_COLOR = 0xFFFFFFFF;
int BORDER_COLOR = 0xFFFF0000;
int ALERT_COLOR = 0xFFFF0000;
int TEXT_COLOR = 0xFF000000;
int TEXT_ALERT_COLOR = 0xFFFFFFFF;
int UNLIMITED_BORDER_COLOR = 0xFF000000;
int UNLIMITED_STRIPE_COLOR = 0xFF000000;
}

View File

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

View File

@@ -72,7 +72,7 @@ public class MyPositionButton
case LocationState.FOLLOW_AND_ROTATE -> R.drawable.ic_follow_and_rotate;
default -> throw new IllegalArgumentException("Invalid button mode: " + mode);
};
image = ResourcesCompat.getDrawable(resources, drawableRes, context.getTheme());
image = ResourcesCompat.getDrawable(resources, drawableRes, context.getTheme());
mIcons.put(mode, image);
}

View File

@@ -1,9 +1,9 @@
package app.organicmaps.widget.placepage;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import app.organicmaps.sdk.util.StringUtils;
import com.github.mikephil.charting.charts.BarLineChartBase;
import androidx.annotation.Nullable;
import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.formatter.IAxisValueFormatter;

View File

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

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