Merge pull request #10476 from osmandapp/OnlineRoutingUi

Online Routing UI
This commit is contained in:
Vitaliy 2021-01-04 10:54:32 +02:00 committed by GitHub
commit 800fde9917
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 1748 additions and 39 deletions

View file

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:minHeight="@dimen/setting_list_item_group_height"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding"
android:paddingStart="@dimen/content_padding">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/icon"
android:layout_width="@dimen/standard_icon_size"
android:layout_height="@dimen/standard_icon_size"
android:layout_gravity="center_vertical"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
tools:src="@drawable/list_destination"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginStart="@dimen/content_padding"
android:orientation="vertical">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
app:typeface="@string/font_roboto_regular"
tools:text="Some title" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/default_desc_text_size"
app:typeface="@string/font_roboto_regular"
tools:text="Some description" />
</LinearLayout>
</LinearLayout>

View file

@ -9,7 +9,7 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="63dp"
android:layout_height="@dimen/bottom_sheet_large_list_item_height"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="@dimen/list_content_padding"
@ -71,8 +71,8 @@
android:id="@+id/divider_bottom"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginStart="64dp"
android:layout_marginLeft="64dp"
android:layout_marginStart="@dimen/bottom_sheet_divider_margin_start"
android:layout_marginLeft="@dimen/bottom_sheet_divider_margin_start"
android:background="?attr/divider_color" />
</LinearLayout>

View file

@ -0,0 +1,111 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="@dimen/bottom_sheet_large_list_item_height"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="?attr/selectableItemBackground"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/bottom_sheet_large_list_item_height"
android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/main_item_part"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:paddingLeft="@dimen/content_padding"
android:paddingStart="@dimen/content_padding"
android:paddingRight="0dp"
android:paddingEnd="0dp"
android:layout_weight="1"
android:gravity="center_vertical">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/bottom_sheet_icon_margin"
android:layout_marginRight="@dimen/bottom_sheet_icon_margin"
tools:src="@drawable/ic_action_coordinates_latitude"
tools:tint="?attr/default_icon_color" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
android:textAppearance="@style/TextAppearance.ListItemTitle"
android:textColor="?android:textColorPrimary"
tools:text="Item Title" />
<TextView
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?android:textColorSecondary"
tools:text="Item additional desription" />
</LinearLayout>
<androidx.appcompat.widget.AppCompatRadioButton
android:id="@+id/compound_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:clickable="false"
android:focusable="false"
android:saveEnabled="false"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding" />
</LinearLayout>
<View
android:layout_width="1dp"
android:layout_height="36dp"
android:background="?attr/divider_color_basic"/>
<LinearLayout
android:id="@+id/eng_button"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="@dimen/standard_icon_size"
android:layout_height="@dimen/standard_icon_size"
android:layout_gravity="center_vertical"
app:srcCompat="@drawable/ic_action_settings"
android:tint="?attr/default_icon_color" />
</LinearLayout>
</LinearLayout>
<View
android:id="@+id/divider_bottom"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginStart="@dimen/bottom_sheet_divider_margin_start"
android:layout_marginLeft="@dimen/bottom_sheet_divider_margin_start"
android:background="?attr/divider_color" />
</LinearLayout>

View file

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/list_background_color"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include layout="@layout/preference_toolbar_with_action_button" />
</com.google.android.material.appbar.AppBarLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<LinearLayout
android:id="@+id/segments_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</ScrollView>
<include
layout="@layout/bottom_buttons"
android:layout_width="match_parent"
android:layout_height="@dimen/dialog_button_ex_height" />
</LinearLayout>

View file

@ -0,0 +1,186 @@
<?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="wrap_content"
android:orientation="vertical">
<FrameLayout
android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/bottom_sheet_list_item_height"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_half"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_half"
tools:visibility="visible"
android:visibility="gone">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:letterSpacing="@dimen/description_letter_spacing"
android:singleLine="true"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:visibility="visible"
android:visibility="gone"
tools:text="Title" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|center_vertical"
android:letterSpacing="@dimen/description_letter_spacing"
android:singleLine="true"
android:textColor="?android:attr/textColorSecondary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:visibility="visible"
android:visibility="gone"
tools:text="Subtitle" />
</FrameLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/selection_menu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:orientation="horizontal"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:layout_marginBottom="@dimen/content_padding"
tools:itemCount="3"
tools:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/point_editor_icon_category_item"
tools:orientation="horizontal"
tools:visibility="visible"
android:visibility="gone" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:letterSpacing="@dimen/description_letter_spacing"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_half"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding"
android:textColor="?android:attr/textColorSecondary"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:text="Description"
tools:visibility="visible"
android:visibility="gone" />
<LinearLayout
android:id="@+id/field_box_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:orientation="vertical"
tools:visibility="visible"
android:visibility="gone">
<net.osmand.plus.widgets.OsmandTextFieldBoxes
android:id="@+id/field_box"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:focusableInTouchMode="true"
osmand:errorColor="@color/color_invalid"
osmand:helperTextColor="?android:textColorSecondary"
tools:labelText="Hint"
osmand:primaryColor="@color/active_color_primary_dark"
osmand:secondaryColor="?android:textColorSecondary">
<studio.carbonylgroup.textfieldboxes.ExtendedEditText
android:id="@+id/edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textMultiLine|textNoSuggestions"
android:maxLines="4"
android:saveEnabled="false"
android:scrollHorizontally="false"
tools:text="Text" />
</net.osmand.plus.widgets.OsmandTextFieldBoxes>
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/helper_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:letterSpacing="@dimen/description_letter_spacing"
android:paddingTop="@dimen/content_padding_half"
android:textColor="?android:attr/textColorSecondary"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:text="Helper text"
tools:visibility="visible"
android:visibility="gone" />
</LinearLayout>
<View
android:id="@+id/bottom_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/divider_color_basic"
android:layout_marginTop="@dimen/content_padding"
tools:visibility="visible"
android:visibility="gone" />
<include
android:id="@+id/button"
layout="@layout/bottom_sheet_dialog_button"
android:layout_width="match_parent"
android:layout_height="@dimen/dialog_button_height"
android:layout_marginTop="@dimen/content_padding_half"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
tools:visibility="visible"
android:visibility="gone" />
<LinearLayout
android:id="@+id/result_container"
android:layout_width="match_parent"
android:layout_height="@dimen/setting_list_item_group_height"
android:orientation="horizontal"
tools:visibility="visible"
android:visibility="gone">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/result_icon"
android:layout_width="@dimen/standard_icon_size"
android:layout_height="@dimen/standard_icon_size"
android:layout_gravity="center_vertical"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:tint="?attr/default_icon_color"
tools:src="@drawable/ic_action_gdirections_dark" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/result_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|center_vertical"
android:letterSpacing="@dimen/description_letter_spacing"
android:singleLine="true"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:text="OK" />
</LinearLayout>
</LinearLayout>

View file

