Compare commits

...

10 commits

Author SHA1 Message Date
androiddevkotlin
e3047f151d Use variable to store data from server 2021-04-22 11:36:41 +03:00
androiddevkotlin
85114b049d Fix compound button 2021-04-21 20:26:52 +03:00
Vitaliy
2ee1b26289 Merge branch 'master' into Redesign-voice 2021-04-21 14:02:14 +03:00
Vitaliy
daf31151f6 Merge branch 'master' into Redesign-voice 2021-04-20 19:12:31 +03:00
androiddevkotlin
d157d686ec Replace block code to createMenuItems, downloadThread field added, padding inline variable 2021-04-19 20:33:09 +03:00
androiddevkotlin
ed113a3835 Refactor, setting added 2021-04-19 19:58:08 +03:00
androiddevkotlin
ea553717d8 Small fixes UI 2021-04-19 15:05:33 +03:00
androiddevkotlin
bd1fbe859e Review 2021-04-19 14:25:53 +03:00
androiddevkotlin
66ba7ff2f6 Spillover from Voice Prompts
Replace string "Languages" > "Language"
"Language" icon ic_action_map_language
It seems 2 dividers below the "Options" header, remove one.
It seems we lost the warning banner below the "Speed cameras" switch.
New headers is blinking after taping on a switch.
Min. item height = 48dp
Remove "Navigation instructions" option
2021-04-18 21:12:43 +03:00
androiddevkotlin
23cc2430f1 New UI
Navigation settings > Voice prompts
0. New UI

    Rename the Voice guidance menu item to Language.
    Language dialog changes:
    • Add toggle between "TTS | Recorded"
    • Remove "Install more" item and download "Recorded" voice packages without leaving the dialog.
    • Delete the "Don't use" option, because currently, we have the main switch on the "Voice prompts" screen in Navigation settings.
    • Add option "Use system language", detect system language (we do similar in Wikipedia, where we get system languages and put them at the top of the list), and use it by default.
2021-04-18 11:46:21 +03:00
10 changed files with 459 additions and 111 deletions

View file

@ -79,6 +79,21 @@
</LinearLayout> </LinearLayout>
<androidx.appcompat.widget.AppCompatRadioButton
android:id="@+id/compound_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:scaleType="center"
android:background="@null"
android:layout_marginEnd="@dimen/dashFavDirectionSize"
android:layout_marginRight="@dimen/dashFavDirectionSize"
android:clickable="false"
android:focusable="false"
android:visibility="gone"
android:saveEnabled="false"
tools:visibility="visible"/>
<androidx.appcompat.widget.AppCompatImageView <androidx.appcompat.widget.AppCompatImageView
android:id="@+id/secondary_icon" android:id="@+id/secondary_icon"
android:layout_width="@dimen/list_item_height" android:layout_width="@dimen/list_item_height"

View file

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="@dimen/card_row_min_height"
android:background="?attr/list_background_color"
android:gravity="center_vertical"
android:minHeight="@dimen/bottom_sheet_cancel_button_height"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatImageView
android:id="@android:id/icon"
android:layout_width="@dimen/standard_icon_size"
android:layout_height="@dimen/standard_icon_size"
android:layout_gravity="center"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding" />
<net.osmand.plus.widgets.TextViewEx
android:id="@android:id/title"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:textColor="@color/preference_category_title"
android:layout_gravity="center_vertical|start"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="@string/plugin_settings"
android:paddingEnd="@dimen/content_padding"
android:paddingStart="@dimen/content_padding" />
</LinearLayout>

View file

@ -12,6 +12,11 @@
--> -->
<string name="use_system_language">Use system language</string>
<string name="recorded_description">Recorded voice sounds better, but can pronounce only prerecorded phrases: turn instructions. Can\'t announce street names or POI names.</string>
<string name="tts_title">TTS</string>
<string name="tts_description">Text-to-speech (TTS) can pronounce all types of instructions: street names, turn instruction, POI names etc.</string>
<string name="language_description">Select preferred language and type of voice guidance.</string>
<string name="output">Output</string> <string name="output">Output</string>
<string name="user_points">User points</string> <string name="user_points">User points</string>
<string name="announce_when_exceeded">Announce when exceeded</string> <string name="announce_when_exceeded">Announce when exceeded</string>

View file

