mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-19 21:13:35 +00:00
Compare commits
23 Commits
generate-n
...
matheusgom
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f4eb8628e0 | ||
|
|
4c715cd2ee | ||
|
|
c2bc6c27aa | ||
|
|
1095e5dbc3 | ||
|
|
a1cbcc5885 | ||
|
|
641f2308c6 | ||
|
|
f858ebcce0 | ||
|
|
eb376f5afc | ||
|
|
71b47719af | ||
|
|
4f7230fcbe | ||
|
|
2dafdd4338 | ||
|
|
0237751afe | ||
|
|
e7fb3a2f2c | ||
|
|
e08d60bb40 | ||
|
|
de4252f86c | ||
|
|
9d87d77055 | ||
|
|
c88f59eb75 | ||
|
|
9b5c700ad8 | ||
|
|
7d5e6fabcd | ||
|
|
ebe0364030 | ||
|
|
43e7e1eb2e | ||
|
|
ce9af79a68 | ||
|
|
b54b77bce6 |
@@ -105,17 +105,17 @@ jobs:
|
||||
run: |
|
||||
echo "Cloning $FORGEJO_SERVER_URL/$FORGEJO_REPOSITORY branch $FORGEJO_REF_NAME"
|
||||
cd ~
|
||||
git clone --recurse-submodules --shallow-submodules -b $FORGEJO_REF_NAME --single-branch $FORGEJO_SERVER_URL/$FORGEJO_REPOSITORY.git comaps
|
||||
git clone --depth 1 --recurse-submodules --shallow-submodules -b $FORGEJO_REF_NAME --single-branch $FORGEJO_SERVER_URL/$FORGEJO_REPOSITORY.git comaps
|
||||
- name: Checkout wikiparser repo
|
||||
shell: bash
|
||||
run: |
|
||||
cd ~
|
||||
git clone https://codeberg.org/comaps/wikiparser.git
|
||||
git clone --depth 1 --single-branch https://codeberg.org/comaps/wikiparser.git
|
||||
- name: Checkout subways repo
|
||||
shell: bash
|
||||
run: |
|
||||
cd ~
|
||||
git clone https://codeberg.org/comaps/subways.git
|
||||
git clone --depth 1 --single-branch https://codeberg.org/comaps/subways.git
|
||||
|
||||
copy-coasts:
|
||||
# if: inputs.run-copy-coasts
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
This file contains a list of people who have contributed to this project.
|
||||
Its not neccesarily comprehensive.
|
||||
It is not necessarily comprehensive as contributors must manually add themselves.
|
||||
Feel free to add yourself here along with your first contribution!
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
CoMaps contributors:
|
||||
(in alphabetic order)
|
||||
(in alphabetical order)
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Bastian Greshake Tzovaras
|
||||
clover sage
|
||||
Harry Bond <me@hbond.xyz>
|
||||
thesupertechie
|
||||
vikiawv
|
||||
Yannik Bloscheck
|
||||
|
||||
|
||||
@@ -107,6 +107,7 @@ import app.organicmaps.sdk.routing.RoutingOptions;
|
||||
import app.organicmaps.sdk.search.SearchEngine;
|
||||
import app.organicmaps.sdk.settings.RoadType;
|
||||
import app.organicmaps.sdk.settings.UnitLocale;
|
||||
import app.organicmaps.sdk.sound.TtsPlayer;
|
||||
import app.organicmaps.sdk.util.Config;
|
||||
import app.organicmaps.sdk.util.LocationUtils;
|
||||
import app.organicmaps.sdk.util.PowerManagment;
|
||||
@@ -132,7 +133,6 @@ 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;
|
||||
|
||||
@@ -1813,6 +1813,18 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
return false;
|
||||
}
|
||||
|
||||
private void deliverTtsMessage()
|
||||
{
|
||||
if (Config.isTtsMessageDelivered())
|
||||
return;
|
||||
|
||||
String navigationStartMessage = getResources().getString(R.string.navigation_start_tts_message);
|
||||
navigationStartMessage += TtsPlayer.INSTANCE.getLanguageDisplayName();
|
||||
Toast.makeText(this, navigationStartMessage, Toast.LENGTH_LONG).show();
|
||||
|
||||
Config.setTtsMessageDelivered();
|
||||
}
|
||||
|
||||
private boolean showStartPointNotice()
|
||||
{
|
||||
final RoutingController controller = RoutingController.get();
|
||||
@@ -2189,6 +2201,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
if (!showRoutingDisclaimer())
|
||||
return;
|
||||
|
||||
deliverTtsMessage();
|
||||
|
||||
closeFloatingPanels();
|
||||
setFullscreen(false);
|
||||
RoutingController.get().start();
|
||||
|
||||
@@ -6,7 +6,6 @@ import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ProgressBar;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.view.ViewCompat;
|
||||
@@ -23,6 +22,7 @@ import app.organicmaps.util.Utils;
|
||||
import app.organicmaps.util.WindowInsetUtils;
|
||||
import app.organicmaps.widget.StackedButtonDialogFragment;
|
||||
import com.google.android.material.imageview.ShapeableImageView;
|
||||
import com.google.android.material.progressindicator.CircularProgressIndicator;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
import java.text.NumberFormat;
|
||||
|
||||
@@ -50,7 +50,7 @@ public class ProfileFragment extends BaseMwmToolbarFragment
|
||||
private MaterialTextView mEditsSent;
|
||||
private MaterialTextView mProfileName;
|
||||
private ShapeableImageView mProfileImage;
|
||||
private ProgressBar mProfileInfoLoading;
|
||||
private CircularProgressIndicator mProfileInfoLoading;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
|
||||
@@ -33,9 +33,13 @@
|
||||
style="@style/MwmWidget.TextView.NavStreet"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="@dimen/margin_quarter_plus"
|
||||
android:maxLines="2"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:gravity="center"
|
||||
android:autoSizeTextType="uniform"
|
||||
android:autoSizeMinTextSize="16sp"
|
||||
android:autoSizeMaxTextSize="25sp"
|
||||
android:textColor="@android:color/white"
|
||||
tools:text="Sample street name.\nLong looooooooong!!!!"/>
|
||||
</RelativeLayout>
|
||||
|
||||
@@ -30,12 +30,14 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/margin_base"
|
||||
android:background="?colorPrimary">
|
||||
<ProgressBar
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:id="@+id/user_profile_loading"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:trackColor="@color/text_light"
|
||||
app:indicatorColor="@color/text_light"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminateTint="@color/text_light"
|
||||
android:indeterminate="true"
|
||||
android:visibility="invisible"
|
||||
tools:visibility="visible" />
|
||||
<LinearLayout
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone" />
|
||||
<ProgressBar
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:id="@+id/progress"
|
||||
style="@style/Widget.AppCompat.ProgressBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center" />
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true"/>
|
||||
<include
|
||||
layout="@layout/feedback_fab"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<ProgressBar
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:id="@+id/progress"
|
||||
style="@style/Widget.AppCompat.ProgressBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"/>
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true"/>
|
||||
|
||||
<include layout="@layout/shadow_top"/>
|
||||
</FrameLayout>
|
||||
|
||||
@@ -24,6 +24,6 @@
|
||||
android:layout_gravity="center_vertical"
|
||||
android:fontFamily="@string/robotoMedium"
|
||||
tools:text="Some text should go here"
|
||||
android:textAppearance="@style/MwmTextAppearance.Body3"
|
||||
android:textAppearance="@style/MwmTextAppearance.Body1"
|
||||
android:textColor="?colorSecondary"/>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|bottom"
|
||||
android:background="@android:color/transparent"
|
||||
android:clickable="true"
|
||||
android:gravity="start|top"
|
||||
android:text="@string/category_desc_more"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/editor_height_field"
|
||||
android:layout_height="wrap_content"
|
||||
android:animateLayoutChanges="true"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
@@ -14,8 +14,7 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:hint="@string/editor_edit_place_name_hint"
|
||||
android:textColorHint="?android:textColorSecondary">
|
||||
android:hint="@string/editor_edit_place_name_hint">
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/input"
|
||||
style="@style/MwmWidget.Editor.FieldLayout.EditText"
|
||||
@@ -31,5 +30,5 @@
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:padding="@dimen/margin_half_plus"
|
||||
app:srcCompat="@drawable/ic_close"
|
||||
app:tint="@color/base_red" />
|
||||
app:tint="?iconTint" />
|
||||
</LinearLayout>
|
||||
@@ -35,6 +35,10 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="2"
|
||||
android:padding="@dimen/margin_half"
|
||||
android:autoSizeTextType="uniform"
|
||||
android:autoSizeMinTextSize="19sp"
|
||||
android:autoSizeMaxTextSize="24sp"
|
||||
android:minHeight="60dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:gravity="center"
|
||||
|
||||
@@ -34,8 +34,7 @@
|
||||
android:textAppearance="?android:attr/textAppearance"
|
||||
android:gravity="start|top"
|
||||
android:textColor="?attr/colorSecondary"
|
||||
android:text="@string/category_desc_more"
|
||||
android:background="@android:color/transparent"/>
|
||||
android:text="@string/category_desc_more" />
|
||||
<include
|
||||
layout="@layout/item_divider"/>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -6,11 +6,10 @@
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
<ProgressBar
|
||||
style="@style/Widget.AppCompat.ProgressBar"
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null" />
|
||||
android:indeterminate="true"/>
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
@@ -6,9 +6,8 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/search_show_on_map"
|
||||
style="@style/FAB"
|
||||
style="@style/MwmWidget.ExtendedFAB"
|
||||
app:icon="@drawable/ic_show_on_map"
|
||||
android:text="@string/search_show_on_map"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
app:fabSize="mini"/>
|
||||
android:focusable="true" />
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ProgressBar
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
style="@style/Widget.AppCompat.ProgressBar"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="@dimen/height_block_base"
|
||||
android:layout_height="@dimen/height_block_base"
|
||||
android:padding="@dimen/margin_half"
|
||||
android:background="@null"/>
|
||||
android:indeterminate="true"
|
||||
app:trackColor="@color/text_light"
|
||||
app:indicatorColor="@color/text_light" />
|
||||
|
||||
@@ -34,16 +34,17 @@
|
||||
android:singleLine="true"
|
||||
android:textCursorDrawable="@drawable/cursor_drawable" />
|
||||
|
||||
<ProgressBar
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:id="@+id/progress"
|
||||
style="@style/Widget.AppCompat.ProgressBar"
|
||||
android:layout_width="@dimen/search_progress_size"
|
||||
android:layout_height="@dimen/search_progress_size"
|
||||
android:layout_marginEnd="@dimen/margin_half"
|
||||
android:layout_weight="0"
|
||||
android:background="@null"
|
||||
android:minHeight="@dimen/search_progress_size"
|
||||
android:minWidth="@dimen/search_progress_size"/>
|
||||
android:minWidth="@dimen/search_progress_size"
|
||||
app:trackColor="@color/text_light"
|
||||
app:indicatorColor="@color/text_light"
|
||||
android:indeterminate="true"/>
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/clear"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<style name="MwmTheme.Base" parent="Theme.Material3.DayNight.NoActionBar">
|
||||
<item name="materialCalendarStyle">@style/Widget.MaterialComponents.MaterialCalendar</item>
|
||||
<item name="materialCalendarStyle">@style/Widget.Material3.MaterialCalendar</item>
|
||||
<item name="materialCalendarFullscreenTheme">@style/MwmWidget.MaterialCalendar.Theme.FullScreen.Dark</item>
|
||||
<item name="materialCalendarTheme">@style/MwmWidget.MaterialCalendar.Theme.Dark</item>
|
||||
<item name="android:listViewStyle">@style/MwmWidget.ListView</item>
|
||||
@@ -111,7 +111,7 @@
|
||||
<item name="elevationProfileSelectedPointTriangle">@drawable/ic_ascent</item>
|
||||
<item name="elevationProfileFloatingTriangle">@drawable/ic_triangle_elevation</item>
|
||||
<item name="elevationProfileColor">@color/elevation_profile</item>
|
||||
<item name="android:popupMenuStyle">@style/PopupMenu</item>
|
||||
<item name="android:popupMenuStyle">@style/Widget.Material3.PopupMenu</item>
|
||||
|
||||
<item name="bottomSheetStyle">@style/MwmWidget.BottomSheet</item>
|
||||
<item name="bottomSheetDialogTheme">@style/MwmTheme.BottomSheetDialog</item>
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
|
||||
<!-- Nav menu -->
|
||||
<dimen name="nav_elevation">6dp</dimen>
|
||||
<dimen name="nav_street_height">44dp</dimen>
|
||||
<dimen name="nav_street_height">50dp</dimen>
|
||||
<dimen name="nav_street_left">100dp</dimen>
|
||||
<dimen name="nav_next_turn_frame">88dp</dimen>
|
||||
<dimen name="nav_next_turn_top">8dp</dimen>
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
<string name="pref_tts_info" translatable="false">TtsInfo</string>
|
||||
<string name="pref_tts_info_link" translatable="false">TtsInfoLink</string>
|
||||
<string name="pref_tts_speed_cameras" translatable="false">SpeedCameras</string>
|
||||
<string name="pref_tts_speed_cameras_info" translatable="false">SpeedCamerasInfo</string>
|
||||
<string name="prefs_routing" translatable="false">RoutingOptions</string>
|
||||
<string name="pref_autodownload" translatable="false">AutoDownloadMap</string>
|
||||
<string name="pref_3d" translatable="false">3D</string>
|
||||
|
||||
@@ -609,6 +609,7 @@
|
||||
\nOpen your device\'s settings → Language and input → Speech → Text to speech output.
|
||||
\nHere you can manage settings for speech synthesis (for example, download language pack for offline use) and select another text-to-speech engine.</string>
|
||||
<string name="prefs_languages_information_off_link">For more information please check this guide</string>
|
||||
<string name="prefs_speed_cameras_information">Speed camera warnings are disabled in countries where alerts are prohibited by local law.</string>
|
||||
<string name="transliteration_title">Transliterate into Latin alphabet</string>
|
||||
<string name="learn_more">Learn more</string>
|
||||
<!-- User selected the destination by pressing Route To, but the current position is unknown. User needs to select a starting point of a route using search or by tapping on the map and then pressing "Route From". -->
|
||||
@@ -932,6 +933,7 @@
|
||||
<string name="share_track">Share Track</string>
|
||||
<string name="delete_track_dialog_title">Delete %s?</string>
|
||||
<string name="pref_tts_no_system_tts_short">No text-to-speech engine found, check the app settings</string>
|
||||
<string name="navigation_start_tts_message">"Starting Navigation, voice instruction language: "</string>
|
||||
<string name="unknown_power_output">unknown</string>
|
||||
<string name="charge_socket_type2">Type 2 (no cable)</string>
|
||||
<string name="charge_socket_type2_cable">Type 2 (w/ cable)</string>
|
||||
|
||||
@@ -364,23 +364,13 @@
|
||||
<item name="behavior_hideable">false</item>
|
||||
</style>
|
||||
|
||||
<style name="FAB" parent="Widget.MaterialComponents.ExtendedFloatingActionButton">
|
||||
<style name="MwmWidget.ExtendedFAB" parent="Widget.Material3.ExtendedFloatingActionButton.Primary">
|
||||
<item name="android:minHeight">30dp</item>
|
||||
<item name="android:minWidth">30dp</item>
|
||||
<item name="android:paddingTop">7dp</item>
|
||||
<item name="android:paddingBottom">7dp</item>
|
||||
<item name="android:paddingStart">12dp</item>
|
||||
<item name="android:paddingEnd">12dp</item>
|
||||
<item name="android:paddingLeft">12dp</item>
|
||||
<item name="android:paddingRight">12dp</item>
|
||||
<item name="iconPadding">4dp</item>
|
||||
<item name="iconSize">20dp</item>
|
||||
<item name="iconTint">?accentButtonTextColor</item>
|
||||
<item name="android:textColor">?accentButtonTextColor</item>
|
||||
<item name="backgroundTint">?colorSecondary</item>
|
||||
<item name="android:textSize">14sp</item>
|
||||
<item name="textAllCaps">false</item>
|
||||
<item name="android:textAllCaps">false</item>
|
||||
</style>
|
||||
|
||||
<style name="MwmWidget.M3.Button" parent="Widget.Material3.Button">
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
<item name="elevationProfileSelectedPointTriangle">@drawable/ic_ascent</item>
|
||||
<item name="elevationProfileFloatingTriangle">@drawable/ic_triangle_elevation</item>
|
||||
<item name="elevationProfileColor">@color/elevation_profile</item>
|
||||
<item name="android:popupMenuStyle">@style/PopupMenu</item>
|
||||
<item name="android:popupMenuStyle">@style/Widget.Material3.PopupMenu</item>
|
||||
|
||||
<!-- Style used for bottom sheet behavior components -->
|
||||
<item name="bottomSheetStyle">@style/MwmWidget.BottomSheet</item>
|
||||
|
||||
@@ -57,4 +57,11 @@
|
||||
android:entryValues="@array/speed_cameras_values"
|
||||
android:defaultValue="@string/auto_enum_value"
|
||||
app:iconSpaceReserved="false" />
|
||||
<Preference
|
||||
android:enabled="true"
|
||||
android:key="@string/pref_tts_info_link"
|
||||
android:persistent="false"
|
||||
android:selectable="false"
|
||||
android:summary="@string/prefs_speed_cameras_information"
|
||||
app:iconSpaceReserved="false" />
|
||||
</androidx.preference.PreferenceScreen>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package app.organicmaps.sdk.sound;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.database.ContentObserver;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Bundle;
|
||||
@@ -14,6 +15,8 @@ import android.util.Pair;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.os.ConfigurationCompat;
|
||||
import androidx.core.os.LocaleListCompat;
|
||||
import androidx.media.AudioAttributesCompat;
|
||||
import androidx.media.AudioFocusRequestCompat;
|
||||
import androidx.media.AudioManagerCompat;
|
||||
@@ -23,6 +26,7 @@ import app.organicmaps.sdk.util.log.Logger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* {@code TtsPlayer} class manages available TTS voice languages.
|
||||
@@ -33,9 +37,9 @@ import java.util.Locale;
|
||||
* unsupported voices are excluded.
|
||||
* <p>
|
||||
* At startup we check whether currently selected language is in our list of supported voices and its data is
|
||||
* downloaded. If not, we check system default locale. If failed, the same check is made for English language. Finally,
|
||||
* if mentioned checks fail we manually disable TTS, so the user must go to the settings and select preferred voice
|
||||
* language by hand. <p> If no core supported languages can be used by the system, TTS is locked down and can not be
|
||||
* downloaded. If not, we check system default locale. If failed, the same check is made for other system locales.
|
||||
* If those fail too, we check for English language. Then, as a final resort, all installed TTS locales are checked.
|
||||
* <p> If no core supported languages can be used by the system, TTS is locked down and can not be
|
||||
* enabled and used.
|
||||
*/
|
||||
public enum TtsPlayer
|
||||
@@ -78,6 +82,8 @@ public enum TtsPlayer
|
||||
// TTS is locked down due to absence of supported languages
|
||||
private boolean mUnavailable;
|
||||
|
||||
private LocaleListCompat mInstalledSystemLocales;
|
||||
|
||||
TtsPlayer() {}
|
||||
|
||||
private static @Nullable LanguageData findSupportedLanguage(String internalCode, List<LanguageData> langs)
|
||||
@@ -126,28 +132,57 @@ public enum TtsPlayer
|
||||
return (lang != null && setLanguageInternal(lang));
|
||||
}
|
||||
|
||||
private static @Nullable LanguageData getDefaultLanguage(List<LanguageData> langs)
|
||||
public static @Nullable LanguageData getSelectedLanguage(List<LanguageData> langs)
|
||||
{
|
||||
return findSupportedLanguage(Config.TTS.getLanguage(), langs);
|
||||
}
|
||||
|
||||
private @Nullable LanguageData getSystemLanguage(List<LanguageData> langs)
|
||||
{
|
||||
LanguageData res;
|
||||
|
||||
// Try default system locale
|
||||
Locale defLocale = Locale.getDefault();
|
||||
if (defLocale != null)
|
||||
res = findSupportedLanguage(defLocale, langs);
|
||||
if (res != null && res.downloaded)
|
||||
return res;
|
||||
|
||||
// Try other installed system locales
|
||||
for (int i = 0; i < mInstalledSystemLocales.size(); i++)
|
||||
{
|
||||
res = findSupportedLanguage(defLocale, langs);
|
||||
Locale loc = mInstalledSystemLocales.get(i);
|
||||
res = findSupportedLanguage(loc, langs);
|
||||
if (res != null && res.downloaded)
|
||||
return res;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private @Nullable LanguageData getTTSLanguage(List<LanguageData> langs)
|
||||
{
|
||||
LanguageData res;
|
||||
|
||||
// Try all TTS installed languages
|
||||
Set<Locale> ttsLocales = mTts.getAvailableLanguages();
|
||||
for (Locale loc : ttsLocales)
|
||||
{
|
||||
res = findSupportedLanguage(loc, langs);
|
||||
if (res != null && res.downloaded)
|
||||
return res;
|
||||
}
|
||||
|
||||
res = findSupportedLanguage(DEFAULT_LOCALE, langs);
|
||||
if (res != null && res.downloaded)
|
||||
return res;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static @Nullable LanguageData getSelectedLanguage(List<LanguageData> langs)
|
||||
private static @Nullable LanguageData getDefaultLanguage(List<LanguageData> langs)
|
||||
{
|
||||
return findSupportedLanguage(Config.TTS.getLanguage(), langs);
|
||||
LanguageData res;
|
||||
|
||||
// Try default app locale (en.US)
|
||||
res = findSupportedLanguage(DEFAULT_LOCALE, langs);
|
||||
if (res != null && res.downloaded)
|
||||
return res;
|
||||
return null;
|
||||
}
|
||||
|
||||
private void lockDown()
|
||||
@@ -167,6 +202,10 @@ public enum TtsPlayer
|
||||
// TextToSpeech.OnInitListener() can be called from a non-main thread
|
||||
// on LineageOS '20.0-20231127-RELEASE-thyme' 'Xiaomi/thyme/thyme'.
|
||||
// https://github.com/organicmaps/organicmaps/issues/6903
|
||||
|
||||
Configuration config = context.getResources().getConfiguration();
|
||||
mInstalledSystemLocales = ConfigurationCompat.getLocales(config);
|
||||
|
||||
mTts = new TextToSpeech(context, status -> UiThread.run(() -> {
|
||||
if (status == TextToSpeech.ERROR)
|
||||
{
|
||||
@@ -239,6 +278,17 @@ public enum TtsPlayer
|
||||
return (INSTANCE.mTts != null && !INSTANCE.mUnavailable && !INSTANCE.mInitializing);
|
||||
}
|
||||
|
||||
public Locale getVoiceLocale()
|
||||
{
|
||||
return mTts.getVoice().getLocale();
|
||||
}
|
||||
|
||||
public String getLanguageDisplayName()
|
||||
{
|
||||
Locale locale = getVoiceLocale();
|
||||
return locale.getDisplayName(locale);
|
||||
}
|
||||
|
||||
public void speak(String textToSpeak)
|
||||
{
|
||||
if (Config.TTS.isEnabled())
|
||||
@@ -328,24 +378,49 @@ public enum TtsPlayer
|
||||
|
||||
if (outList.isEmpty())
|
||||
{
|
||||
// No supported languages found, lock down TTS :(
|
||||
Logger.d("TtsPlayer", "No supported languages found, lock down TTS :( ");
|
||||
lockDown();
|
||||
return null;
|
||||
}
|
||||
|
||||
LanguageData res = getSelectedLanguage(outList);
|
||||
if (res == null || !res.downloaded)
|
||||
// Selected locale is not available or not downloaded
|
||||
res = getDefaultLanguage(outList);
|
||||
|
||||
if (res == null || !res.downloaded)
|
||||
if (res != null && res.downloaded)
|
||||
{
|
||||
// Default locale can not be used too
|
||||
Config.TTS.setEnabled(false);
|
||||
return null;
|
||||
Logger.d("TtsPlayer", "Selected locale " + res.internalCode + " will be used for TTS");
|
||||
return res;
|
||||
}
|
||||
Logger.d("TtsPlayer", "Selected locale " + Config.TTS.getLanguage()
|
||||
+ " is not available or not downloaded, trying system locales...");
|
||||
|
||||
res = getSystemLanguage(outList);
|
||||
if (res != null && res.downloaded)
|
||||
{
|
||||
Logger.d("TtsPlayer", "System locale " + res.internalCode + " will be used for TTS");
|
||||
return res;
|
||||
}
|
||||
Logger.d("TtsPlayer",
|
||||
"None of the system locales are available, or they are not downloaded, trying default locale...");
|
||||
|
||||
res = getDefaultLanguage(outList);
|
||||
if (res != null && res.downloaded)
|
||||
{
|
||||
Logger.d("TtsPlayer", "Default locale " + res.internalCode + " will be used for TTS");
|
||||
return res;
|
||||
}
|
||||
Logger.d("TtsPlayer",
|
||||
"Default locale " + DEFAULT_LOCALE + " can not be used either, trying all installed TTS locales...");
|
||||
|
||||
res = getTTSLanguage(outList);
|
||||
if (res != null && res.downloaded)
|
||||
{
|
||||
Logger.d("TtsPlayer", "TTS locale " + res.internalCode + " will be used for TTS");
|
||||
return res;
|
||||
}
|
||||
|
||||
return res;
|
||||
Logger.d("TtsPlayer",
|
||||
"None of the TTS engine locales are available, or they are not downloaded, disabling TTS :( ");
|
||||
Config.TTS.setEnabled(false);
|
||||
return null;
|
||||
}
|
||||
|
||||
public @NonNull List<LanguageData> refreshLanguages()
|
||||
|
||||
@@ -36,6 +36,7 @@ public final class Config
|
||||
private static final String KEY_PREF_USE_GS = "UseGoogleServices";
|
||||
|
||||
private static final String KEY_MISC_DISCLAIMER_ACCEPTED = "IsDisclaimerApproved";
|
||||
private static final String KEY_MISC_TTS_MESSAGE_DELIVERED = "TtsMessageDelivered";
|
||||
private static final String KEY_MISC_LOCATION_REQUESTED = "LocationRequested";
|
||||
private static final String KEY_MISC_USE_MOBILE_DATA = "UseMobileData";
|
||||
private static final String KEY_MISC_USE_MOBILE_DATA_TIMESTAMP = "UseMobileDataTimestamp";
|
||||
@@ -237,6 +238,16 @@ public final class Config
|
||||
setBool(KEY_MISC_DISCLAIMER_ACCEPTED);
|
||||
}
|
||||
|
||||
public static boolean isTtsMessageDelivered()
|
||||
{
|
||||
return getBool(KEY_MISC_TTS_MESSAGE_DELIVERED);
|
||||
}
|
||||
|
||||
public static void setTtsMessageDelivered()
|
||||
{
|
||||
setBool(KEY_MISC_TTS_MESSAGE_DELIVERED);
|
||||
}
|
||||
|
||||
public static boolean isLocationRequested()
|
||||
{
|
||||
return getBool(KEY_MISC_LOCATION_REQUESTED);
|
||||
|
||||
@@ -137,6 +137,7 @@ node[amenity=prison],
|
||||
node[amenity=recycling][recycling_type=centre],
|
||||
node[amenity=sailing_school],
|
||||
node[amenity=school],
|
||||
node[amenity=toilets],
|
||||
node[amenity=townhall],
|
||||
node[amenity=university][name],
|
||||
node[barrier=border_control],
|
||||
|
||||
@@ -151,7 +151,7 @@ public:
|
||||
// Set speed as-is from parent link.
|
||||
if (parentHwType == hwType)
|
||||
return {{s.GetForward(), s.GetUnits()}};
|
||||
|
||||
/*
|
||||
using routing::HighwayType;
|
||||
if ((*parentHwType == HighwayType::HighwayMotorway && hwType == HighwayType::HighwayMotorwayLink) ||
|
||||
(*parentHwType == HighwayType::HighwayTrunk && hwType == HighwayType::HighwayTrunkLink) ||
|
||||
@@ -163,6 +163,7 @@ public:
|
||||
return converter.ClosestValidMacro(
|
||||
{base::asserted_cast<MaxspeedType>(std::lround(s.GetForward() * kLinkToMainSpeedFactor)), s.GetUnits()});
|
||||
}
|
||||
*/
|
||||
|
||||
return {};
|
||||
};
|
||||
|
||||
@@ -541,8 +541,8 @@
|
||||
|
||||
/* Voice */
|
||||
"voice" = "Voice";
|
||||
"voice_explanation" = "It's possible to pick a better voice in the system settings under *Accesibility*, *Read & Speak*, *Voices*.";
|
||||
"voice_explanation_before_version26" = "It's possible to pick a better voice in the system settings under *Accesibility*, *Spoken Content*, *Voices*.";
|
||||
"voice_explanation" = "It's possible to pick a better voice in the system settings under *Accessibility*, *Read & Speak*, *Voices*.";
|
||||
"voice_explanation_before_version26" = "It's possible to pick a better voice in the system settings under *Accessibility*, *Spoken Content*, *Voices*.";
|
||||
"unknown" = "Unknown";
|
||||
|
||||
/* Place page confirmation messages and time ago formatting */
|
||||
@@ -1045,25 +1045,25 @@
|
||||
/* Message for the bug report alert. */
|
||||
"bugreport_alert_message" = "Would you like to send a bug report to the developers?\nWe rely on our users as CoMaps doesn't collect any error information automatically. Thank you in advance for supporting CoMaps!";
|
||||
|
||||
/* Title for the iCloud syncronization setting */
|
||||
"icloud_sync" = "iCloud Syncronization (Beta)";
|
||||
/* Title for the iCloud synchronization setting */
|
||||
"icloud_sync" = "iCloud Synchronization (Beta)";
|
||||
|
||||
/* Title for the "Enable iCloud Syncronization" alert. */
|
||||
"enable_icloud_synchronization_title" = "Enable iCloud Syncronization";
|
||||
/* Title for the "Enable iCloud Synchronization" alert. */
|
||||
"enable_icloud_synchronization_title" = "Enable iCloud Synchronization";
|
||||
|
||||
/* Message for the "Enable iCloud Syncronization" alert. */
|
||||
/* Message for the "Enable iCloud Synchronization" alert. */
|
||||
"enable_icloud_synchronization_message" = "iCloud synchronization is an experimental feature under development. Make sure that you have made a backup of all your bookmarks and tracks.";
|
||||
|
||||
/* Title for the "iCloud Is Disabled" alert. */
|
||||
"icloud_disabled_title" = "iCloud Is Disabled";
|
||||
|
||||
/* Message for the "iCloud is Disabled" alert. */
|
||||
"icloud_disabled_message" = "Please enable iCloud in your device's settings to use this feature.";
|
||||
"icloud_disabled_message" = "Please enable iCloud for CoMaps in your Apple Account's settings to use this feature.";
|
||||
|
||||
/* Title for the "Enable iCloud Syncronization" alert's "Enable" action button. */
|
||||
/* Title for the "Enable iCloud Synchronization" alert's "Enable" action button. */
|
||||
"enable" = "Enable";
|
||||
|
||||
/* Title for the "Enable iCloud Syncronization" alert's "Backup" action button. */
|
||||
/* Title for the "Enable iCloud Synchronization" alert's "Backup" action button. */
|
||||
"backup" = "Backup";
|
||||
|
||||
/* Title for the "iCloud synchronization failure" alert. */
|
||||
|
||||
@@ -560,8 +560,8 @@
|
||||
|
||||
/* Voice */
|
||||
"voice" = "Voice";
|
||||
"voice_explanation" = "It's possible to pick a better voice in the system settings under *Accesibility*, *Read & Speak*, *Voices*.";
|
||||
"voice_explanation_before_version26" = "It's possible to pick a better voice in the system settings under *Accesibility*, *Spoken Content*, *Voices*.";
|
||||
"voice_explanation" = "It's possible to pick a better voice in the system settings under *Accessibility*, *Read & Speak*, *Voices*.";
|
||||
"voice_explanation_before_version26" = "It's possible to pick a better voice in the system settings under *Accessibility*, *Spoken Content*, *Voices*.";
|
||||
"unknown" = "Unknown";
|
||||
|
||||
/* Place page confirmation messages and time ago formatting */
|
||||
@@ -1070,25 +1070,25 @@
|
||||
/* Message for the bug report alert. */
|
||||
"bugreport_alert_message" = "Would you like to send a bug report to the developers?\nWe rely on our users as CoMaps doesn't collect any error information automatically. Thank you in advance for supporting CoMaps!";
|
||||
|
||||
/* Title for the iCloud syncronization setting */
|
||||
"icloud_sync" = "iCloud Syncronization (Beta)";
|
||||
/* Title for the iCloud synchronization setting */
|
||||
"icloud_sync" = "iCloud Synchronization (Beta)";
|
||||
|
||||
/* Title for the "Enable iCloud Syncronization" alert. */
|
||||
"enable_icloud_synchronization_title" = "Enable iCloud Syncronization";
|
||||
/* Title for the "Enable iCloud Synchronization" alert. */
|
||||
"enable_icloud_synchronization_title" = "Enable iCloud Synchronization";
|
||||
|
||||
/* Message for the "Enable iCloud Syncronization" alert. */
|
||||
/* Message for the "Enable iCloud Synchronization" alert. */
|
||||
"enable_icloud_synchronization_message" = "iCloud synchronization is an experimental feature under development. Make sure that you have made a backup of all your bookmarks and tracks.";
|
||||
|
||||
/* Title for the "iCloud Is Disabled" alert. */
|
||||
"icloud_disabled_title" = "iCloud Is Disabled";
|
||||
|
||||
/* Message for the "iCloud is Disabled" alert. */
|
||||
"icloud_disabled_message" = "Please enable iCloud in your device's settings to use this feature.";
|
||||
"icloud_disabled_message" = "Please enable iCloud for CoMaps in your Apple Account's settings to use this feature.";
|
||||
|
||||
/* Title for the "Enable iCloud Syncronization" alert's "Enable" action button. */
|
||||
/* Title for the "Enable iCloud Synchronization" alert's "Enable" action button. */
|
||||
"enable" = "Enable";
|
||||
|
||||
/* Title for the "Enable iCloud Syncronization" alert's "Backup" action button. */
|
||||
/* Title for the "Enable iCloud Synchronization" alert's "Backup" action button. */
|
||||
"backup" = "Backup";
|
||||
|
||||
/* Title for the "iCloud synchronization failure" alert. */
|
||||
|
||||
@@ -441,12 +441,13 @@ void DrapeEngine::SetCompassInfo(location::CompassInfo const & info)
|
||||
MessagePriority::Normal);
|
||||
}
|
||||
|
||||
void DrapeEngine::SetGpsInfo(location::GpsInfo const & info, bool isNavigable,
|
||||
void DrapeEngine::SetGpsInfo(location::GpsInfo const & info, bool isNavigable, double distToNextTurn, double speedLimit,
|
||||
location::RouteMatchingInfo const & routeInfo)
|
||||
{
|
||||
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
|
||||
make_unique_dp<GpsInfoMessage>(info, isNavigable, routeInfo),
|
||||
MessagePriority::Normal);
|
||||
m_threadCommutator->PostMessage(
|
||||
ThreadsCommutator::RenderThread,
|
||||
make_unique_dp<GpsInfoMessage>(info, isNavigable, distToNextTurn, speedLimit, routeInfo),
|
||||
MessagePriority::Normal);
|
||||
}
|
||||
|
||||
void DrapeEngine::SwitchMyPositionNextMode()
|
||||
|
||||
@@ -154,7 +154,8 @@ public:
|
||||
void UpdateMapStyle();
|
||||
|
||||
void SetCompassInfo(location::CompassInfo const & info);
|
||||
void SetGpsInfo(location::GpsInfo const & info, bool isNavigable, location::RouteMatchingInfo const & routeInfo);
|
||||
void SetGpsInfo(location::GpsInfo const & info, bool isNavigable, double distToNextTurn, double speedLimit,
|
||||
location::RouteMatchingInfo const & routeInfo);
|
||||
void SwitchMyPositionNextMode();
|
||||
void LoseLocation();
|
||||
void StopLocationFollow();
|
||||
|
||||
@@ -438,7 +438,8 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
|
||||
break;
|
||||
#endif
|
||||
ref_ptr<GpsInfoMessage> msg = message;
|
||||
m_myPositionController->OnLocationUpdate(msg->GetInfo(), msg->IsNavigable(), m_userEventStream.GetCurrentScreen());
|
||||
m_myPositionController->OnLocationUpdate(msg->GetInfo(), msg->IsNavigable(), msg->GetDistanceToNextTurn(),
|
||||
msg->GetSpeedLimit(), m_userEventStream.GetCurrentScreen());
|
||||
|
||||
location::RouteMatchingInfo const & info = msg->GetRouteInfo();
|
||||
if (info.HasDistanceFromBegin())
|
||||
|
||||
@@ -481,9 +481,12 @@ private:
|
||||
class GpsInfoMessage : public Message
|
||||
{
|
||||
public:
|
||||
GpsInfoMessage(location::GpsInfo const & info, bool isNavigable, location::RouteMatchingInfo const & routeInfo)
|
||||
GpsInfoMessage(location::GpsInfo const & info, bool isNavigable, double distToNextTurn, double speedLimit,
|
||||
location::RouteMatchingInfo const & routeInfo)
|
||||
: m_info(info)
|
||||
, m_isNavigable(isNavigable)
|
||||
, m_distToNextTurn(distToNextTurn)
|
||||
, m_speedLimit(speedLimit)
|
||||
, m_routeInfo(routeInfo)
|
||||
{}
|
||||
|
||||
@@ -491,11 +494,15 @@ public:
|
||||
|
||||
location::GpsInfo const & GetInfo() const { return m_info; }
|
||||
bool IsNavigable() const { return m_isNavigable; }
|
||||
double const & GetSpeedLimit() const { return m_speedLimit; }
|
||||
double const & GetDistanceToNextTurn() const { return m_distToNextTurn; }
|
||||
location::RouteMatchingInfo const & GetRouteInfo() const { return m_routeInfo; }
|
||||
|
||||
private:
|
||||
location::GpsInfo const m_info;
|
||||
bool const m_isNavigable;
|
||||
double const m_distToNextTurn;
|
||||
double const m_speedLimit;
|
||||
location::RouteMatchingInfo const m_routeInfo;
|
||||
};
|
||||
|
||||
|
||||
@@ -56,32 +56,18 @@ inline double GetVisualScale()
|
||||
return df::VisualParams::Instance().GetVisualScale();
|
||||
}
|
||||
|
||||
// Calculate zoom value in meters per pixel
|
||||
double CalculateZoomBySpeed(double speedMpS, bool isPerspectiveAllowed)
|
||||
double CalculateZoomByMaxSpeed(double speedMpS, bool isPerspectiveAllowed)
|
||||
{
|
||||
using TSpeedScale = std::pair<double, double>;
|
||||
static std::array<TSpeedScale, 6> const scales3d = {{
|
||||
{20.0, 0.25},
|
||||
{40.0, 0.75},
|
||||
{60.0, 1.50},
|
||||
{75.0, 2.50},
|
||||
{85.0, 3.75},
|
||||
{95.0, 6.00},
|
||||
static std::array<TSpeedScale, 2> const scales2d = {{
|
||||
{0.0, 1.75}, {77.0, 4.50} // 48 mph
|
||||
}};
|
||||
static std::array<TSpeedScale, 2> const scales3d = {{{0.0, 1.00}, {77.0, 4.50}}};
|
||||
|
||||
static std::array<TSpeedScale, 6> const scales2d = {{
|
||||
{20.0, 0.70},
|
||||
{40.0, 1.25},
|
||||
{60.0, 2.25},
|
||||
{75.0, 3.00},
|
||||
{85.0, 3.75},
|
||||
{95.0, 6.00},
|
||||
}};
|
||||
std::array<TSpeedScale, 2> const & scales = isPerspectiveAllowed ? scales3d : scales2d;
|
||||
|
||||
std::array<TSpeedScale, 6> const & scales = isPerspectiveAllowed ? scales3d : scales2d;
|
||||
|
||||
double constexpr kDefaultSpeedKmpH = 80.0;
|
||||
double const speedKmpH = speedMpS >= 0 ? measurement_utils::MpsToKmph(speedMpS) : kDefaultSpeedKmpH;
|
||||
double constexpr kDefaultSpeedLimitKmpH = 50.0;
|
||||
double const speedKmpH = speedMpS > 0 ? measurement_utils::MpsToKmph(speedMpS) : kDefaultSpeedLimitKmpH;
|
||||
|
||||
size_t i = 0;
|
||||
for (size_t sz = scales.size(); i < sz; ++i)
|
||||
@@ -92,20 +78,64 @@ double CalculateZoomBySpeed(double speedMpS, bool isPerspectiveAllowed)
|
||||
|
||||
if (i == 0)
|
||||
return scales.front().second / vs;
|
||||
if (i == scales.size())
|
||||
return scales.back().second / vs;
|
||||
|
||||
double const minSpeed = scales[i - 1].first;
|
||||
double const maxSpeed = scales[i].first;
|
||||
double const k = (speedKmpH - minSpeed) / (maxSpeed - minSpeed);
|
||||
return scales[i - 1].second / vs;
|
||||
}
|
||||
|
||||
double const minScale = scales[i - 1].second;
|
||||
double const maxScale = scales[i].second;
|
||||
double CalculateZoomByDistanceToTurn(double distance, bool isPerspectiveAllowed)
|
||||
{
|
||||
using TSpeedScale = std::pair<double, double>;
|
||||
static std::array<TSpeedScale, 5> const scales2d = {{
|
||||
{200, 0.50},
|
||||
{500, 0.80}, // 0.3 mi
|
||||
{1200, 1.75}, // 0.75 mi
|
||||
{2000, 3.50}, // 1.2 mi
|
||||
{5000, 6.50} // 3 mi
|
||||
}};
|
||||
static std::array<TSpeedScale, 5> const scales3d = {{
|
||||
{200, 0.25},
|
||||
{500, 0.60}, // 0.3 mi
|
||||
{1200, 1.25}, // 0.75 mi
|
||||
{2000, 3.50}, // 1.2 mi
|
||||
{5000, 6.50} // 3 mi
|
||||
}};
|
||||
|
||||
std::array<TSpeedScale, 5> const & scale = isPerspectiveAllowed ? scales3d : scales2d;
|
||||
|
||||
double constexpr kDefaultDistance = 2000;
|
||||
double const distanceM = distance >= 0 ? distance : kDefaultDistance;
|
||||
|
||||
size_t i = 0;
|
||||
for (size_t sz = scale.size(); i < sz; ++i)
|
||||
if (scale[i].first >= distanceM)
|
||||
break;
|
||||
|
||||
double const vs = GetVisualScale();
|
||||
|
||||
if (i == 0)
|
||||
return scale.front().second / vs;
|
||||
if (i == scale.size())
|
||||
return scale.back().second / vs;
|
||||
|
||||
double const minDist = scale[i - 1].first;
|
||||
double const maxDist = scale[i].first;
|
||||
double const k = (distanceM - minDist) / (maxDist - minDist);
|
||||
|
||||
double const minScale = scale[i - 1].second;
|
||||
double const maxScale = scale[i].second;
|
||||
double const zoom = minScale + k * (maxScale - minScale);
|
||||
|
||||
return zoom / vs;
|
||||
}
|
||||
|
||||
double CalculateAutoZoom(double speedMpS, double distanceToTurn, bool isPerspectiveAllowed)
|
||||
{
|
||||
double const zoomByDistance = CalculateZoomByDistanceToTurn(distanceToTurn, isPerspectiveAllowed);
|
||||
double const zoomByMaxSpeed = CalculateZoomByMaxSpeed(speedMpS, isPerspectiveAllowed);
|
||||
|
||||
return std::min(zoomByDistance, zoomByMaxSpeed);
|
||||
}
|
||||
|
||||
void ResetNotification(uint64_t & notifyId)
|
||||
{
|
||||
notifyId = DrapeNotifier::kInvalidId;
|
||||
@@ -395,7 +425,8 @@ void MyPositionController::NextMode(ScreenBase const & screen)
|
||||
}
|
||||
}
|
||||
|
||||
void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, ScreenBase const & screen)
|
||||
void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, double distanceToNextTurn,
|
||||
double speedLimit, ScreenBase const & screen)
|
||||
{
|
||||
m2::PointD const oldPos = GetDrawablePosition();
|
||||
double const oldAzimut = GetDrawableAzimut();
|
||||
@@ -407,11 +438,13 @@ void MyPositionController::OnLocationUpdate(location::GpsInfo const & info, bool
|
||||
m_errorRadius = rect.SizeX() * 0.5;
|
||||
m_horizontalAccuracy = info.m_horizontalAccuracy;
|
||||
|
||||
if (info.m_speed > 0.0)
|
||||
if (distanceToNextTurn >= 0.0 || speedLimit >= 0.0)
|
||||
{
|
||||
double const mercatorPerMeter = m_errorRadius / info.m_horizontalAccuracy;
|
||||
m_autoScale2d = mercatorPerMeter * CalculateZoomBySpeed(info.m_speed, false /* isPerspectiveAllowed */);
|
||||
m_autoScale3d = mercatorPerMeter * CalculateZoomBySpeed(info.m_speed, true /* isPerspectiveAllowed */);
|
||||
m_autoScale2d =
|
||||
mercatorPerMeter * CalculateAutoZoom(speedLimit, distanceToNextTurn, false /* isPerspectiveAllowed */);
|
||||
m_autoScale3d =
|
||||
mercatorPerMeter * CalculateAutoZoom(speedLimit, distanceToNextTurn, true /* isPerspectiveAllowed */);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -117,7 +117,8 @@ public:
|
||||
void OnEnterBackground();
|
||||
|
||||
void OnCompassTapped();
|
||||
void OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, ScreenBase const & screen);
|
||||
void OnLocationUpdate(location::GpsInfo const & info, bool isNavigable, double distanceToNextTurn, double speedLimit,
|
||||
ScreenBase const & screen);
|
||||
void OnCompassUpdate(location::CompassInfo const & info, ScreenBase const & screen);
|
||||
|
||||
void Render(ref_ptr<dp::GraphicsContext> context, ref_ptr<gpu::ProgramManager> mng, ScreenBase const & screen,
|
||||
|
||||
@@ -1171,6 +1171,7 @@ void RoutingManager::SetDrapeEngine(ref_ptr<df::DrapeEngine> engine, bool is3dAl
|
||||
{
|
||||
auto routeMatchingInfo = GetRouteMatchingInfo(*m_gpsInfoCache);
|
||||
m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, *m_gpsInfoCache, m_routingSession.IsNavigable(),
|
||||
m_routingSession.GetDistanceToNextTurn(), m_routingSession.GetCurrentSpeedLimit(),
|
||||
routeMatchingInfo);
|
||||
m_gpsInfoCache.reset();
|
||||
}
|
||||
@@ -1515,7 +1516,9 @@ void RoutingManager::OnExtrapolatedLocationUpdate(location::GpsInfo const & info
|
||||
m_gpsInfoCache = make_unique<location::GpsInfo>(gpsInfo);
|
||||
|
||||
auto routeMatchingInfo = GetRouteMatchingInfo(gpsInfo);
|
||||
m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, gpsInfo, m_routingSession.IsNavigable(), routeMatchingInfo);
|
||||
m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, gpsInfo, m_routingSession.IsNavigable(),
|
||||
m_routingSession.GetDistanceToNextTurn(), m_routingSession.GetCurrentSpeedLimit(),
|
||||
routeMatchingInfo);
|
||||
}
|
||||
|
||||
void RoutingManager::DeleteSavedRoutePoints()
|
||||
|
||||
@@ -363,6 +363,32 @@ void GetFullRoadName(RouteSegment::RoadNameInfo & road, std::string & name)
|
||||
}
|
||||
}
|
||||
|
||||
double RoutingSession::GetDistanceToNextTurn() const
|
||||
{
|
||||
if (!m_route->IsValid())
|
||||
return -1;
|
||||
|
||||
double distanceToTurnMeters = 0.;
|
||||
turns::TurnItem turn;
|
||||
m_route->GetNearestTurn(distanceToTurnMeters, turn);
|
||||
return distanceToTurnMeters;
|
||||
}
|
||||
|
||||
double RoutingSession::GetCurrentSpeedLimit() const
|
||||
{
|
||||
if (!m_route->IsValid())
|
||||
return -1;
|
||||
|
||||
SpeedInUnits speedLimit;
|
||||
m_route->GetCurrentSpeedLimit(speedLimit);
|
||||
if (speedLimit.IsNumeric())
|
||||
return measurement_utils::KmphToMps(speedLimit.GetSpeedKmPH());
|
||||
else if (speedLimit.GetSpeed() == kNoneMaxSpeed)
|
||||
return 0;
|
||||
else
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info) const
|
||||
{
|
||||
CHECK_THREAD_CHECKER(m_threadChecker, ());
|
||||
@@ -392,14 +418,7 @@ void RoutingSession::GetRouteFollowingInfo(FollowingInfo & info) const
|
||||
info.m_distToTurn = platform::Distance::CreateFormatted(distanceToTurnMeters);
|
||||
info.m_turn = turn.m_turn;
|
||||
|
||||
SpeedInUnits speedLimit;
|
||||
m_route->GetCurrentSpeedLimit(speedLimit);
|
||||
if (speedLimit.IsNumeric())
|
||||
info.m_speedLimitMps = measurement_utils::KmphToMps(speedLimit.GetSpeedKmPH());
|
||||
else if (speedLimit.GetSpeed() == kNoneMaxSpeed)
|
||||
info.m_speedLimitMps = 0;
|
||||
else
|
||||
info.m_speedLimitMps = -1.0;
|
||||
info.m_speedLimitMps = GetCurrentSpeedLimit();
|
||||
|
||||
// The turn after the next one.
|
||||
if (m_routingSettings.m_showTurnAfterNext)
|
||||
|
||||
@@ -100,6 +100,8 @@ public:
|
||||
|
||||
SessionState OnLocationPositionChanged(location::GpsInfo const & info);
|
||||
void GetRouteFollowingInfo(FollowingInfo & info) const;
|
||||
double GetDistanceToNextTurn() const;
|
||||
double GetCurrentSpeedLimit() const;
|
||||
|
||||
bool MatchLocationToRoute(location::GpsInfo & location, location::RouteMatchingInfo & routeMatchingInfo);
|
||||
void MatchLocationToRoadGraph(location::GpsInfo & location);
|
||||
|
||||
@@ -76,7 +76,7 @@ char const * g_strings[] = {
|
||||
// ./clusterize-tag-values.lisp house-number path-to-taginfo-db.db > numbers.txt
|
||||
// tail -n +2 numbers.txt | head -78 | sed 's/^.*) \(.*\) \[.*$/"\1"/g;s/[ -/]//g;s/$/,/' |
|
||||
// sort | uniq
|
||||
vector<string> const g_patterns = {"BL", "BLN", "BLNSL", "BN", "BNL", "BNSL", "L", "LL", "LN", "LNL", "LNLN", "LNN",
|
||||
array<string_view, 48> constexpr g_patterns = {"BL", "BLN", "BLNSL", "BN", "BNL", "BNSL", "L", "LL", "LN", "LNL", "LNLN", "LNN",
|
||||
"N", "NBL", "NBLN", "NBN", "NBNBN", "NBNL", "NL", "NLBN", "NLL", "NLLN", "NLN",
|
||||
"NLNL", "NLS", "NLSN", "NN", "NNBN", "NNL", "NNLN", "NNN", "NNS", "NS", "NSN", "NSS",
|
||||
"S", "SL", "SLL", "SLN", "SN", "SNBNSS", "SNL", "SNN", "SS", "SSN", "SSS", "SSSS",
|
||||
@@ -85,13 +85,14 @@ vector<string> const g_patterns = {"BL", "BLN", "BLNSL", "BN", "BNL", "BNSL", "L
|
||||
"NNBNL"};
|
||||
|
||||
// List of patterns which look like house numbers more than other patterns. Constructed by hand.
|
||||
vector<string> const g_patternsStrict = {"N", "NBN", "NBL", "NL"};
|
||||
array<string_view, 4> constexpr g_patternsStrict = {"N", "NBN", "NBL", "NL"};
|
||||
|
||||
// List of common synonyms for building parts. Constructed by hand.
|
||||
char const * g_buildingPartSynonyms[] = {"building", "bldg", "bld", "bl", "unit", "block", "blk", "корпус",
|
||||
"корп", "кор", "литер", "лит", "строение", "стр", "блок", "бл"};
|
||||
|
||||
// List of common stop words for buildings. Constructed by hand.
|
||||
// TODO: add more stop words?
|
||||
UniString const g_stopWords[] = {MakeUniString("дом"), MakeUniString("house"), MakeUniString("д")};
|
||||
|
||||
bool IsStopWord(UniString const & s, bool isPrefix)
|
||||
@@ -167,7 +168,8 @@ class HouseNumberClassifier
|
||||
public:
|
||||
using Patterns = StringSet<Token::Type, 4>;
|
||||
|
||||
HouseNumberClassifier(vector<string> const & patterns = g_patterns)
|
||||
template <size_t size>
|
||||
HouseNumberClassifier(array<string_view, size> const & patterns)
|
||||
{
|
||||
for (auto const & p : patterns)
|
||||
m_patterns.Add(make_transform_iterator(p.begin(), &CharToType), make_transform_iterator(p.end(), &CharToType));
|
||||
@@ -590,7 +592,7 @@ bool HouseNumbersMatchRange(std::string_view const & hnRange, TokensT const & qu
|
||||
|
||||
bool LooksLikeHouseNumber(UniString const & s, bool isPrefix)
|
||||
{
|
||||
static HouseNumberClassifier const classifier;
|
||||
static HouseNumberClassifier const classifier(g_patterns);
|
||||
return classifier.LooksGood(s, isPrefix);
|
||||
}
|
||||
|
||||
|
||||
@@ -298,8 +298,7 @@ void LocalityScorer::GetDocVecs(uint32_t localityId, vector<DocVec> & dvs) const
|
||||
DocVec::Builder builder;
|
||||
ForEachNormalizedToken(name, [&](strings::UniString const & token)
|
||||
{
|
||||
if (!IsStopWord(token))
|
||||
builder.Add(token);
|
||||
builder.Add(token);
|
||||
});
|
||||
dvs.emplace_back(std::move(builder));
|
||||
}
|
||||
|
||||
@@ -69,21 +69,6 @@ m2::RectD GetRectAroundPosition(m2::PointD const & position)
|
||||
return mercator::RectByCenterXYAndSizeInMeters(position, kMaxPositionRadiusM);
|
||||
}
|
||||
|
||||
// Removes all full-token stop words from |tokens|.
|
||||
// Does nothing if all tokens are non-prefix stop words.
|
||||
void RemoveStopWordsIfNeeded(QueryTokens & tokens, strings::UniString & prefix)
|
||||
{
|
||||
size_t numStopWords = 0;
|
||||
for (auto const & token : tokens)
|
||||
if (IsStopWord(token))
|
||||
++numStopWords;
|
||||
|
||||
if (numStopWords == tokens.size() && prefix.empty())
|
||||
return;
|
||||
|
||||
tokens.erase_if(&IsStopWord);
|
||||
}
|
||||
|
||||
void TrimLeadingSpaces(string & s)
|
||||
{
|
||||
while (!s.empty() && strings::IsASCIISpace(s.front()))
|
||||
@@ -277,9 +262,6 @@ void Processor::SetQuery(string const & query, bool categorialRequest /* = false
|
||||
}
|
||||
}
|
||||
|
||||
// Remove stopwords *after* FillCategories call (it makes exact tokens match).
|
||||
RemoveStopWordsIfNeeded(m_query.m_tokens, m_query.m_prefix);
|
||||
|
||||
if (!m_isCategorialRequest)
|
||||
{
|
||||
// Assign tokens and prefix to scorer.
|
||||
|
||||
@@ -1482,13 +1482,7 @@ unordered_map<string, vector<string>> const kSynonyms = {
|
||||
// QueryParams::Token ------------------------------------------------------------------------------
|
||||
void QueryParams::Token::AddSynonym(string const & s)
|
||||
{
|
||||
AddSynonym(strings::MakeUniString(s));
|
||||
}
|
||||
|
||||
void QueryParams::Token::AddSynonym(String const & s)
|
||||
{
|
||||
if (!IsStopWord(s))
|
||||
m_synonyms.push_back(s);
|
||||
m_synonyms.push_back(strings::MakeUniString(s));
|
||||
}
|
||||
|
||||
string DebugPrint(QueryParams::Token const & token)
|
||||
@@ -1510,10 +1504,12 @@ void QueryParams::ClearStreetIndices()
|
||||
AdditionalCommonTokens()
|
||||
{
|
||||
char const * arr[] = {
|
||||
"the", // English
|
||||
"der", "zum", "und", "auf", // German
|
||||
"del", "les", // Spanish
|
||||
"в", "на" // Cyrillic
|
||||
"a", "and", "s", "the", // English
|
||||
"am", "an", "auf", "der", "im", "und", "zum", // German
|
||||
"as", "d", "da", "das", "de", "del", "di", "do",
|
||||
"dos", "du", "e", "el", "et", "la", "las", "le",
|
||||
"les", "los", "o", "os", "y", // French, Italian, Portuguese, Spanish
|
||||
"в", "и", "на", "я" // Cyrillic
|
||||
};
|
||||
for (char const * s : arr)
|
||||
m_strings.insert(NormalizeAndSimplifyString(s));
|
||||
|
||||
@@ -28,7 +28,6 @@ public:
|
||||
Token(String const & original) : m_original(original) {}
|
||||
|
||||
void AddSynonym(std::string const & s);
|
||||
void AddSynonym(String const & s);
|
||||
|
||||
template <typename Fn>
|
||||
void ForEachSynonym(Fn && fn) const
|
||||
|
||||
@@ -94,42 +94,9 @@ ErrorsMade GetPrefixErrorsMade(QueryParams::Token const & token, strings::UniStr
|
||||
}
|
||||
} // namespace impl
|
||||
|
||||
bool IsStopWord(UniString const & s)
|
||||
{
|
||||
/// @todo Get all common used stop words and take out this array into search_string_utils.cpp module for example.
|
||||
/// Should skip this tokens when building search index?
|
||||
class StopWordsChecker
|
||||
{
|
||||
set<UniString> m_set;
|
||||
|
||||
public:
|
||||
StopWordsChecker()
|
||||
{
|
||||
// Don't want to put _full_ stopwords list, not to break current ranking.
|
||||
// Only 2-letters and the most common.
|
||||
char const * arr[] = {
|
||||
"a", "s", "the", // English
|
||||
"am", "im", "an", // German
|
||||
"d", "da", "de", "di", "du", "la", "le", // French, Spanish, Italian
|
||||
"и", "я" // Cyrillic
|
||||
};
|
||||
for (char const * s : arr)
|
||||
m_set.insert(MakeUniString(s));
|
||||
}
|
||||
bool Has(UniString const & s) const { return m_set.count(s) > 0; }
|
||||
};
|
||||
|
||||
static StopWordsChecker const swChecker;
|
||||
return swChecker.Has(s);
|
||||
}
|
||||
|
||||
TokensVector::TokensVector(string_view name)
|
||||
{
|
||||
ForEachNormalizedToken(name, [this](strings::UniString && token)
|
||||
{
|
||||
if (!IsStopWord(token))
|
||||
m_tokens.push_back(std::move(token));
|
||||
});
|
||||
m_tokens = NormalizeAndTokenizeString(std::move(name));
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
@@ -180,9 +180,6 @@ struct NameScores
|
||||
std::string DebugPrint(NameScore const & score);
|
||||
std::string DebugPrint(NameScores const & scores);
|
||||
|
||||
// Returns true when |s| is a stop-word and may be removed from a query.
|
||||
bool IsStopWord(strings::UniString const & s);
|
||||
|
||||
class TokensVector
|
||||
{
|
||||
std::vector<strings::UniString> m_tokens;
|
||||
|
||||
@@ -44,11 +44,7 @@ public:
|
||||
m_scorer.SetPivotForTesting(pivot);
|
||||
|
||||
vector<UniString> tokens;
|
||||
search::ForEachNormalizedToken(query, [&tokens](strings::UniString && token)
|
||||
{
|
||||
if (!IsStopWord(token))
|
||||
tokens.push_back(std::move(token));
|
||||
});
|
||||
tokens = NormalizeAndTokenizeString(query);
|
||||
|
||||
m_params.Init(query, tokens, lastTokenIsPrefix);
|
||||
}
|
||||
|
||||
@@ -31,22 +31,22 @@ python3 -m venv /tmp/venv
|
||||
echo "<$(date +%T)> Copying map generator INI..."
|
||||
cp var/etc/map_generator.ini.prod var/etc/map_generator.ini
|
||||
|
||||
$GENARGS=""
|
||||
GENARGS=""
|
||||
|
||||
if [ $MWMTEST -gt 0 ]; then
|
||||
if [ $MWMTEST == "true" ]; then
|
||||
echo "Marking as a test (non-prod) generation"
|
||||
# TODO: output test maps into e.g. osm-maps-test/ and use a different generation.log
|
||||
$GENARGS="$GENARGS -s=test"
|
||||
GENARGS="$GENARGS -s=test"
|
||||
fi
|
||||
|
||||
if [ $MWMCONTINUE -gt 0 ]; then
|
||||
if [ $MWMCONTINUE == "true" ]; then
|
||||
echo "Continuing from preexisting generator run"
|
||||
$GENARGS="$GENARGS --continue"
|
||||
GENARGS="$GENARGS --continue"
|
||||
fi
|
||||
|
||||
if [[ -n $MWMCOUNTRIES ]]; then
|
||||
echo "Generating only specific maps for [$MWMCOUNTRIES]"
|
||||
$GENARGS="$GENARGS --countries=$MWMCOUNTRIES"
|
||||
GENARGS="$GENARGS --countries=$MWMCOUNTRIES"
|
||||
fi
|
||||
|
||||
cd ~/comaps/tools/python
|
||||
|
||||
Reference in New Issue
Block a user