@ -0,0 +1,95 @@
<androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/toolbar_height"
app:contentInsetLeft="0dp"
app:contentInsetStart="0dp"
app:contentInsetRight="0dp"
app:contentInsetEnd="0dp"
app:theme="@style/ThemeOverlay.AppCompat.ActionBar">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="@dimen/toolbar_height"
android:background="?attr/card_and_list_background_basic"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageButton
android:id="@+id/close_button"
style="@style/Widget.AppCompat.Toolbar.Button.Navigation"
android:layout_width="@dimen/toolbar_height"
android:layout_height="@dimen/toolbar_height"
android:contentDescription="@string/access_shared_string_navigate_up"
app:srcCompat="@drawable/ic_arrow_back"
android:tint="?attr/default_icon_color" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_half"
android:paddingBottom="@dimen/content_padding_half"
android:background="?attr/card_and_list_background_basic"
android:orientation="vertical">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:letterSpacing="@dimen/text_button_letter_spacing"
android:maxLines="2"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/dialog_header_text_size"
app:typeface="@string/font_roboto_medium"
tools:text="@string/routing_settings_2" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/toolbar_subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
android:textAppearance="@style/TextAppearance.ContextMenuSubtitle"
android:textColor="@null"
tools:text="Some description" />
</LinearLayout>
<FrameLayout
android:id="@+id/action_button"
android:layout_gravity="center"
android:layout_width="@dimen/acceptable_touch_radius"
android:layout_height="@dimen/acceptable_touch_radius">
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/action_button_icon"
style="@style/Widget.AppCompat.Toolbar.Button.Navigation"
android:layout_width="@dimen/standard_icon_size"
android:layout_height="@dimen/standard_icon_size"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:contentDescription="@string/access_shared_string_navigate_up"
android:duplicateParentState="true"
android:clickable="false"
android:focusable="false"
android:layout_gravity="center"
android:scaleType="fitCenter"
tools:src="@drawable/ic_action_info_dark" />
</FrameLayout>
</LinearLayout>
</androidx.appcompat.widget.Toolbar>

View file

@ -11,7 +11,21 @@
Thx - Hardy
-->
<string name="message_error_recheck_parameters">Error, recheck parameters</string>
<string name="routing_engine_vehicle_type_car">Car</string>
<string name="routing_engine_vehicle_type_bike">Bike</string>
<string name="routing_engine_vehicle_type_foot">Foot</string>
<string name="routing_engine_vehicle_type_driving">Driving</string>
<string name="test_route_calculation">Test route calculation</string>
<string name="online_routing_example_hint">URL with all parameters will look like this:</string>
<string name="keep_it_empty_if_not">Keep it empty if not</string>
<string name="shared_string_enter_param">Enter param</string>
<string name="shared_string_server_url">Server URL</string>
<string name="shared_string_api_key">API key</string>
<string name="shared_string_vehicle">Vehicle</string>
<string name="shared_string_subtype">Subtype</string>
<string name="edit_online_routing_engine">Edit online routing engine</string>
<string name="add_online_routing_engine">Add online routing engine</string>
<string name="routing_attr_allow_intermittent_name">Allow intermittent water ways</string>
<string name="routing_attr_allow_intermittent_description">Allow intermittent water ways</string>
<string name="routing_attr_allow_streams_name">Allow streams and drains</string>

View file

@ -44,6 +44,7 @@ import net.osmand.plus.mapmarkers.MapMarkersDbHelper;
import net.osmand.plus.mapmarkers.MapMarkersHelper;
import net.osmand.plus.monitoring.LiveMonitoringHelper;
import net.osmand.plus.monitoring.OsmandMonitoringPlugin;
import net.osmand.plus.onlinerouting.OnlineRoutingHelper;
import net.osmand.plus.osmedit.oauth.OsmOAuthHelper;
import net.osmand.plus.poi.PoiFiltersHelper;
import net.osmand.plus.quickaction.QuickActionRegistry;
@ -467,6 +468,7 @@ public class AppInitializer implements IProgress {
app.settingsHelper = startupInit(new SettingsHelper(app), SettingsHelper.class);
app.quickActionRegistry = startupInit(new QuickActionRegistry(app.getSettings()), QuickActionRegistry.class);
app.osmOAuthHelper = startupInit(new OsmOAuthHelper(app), OsmOAuthHelper.class);
app.onlineRoutingHelper = startupInit(new OnlineRoutingHelper(app), OnlineRoutingHelper.class);
initOpeningHoursParser();
}

View file

@ -66,6 +66,7 @@ import net.osmand.plus.mapmarkers.MapMarkersDbHelper;
import net.osmand.plus.mapmarkers.MapMarkersHelper;
import net.osmand.plus.measurementtool.MeasurementEditingContext;
import net.osmand.plus.monitoring.LiveMonitoringHelper;
import net.osmand.plus.onlinerouting.OnlineRoutingHelper;
import net.osmand.plus.osmedit.oauth.OsmOAuthHelper;
import net.osmand.plus.poi.PoiFiltersHelper;
import net.osmand.plus.quickaction.QuickActionRegistry;
@ -158,6 +159,7 @@ public class OsmandApplication extends MultiDexApplication {
QuickActionRegistry quickActionRegistry;
OsmOAuthHelper osmOAuthHelper;
MeasurementEditingContext measurementEditingContext;
OnlineRoutingHelper onlineRoutingHelper;
private Resources localizedResources;
private Map<String, Builder> customRoutingConfigs = new ConcurrentHashMap<>();
@ -475,6 +477,10 @@ public class OsmandApplication extends MultiDexApplication {
this.measurementEditingContext = context;
}
public OnlineRoutingHelper getOnlineRoutingHelper() {
return onlineRoutingHelper;
}
public TransportRoutingHelper getTransportRoutingHelper() {
return transportRoutingHelper;
}

View file

@ -102,6 +102,14 @@ public class AndroidUiHelper {
}
}
}
public static void setVisibility(int visibility, View ... views) {
for (View view : views) {
if (view != null && view.getVisibility() != visibility) {
view.setVisibility(visibility);
}
}
}
public static boolean isXLargeDevice(@NonNull Activity ctx) {
int lt = (ctx.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK);

View file

@ -67,8 +67,9 @@ public class HorizontalSelectionAdapter extends RecyclerView.Adapter<HorizontalS
textView.setPadding(innerPadding, 0, innerPadding, 0);
int activeColorResId = nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light;
if (item.equals(selectedItem) && item.isEnabled()) {
AndroidUtils.setBackground(holder.button, app.getUIUtilities().getPaintedIcon(
R.drawable.bg_select_icon_group_button, ContextCompat.getColor(app, activeColorResId)));
AndroidUtils.setBackground(holder.button, UiUtilities.createTintedDrawable(app,
R.drawable.bg_select_icon_group_button,
ContextCompat.getColor(app, activeColorResId)));
textView.setTextColor(ContextCompat.getColor(app, R.color.color_white));
} else {
if (!item.isEnabled()) {

View file

@ -0,0 +1,196 @@
package net.osmand.plus.onlinerouting;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.widget.EditText;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import net.osmand.AndroidUtils;
import net.osmand.CallbackWithObject;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.UiUtilities.DialogButtonType;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter;
import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionAdapterListener;
import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionItem;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.plus.widgets.OsmandTextFieldBoxes;
import java.util.List;
public class OnlineRoutingCard extends BaseCard {
private View headerContainer;
private TextView tvHeaderTitle;
private TextView tvHeaderSubtitle;
private RecyclerView rvSelectionMenu;
private HorizontalSelectionAdapter adapter;
private TextView tvDescription;
private View fieldBoxContainer;
private OsmandTextFieldBoxes textFieldBoxes;
private EditText editText;
private TextView tvHelperText;
private View bottomDivider;
private View button;
private OnTextChangedListener onTextChangedListener;
public OnlineRoutingCard(@NonNull MapActivity mapActivity, boolean nightMode) {
super(mapActivity);
this.nightMode = nightMode;
}
@Override
public int getCardLayoutId() {
return R.layout.online_routing_preference_segment;
}
@Override
protected void updateContent() {
headerContainer = view.findViewById(R.id.header);
tvHeaderTitle = view.findViewById(R.id.title);
tvHeaderSubtitle = view.findViewById(R.id.subtitle);
rvSelectionMenu = view.findViewById(R.id.selection_menu);
tvDescription = view.findViewById(R.id.description);
fieldBoxContainer = view.findViewById(R.id.field_box_container);
textFieldBoxes = view.findViewById(R.id.field_box);
editText = view.findViewById(R.id.edit_text);
tvHelperText = view.findViewById(R.id.helper_text);
bottomDivider = view.findViewById(R.id.bottom_divider);
button = view.findViewById(R.id.button);
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (onTextChangedListener != null) {
boolean editedByUser = editText.getTag() == null;
String text = editText.getText().toString();
onTextChangedListener.onTextChanged(editedByUser, text);
}
}
});
editText.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
editText.setSelection(editText.getText().length());
AndroidUtils.showSoftKeyboard(getMapActivity(), editText);
}
}
});
}
public void setHeaderTitle(@NonNull String title) {
showElements(headerContainer, tvHeaderTitle);
tvHeaderTitle.setText(title);
}
public void setHeaderSubtitle(@NonNull String subtitle) {
showElements(headerContainer, tvHeaderSubtitle);
tvHeaderSubtitle.setText(subtitle);
}
public void setSelectionMenu(List<HorizontalSelectionItem> items,
String selectedItemTitle,
final CallbackWithObject<HorizontalSelectionItem> callback) {
showElements(rvSelectionMenu);
rvSelectionMenu.setLayoutManager(
new LinearLayoutManager(app, RecyclerView.HORIZONTAL, false));
adapter = new HorizontalSelectionAdapter(app, nightMode);
adapter.setItems(items);
adapter.setSelectedItemByTitle(selectedItemTitle);
adapter.setListener(new HorizontalSelectionAdapterListener() {
@Override
public void onItemSelected(HorizontalSelectionItem item) {
if (callback.processResult(item)) {
adapter.setSelectedItem(item);
}
}
});
rvSelectionMenu.setAdapter(adapter);
}
public void setDescription(@NonNull String description) {
showElements(tvDescription);
tvDescription.setText(description);
}
public void setFieldBoxLabelText(@NonNull String labelText) {
showElements(fieldBoxContainer);
textFieldBoxes.setLabelText(labelText);
}
public void setFieldBoxHelperText(@NonNull String helperText) {
showElements(fieldBoxContainer, tvHelperText);
tvHelperText.setText(helperText);
}
public void setEditedText(@NonNull String text) {
editText.setTag(""); // needed to indicate that the text was edited programmatically
editText.setText(text);
editText.setTag(null);
}
public String getEditedText() {
return editText.getText().toString();
}
public void showDivider() {
showElements(bottomDivider);
}
public void setButton(String title, OnClickListener listener) {
showElements(button);
button.setOnClickListener(listener);
UiUtilities.setupDialogButton(nightMode, button, DialogButtonType.PRIMARY, title);
}
public void show() {
showElements(view);
}
public void hide() {
hideElements(view);
}
public void showFieldBox() {
showElements(fieldBoxContainer);
}
public void hideFieldBox() {
hideElements(fieldBoxContainer);
}
private void showElements(View... views) {
AndroidUiHelper.setVisibility(View.VISIBLE, views);
}
private void hideElements(View... views) {
AndroidUiHelper.setVisibility(View.GONE, views);
}
public void setOnTextChangedListener(OnTextChangedListener onTextChangedListener) {
this.onTextChangedListener = onTextChangedListener;
}
public interface OnTextChangedListener {
void onTextChanged(boolean editedByUser, String text);
}
}