@ -15,23 +15,19 @@
android:key="voice_provider" android:key="voice_provider"
android:layout="@layout/preference_with_descr" android:layout="@layout/preference_with_descr"
android:persistent="false" android:persistent="false"
android:title="@string/shared_string_languages" android:title="@string/shared_string_language"
tools:icon="@drawable/ic_action_volume_up" /> tools:icon="@drawable/ic_action_volume_up" />
<Preference <Preference
android:key="language_divider"
android:layout="@layout/simple_divider_item" android:layout="@layout/simple_divider_item"
android:selectable="false" /> android:selectable="false" />
<PreferenceCategory <PreferenceCategory
android:key="language_and_output" android:key="announce_header"
android:layout="@layout/preference_category_with_descr" android:layout="@layout/preference_category_title"
android:title="@string/accessibility_announce" /> android:title="@string/accessibility_announce" />
<net.osmand.plus.settings.preferences.SwitchPreferenceEx
android:key="turn_screen_on_navigation_instructions"
android:layout="@layout/preference_with_descr"
android:title="@string/turn_screen_on_navigation_instructions" />
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:key="speak_street_names" android:key="speak_street_names"
android:layout="@layout/preference_switch" android:layout="@layout/preference_switch"
@ -43,6 +39,7 @@
android:title="@string/exit_number" /> android:title="@string/exit_number" />
<Preference <Preference
android:key="exit_number_divider"
android:layout="@layout/divider_half_item" android:layout="@layout/divider_half_item"
android:selectable="false" /> android:selectable="false" />
@ -61,18 +58,27 @@
android:layout="@layout/preference_switch" android:layout="@layout/preference_switch"
android:title="@string/speak_cameras" /> android:title="@string/speak_cameras" />
<Preference
android:key="speed_cameras_uninstalled"
android:layout="@layout/preference_permission"
android:persistent="false"
android:summary="@string/read_more"
android:title="@string/speed_cameras_alert"
tools:icon="@drawable/ic_action_alert" />
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:key="speak_tunnels" android:key="speak_tunnels"
android:layout="@layout/preference_switch" android:layout="@layout/preference_switch"
android:title="@string/show_tunnels" /> android:title="@string/show_tunnels" />
<Preference <Preference
android:key="announce_divider"
android:layout="@layout/divider_half_item" android:layout="@layout/divider_half_item"
android:selectable="false" /> android:selectable="false" />
<PreferenceCategory <PreferenceCategory
android:key="language_and_output" android:key="user_points_header"
android:layout="@layout/preference_category_with_descr" android:layout="@layout/preference_category_title"
android:title="@string/user_points" /> android:title="@string/user_points" />
<SwitchPreferenceCompat <SwitchPreferenceCompat
@ -91,12 +97,13 @@
android:title="@string/speak_poi" /> android:title="@string/speak_poi" />
<Preference <Preference
android:key="user_points_divider"
android:layout="@layout/divider_half_item" android:layout="@layout/divider_half_item"
android:selectable="false" /> android:selectable="false" />
<PreferenceCategory <PreferenceCategory
android:key="language_and_output" android:key="speed_limit_header"
android:layout="@layout/preference_category_with_descr" android:layout="@layout/preference_category_title"
android:title="@string/speak_speed_limit" /> android:title="@string/speak_speed_limit" />
<SwitchPreferenceCompat <SwitchPreferenceCompat
@ -110,16 +117,13 @@
android:title="@string/speed_limit_exceed" /> android:title="@string/speed_limit_exceed" />
<Preference <Preference
android:layout="@layout/simple_divider_item" android:key="speed_limit_divider"
android:selectable="false" />
<Preference
android:layout="@layout/simple_divider_item" android:layout="@layout/simple_divider_item"
android:selectable="false" /> android:selectable="false" />
<PreferenceCategory <PreferenceCategory
android:key="language_and_output" android:key="options_header"
android:layout="@layout/preference_category_with_descr" android:layout="@layout/preference_category_title"
android:title="@string/shared_string_options" /> android:title="@string/shared_string_options" />
<net.osmand.plus.settings.preferences.ListPreferenceEx <net.osmand.plus.settings.preferences.ListPreferenceEx
@ -133,12 +137,13 @@
android:title="@string/announcement_time_title" /> android:title="@string/announcement_time_title" />
<Preference <Preference
android:key="options_divider"
android:layout="@layout/simple_divider_item" android:layout="@layout/simple_divider_item"
android:selectable="false" /> android:selectable="false" />
<PreferenceCategory <PreferenceCategory
android:key="language_and_output" android:key="output_header"
android:layout="@layout/preference_category_with_descr" android:layout="@layout/preference_category_title"
android:title="@string/output" /> android:title="@string/output" />
</PreferenceScreen> </PreferenceScreen>

View file

@ -662,6 +662,14 @@ public class DownloadResources extends DownloadResourceGroup {
return res; return res;
} }
public List<DownloadItem> getDownloadItemsForGroup(String groupId) {
DownloadResourceGroup group = getSubGroupById(groupId);
if (group != null) {
return group.getIndividualDownloadItems();
}
return Collections.emptyList();
}
public static List<IndexItem> findIndexItemsAt(OsmandApplication app, public static List<IndexItem> findIndexItemsAt(OsmandApplication app,
List<String> names, List<String> names,
DownloadActivityType type, DownloadActivityType type,

View file

@ -2641,7 +2641,7 @@ public class OsmandSettings {
return lang + IndexConstants.VOICE_PROVIDER_SUFFIX; return lang + IndexConstants.VOICE_PROVIDER_SUFFIX;
} }
} }
return "en-tts"; return VOICE_PROVIDER_NOT_USE;
} }
}.makeProfile(); }.makeProfile();