View file

@ -0,0 +1,106 @@
package net.osmand.plus.onlinerouting;
import android.content.Context;
import androidx.annotation.NonNull;
import net.osmand.plus.R;
import net.osmand.util.Algorithms;
import java.util.HashMap;
import java.util.Map;
public class OnlineRoutingEngine {
public final static String ONLINE_ROUTING_ENGINE_PREFIX = "online_routing_engine_";
public enum EngineParameterType {
CUSTOM_SERVER_URL,
CUSTOM_NAME,
API_KEY
}
private String stringKey;
private ServerType serverType;
private String vehicleKey;
private Map<String, String> params = new HashMap<>();
public OnlineRoutingEngine(@NonNull String stringKey,
@NonNull ServerType serverType,
@NonNull String vehicleKey,
Map<String, String> params) {
this(stringKey, serverType, vehicleKey);
this.params = params;
}
public OnlineRoutingEngine(@NonNull String stringKey,
@NonNull ServerType serverType,
@NonNull String vehicleKey) {
this.stringKey = stringKey;
this.serverType = serverType;
this.vehicleKey = vehicleKey;
}
public String getStringKey() {
return stringKey;
}
public ServerType getServerType() {
return serverType;
}
public String getVehicleKey() {
return vehicleKey;
}
public Map<String, String> getParams() {
return params;
}
public String getBaseUrl() {
String customServerUrl = getParameter(EngineParameterType.CUSTOM_SERVER_URL);
if (!Algorithms.isEmpty(customServerUrl)) {
return customServerUrl;
} else {
return serverType.getBaseUrl();
}
}
public String getParameter(EngineParameterType paramType) {
return params.get(paramType.name());
}
public void putParameter(EngineParameterType paramType, String paramValue) {
params.put(paramType.name(), paramValue);
}
public String getName(@NonNull Context ctx) {
String customName = getParameter(EngineParameterType.CUSTOM_NAME);
if (customName != null) {
return customName;
} else {
return getStandardName(ctx);
}
}
private String getStandardName(@NonNull Context ctx) {
return getStandardName(ctx, serverType, vehicleKey);
}
public static String getStandardName(@NonNull Context ctx,
@NonNull ServerType serverType,
@NonNull String vehicleKey) {
String vehicleTitle = VehicleType.toHumanString(ctx, vehicleKey);
String pattern = ctx.getString(R.string.ltr_or_rtl_combine_via_dash);
return String.format(pattern, serverType.getTitle(), vehicleTitle);
}
public static OnlineRoutingEngine createNewEngine(@NonNull ServerType serverType,
@NonNull String vehicleKey) {
return new OnlineRoutingEngine(generateKey(), serverType, vehicleKey);
}
private static String generateKey() {
return ONLINE_ROUTING_ENGINE_PREFIX + System.currentTimeMillis();
}
}

View file

@ -0,0 +1,610 @@
package net.osmand.plus.onlinerouting;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidNetworkUtils;
import net.osmand.AndroidNetworkUtils.OnRequestResultListener;
import net.osmand.AndroidUtils;
import net.osmand.CallbackWithObject;
import net.osmand.data.LatLon;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.UiUtilities.DialogButtonType;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.BaseOsmAndFragment;
import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionItem;
import net.osmand.plus.onlinerouting.OnlineRoutingCard.OnTextChangedListener;
import net.osmand.plus.onlinerouting.OnlineRoutingEngine.EngineParameterType;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.util.Algorithms;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
public static final String TAG = OnlineRoutingEngineFragment.class.getSimpleName();
private static final String ENGINE_NAME_KEY = "engine_name";
private static final String ENGINE_SERVER_KEY = "engine_server";
private static final String ENGINE_SERVER_URL_KEY = "engine_server_url";
private static final String ENGINE_VEHICLE_TYPE_KEY = "engine_vehicle_type";
private static final String ENGINE_CUSTOM_VEHICLE_KEY = "engine_custom_vehicle";
private static final String ENGINE_API_KEY_KEY = "engine_api_key";
private static final String EXAMPLE_LOCATION_KEY = "example_location";
private static final String APP_MODE_KEY = "app_mode";
private static final String EDITED_ENGINE_KEY = "edited_engine_key";
private OsmandApplication app;
private MapActivity mapActivity;
private OnlineRoutingHelper helper;
private View view;
private ViewGroup segmentsContainer;
private OnlineRoutingCard nameCard;
private OnlineRoutingCard serverCard;
private OnlineRoutingCard vehicleCard;
private OnlineRoutingCard apiKeyCard;
private OnlineRoutingCard exampleCard;
private View testResultsContainer;
private ApplicationMode appMode;
private OnlineRoutingEngineObject engine;
private ExampleLocation selectedLocation;
private String editedEngineKey;
private enum ExampleLocation {
AMSTERDAM("Amsterdam",
new LatLon(52.379189, 4.899431),
new LatLon(52.308056, 4.764167)),
BERLIN("Berlin",
new LatLon(52.520008, 13.404954),
new LatLon(52.3666652, 13.501997992)),
NEW_YORK("New York",
new LatLon(43.000000, -75.000000),
new LatLon(40.641766, -73.780968)),
PARIS("Paris",
new LatLon(48.864716, 2.349014),
new LatLon(48.948437, 2.434931));
ExampleLocation(String name, LatLon cityCenterLatLon, LatLon cityAirportLatLon) {
this.name = name;
this.cityCenterLatLon = cityCenterLatLon;
this.cityAirportLatLon = cityAirportLatLon;
}
private String name;
private LatLon cityCenterLatLon;
private LatLon cityAirportLatLon;
public String getName() {
return name;
}
public LatLon getCityCenterLatLon() {
return cityCenterLatLon;
}
public LatLon getCityAirportLatLon() {
return cityAirportLatLon;
}
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
app = requireMyApplication();
mapActivity = getMapActivity();
helper = app.getOnlineRoutingHelper();
engine = new OnlineRoutingEngineObject();
if (savedInstanceState != null) {
restoreState(savedInstanceState);
} else {
initState();
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
view = getInflater().inflate(
R.layout.online_routing_engine_fragment, container, false);
segmentsContainer = (ViewGroup) view.findViewById(R.id.segments_container);
if (Build.VERSION.SDK_INT >= 21) {
AndroidUtils.addStatusBarPadding21v(getContext(), view);
}
setupToolbar((Toolbar) view.findViewById(R.id.toolbar));
setupNameCard();
setupServerCard();
setupVehicleCard();
setupApiKeyCard();
setupExampleCard();
setupResultsContainer();
addSpaceSegment();
setupButtons();
updateCardViews(nameCard, serverCard, vehicleCard, exampleCard);
return view;
}
private void setupNameCard() {
nameCard = new OnlineRoutingCard(mapActivity, isNightMode());
nameCard.build(mapActivity);
nameCard.setDescription(getString(R.string.select_nav_profile_dialog_message));
nameCard.setEditedText(engine.getName(app));
nameCard.setFieldBoxLabelText(getString(R.string.shared_string_name));
nameCard.setOnTextChangedListener(new OnTextChangedListener() {
@Override
public void onTextChanged(boolean changedByUser, String text) {
if (changedByUser) {
engine.customName = text;
}
}
});
nameCard.showDivider();
segmentsContainer.addView(nameCard.getView());
}
private void setupServerCard() {
serverCard = new OnlineRoutingCard(mapActivity, isNightMode());
serverCard.build(mapActivity);
serverCard.setHeaderTitle(getString(R.string.shared_string_type));
List<HorizontalSelectionItem> serverItems = new ArrayList<>();
for (ServerType server : ServerType.values()) {
serverItems.add(new HorizontalSelectionItem(server.getTitle(), server));
}
serverCard.setSelectionMenu(serverItems, engine.serverType.getTitle(),
new CallbackWithObject<HorizontalSelectionItem>() {
@Override
public boolean processResult(HorizontalSelectionItem result) {
ServerType server = (ServerType) result.getObject();
if (engine.serverType != server) {
engine.serverType = server;
updateCardViews(nameCard, serverCard, exampleCard);
return true;
}
return false;
}
});
serverCard.setOnTextChangedListener(new OnTextChangedListener() {
@Override
public void onTextChanged(boolean editedByUser, String text) {
if (editedByUser) {
engine.customServerUrl = text;
}
}
});
serverCard.setFieldBoxLabelText(getString(R.string.shared_string_server_url));
serverCard.showDivider();
segmentsContainer.addView(serverCard.getView());
}
private void setupVehicleCard() {
vehicleCard = new OnlineRoutingCard(mapActivity, isNightMode());
vehicleCard.build(mapActivity);
vehicleCard.setHeaderTitle(getString(R.string.shared_string_vehicle));
List<HorizontalSelectionItem> vehicleItems = new ArrayList<>();
for (VehicleType vehicle : VehicleType.values()) {
vehicleItems.add(new HorizontalSelectionItem(vehicle.getTitle(app), vehicle));
}
vehicleCard.setSelectionMenu(vehicleItems, engine.vehicleType.getTitle(app),
new CallbackWithObject<HorizontalSelectionItem>() {
@Override
public boolean processResult(HorizontalSelectionItem result) {
VehicleType vehicle = (VehicleType) result.getObject();
if (engine.vehicleType != vehicle) {
engine.vehicleType = vehicle;
updateCardViews(nameCard, vehicleCard, exampleCard);
return true;
}
return false;
}
});
vehicleCard.setFieldBoxLabelText(getString(R.string.shared_string_custom));
vehicleCard.setOnTextChangedListener(new OnTextChangedListener() {
@Override
public void onTextChanged(boolean editedByUser, String text) {
if (editedByUser) {
engine.customVehicleKey = text;
updateCardViews(nameCard, exampleCard);
}
}
});
vehicleCard.setEditedText(engine.customVehicleKey);
vehicleCard.setFieldBoxHelperText(getString(R.string.shared_string_enter_param));
vehicleCard.showDivider();
segmentsContainer.addView(vehicleCard.getView());
}
private void setupApiKeyCard() {
apiKeyCard = new OnlineRoutingCard(mapActivity, isNightMode());
apiKeyCard.build(mapActivity);
apiKeyCard.setHeaderTitle(getString(R.string.shared_string_api_key));
apiKeyCard.setFieldBoxLabelText(getString(R.string.keep_it_empty_if_not));
apiKeyCard.setEditedText(engine.apiKey);
apiKeyCard.showDivider();
apiKeyCard.setOnTextChangedListener(new OnTextChangedListener() {
@Override
public void onTextChanged(boolean editedByUser, String text) {
engine.apiKey = text;
updateCardViews(exampleCard);
}
});
segmentsContainer.addView(apiKeyCard.getView());
}
private void setupExampleCard() {
exampleCard = new OnlineRoutingCard(mapActivity, isNightMode());
exampleCard.build(mapActivity);
exampleCard.setHeaderTitle(getString(R.string.shared_string_example));
List<HorizontalSelectionItem> locationItems = new ArrayList<>();
for (ExampleLocation location : ExampleLocation.values()) {
locationItems.add(new HorizontalSelectionItem(location.getName(), location));
}
exampleCard.setSelectionMenu(locationItems, selectedLocation.getName(),
new CallbackWithObject<HorizontalSelectionItem>() {
@Override
public boolean processResult(HorizontalSelectionItem result) {
ExampleLocation location = (ExampleLocation) result.getObject();
if (selectedLocation != location) {
selectedLocation = location;
updateCardViews(exampleCard);
return true;
}
return false;
}
});
exampleCard.setFieldBoxHelperText(getString(R.string.online_routing_example_hint));
exampleCard.setButton(getString(R.string.test_route_calculation), new View.OnClickListener() {
@Override
public void onClick(View v) {
testEngineWork();
}
});
segmentsContainer.addView(exampleCard.getView());
}
private void setupResultsContainer() {
testResultsContainer = getInflater().inflate(
R.layout.bottom_sheet_item_with_descr_64dp, segmentsContainer, false);
testResultsContainer.setVisibility(View.GONE);
segmentsContainer.addView(testResultsContainer);
}
private void addSpaceSegment() {
int space = (int) getResources().getDimension(R.dimen.empty_state_text_button_padding_top);
View bottomSpaceView = new View(app);
bottomSpaceView.setLayoutParams(
new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, space));
segmentsContainer.addView(bottomSpaceView);
}
private void setupToolbar(Toolbar toolbar) {
ImageView navigationIcon = toolbar.findViewById(R.id.close_button);
navigationIcon.setImageResource(R.drawable.ic_action_close);
navigationIcon.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
TextView title = toolbar.findViewById(R.id.toolbar_title);
toolbar.findViewById(R.id.toolbar_subtitle).setVisibility(View.GONE);
View actionBtn = toolbar.findViewById(R.id.action_button);
if (isEditingMode()) {
title.setText(getString(R.string.edit_online_routing_engine));
ImageView ivBtn = toolbar.findViewById(R.id.action_button_icon);
ivBtn.setImageDrawable(
getIcon(R.drawable.ic_action_delete_dark, R.color.color_osm_edit_delete));
actionBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
deleteEngine();
dismiss();
}
});
} else {
title.setText(getString(R.string.add_online_routing_engine));
actionBtn.setVisibility(View.GONE);
}
}
private void updateCardViews(BaseCard... cardsToUpdate) {
for (BaseCard card : cardsToUpdate) {
if (nameCard.equals(card)) {
if (Algorithms.isEmpty(engine.customName)) {
String name = OnlineRoutingEngine.getStandardName(app, engine.serverType, engine.getVehicleKey());
nameCard.setEditedText(name);
}
} else if (serverCard.equals(card)) {
serverCard.setHeaderSubtitle(engine.serverType.getTitle());
serverCard.setEditedText(engine.getBaseUrl());
if (engine.serverType == ServerType.GRAPHHOPER) {
apiKeyCard.show();
} else {
apiKeyCard.hide();
}
} else if (vehicleCard.equals(card)) {
vehicleCard.setHeaderSubtitle(engine.vehicleType.getTitle(app));
if (engine.vehicleType == VehicleType.CUSTOM) {
vehicleCard.showFieldBox();
vehicleCard.setEditedText(engine.getVehicleKey());
} else {
vehicleCard.hideFieldBox();
}
} else if (exampleCard.equals(card)) {
exampleCard.setEditedText(getTestUrl());
}
}
}
private void setupButtons() {
boolean nightMode = isNightMode();
View cancelButton = view.findViewById(R.id.dismiss_button);
UiUtilities.setupDialogButton(nightMode, cancelButton,
DialogButtonType.SECONDARY, R.string.shared_string_cancel);
cancelButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
view.findViewById(R.id.buttons_divider).setVisibility(View.VISIBLE);
View saveButton = view.findViewById(R.id.right_bottom_button);
UiUtilities.setupDialogButton(nightMode, saveButton,
UiUtilities.DialogButtonType.PRIMARY, R.string.shared_string_save);
saveButton.setVisibility(View.VISIBLE);
saveButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
saveChanges();
dismiss();
}
});
}
private void saveChanges() {
OnlineRoutingEngine engineToSave;
if (isEditingMode()) {
engineToSave = new OnlineRoutingEngine(editedEngineKey, engine.serverType, engine.getVehicleKey());
} else {
engineToSave = OnlineRoutingEngine.createNewEngine(engine.serverType, engine.getVehicleKey());
}
engineToSave.putParameter(EngineParameterType.CUSTOM_SERVER_URL, engine.customServerUrl);
engineToSave.putParameter(EngineParameterType.CUSTOM_NAME, engine.customName);
if (engine.serverType == ServerType.GRAPHHOPER) {
engineToSave.putParameter(EngineParameterType.API_KEY, engine.apiKey);
}
helper.saveEngine(engineToSave);
}
private void deleteEngine() {
helper.deleteEngine(editedEngineKey);
}
private String getTestUrl() {
String baseUrl = engine.serverType.getBaseUrl();
String vehicle = engine.getVehicleKey();
LatLon startPoint = selectedLocation.getCityCenterLatLon();
LatLon endPoint = selectedLocation.getCityAirportLatLon();
if (engine.serverType == ServerType.GRAPHHOPER) {
return baseUrl + "?" + "point=" + startPoint.getLatitude()
+ "," + startPoint.getLongitude()
+ "&" + "point=" + endPoint.getLatitude()
+ "," + endPoint.getLongitude()
+ "&" + "vehicle=" + vehicle
+ (!Algorithms.isEmpty(engine.apiKey) ? ("&" + "key=" + engine.apiKey) : "");
} else {
return baseUrl + vehicle + "/" + startPoint.getLatitude()
+ "," + startPoint.getLongitude()
+ ";" + endPoint.getLatitude()
+ "," + endPoint.getLongitude()
+ "?" + "geometries=geojson";
}
}
private void testEngineWork() {
final ServerType server = engine.serverType;
final ExampleLocation location = selectedLocation;
AndroidNetworkUtils.sendRequestAsync(app, exampleCard.getEditedText(), null,
null, false, false, new OnRequestResultListener() {
@Override
public void onResult(String response) {
boolean resultOk = false;
if (response != null) {
try {
JSONObject obj = new JSONObject(response);
if (server == ServerType.GRAPHHOPER) {
resultOk = obj.has("paths");
} else if (server == ServerType.OSRM) {
resultOk = obj.has("routes");
}
} catch (JSONException e) {
}
}
showTestResults(resultOk, location);
}
});
}
private void showTestResults(boolean resultOk, ExampleLocation location) {
testResultsContainer.setVisibility(View.VISIBLE);
ImageView ivImage = testResultsContainer.findViewById(R.id.icon);
TextView tvTitle = testResultsContainer.findViewById(R.id.title);
TextView tvDescription = testResultsContainer.findViewById(R.id.description);
if (resultOk) {
ivImage.setImageDrawable(getContentIcon(R.drawable.ic_action_gdirections_dark));
tvTitle.setText(getString(R.string.shared_string_ok));
} else {
ivImage.setImageDrawable(getContentIcon(R.drawable.ic_action_alert));
tvTitle.setText(getString(R.string.message_error_recheck_parameters));
}
tvDescription.setText(location.getName());
}
private boolean isEditingMode() {
return editedEngineKey != null;
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
saveState(outState);
}
private void saveState(Bundle outState) {
outState.putString(ENGINE_NAME_KEY, engine.customName);
outState.putString(ENGINE_SERVER_KEY, engine.serverType.name());
outState.putString(ENGINE_SERVER_URL_KEY, engine.customServerUrl);
outState.putString(ENGINE_VEHICLE_TYPE_KEY, engine.vehicleType.name());
outState.putString(ENGINE_CUSTOM_VEHICLE_KEY, engine.customVehicleKey);
outState.putString(ENGINE_API_KEY_KEY, engine.apiKey);
outState.putString(EXAMPLE_LOCATION_KEY, selectedLocation.name());
if (appMode != null) {
outState.putString(APP_MODE_KEY, appMode.getStringKey());
}
outState.putString(EDITED_ENGINE_KEY, editedEngineKey);
}
private void restoreState(Bundle savedState) {
engine.customName = savedState.getString(ENGINE_NAME_KEY);
engine.serverType = ServerType.valueOf(savedState.getString(ENGINE_SERVER_KEY));
engine.customServerUrl = savedState.getString(ENGINE_SERVER_URL_KEY);
engine.vehicleType = VehicleType.valueOf(savedState.getString(ENGINE_VEHICLE_TYPE_KEY));
engine.customVehicleKey = savedState.getString(ENGINE_CUSTOM_VEHICLE_KEY);
engine.apiKey = savedState.getString(ENGINE_API_KEY_KEY);
selectedLocation = ExampleLocation.valueOf(savedState.getString(EXAMPLE_LOCATION_KEY));
appMode = ApplicationMode.valueOfStringKey(savedState.getString(APP_MODE_KEY), null);
editedEngineKey = savedState.getString(EDITED_ENGINE_KEY);
}
private void initState() {
engine.serverType = ServerType.values()[0];
engine.vehicleType = VehicleType.values()[0];
selectedLocation = ExampleLocation.values()[0];
if (isEditingMode()) {
OnlineRoutingEngine editedEngine = helper.getEngineByKey(editedEngineKey);
if (editedEngine != null) {
engine.customName = editedEngine.getParameter(EngineParameterType.CUSTOM_NAME);
engine.serverType = editedEngine.getServerType();
engine.customServerUrl = editedEngine.getParameter(EngineParameterType.CUSTOM_SERVER_URL);
String vehicleKey = editedEngine.getVehicleKey();
if (vehicleKey != null) {
VehicleType vehicleType = VehicleType.getVehicleByKey(vehicleKey);
if (vehicleType == VehicleType.CUSTOM) {
engine.customVehicleKey = vehicleKey;
}
engine.vehicleType = vehicleType;
}
engine.apiKey = editedEngine.getParameter(EngineParameterType.API_KEY);
}
}
}
private void dismiss() {
FragmentActivity activity = getActivity();
if (activity != null) {
activity.onBackPressed();
}
}
private boolean isNightMode() {
return !app.getSettings().isLightContentForMode(appMode);
}
@Nullable
private MapActivity getMapActivity() {
FragmentActivity activity = getActivity();
if (activity instanceof MapActivity) {
return (MapActivity) activity;
} else {
return null;
}
}
private LayoutInflater getInflater() {
return UiUtilities.getInflater(mapActivity, isNightMode());
}
public static void showInstance(@NonNull FragmentActivity activity,
@NonNull ApplicationMode appMode,
String editedEngineKey) {
FragmentManager fm = activity.getSupportFragmentManager();
if (!fm.isStateSaved() && fm.findFragmentByTag(OnlineRoutingEngineFragment.TAG) == null) {
OnlineRoutingEngineFragment fragment = new OnlineRoutingEngineFragment();
fragment.appMode = appMode;
fragment.editedEngineKey = editedEngineKey;
fm.beginTransaction()
.add(R.id.fragmentContainer, fragment, TAG)
.addToBackStack(TAG).commitAllowingStateLoss();
}
}
private static class OnlineRoutingEngineObject {
private String customName;
private ServerType serverType;
private String customServerUrl;
private VehicleType vehicleType;
private String customVehicleKey;
private String apiKey;
public String getVehicleKey() {
if (vehicleType == VehicleType.CUSTOM) {
return customVehicleKey;
}
return vehicleType.getKey();
}
public String getBaseUrl() {
return customServerUrl != null ? customServerUrl : serverType.getBaseUrl();
}
public String getName(Context ctx) {
if (customName != null) {
return customName;
}
return OnlineRoutingEngine.getStandardName(ctx, serverType, getVehicleKey());
}
}
}