View file

@ -923,6 +923,12 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl
} }
} }
public void setupSpeedCamerasAlert() {
Preference speedCamerasAlert = findPreference(settings.SPEED_CAMERAS_UNINSTALLED.getId());
speedCamerasAlert.setIcon(getContentIcon(R.drawable.ic_action_alert));
speedCamerasAlert.setVisible(!settings.SPEED_CAMERAS_UNINSTALLED.get());
}
public void setupPrefRoundedBg(PreferenceViewHolder holder) { public void setupPrefRoundedBg(PreferenceViewHolder holder) {
View selectableView = holder.itemView.findViewById(R.id.selectable_list_item); View selectableView = holder.itemView.findViewById(R.id.selectable_list_item);
if (selectableView != null) { if (selectableView != null) {

View file

@ -164,10 +164,4 @@ public class ScreenAlertsFragment extends BaseSettingsFragment implements OnPref
showCameras.setIcon(getIcon(R.drawable.list_warnings_speed_camera)); showCameras.setIcon(getIcon(R.drawable.list_warnings_speed_camera));
showCameras.setVisible(!settings.SPEED_CAMERAS_UNINSTALLED.get()); showCameras.setVisible(!settings.SPEED_CAMERAS_UNINSTALLED.get());
} }
public void setupSpeedCamerasAlert() {
Preference speedCamerasAlert = findPreference(settings.SPEED_CAMERAS_UNINSTALLED.getId());
speedCamerasAlert.setIcon(getContentIcon(R.drawable.ic_action_alert));
speedCamerasAlert.setVisible(!settings.SPEED_CAMERAS_UNINSTALLED.get());
}
} }

View file