View file

@ -0,0 +1,155 @@
package net.osmand.plus.onlinerouting;
import androidx.annotation.NonNull;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import net.osmand.PlatformUtil;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class OnlineRoutingHelper {
private static final Log LOG = PlatformUtil.getLog(OnlineRoutingHelper.class);
private OsmandApplication app;
private OsmandSettings settings;
private List<OnlineRoutingEngine> cachedEngines;
private Map<String, OnlineRoutingEngine> cachedEnginesMap;
public OnlineRoutingHelper(OsmandApplication app) {
this.app = app;
this.settings = app.getSettings();
loadFromSettings();
}
@NonNull
public List<OnlineRoutingEngine> getEngines() {
return cachedEngines;
}
public OnlineRoutingEngine getEngineByKey(String stringKey) {
return cachedEnginesMap.get(stringKey);
}
public void saveEngine(@NonNull OnlineRoutingEngine engine) {
String stringKey = engine.getStringKey();
OnlineRoutingEngine existedEngine = cachedEnginesMap.get(stringKey);
if (existedEngine != null) {
int index = cachedEngines.indexOf(existedEngine);
cachedEngines.set(index, engine);
} else {
cachedEngines.add(engine);
}
cachedEnginesMap.put(stringKey, engine);
saveToSettings();
}
public void deleteEngine(@NonNull String stringKey) {
OnlineRoutingEngine engine = getEngineByKey(stringKey);
if (engine != null) {
deleteEngine(engine);
}
}
public void deleteEngine(@NonNull OnlineRoutingEngine engine) {
String stringKey = engine.getStringKey();
if (cachedEnginesMap.containsKey(stringKey)) {
OnlineRoutingEngine existedEngine = cachedEnginesMap.remove(stringKey);
cachedEngines.remove(existedEngine);
saveToSettings();
}
}
private void loadFromSettings() {
cachedEngines = readFromSettings();
cachedEnginesMap = new HashMap<>();
for (OnlineRoutingEngine engine : cachedEngines) {
cachedEnginesMap.put(engine.getStringKey(), engine);
}
}
@NonNull
private List<OnlineRoutingEngine> readFromSettings() {
List<OnlineRoutingEngine> engines = new ArrayList<>();
String jsonString = settings.ONLINE_ROUTING_ENGINES.get();
if (!Algorithms.isEmpty(jsonString)) {
try {
JSONObject json = new JSONObject(jsonString);
readFromJson(json, engines);
} catch (JSONException e) {
LOG.debug("Error when create a new JSONObject: " + e.toString());
}
}
return engines;
}
private void saveToSettings() {
if (!Algorithms.isEmpty(cachedEngines)) {
JSONObject json = new JSONObject();
if (writeToJson(json, cachedEngines)) {
settings.ONLINE_ROUTING_ENGINES.set(json.toString());
}
} else {
settings.ONLINE_ROUTING_ENGINES.set(null);
}
}
private static void readFromJson(JSONObject json, List<OnlineRoutingEngine> engines) {
try {
if (!json.has("items")) {
return;
}
Gson gson = new Gson();
Type type = new TypeToken<HashMap<String, String>>() {
}.getType();
JSONArray itemsJson = json.getJSONArray("items");
for (int i = 0; i < itemsJson.length(); i++) {
JSONObject object = itemsJson.getJSONObject(i);
String key = object.getString("key");
String vehicleKey = object.getString("vehicle");
ServerType serverType = ServerType.valueOf(object.getString("serverType"));
String paramsString = object.getString("params");
HashMap<String, String> params = gson.fromJson(paramsString, type);
engines.add(new OnlineRoutingEngine(key, serverType, vehicleKey, params));
}
} catch (JSONException e) {
LOG.debug("Error when reading engines from JSON: " + e.toString());
}
}
private static boolean writeToJson(JSONObject json, List<OnlineRoutingEngine> engines) {
JSONArray jsonArray = new JSONArray();
Gson gson = new Gson();
Type type = new TypeToken<HashMap<String, String>>() {
}.getType();
try {
for (OnlineRoutingEngine engine : engines) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("key", engine.getStringKey());
jsonObject.put("serverType", engine.getServerType().name());
jsonObject.put("vehicle", engine.getVehicleKey());
jsonObject.put("params", gson.toJson(engine.getParams(), type));
jsonArray.put(jsonObject);
}
json.put("items", jsonArray);
return true;
} catch (JSONException e) {
LOG.debug("Error when writing engines to JSON: " + e.toString());
return false;
}
}
}

View file

@ -0,0 +1,22 @@
package net.osmand.plus.onlinerouting;
public enum ServerType {
GRAPHHOPER("Graphhoper", "https://graphhopper.com/api/1/route"),
OSRM("OSRM", "https://zlzk.biz/route/v1/");
ServerType(String title, String baseUrl) {
this.title = title;
this.baseUrl = baseUrl;
}
private String title;
private String baseUrl;
public String getTitle() {
return title;
}
public String getBaseUrl() {
return baseUrl;
}
}

View file

@ -0,0 +1,50 @@
package net.osmand.plus.onlinerouting;
import android.content.Context;
import androidx.annotation.NonNull;
import net.osmand.plus.R;
import net.osmand.util.Algorithms;
public enum VehicleType {
CAR("car", R.string.routing_engine_vehicle_type_car),
BIKE("bike", R.string.routing_engine_vehicle_type_bike),
FOOT("foot", R.string.routing_engine_vehicle_type_foot),
DRIVING("driving", R.string.routing_engine_vehicle_type_driving),
CUSTOM("", R.string.shared_string_custom);
VehicleType(String key, int titleId) {
this.key = key;
this.titleId = titleId;
}
private String key;
private int titleId;
public String getKey() {
return key;
}
public String getTitle(Context ctx) {
return ctx.getString(titleId);
}
public static String toHumanString(@NonNull Context ctx,
@NonNull String key) {
VehicleType vehicleType = getVehicleByKey(key);
if (vehicleType == CUSTOM) {
return Algorithms.capitalizeFirstLetter(key);
}
return vehicleType.getTitle(ctx);
}
public static VehicleType getVehicleByKey(String key) {
for (VehicleType v : values()) {
if (Algorithms.objectEquals(v.getKey(), key)) {
return v;
}
}
return CUSTOM;
}
}