@ -1,9 +1,6 @@
package net.osmand.plus.settings.fragments; package net.osmand.plus.settings.fragments;
import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.media.AudioManager; import android.media.AudioManager;
import android.net.Uri; import android.net.Uri;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -23,21 +20,13 @@ import net.osmand.plus.R;
import net.osmand.plus.UiUtilities; import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.dialogs.SpeedCamerasBottomSheet; import net.osmand.plus.dialogs.SpeedCamerasBottomSheet;
import net.osmand.plus.download.DownloadActivity;
import net.osmand.plus.download.DownloadActivityType;
import net.osmand.plus.helpers.FileNameTranslationHelper;
import net.osmand.plus.helpers.enums.MetricsConstants; import net.osmand.plus.helpers.enums.MetricsConstants;
import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.bottomsheets.AnnouncementTimeBottomSheet; import net.osmand.plus.settings.bottomsheets.AnnouncementTimeBottomSheet;
import net.osmand.plus.settings.preferences.ListPreferenceEx; import net.osmand.plus.settings.preferences.ListPreferenceEx;
import net.osmand.plus.settings.preferences.SwitchPreferenceEx;
import net.osmand.plus.wikipedia.WikipediaDialogFragment; import net.osmand.plus.wikipedia.WikipediaDialogFragment;
import java.util.Set;
import static net.osmand.plus.UiUtilities.CompoundButtonType.TOOLBAR; import static net.osmand.plus.UiUtilities.CompoundButtonType.TOOLBAR;
import static net.osmand.plus.settings.backend.OsmandSettings.VOICE_PROVIDER_NOT_USE;
public class VoiceAnnouncesFragment extends BaseSettingsFragment implements OnPreferenceChanged { public class VoiceAnnouncesFragment extends BaseSettingsFragment implements OnPreferenceChanged {
@ -106,18 +95,20 @@ public class VoiceAnnouncesFragment extends BaseSettingsFragment implements OnPr
Preference voiceAnnouncesInfo = findPreference("voice_announces_info"); Preference voiceAnnouncesInfo = findPreference("voice_announces_info");
voiceAnnouncesInfo.setIcon(getContentIcon(R.drawable.ic_action_info_dark)); voiceAnnouncesInfo.setIcon(getContentIcon(R.drawable.ic_action_info_dark));
Preference languageSetting = findPreference("voice_provider");
languageSetting.setIcon(getContentIcon(R.drawable.ic_action_map_language));
setupSpeedLimitExceedPref(); setupSpeedLimitExceedPref();
setupKeepInformingPref(); setupKeepInformingPref();
setupArrivalAnnouncementPref(); setupArrivalAnnouncementPref();
setupVoiceProviderPref();
setupAudioStreamGuidancePref(); setupAudioStreamGuidancePref();
setupInterruptMusicPref(); setupInterruptMusicPref();
enableDisablePreferences(!settings.VOICE_MUTE.getModeValue(getSelectedAppMode())); enableDisablePreferences(!settings.VOICE_MUTE.getModeValue(getSelectedAppMode()));
setupSpeakCamerasPref(); setupSpeakCamerasPref();
setupTurnScreenOnNavigationInstructionsPref(); setupSpeedCamerasAlert();
} }
private void setupSpeedLimitExceedPref() { private void setupSpeedLimitExceedPref() {
@ -168,37 +159,6 @@ public class VoiceAnnouncesFragment extends BaseSettingsFragment implements OnPr
arrivalDistanceFactor.setEntryValues(arrivalValues); arrivalDistanceFactor.setEntryValues(arrivalValues);
} }
private void setupVoiceProviderPref() {
Activity activity = getActivity();
if (activity == null) {
return;
}
Set<String> voiceFiles = app.getRoutingOptionsHelper().getVoiceFiles(activity);
String[] entries = new String[voiceFiles.size() + 2];
String[] entryValues = new String[voiceFiles.size() + 2];
int k = 0;
// entries[k++] = getString(R.string.shared_string_none);
entryValues[k] = OsmandSettings.VOICE_PROVIDER_NOT_USE;
entries[k++] = getString(R.string.shared_string_do_not_use);
for (String s : voiceFiles) {
entries[k] = (s.contains("tts") ? getString(R.string.ttsvoice) + " " : "") + FileNameTranslationHelper.getVoiceName(activity, s);
entryValues[k] = s;
k++;
}
entryValues[k] = MORE_VALUE;
entries[k] = getString(R.string.install_more);
Drawable disabled = getContentIcon(R.drawable.ic_action_volume_mute);
Drawable enabled = getActiveIcon(R.drawable.ic_action_volume_up);
Drawable icon = getPersistentPrefIcon(enabled, disabled);
ListPreferenceEx voiceProvider = findPreference(settings.VOICE_PROVIDER.getId());
voiceProvider.setEntries(entries);
voiceProvider.setEntryValues(entryValues);
voiceProvider.setIcon(icon);
}
private void setupAudioStreamGuidancePref() { private void setupAudioStreamGuidancePref() {
String[] streamTypes = new String[]{ String[] streamTypes = new String[]{
getString(R.string.voice_stream_music), getString(R.string.voice_stream_music),
@ -223,11 +183,6 @@ public class VoiceAnnouncesFragment extends BaseSettingsFragment implements OnPr
getPreferenceScreen().addPreference(interruptMusicPref); getPreferenceScreen().addPreference(interruptMusicPref);
} }
private void setupTurnScreenOnNavigationInstructionsPref() {
SwitchPreferenceEx turnScreenOnNavigationInstructions = findPreference(settings.TURN_SCREEN_ON_NAVIGATION_INSTRUCTIONS.getId());
turnScreenOnNavigationInstructions.setDescription(R.string.turn_screen_on_navigation_instructions_descr);
}
private void updateMenu() { private void updateMenu() {
MapActivity mapActivity = getMapActivity(); MapActivity mapActivity = getMapActivity();
if (mapActivity != null) { if (mapActivity != null) {
@ -238,17 +193,7 @@ public class VoiceAnnouncesFragment extends BaseSettingsFragment implements OnPr
@Override @Override
protected void onBindPreferenceViewHolder(Preference preference, PreferenceViewHolder holder) { protected void onBindPreferenceViewHolder(Preference preference, PreferenceViewHolder holder) {
super.onBindPreferenceViewHolder(preference, holder); super.onBindPreferenceViewHolder(preference, holder);
if (settings.VOICE_PROVIDER.getId().equals(preference.getKey()) && preference instanceof ListPreferenceEx) { if (settings.SPEED_CAMERAS_UNINSTALLED.getId().equals(preference.getKey())) {
TextView titleView = (TextView) holder.findViewById(android.R.id.title);
if (titleView != null) {
titleView.setTextColor(preference.isEnabled() ? getActiveTextColor() : getDisabledTextColor());
}
ImageView imageView = (ImageView) holder.findViewById(android.R.id.icon);
if (imageView != null) {
Object currentValue = ((ListPreferenceEx) preference).getValue();
imageView.setEnabled(preference.isEnabled() && !OsmandSettings.VOICE_PROVIDER_NOT_USE.equals(currentValue));
}
} else if (settings.SPEED_CAMERAS_UNINSTALLED.getId().equals(preference.getKey())) {
setupPrefRoundedBg(holder); setupPrefRoundedBg(holder);
} }
} }
@ -257,20 +202,6 @@ public class VoiceAnnouncesFragment extends BaseSettingsFragment implements OnPr
public boolean onPreferenceChange(Preference preference, Object newValue) { public boolean onPreferenceChange(Preference preference, Object newValue) {
String prefId = preference.getKey(); String prefId = preference.getKey();
ApplicationMode selectedMode = getSelectedAppMode(); ApplicationMode selectedMode = getSelectedAppMode();
if (prefId.equals(settings.VOICE_PROVIDER.getId())) {
if (MORE_VALUE.equals(newValue)) {
// listPref.set(oldValue); // revert the change..
final Intent intent = new Intent(getContext(), DownloadActivity.class);
intent.putExtra(DownloadActivity.TAB_TO_OPEN, DownloadActivity.DOWNLOAD_TAB);
intent.putExtra(DownloadActivity.FILTER_CAT, DownloadActivityType.VOICE_FILE.getTag());
startActivity(intent);
return false;
} else if (newValue instanceof String) {
onConfirmPreferenceChange(settings.VOICE_PROVIDER.getId(), newValue, ApplyQueryType.SNACK_BAR);
}
return true;
}
if (prefId.equals(settings.SPEAK_SPEED_CAMERA.getId())) { if (prefId.equals(settings.SPEAK_SPEED_CAMERA.getId())) {
if (!settings.SPEAK_SPEED_CAMERA.getModeValue(selectedMode)) { if (!settings.SPEAK_SPEED_CAMERA.getModeValue(selectedMode)) {
return onConfirmPreferenceChange( return onConfirmPreferenceChange(
@ -290,15 +221,7 @@ public class VoiceAnnouncesFragment extends BaseSettingsFragment implements OnPr
@Override @Override
public void onApplyPreferenceChange(String prefId, boolean applyToAllProfiles, Object newValue) { public void onApplyPreferenceChange(String prefId, boolean applyToAllProfiles, Object newValue) {
if (prefId.equals(settings.VOICE_PROVIDER.getId()) && newValue instanceof String) { if (prefId.equals(settings.AUDIO_MANAGER_STREAM.getId())) {
if (VOICE_PROVIDER_NOT_USE.equals(newValue)) {
applyPreference(settings.VOICE_MUTE.getId(), applyToAllProfiles, true);
updateToolbar();
}
applyPreference(settings.VOICE_PROVIDER.getId(), applyToAllProfiles, newValue);
app.initVoiceCommandPlayer(getActivity(), getSelectedAppMode(),
false, null, true, false, applyToAllProfiles);
} else if (prefId.equals(settings.AUDIO_MANAGER_STREAM.getId())) {
// Sync DEFAULT value with CAR value, as we have other way to set it for now // Sync DEFAULT value with CAR value, as we have other way to set it for now
if (getSelectedAppMode().equals(ApplicationMode.CAR) && newValue instanceof Integer) { if (getSelectedAppMode().equals(ApplicationMode.CAR) && newValue instanceof Integer) {
@ -324,12 +247,13 @@ public class VoiceAnnouncesFragment extends BaseSettingsFragment implements OnPr
@Override @Override
public void onDisplayPreferenceDialog(Preference preference) { public void onDisplayPreferenceDialog(Preference preference) {
String prefId = preference.getKey(); String prefId = preference.getKey();
if (settings.ARRIVAL_DISTANCE_FACTOR.getId().equals(prefId)) { if (settings.ARRIVAL_DISTANCE_FACTOR.getId().equals(prefId)) {
FragmentManager fragmentManager = getFragmentManager(); FragmentManager fragmentManager = getFragmentManager();
if (fragmentManager != null) { if (fragmentManager != null) {
AnnouncementTimeBottomSheet.showInstance(fragmentManager, preference.getKey(), this, getSelectedAppMode(), false); AnnouncementTimeBottomSheet.showInstance(fragmentManager, preference.getKey(), this, getSelectedAppMode(), false);
} }
} else if (settings.VOICE_PROVIDER.getId().equals(prefId)) {
VoiceLanguageBottomSheetFragment.showInstance(requireActivity().getSupportFragmentManager(), this, preference.getKey(), false);
} else { } else {
super.onDisplayPreferenceDialog(preference); super.onDisplayPreferenceDialog(preference);
} }
@ -339,6 +263,7 @@ public class VoiceAnnouncesFragment extends BaseSettingsFragment implements OnPr
public void onPreferenceChanged(String prefId) { public void onPreferenceChanged(String prefId) {
if (prefId.equals(settings.SPEED_CAMERAS_UNINSTALLED.getId())) { if (prefId.equals(settings.SPEED_CAMERAS_UNINSTALLED.getId())) {
setupSpeakCamerasPref(); setupSpeakCamerasPref();
setupSpeedCamerasAlert();
} }
} }
@ -346,4 +271,5 @@ public class VoiceAnnouncesFragment extends BaseSettingsFragment implements OnPr
SwitchPreferenceCompat showCameras = findPreference(settings.SPEAK_SPEED_CAMERA.getId()); SwitchPreferenceCompat showCameras = findPreference(settings.SPEAK_SPEED_CAMERA.getId());
showCameras.setVisible(!settings.SPEED_CAMERAS_UNINSTALLED.get()); showCameras.setVisible(!settings.SPEED_CAMERAS_UNINSTALLED.get());
} }
} }

View file

@ -0,0 +1,352 @@
package net.osmand.plus.settings.fragments;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RadioButton;
import android.widget.TextView;
import androidx.annotation.DimenRes;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils;
import net.osmand.PlatformUtil;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton;
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerSpaceItem;
import net.osmand.plus.download.DownloadIndexesThread;
import net.osmand.plus.download.DownloadItem;
import net.osmand.plus.download.DownloadValidationManager;
import net.osmand.plus.download.IndexItem;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.track.TrackSelectSegmentBottomSheet;
import net.osmand.plus.widgets.multistatetoggle.RadioItem;
import net.osmand.plus.widgets.multistatetoggle.RadioItem.OnRadioItemClickListener;
import net.osmand.plus.widgets.multistatetoggle.TextToggleButton;
import net.osmand.plus.widgets.multistatetoggle.TextToggleButton.TextRadioItem;
import org.apache.commons.logging.Log;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import static net.osmand.plus.UiUtilities.CompoundButtonType.PROFILE_DEPENDENT;
import static net.osmand.plus.download.DownloadResourceGroup.DownloadResourceGroupType.OTHER_GROUP;
import static net.osmand.plus.download.DownloadResourceGroup.DownloadResourceGroupType.VOICE_HEADER_REC;
import static net.osmand.plus.download.DownloadResourceGroup.DownloadResourceGroupType.VOICE_HEADER_TTS;
import static net.osmand.plus.download.DownloadResourceGroup.DownloadResourceGroupType.VOICE_REC;
import static net.osmand.plus.download.DownloadResourceGroup.DownloadResourceGroupType.VOICE_TTS;
import static net.osmand.plus.settings.bottomsheets.BasePreferenceBottomSheet.PREFERENCE_ID;
public class VoiceLanguageBottomSheetFragment extends MenuBottomSheetDialogFragment implements DownloadIndexesThread.DownloadEvents {
private static final String TAG = TrackSelectSegmentBottomSheet.class.getSimpleName();
private static final Log LOG = PlatformUtil.getLog(VoiceLanguageBottomSheetFragment.class);
private static final String VOICE_REC_KEY = OTHER_GROUP.getDefaultId() + "#" + VOICE_TTS.getDefaultId() + "#" + VOICE_HEADER_TTS.getDefaultId();
private static final String VOICE_TTS_KEY = OTHER_GROUP.getDefaultId() + "#" + VOICE_REC.getDefaultId() + "#" + VOICE_HEADER_REC.getDefaultId();
private static final int DEFAULT_LANGUAGE_POSITION = 6;
private OsmandApplication app;
private OsmandSettings settings;
private DownloadIndexesThread downloadThread;
List<DownloadItem> voiceItems;
List<DownloadItem> voiceItemsRec;
private InfoType selectedVoiceType = InfoType.TTS;
public static void showInstance(@NonNull FragmentManager fm, Fragment targetFragment, String key, boolean usedOnMap) {
try {
if (!fm.isStateSaved()) {
Bundle args = new Bundle();
args.putString(PREFERENCE_ID, key);
VoiceLanguageBottomSheetFragment fragment = new VoiceLanguageBottomSheetFragment();
fragment.setRetainInstance(true);
fragment.setArguments(args);
fragment.setUsedOnMap(usedOnMap);
fragment.setTargetFragment(targetFragment, 0);
fragment.show(fm, TAG);
}
} catch (RuntimeException e) {
LOG.error("showInstance", e);
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
app = requiredMyApplication();
}
@Override
public void createMenuItems(Bundle savedInstanceState) {
Context context = requireContext();
settings = app.getSettings();
downloadThread = app.getDownloadThread();
int padding = getDimen(R.dimen.content_padding_small);
LayoutInflater inflater = UiUtilities.getInflater(app, nightMode);
BaseBottomSheetItem titleItem = new BottomSheetItemWithDescription.Builder()
.setDescription(getString(R.string.language_description))
.setDescriptionColorId(nightMode ? R.color.text_color_primary_dark : R.color.text_color_primary_light)
.setTitle(getString(R.string.shared_string_language))
.setLayoutId(R.layout.bottom_sheet_item_title_with_description)
.create();
items.add(titleItem);
items.add(new DividerSpaceItem(context, padding));
LinearLayout voiceTypeButtons = (LinearLayout) inflater.inflate(R.layout.custom_radio_buttons, null);
LinearLayout.MarginLayoutParams itemTimeOfDayParams = new LinearLayout.MarginLayoutParams(
LinearLayout.MarginLayoutParams.MATCH_PARENT, LinearLayout.MarginLayoutParams.WRAP_CONTENT);
AndroidUtils.setMargins(itemTimeOfDayParams, padding, 0, padding, 0);
voiceTypeButtons.setLayoutParams(itemTimeOfDayParams);
setupTypeRadioGroup(voiceTypeButtons);
items.add(new BaseBottomSheetItem.Builder()
.setCustomView(voiceTypeButtons)
.create()
);
items.add(new DividerSpaceItem(context, padding));
BaseBottomSheetItem switchStartAndEndItem = new BottomSheetItemWithDescription.Builder()
.setDescription(getString(selectedVoiceType == InfoType.TTS ? R.string.tts_description : R.string.recorded_description))
.setLayoutId(R.layout.bottom_sheet_item_description_long)
.create();
items.add(switchStartAndEndItem);
items.add(createDividerItem());
createVoiceView();
}
@Override
public void newDownloadIndexes() {
updateItems();
}
private void updateItems() {
Activity activity = getActivity();
View mainView = getView();
if (activity != null && mainView != null) {
Context context = requireContext();
LinearLayout itemsContainer = (LinearLayout) mainView.findViewById(useScrollableItemsContainer()
? R.id.scrollable_items_container : R.id.non_scrollable_items_container);
if (itemsContainer != null) {
itemsContainer.removeAllViews();
}
items.clear();
createMenuItems(null);
for (BaseBottomSheetItem item : items) {
item.inflate(context, itemsContainer, nightMode);
}
setupHeightAndBackground(mainView);
}
}
@Override
public void downloadInProgress() {
IndexItem downloadIndexItem = downloadThread.getCurrentDownloadingItem();
if (downloadIndexItem != null) {
for (BaseBottomSheetItem item : items) {
if (item instanceof BottomSheetItemWithDescription) {
Object tag = item.getTag();
if (tag instanceof IndexItem) {
IndexItem indexItem = (IndexItem) tag;
BottomSheetItemWithDescription mapItem = (BottomSheetItemWithDescription) item;
ProgressBar progressBar = mapItem.getView().findViewById(R.id.ProgressBar);
if (downloadIndexItem.equals(indexItem)) {
progressBar.setProgress(downloadThread.getCurrentDownloadingItemProgress());
progressBar.setIndeterminate(false);
} else if (indexItem.isDownloaded()) {
AndroidUiHelper.updateVisibility(progressBar, false);
}
}
}
}
}
}
@Override
public void downloadHasFinished() {
updateItems();
}
private void setupTypeRadioGroup(LinearLayout buttonsContainer) {
TextRadioItem tts = createRadioButton(InfoType.TTS, R.string.tts_title);
TextRadioItem recorded = createRadioButton(InfoType.RECORDED, R.string.shared_string_recorded);
TextToggleButton radioGroup = new TextToggleButton(app, buttonsContainer, nightMode);
radioGroup.setItems(tts, recorded);
if (selectedVoiceType == InfoType.TTS) {
radioGroup.setSelectedItem(tts);
} else {
radioGroup.setSelectedItem(recorded);
}
}
private TextRadioItem createRadioButton(final InfoType voiceType, int titleId) {
String title = app.getString(titleId);
TextRadioItem item = new TextRadioItem(title);
item.setOnClickListener(new OnRadioItemClickListener() {
@Override
public boolean onRadioItemClick(RadioItem radioItem, View view) {
selectedVoiceType = voiceType;
createVoiceView();
updateItems();
return true;
}
});
return item;
}
private void createVoiceView() {
if (selectedVoiceType == InfoType.TTS && voiceItems == null) {
voiceItems = getVoiceList(VOICE_TTS_KEY);
} else if(selectedVoiceType == InfoType.RECORDED && voiceItemsRec == null) {
voiceItemsRec = getVoiceList(VOICE_REC_KEY);
}
createSuggestedVoiceItemsView(selectedVoiceType == InfoType.TTS ? voiceItems : voiceItemsRec);
}
private void createSuggestedVoiceItemsView(List<DownloadItem> suggestedMaps) {
final Context context = requireContext();
final OsmandSettings settings = app.getSettings();
final ApplicationMode applicationMode = settings.getApplicationMode();
final LayoutInflater inflater = UiUtilities.getInflater(app, nightMode);
for (final DownloadItem indexItem : suggestedMaps) {
View container = inflater.inflate(R.layout.list_item_icon_and_download, null);
AndroidUtils.setBackground(container, UiUtilities.getSelectableDrawable(context));
container.findViewById(R.id.divider).setVisibility(View.GONE);
String systemLanguage = Resources.getSystem().getConfiguration().locale.getLanguage();
DateFormat df = SimpleDateFormat.getDateInstance(DateFormat.DEFAULT);
boolean isDefault = indexItem.isDownloaded() && indexItem.getBasename().equals(systemLanguage);
String title = isDefault ? getString(R.string.use_system_language) : indexItem.getVisibleName(app, app.getRegions(), false);
String dateUpdate = ((IndexItem) indexItem).getDate(df);
String description = isDefault ? indexItem.getVisibleName(app, app.getRegions(), false) : indexItem.getSizeDescription(app) + "" + dateUpdate;
int position = isDefault ? DEFAULT_LANGUAGE_POSITION : -1;
final ImageView secondaryIcon = container.findViewById(R.id.secondary_icon);
int activeColorResId = nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light;
secondaryIcon.setColorFilter(ContextCompat.getColor(context, activeColorResId));
final ProgressBar progressBar = container.findViewById(R.id.ProgressBar);
final TextView textDescription = container.findViewById(R.id.description);
RadioButton radioButton = (RadioButton) container.findViewById(R.id.compound_button);
UiUtilities.setupCompoundButton(radioButton, nightMode, PROFILE_DEPENDENT);
AndroidUiHelper.updateVisibility(secondaryIcon, true);
AndroidUiHelper.updateVisibility(progressBar, downloadThread.isDownloading((IndexItem) indexItem));
if (indexItem == downloadThread.getCurrentDownloadingItem()) {
progressBar.setProgress(downloadThread.getCurrentDownloadingItemProgress());
progressBar.setIndeterminate(false);
secondaryIcon.setImageDrawable(getContentIcon(R.drawable.ic_action_remove_dark));
} else {
progressBar.setIndeterminate(downloadThread.isDownloading());
secondaryIcon.setImageDrawable(getContentIcon(R.drawable.ic_action_gsave_dark));
}
if (indexItem.isDownloaded()) {
AndroidUiHelper.updateVisibility(radioButton, true);
AndroidUiHelper.updateVisibility(secondaryIcon, false);
} else {
AndroidUiHelper.updateVisibility(radioButton, false);
AndroidUiHelper.updateVisibility(secondaryIcon, true);
}
boolean selected = settings.VOICE_PROVIDER.getModeValue(applicationMode).contains(indexItem.getBasename());
final BottomSheetItemWithCompoundButton[] voiceDownloadedItem = new BottomSheetItemWithCompoundButton[1];
voiceDownloadedItem[0] = (BottomSheetItemWithCompoundButton) new BottomSheetItemWithCompoundButton.Builder()
.setCompoundButtonColorId(activeColorResId)
.setChecked(selected)
.setDescription(description)
.setIconHidden(true)
.setTitle(title)
.setPosition(position)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (indexItem.isDownloaded()) {
boolean checked = !voiceDownloadedItem[0].isChecked();
voiceDownloadedItem[0].setChecked(checked);
settings.VOICE_PROVIDER.setModeValue(applicationMode, indexItem.getBasename());
dismiss();
} else {
if (downloadThread.isDownloading((IndexItem) indexItem)) {
downloadThread.cancelDownload(indexItem);
AndroidUiHelper.updateVisibility(progressBar, false);
AndroidUiHelper.updateVisibility(textDescription, true);
secondaryIcon.setImageDrawable(getContentIcon(R.drawable.ic_action_gsave_dark));
} else {
AndroidUiHelper.updateVisibility(progressBar, true);
AndroidUiHelper.updateVisibility(textDescription, false);
progressBar.setIndeterminate(downloadThread.isDownloading());
secondaryIcon.setImageDrawable(getContentIcon(R.drawable.ic_action_remove_dark));
new DownloadValidationManager(app).startDownload(getActivity(), (IndexItem) indexItem);
}
}
}
})
.setCustomView(container)
.create();
items.add(voiceDownloadedItem[0]);
}
}
public int getDimen(@DimenRes int id) {
return getResources().getDimensionPixelSize(id);
}
private BaseBottomSheetItem createDividerItem() {
DividerItem dividerItem = new DividerItem(app);
int start = getDimen(R.dimen.content_padding);
int vertical = getDimen(R.dimen.content_padding_small_half);
dividerItem.setMargins(start, vertical, 0, vertical);
return dividerItem;
}
public List<DownloadItem> getVoiceList(String type) {
if (!downloadThread.getIndexes().isDownloadedFromInternet && settings.isInternetConnectionAvailable()) {
downloadThread.runReloadIndexFiles();
}
boolean downloadIndexes = settings.isInternetConnectionAvailable()
&& !downloadThread.getIndexes().isDownloadedFromInternet
&& !downloadThread.getIndexes().downloadFromInternetFailed;
List<DownloadItem> suggestedVoice = new ArrayList<>();
if (!downloadIndexes) {
suggestedVoice.addAll(app.getDownloadThread().getIndexes().getDownloadItemsForGroup(type));
}
return suggestedVoice;
}
private enum InfoType {
TTS,
RECORDED
}
}