View file

@ -0,0 +1,12 @@
package net.osmand.plus.profiles;
import net.osmand.plus.R;
public class OnlineRoutingEngineDataObject extends ProfileDataObject {
public OnlineRoutingEngineDataObject(String name,
String description,
String stringKey) {
super(name, description, stringKey, R.drawable.ic_world_globe_dark, false, null);
}
}

View file

@ -5,6 +5,8 @@ import android.content.Context;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.onlinerouting.OnlineRoutingEngine;
import net.osmand.plus.profiles.RoutingProfileDataObject.RoutingProfilesResources;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.router.GeneralRouter;
import net.osmand.router.RoutingConfiguration;
@ -66,6 +68,15 @@ public class ProfileDataUtils {
return result;
}
public static List<OnlineRoutingEngineDataObject> getOnlineRoutingProfiles(OsmandApplication app) {
List<OnlineRoutingEngineDataObject> objects = new ArrayList<>();
for (OnlineRoutingEngine engine : app.getOnlineRoutingHelper().getEngines()) {
objects.add(new OnlineRoutingEngineDataObject(
engine.getName(app), engine.getBaseUrl(), engine.getStringKey()));
}
return objects;
}
public static Map<String, List<RoutingProfileDataObject>> getRoutingProfilesByFileNames(OsmandApplication app) {
Map<String, List<RoutingProfileDataObject>> result = new HashMap<>();
for (final RoutingProfileDataObject profile : getRoutingProfiles(app).values()) {
@ -83,24 +94,24 @@ public class ProfileDataUtils {
public static Map<String, RoutingProfileDataObject> getRoutingProfiles(OsmandApplication context) {
Map<String, RoutingProfileDataObject> profilesObjects = new HashMap<>();
profilesObjects.put(RoutingProfileDataObject.RoutingProfilesResources.STRAIGHT_LINE_MODE.name(), new RoutingProfileDataObject(
RoutingProfileDataObject.RoutingProfilesResources.STRAIGHT_LINE_MODE.name(),
context.getString(RoutingProfileDataObject.RoutingProfilesResources.STRAIGHT_LINE_MODE.getStringRes()),
profilesObjects.put(RoutingProfilesResources.STRAIGHT_LINE_MODE.name(), new RoutingProfileDataObject(
RoutingProfilesResources.STRAIGHT_LINE_MODE.name(),
context.getString(RoutingProfilesResources.STRAIGHT_LINE_MODE.getStringRes()),
context.getString(R.string.special_routing_type),
RoutingProfileDataObject.RoutingProfilesResources.STRAIGHT_LINE_MODE.getIconRes(),
RoutingProfilesResources.STRAIGHT_LINE_MODE.getIconRes(),
false, null));
profilesObjects.put(RoutingProfileDataObject.RoutingProfilesResources.DIRECT_TO_MODE.name(), new RoutingProfileDataObject(
RoutingProfileDataObject.RoutingProfilesResources.DIRECT_TO_MODE.name(),
context.getString(RoutingProfileDataObject.RoutingProfilesResources.DIRECT_TO_MODE.getStringRes()),
profilesObjects.put(RoutingProfilesResources.DIRECT_TO_MODE.name(), new RoutingProfileDataObject(
RoutingProfilesResources.DIRECT_TO_MODE.name(),
context.getString(RoutingProfilesResources.DIRECT_TO_MODE.getStringRes()),
context.getString(R.string.special_routing_type),
RoutingProfileDataObject.RoutingProfilesResources.DIRECT_TO_MODE.getIconRes(),
RoutingProfilesResources.DIRECT_TO_MODE.getIconRes(),
false, null));
if (context.getBRouterService() != null) {
profilesObjects.put(RoutingProfileDataObject.RoutingProfilesResources.BROUTER_MODE.name(), new RoutingProfileDataObject(
RoutingProfileDataObject.RoutingProfilesResources.BROUTER_MODE.name(),
context.getString(RoutingProfileDataObject.RoutingProfilesResources.BROUTER_MODE.getStringRes()),
profilesObjects.put(RoutingProfilesResources.BROUTER_MODE.name(), new RoutingProfileDataObject(
RoutingProfilesResources.BROUTER_MODE.name(),
context.getString(RoutingProfilesResources.BROUTER_MODE.getStringRes()),
context.getString(R.string.third_party_routing_type),
RoutingProfileDataObject.RoutingProfilesResources.BROUTER_MODE.getIconRes(),
RoutingProfilesResources.BROUTER_MODE.getIconRes(),
false, null));
}
@ -123,9 +134,9 @@ public class ProfileDataUtils {
String fileName = router.getFilename();
if (!Algorithms.isEmpty(fileName)) {
description = fileName;
} else if (RoutingProfileDataObject.RoutingProfilesResources.isRpValue(name.toUpperCase())) {
iconRes = RoutingProfileDataObject.RoutingProfilesResources.valueOf(name.toUpperCase()).getIconRes();
name = app.getString(RoutingProfileDataObject.RoutingProfilesResources.valueOf(name.toUpperCase()).getStringRes());
} else if (RoutingProfilesResources.isRpValue(name.toUpperCase())) {
iconRes = RoutingProfilesResources.valueOf(name.toUpperCase()).getIconRes();
name = app.getString(RoutingProfilesResources.valueOf(name.toUpperCase()).getStringRes());
}
profilesObjects.put(routerKey, new RoutingProfileDataObject(routerKey, name, description,
iconRes, false, fileName));

View file

@ -22,7 +22,6 @@ import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils;
import net.osmand.CallbackWithObject;
@ -39,6 +38,7 @@ import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
import net.osmand.plus.helpers.FontCache;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.bottomsheets.BasePreferenceBottomSheet;
import net.osmand.plus.onlinerouting.OnlineRoutingEngineFragment;
import net.osmand.router.RoutingConfiguration;
import org.apache.commons.logging.Log;
@ -149,17 +149,23 @@ public class SelectProfileBottomSheet extends BasePreferenceBottomSheet {
items.add(new TitleItem(getString(R.string.select_nav_profile_dialog_title)));
items.add(new LongDescriptionItem(getString(R.string.select_nav_profile_dialog_message)));
for (int i = 0; i < profiles.size(); i++) {
final RoutingProfileDataObject profile = (RoutingProfileDataObject) profiles.get(i);
boolean showBottomDivider = false;
if (i < profiles.size() - 1) {
RoutingProfileDataObject nextProfile = (RoutingProfileDataObject) profiles.get(i + 1);
if (profile.getFileName() == null) {
showBottomDivider = nextProfile.getFileName() != null;
} else {
showBottomDivider = !profile.getFileName().equals(nextProfile.getFileName());
if (profiles.get(i) instanceof RoutingProfileDataObject) {
final RoutingProfileDataObject profile = (RoutingProfileDataObject) profiles.get(i);
if (i < profiles.size() - 1) {
if (profiles.get(i + 1) instanceof RoutingProfileDataObject) {
RoutingProfileDataObject nextProfile = (RoutingProfileDataObject) profiles.get(i + 1);
if (profile.getFileName() == null) {
showBottomDivider = nextProfile.getFileName() != null;
} else {
showBottomDivider = !profile.getFileName().equals(nextProfile.getFileName());
}
} else {
showBottomDivider = true;
}
}
}
addProfileItem(profile, showBottomDivider);
addProfileItem(profiles.get(i), showBottomDivider);
}
items.add(new DividerItem(app));
items.add(new LongDescriptionItem(app.getString(R.string.osmand_routing_promo)));
@ -179,6 +185,15 @@ public class SelectProfileBottomSheet extends BasePreferenceBottomSheet {
});
}
});
addButtonItem(R.string.add_online_routing_engine, R.drawable.ic_world_globe_dark, new OnClickListener() {
@Override
public void onClick(View v) {
if (getActivity() != null) {
OnlineRoutingEngineFragment.showInstance(getActivity(), getAppMode(), null);
}
dismiss();
}
});
items.add(new BaseBottomSheetItem.Builder()
.setCustomView(bottomSpaceView)
.create());
@ -220,7 +235,10 @@ public class SelectProfileBottomSheet extends BasePreferenceBottomSheet {
int activeColorResId = nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light;
int iconDefaultColorResId = nightMode ? R.color.icon_color_default_dark : R.color.icon_color_default_light;
View itemView = UiUtilities.getInflater(getContext(), nightMode).inflate(R.layout.bottom_sheet_item_with_descr_and_radio_btn, null);
View itemView = UiUtilities.getInflater(getContext(), nightMode).inflate(
profile instanceof OnlineRoutingEngineDataObject ?
R.layout.bottom_sheet_item_with_descr_radio_and_icon_btn :
R.layout.bottom_sheet_item_with_descr_and_radio_btn, null);
TextView tvTitle = itemView.findViewById(R.id.title);
TextView tvDescription = itemView.findViewById(R.id.description);
ImageView ivIcon = itemView.findViewById(R.id.icon);
@ -253,7 +271,14 @@ public class SelectProfileBottomSheet extends BasePreferenceBottomSheet {
args.putString(PROFILE_KEY_ARG, profile.getStringKey());
Fragment target = getTargetFragment();
if (target instanceof OnSelectProfileCallback) {
((OnSelectProfileCallback) target).onProfileSelected(args);
if (profile instanceof OnlineRoutingEngineDataObject) {
if (getActivity() != null) {
OnlineRoutingEngineFragment.showInstance(getActivity(), getAppMode(), profile.getStringKey());
}
dismiss();
} else {
((OnSelectProfileCallback) target).onProfileSelected(args);
}
}
dismiss();
}
@ -338,6 +363,7 @@ public class SelectProfileBottomSheet extends BasePreferenceBottomSheet {
case NAVIGATION_PROFILE:
profiles.addAll(ProfileDataUtils.getSortedRoutingProfiles(app));
profiles.addAll(ProfileDataUtils.getOnlineRoutingProfiles(app));
break;
case DEFAULT_PROFILE:
@ -358,6 +384,7 @@ public class SelectProfileBottomSheet extends BasePreferenceBottomSheet {
public static void showInstance(@NonNull FragmentActivity activity,
@NonNull DialogMode dialogMode,
@Nullable Fragment target,
ApplicationMode appMode,
String selectedItemKey,
boolean usedOnMap) {
SelectProfileBottomSheet fragment = new SelectProfileBottomSheet();
@ -366,6 +393,7 @@ public class SelectProfileBottomSheet extends BasePreferenceBottomSheet {
args.putString(SELECTED_KEY, selectedItemKey);
fragment.setArguments(args);
fragment.setUsedOnMap(usedOnMap);
fragment.setAppMode(appMode);
fragment.setTargetFragment(target, 0);
fragment.show(activity.getSupportFragmentManager(), TAG);
}

View file

@ -48,6 +48,7 @@ import net.osmand.plus.helpers.enums.TracksSortByMode;
import net.osmand.plus.mapillary.MapillaryPlugin;
import net.osmand.plus.mapmarkers.CoordinateInputFormats.Format;
import net.osmand.plus.mapmarkers.MapMarkersMode;
import net.osmand.plus.onlinerouting.OnlineRoutingEngine;
import net.osmand.plus.profiles.LocationIcon;
import net.osmand.plus.profiles.NavigationIcon;
import net.osmand.plus.profiles.ProfileIconColors;
@ -1015,6 +1016,8 @@ public class OsmandSettings {
ROUTE_SERVICE.setModeDefaultValue(ApplicationMode.AIRCRAFT, RouteService.STRAIGHT);
}
public final CommonPreference<String> ONLINE_ROUTING_ENGINES = new StringPreference(this, "online_routing_engines", null);
public final CommonPreference<NavigationIcon> NAVIGATION_ICON = new EnumStringPreference<>(this, "navigation_icon", NavigationIcon.DEFAULT, NavigationIcon.values()).makeProfile().cache();
{

View file

@ -38,12 +38,12 @@ public abstract class BasePreferenceBottomSheet extends MenuBottomSheetDialogFra
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
appMode = ApplicationMode.valueOfStringKey(savedInstanceState.getString(APP_MODE_KEY), null);
applyQueryType = ApplyQueryType.valueOf(savedInstanceState.getString(APPLY_QUERY_TYPE));
profileDependent = savedInstanceState.getBoolean(PROFILE_DEPENDENT, false);
}
super.onCreate(savedInstanceState);
}
@Override

View file

@ -125,8 +125,9 @@ public class GlobalSettingsFragment extends BaseSettingsFragment
if (prefId.equals(settings.DEFAULT_APPLICATION_MODE.getId())) {
if (getActivity() != null) {
String defaultModeKey = settings.DEFAULT_APPLICATION_MODE.get().getStringKey();
SelectProfileBottomSheet.showInstance(getActivity(),
DialogMode.DEFAULT_PROFILE, this, defaultModeKey, false);
SelectProfileBottomSheet.showInstance(
getActivity(), DialogMode.DEFAULT_PROFILE, this,
getSelectedAppMode(), defaultModeKey, false);
}
} else if (settings.SPEED_CAMERAS_UNINSTALLED.getId().equals(prefId) && !settings.SPEED_CAMERAS_UNINSTALLED.get()) {
FragmentManager fm = getFragmentManager();

View file

@ -119,8 +119,9 @@ public class MainSettingsFragment extends BaseSettingsFragment implements OnSele
return true;
} else if (CREATE_PROFILE.equals(prefId)) {
if (getActivity() != null) {
SelectProfileBottomSheet.showInstance(getActivity(),
DialogMode.BASE_PROFILE, this, null, false);
SelectProfileBottomSheet.showInstance(
getActivity(), DialogMode.BASE_PROFILE, this,
getSelectedAppMode(), null, false);
}
} else if (IMPORT_PROFILE.equals(prefId)) {
final MapActivity mapActivity = getMapActivity();

View file

@ -126,7 +126,7 @@ public class NavigationFragment extends BaseSettingsFragment implements OnSelect
if (getActivity() != null) {
SelectProfileBottomSheet.showInstance(
getActivity(), SelectProfileBottomSheet.DialogMode.NAVIGATION_PROFILE,
this, routingProfileKey, false);
this, getSelectedAppMode(), routingProfileKey, false);
}
}
return false;

View file

@ -403,7 +403,7 @@ public class ProfileAppearanceFragment extends BaseSettingsFragment implements O
if (getActivity() != null) {
SelectProfileBottomSheet.showInstance(
getActivity(), DialogMode.BASE_PROFILE, ProfileAppearanceFragment.this,
selectedAppModeKey, false);
getSelectedAppMode(), selectedAppModeKey, false);
}
}
}