diff --git a/OsmAnd-api/src/net/osmand/aidlapi/OsmAndCustomizationConstants.java b/OsmAnd-api/src/net/osmand/aidlapi/OsmAndCustomizationConstants.java
index af48552bc4..53e838a9a7 100644
--- a/OsmAnd-api/src/net/osmand/aidlapi/OsmAndCustomizationConstants.java
+++ b/OsmAnd-api/src/net/osmand/aidlapi/OsmAndCustomizationConstants.java
@@ -11,6 +11,7 @@ public interface OsmAndCustomizationConstants {
String DRAWER_MY_PLACES_ID = DRAWER_ITEM_ID_SCHEME + "my_places";
String DRAWER_SEARCH_ID = DRAWER_ITEM_ID_SCHEME + "search";
String DRAWER_DIRECTIONS_ID = DRAWER_ITEM_ID_SCHEME + "directions";
+ String DRAWER_TRIP_RECORDING_ID = DRAWER_ITEM_ID_SCHEME + "trip_recording";
String DRAWER_CONFIGURE_MAP_ID = DRAWER_ITEM_ID_SCHEME + "configure_map";
String DRAWER_DOWNLOAD_MAPS_ID = DRAWER_ITEM_ID_SCHEME + "download_maps";
String DRAWER_OSMAND_LIVE_ID = DRAWER_ITEM_ID_SCHEME + "osmand_live";
diff --git a/OsmAnd/res/layout/bottom_sheet_item_button_with_icon.xml b/OsmAnd/res/layout/bottom_sheet_item_button_with_icon.xml
new file mode 100644
index 0000000000..3d2d1bbab1
--- /dev/null
+++ b/OsmAnd/res/layout/bottom_sheet_item_button_with_icon.xml
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd/res/values/sizes.xml b/OsmAnd/res/values/sizes.xml
index a086849297..afdc8438af 100644
--- a/OsmAnd/res/values/sizes.xml
+++ b/OsmAnd/res/values/sizes.xml
@@ -413,4 +413,6 @@
32dp
24dp
+
+ 0dp
\ No newline at end of file
diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml
index 8d34bfdc28..6c7b5333dc 100644
--- a/OsmAnd/res/values/strings.xml
+++ b/OsmAnd/res/values/strings.xml
@@ -13,6 +13,10 @@
-->
On pause
+ Are you sure you want to stop recording?\nAll unsaved data will be lost.
+ Track recording stopped
+ Save and stop recording
+ Stop without saving
Login to OpenPlaceReviews
Use test.openplacereviews.org
OpenPlaceReviews
diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java b/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java
index 258ed7be38..625396e5e3 100644
--- a/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java
+++ b/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java
@@ -22,6 +22,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
+import androidx.fragment.app.FragmentActivity;
import net.osmand.AndroidUtils;
import net.osmand.GPXUtilities;
@@ -62,6 +63,8 @@ import net.osmand.plus.mapmarkers.MarkersPlanRouteContext;
import net.osmand.plus.measurementtool.MeasurementToolFragment;
import net.osmand.plus.measurementtool.StartPlanRouteBottomSheet;
import net.osmand.plus.monitoring.OsmandMonitoringPlugin;
+import net.osmand.plus.monitoring.TripRecordingActiveBottomSheet;
+import net.osmand.plus.monitoring.TripRecordingBottomSheet;
import net.osmand.plus.osmedit.dialogs.DismissRouteBottomSheetFragment;
import net.osmand.plus.profiles.ProfileDataObject;
import net.osmand.plus.profiles.ProfileDataUtils;
@@ -98,6 +101,7 @@ import static net.osmand.aidlapi.OsmAndCustomizationConstants.DRAWER_CONFIGURE_P
import static net.osmand.aidlapi.OsmAndCustomizationConstants.DRAWER_CONFIGURE_SCREEN_ID;
import static net.osmand.aidlapi.OsmAndCustomizationConstants.DRAWER_DASHBOARD_ID;
import static net.osmand.aidlapi.OsmAndCustomizationConstants.DRAWER_DIRECTIONS_ID;
+import static net.osmand.aidlapi.OsmAndCustomizationConstants.DRAWER_TRIP_RECORDING_ID;
import static net.osmand.aidlapi.OsmAndCustomizationConstants.DRAWER_DIVIDER_ID;
import static net.osmand.aidlapi.OsmAndCustomizationConstants.DRAWER_DOWNLOAD_MAPS_ID;
import static net.osmand.aidlapi.OsmAndCustomizationConstants.DRAWER_HELP_ID;
@@ -839,6 +843,22 @@ public class MapActivityActions implements DialogProvider {
}
}).createItem());
+ boolean isTripRecordingPluginOn = OsmandPlugin.getEnabledPlugin(OsmandMonitoringPlugin.class) != null;
+ if (isTripRecordingPluginOn) {
+ optionsMenuHelper.addItem(new ItemBuilder().setTitleId(R.string.map_widget_monitoring, mapActivity)
+ .setId(DRAWER_TRIP_RECORDING_ID)
+ .setIcon(R.drawable.ic_action_track_recordable)
+ .setListener(new ItemClickListener() {
+ @Override
+ public boolean onContextMenuClick(ArrayAdapter adapter, int itemId, int pos, boolean isChecked, int[] viewCoordinates) {
+ app.logEvent("trip_recording_open");
+ MapActivity.clearPrevActivityIntent();
+ TripRecordingBottomSheet.showInstance(mapActivity.getSupportFragmentManager());
+ return true;
+ }
+ }).createItem());
+ }
+
optionsMenuHelper.addItem(new ItemBuilder().setTitleId(R.string.get_directions, mapActivity)
.setId(DRAWER_DIRECTIONS_ID)
diff --git a/OsmAnd/src/net/osmand/plus/monitoring/ClearRecordedDataBottomSheetFragment.java b/OsmAnd/src/net/osmand/plus/monitoring/ClearRecordedDataBottomSheetFragment.java
new file mode 100644
index 0000000000..971bfd01e0
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/monitoring/ClearRecordedDataBottomSheetFragment.java
@@ -0,0 +1,160 @@
+package net.osmand.plus.monitoring;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.LinearLayout;
+
+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.BottomSheetItemWithDescription;
+import net.osmand.plus.widgets.TextViewEx;
+
+import androidx.annotation.DimenRes;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.StringRes;
+import androidx.appcompat.widget.AppCompatImageView;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+
+public class ClearRecordedDataBottomSheetFragment extends MenuBottomSheetDialogFragment implements View.OnClickListener {
+
+ public static final String TAG = ClearRecordedDataBottomSheetFragment.class.getSimpleName();
+
+ private OsmandApplication app;
+
+ @Override
+ public void createMenuItems(Bundle savedInstanceState) {
+ app = requiredMyApplication();
+
+ items.add(new BottomSheetItemWithDescription.Builder()
+ .setDescription(app.getString(R.string.clear_recorded_data_warning))
+ .setDescriptionColorId(!nightMode ? R.color.text_color_primary_light : R.color.text_color_primary_dark)
+ .setDescriptionMaxLines(2)
+ .setTitle(app.getString(R.string.clear_recorded_data))
+ .setLayoutId(R.layout.bottom_sheet_item_title_with_description)
+ .create());
+
+ LayoutInflater inflater = UiUtilities.getInflater(getContext(), nightMode);
+
+ items.add(new BaseBottomSheetItem.Builder()
+ .setCustomView(setupBtn(inflater, ButtonType.CLEAR))
+ .setOnClickListener(this)
+ .create());
+
+ items.add(new BaseBottomSheetItem.Builder()
+ .setCustomView(setupBtn(inflater, ButtonType.CANCEL))
+ .setOnClickListener(this)
+ .create());
+
+ }
+
+ private View setupBtn(LayoutInflater inflater, ButtonType type) {
+ View button = inflater.inflate(R.layout.bottom_sheet_item_button_with_icon, null);
+ button.setTag(type);
+ Context context = button.getContext();
+
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
+ int horizontal = context.getResources().getDimensionPixelSize(R.dimen.content_padding);
+ int top = context.getResources().getDimensionPixelSize(type.topMarginRes);
+ int bottom = context.getResources().getDimensionPixelSize(R.dimen.content_padding_small);
+ params.setMargins(horizontal, top, horizontal, bottom);
+ button.setLayoutParams(params);
+
+ UiUtilities.setupDialogButton(nightMode, button, type.effect, type.titleId);
+
+ TextViewEx title = button.findViewById(R.id.button_text);
+ int margin = context.getResources().getDimensionPixelSize(R.dimen.context_menu_padding_margin_medium);
+ UiUtilities.setMargins(title, 0, margin, 0, margin);
+
+ int colorRes;
+ if (type.effect == UiUtilities.DialogButtonType.SECONDARY_HARMFUL) {
+ colorRes = R.color.color_osm_edit_delete;
+ } else {
+ colorRes = nightMode ? R.color.dlg_btn_secondary_text_dark : R.color.dlg_btn_secondary_text_light;
+ }
+ AppCompatImageView icon = button.findViewById(R.id.icon);
+ icon.setImageDrawable(getIcon(type.iconRes, colorRes));
+
+ return button;
+ }
+
+ @Override
+ public void onClick(View v) {
+ Object o = v.getTag();
+ if (!(o instanceof ButtonType)) {
+ return;
+ }
+
+ ButtonType tag = (ButtonType) o;
+ if (tag == ButtonType.CLEAR) {
+ app.getSavingTrackHelper().clearRecordedData(true);
+ }
+ dismiss();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ // Replace later with tTripRecordingActiveBottomSheet.hide()
+ Fragment target = getTargetFragment();
+ if (target instanceof TripRecordingActiveBottomSheet) {
+ Dialog dialog = ((TripRecordingActiveBottomSheet) target).getDialog();
+ if (dialog != null) {
+ dialog.hide();
+ }
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ // Replace later with tTripRecordingActiveBottomSheet.show()
+ Fragment target = getTargetFragment();
+ if (target instanceof TripRecordingActiveBottomSheet) {
+ Dialog dialog = ((TripRecordingActiveBottomSheet) target).getDialog();
+ if (dialog != null) {
+ dialog.show();
+ }
+ }
+ }
+
+ enum ButtonType {
+ CLEAR(R.string.clear_recorded_data, R.drawable.ic_action_delete_dark, R.dimen.dialog_content_margin, UiUtilities.DialogButtonType.SECONDARY_HARMFUL),
+ CANCEL(R.string.shared_string_cancel, R.drawable.ic_action_close, R.dimen.content_padding_small, UiUtilities.DialogButtonType.SECONDARY);
+
+ @StringRes
+ private final int titleId;
+ @DrawableRes
+ private final int iconRes;
+ @DimenRes
+ private final int topMarginRes;
+ private final UiUtilities.DialogButtonType effect;
+
+ ButtonType(int titleId, int iconRes, int topMarginRes, UiUtilities.DialogButtonType effect) {
+ this.titleId = titleId;
+ this.iconRes = iconRes;
+ this.topMarginRes = topMarginRes;
+ this.effect = effect;
+ }
+ }
+
+ @Override
+ protected boolean hideButtonsContainer() {
+ return true;
+ }
+
+ public static void showInstance(@NonNull FragmentManager fragmentManager, @NonNull Fragment target) {
+ if (!fragmentManager.isStateSaved()) {
+ ClearRecordedDataBottomSheetFragment fragment = new ClearRecordedDataBottomSheetFragment();
+ fragment.setTargetFragment(target, 0);
+ fragment.show(fragmentManager, TAG);
+ }
+ }
+}
\ No newline at end of file
diff --git a/OsmAnd/src/net/osmand/plus/monitoring/OsmandMonitoringPlugin.java b/OsmAnd/src/net/osmand/plus/monitoring/OsmandMonitoringPlugin.java
index 48df51a351..65538733b0 100644
--- a/OsmAnd/src/net/osmand/plus/monitoring/OsmandMonitoringPlugin.java
+++ b/OsmAnd/src/net/osmand/plus/monitoring/OsmandMonitoringPlugin.java
@@ -28,7 +28,6 @@ import com.google.android.material.slider.Slider;
import net.osmand.AndroidUtils;
import net.osmand.Location;
import net.osmand.ValueHolder;
-import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.NavigationService;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmAndLocationProvider;
@@ -44,6 +43,7 @@ import net.osmand.plus.dashboard.tools.DashFragmentData;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType;
+import net.osmand.plus.track.TrackDisplayHelper;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.views.layers.MapInfoLayer;
@@ -163,9 +163,9 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
}
}
- public static final int[] SECONDS = new int[]{0, 1, 2, 3, 5, 10, 15, 20, 30, 60, 90};
- public static final int[] MINUTES = new int[]{2, 3, 5};
- public static final int[] MAX_INTERVAL_TO_SEND_MINUTES = new int[]{1, 2, 5, 10, 15, 20, 30, 60, 90, 2 * 60, 3 * 60, 4 * 60, 6 * 60, 12 * 60, 24 * 60};
+ public static final int[] SECONDS = new int[] {0, 1, 2, 3, 5, 10, 15, 20, 30, 60, 90};
+ public static final int[] MINUTES = new int[] {2, 3, 5};
+ public static final int[] MAX_INTERVAL_TO_SEND_MINUTES = new int[] {1, 2, 5, 10, 15, 20, 30, 60, 90, 2 * 60, 3 * 60, 4 * 60, 6 * 60, 12 * 60, 24 * 60};
@Override
public SettingsScreenType getSettingsScreenType() {
@@ -183,10 +183,9 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
private TextInfoWidget createMonitoringControl(final MapActivity map) {
monitoringControl = new TextInfoWidget(map) {
long lastUpdateTime;
-
@Override
public boolean updateInfo(DrawSettings drawSettings) {
- if (isSaving) {
+ if(isSaving){
setText(map.getString(R.string.shared_string_save), "");
setIcons(R.drawable.widget_monitoring_rec_big_day, R.drawable.widget_monitoring_rec_big_night);
return true;
@@ -214,7 +213,7 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
}
final boolean liveMonitoringEnabled = liveMonitoringHelper.isLiveMonitoringEnabled();
- if (globalRecord) {
+ if(globalRecord) {
//indicates global recording (+background recording)
if (liveMonitoringEnabled) {
dn = R.drawable.widget_live_monitoring_rec_big_night;
@@ -320,18 +319,7 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
}
public void controlDialog(final Activity activity, final boolean showTrackSelection) {
-
- SavingTrackHelper helper = app.getSavingTrackHelper();
- SelectedGpxFile selectedGpxFile = helper.getCurrentTrack();
- boolean hasDataToSave = helper.hasDataToSave();
- boolean wasTrackMonitored = settings.SAVE_GLOBAL_TRACK_TO_GPX.get();
- OsmAndLocationProvider locationProvider = app.getLocationProvider();
- Location lastKnownLocation = locationProvider.getLastKnownLocation();
- FragmentActivity fragmentActivity = (FragmentActivity) activity;
- TripRecordingActiveBottomSheet.showInstance(fragmentActivity.getSupportFragmentManager(),
- selectedGpxFile, wasTrackMonitored, hasDataToSave, lastKnownLocation == null);
-
- /*final boolean wasTrackMonitored = settings.SAVE_GLOBAL_TRACK_TO_GPX.get();
+ final boolean wasTrackMonitored = settings.SAVE_GLOBAL_TRACK_TO_GPX.get();
final boolean nightMode;
if (activity instanceof MapActivity) {
nightMode = app.getDaynightHelper().isNightModeForMapControls();
@@ -340,6 +328,8 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
}
AlertDialog.Builder bld = new AlertDialog.Builder(UiUtilities.getThemedContext(activity, nightMode));
final TIntArrayList items = new TIntArrayList();
+ FragmentActivity fragmentActivity = (FragmentActivity) activity;
+ TripRecordingActiveBottomSheet.showInstance(fragmentActivity.getSupportFragmentManager());
if (wasTrackMonitored) {
items.add(R.string.gpx_monitoring_stop);
items.add(R.string.gpx_start_new_segment);
@@ -428,8 +418,8 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
run.run();
}
});
- bld.show();
- }*/
+// bld.show();
+ }
}
public void saveCurrentTrack() {
@@ -491,7 +481,7 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
}
}
- public void stopRecording() {
+ public void stopRecording(){
settings.SAVE_GLOBAL_TRACK_TO_GPX.set(false);
if (app.getNavigationService() != null) {
app.getNavigationService().stopIfNeeded(app, NavigationService.USED_BY_GPX);
@@ -580,11 +570,11 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
public void onValueChange(@NonNull Slider slider, float value, boolean fromUser) {
String s;
int progress = (int) value;
- if (progress == 0) {
+ if(progress == 0) {
s = uiCtx.getString(R.string.int_continuosly);
v.value = 0;
} else {
- if (progress < secondsLength) {
+ if(progress < secondsLength) {
s = seconds[progress] + " " + uiCtx.getString(R.string.int_seconds);
v.value = seconds[progress] * 1000;
} else {
diff --git a/OsmAnd/src/net/osmand/plus/monitoring/StopTrackRecordingBottomFragment.java b/OsmAnd/src/net/osmand/plus/monitoring/StopTrackRecordingBottomFragment.java
new file mode 100644
index 0000000000..b7bf829457
--- /dev/null
+++ b/OsmAnd/src/net/osmand/plus/monitoring/StopTrackRecordingBottomFragment.java
@@ -0,0 +1,187 @@
+package net.osmand.plus.monitoring;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import net.osmand.plus.OsmandApplication;
+import net.osmand.plus.OsmandPlugin;
+import net.osmand.plus.R;
+import net.osmand.plus.UiUtilities;
+import net.osmand.plus.UiUtilities.DialogButtonType;
+import net.osmand.plus.base.MenuBottomSheetDialogFragment;
+import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
+import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription;
+import net.osmand.plus.settings.backend.OsmandSettings;
+import net.osmand.plus.widgets.TextViewEx;
+
+import androidx.annotation.DimenRes;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.StringRes;
+import androidx.appcompat.widget.AppCompatImageView;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+
+public class StopTrackRecordingBottomFragment extends MenuBottomSheetDialogFragment implements View.OnClickListener {
+
+ public static final String TAG = StopTrackRecordingBottomFragment.class.getSimpleName();
+
+ private OsmandApplication app;
+ private OsmandSettings settings;
+ private OsmandMonitoringPlugin plugin;
+
+ @Override
+ public void createMenuItems(Bundle savedInstanceState) {
+ app = requiredMyApplication();
+ settings = app.getSettings();
+ plugin = OsmandPlugin.getPlugin(OsmandMonitoringPlugin.class);
+
+ items.add(new BottomSheetItemWithDescription.Builder()
+ .setDescription(app.getString(R.string.track_recording_description))
+ .setDescriptionColorId(!nightMode ? R.color.text_color_primary_light : R.color.text_color_primary_dark)
+ .setDescriptionMaxLines(4)
+ .setTitle(app.getString(R.string.track_recording_title))
+ .setLayoutId(R.layout.bottom_sheet_item_title_with_description)
+ .create());
+
+ LayoutInflater inflater = UiUtilities.getInflater(getContext(), nightMode);
+
+ items.add(new BaseBottomSheetItem.Builder()
+ .setCustomView(setupButton(inflater, ButtonType.STOP_AND_DISCARD))
+ .setOnClickListener(this)
+ .create());
+
+ items.add(new BaseBottomSheetItem.Builder()
+ .setCustomView(setupButton(inflater, ButtonType.SAVE_AND_STOP))
+ .setOnClickListener(this)
+ .create());
+
+ items.add(new BaseBottomSheetItem.Builder()
+ .setCustomView(setupButton(inflater, ButtonType.CANCEL))
+ .setOnClickListener(this)
+ .create());
+ }
+
+ private View setupButton(LayoutInflater inflater, ButtonType type) {
+ View button = inflater.inflate(R.layout.bottom_sheet_item_button_with_icon, null);
+ button.setTag(type);
+ Context context = button.getContext();
+
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
+ int horizontal = context.getResources().getDimensionPixelSize(R.dimen.content_padding);
+ int top = context.getResources().getDimensionPixelSize(type.topMarginRes);
+ int bottom = context.getResources().getDimensionPixelSize(R.dimen.content_padding_small);
+ params.setMargins(horizontal, top, horizontal, bottom);
+ button.setLayoutParams(params);
+
+ UiUtilities.setupDialogButton(nightMode, button, type.effect, type.titleId);
+
+ TextViewEx title = button.findViewById(R.id.button_text);
+ int margin = context.getResources().getDimensionPixelSize(R.dimen.context_menu_padding_margin_medium);
+ UiUtilities.setMargins(title, 0, margin, 0, margin);
+
+ int colorRes;
+ if (type.effect == DialogButtonType.SECONDARY_HARMFUL) {
+ colorRes = R.color.color_osm_edit_delete;
+ } else {
+ colorRes = nightMode ? R.color.dlg_btn_secondary_text_dark : R.color.dlg_btn_secondary_text_light;
+ }
+ AppCompatImageView icon = button.findViewById(R.id.icon);
+ icon.setImageDrawable(getIcon(type.iconRes, colorRes));
+
+ if (type == ButtonType.STOP_AND_DISCARD) {
+ int size = context.getResources().getDimensionPixelSize(R.dimen.map_widget_height);
+ LinearLayout.LayoutParams iconParams = new LinearLayout.LayoutParams(size, size);
+ icon.setLayoutParams(iconParams);
+ }
+
+ return button;
+ }
+
+ @Override
+ public void onClick(View v) {
+ Object o = v.getTag();
+ if (!(o instanceof ButtonType)) {
+ return;
+ }
+
+ ButtonType tag = (ButtonType) o;
+ if (tag == ButtonType.STOP_AND_DISCARD) {
+ if (plugin != null && settings.SAVE_GLOBAL_TRACK_TO_GPX.get()) {
+ plugin.stopRecording();
+ app.getNotificationHelper().refreshNotifications();
+ }
+ app.getSavingTrackHelper().clearRecordedData(true);
+ } else if (tag == ButtonType.SAVE_AND_STOP) {
+ if (plugin != null && settings.SAVE_GLOBAL_TRACK_TO_GPX.get()) {
+ plugin.saveCurrentTrack();
+ app.getNotificationHelper().refreshNotifications();
+ }
+ }
+ dismiss();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ // Replace later with tTripRecordingActiveBottomSheet.hide()
+ Fragment target = getTargetFragment();
+ if (target instanceof TripRecordingActiveBottomSheet) {
+ Dialog dialog = ((TripRecordingActiveBottomSheet) target).getDialog();
+ if (dialog != null) {
+ dialog.hide();
+ }
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ // Replace later with tTripRecordingActiveBottomSheet.show()
+ Fragment target = getTargetFragment();
+ if (target instanceof TripRecordingActiveBottomSheet) {
+ Dialog dialog = ((TripRecordingActiveBottomSheet) target).getDialog();
+ if (dialog != null) {
+ dialog.show();
+ }
+ }
+ }
+
+ enum ButtonType {
+ STOP_AND_DISCARD(R.string.track_recording_stop_without_saving, R.drawable.ic_action_rec_stop, R.dimen.dialog_content_margin, DialogButtonType.SECONDARY_HARMFUL),
+ SAVE_AND_STOP(R.string.track_recording_save_and_stop, R.drawable.ic_action_save_to_file, R.dimen.content_padding_small, DialogButtonType.SECONDARY),
+ CANCEL(R.string.shared_string_cancel, R.drawable.ic_action_close, R.dimen.zero, DialogButtonType.SECONDARY);
+
+ @StringRes
+ private final int titleId;
+ @DrawableRes
+ private final int iconRes;
+ @DimenRes
+ private final int topMarginRes;
+ private final DialogButtonType effect;
+
+ ButtonType(int titleId, int iconRes, int topMarginRes, DialogButtonType type) {
+ this.titleId = titleId;
+ this.iconRes = iconRes;
+ this.topMarginRes = topMarginRes;
+ this.effect = type;
+ }
+ }
+
+ @Override
+ protected boolean hideButtonsContainer() {
+ return true;
+ }
+
+ public static void showInstance(@NonNull FragmentManager fragmentManager, @NonNull Fragment target) {
+ if (!fragmentManager.isStateSaved()) {
+ StopTrackRecordingBottomFragment fragment = new StopTrackRecordingBottomFragment();
+ fragment.setTargetFragment(target, 0);
+ fragment.show(fragmentManager, TAG);
+ }
+ }
+}
diff --git a/OsmAnd/src/net/osmand/plus/monitoring/TripRecordingActiveBottomSheet.java b/OsmAnd/src/net/osmand/plus/monitoring/TripRecordingActiveBottomSheet.java
index 5f5c662882..23bf24e287 100644
--- a/OsmAnd/src/net/osmand/plus/monitoring/TripRecordingActiveBottomSheet.java
+++ b/OsmAnd/src/net/osmand/plus/monitoring/TripRecordingActiveBottomSheet.java
@@ -6,13 +6,17 @@ import android.app.Dialog;
import android.content.Context;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.util.TypedValue;
+import android.text.format.DateUtils;
+import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
+import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -25,10 +29,15 @@ import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.appcompat.widget.SwitchCompat;
import androidx.core.content.ContextCompat;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.RecyclerView;
+import com.google.android.material.snackbar.Snackbar;
+
import net.osmand.AndroidUtils;
+import net.osmand.GPXUtilities;
import net.osmand.Location;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.OsmAndLocationProvider;
@@ -36,16 +45,25 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
+import net.osmand.plus.activities.SavingTrackHelper;
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.FontCache;
+import net.osmand.plus.myplaces.SaveCurrentTrackTask;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.track.GpxBlockStatisticsBuilder;
+import net.osmand.plus.track.SaveGpxAsyncTask;
import net.osmand.plus.track.TrackAppearanceFragment;
import net.osmand.plus.widgets.TextViewEx;
import net.osmand.util.Algorithms;
+import java.lang.ref.WeakReference;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
import static net.osmand.plus.UiUtilities.CompoundButtonType.PROFILE_DEPENDENT;
public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragment {
@@ -65,6 +83,44 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen
private final Handler handler = new Handler();
private Runnable updatingGPS;
+ SaveGpxAsyncTask.SaveGpxListener saveGpxListener = new SaveGpxAsyncTask.SaveGpxListener() {
+
+ @Override
+ public void gpxSavingStarted() {
+
+ }
+
+ @Override
+ public void gpxSavingFinished(Exception errorMessage) {
+ String gpxFileName = Algorithms.getFileWithoutDirs(app.getSavingTrackHelper().getCurrentTrack().getGpxFile().path);
+ final MapActivity mapActivity = getMapActivity();
+ final Context context = getContext();
+ SavingTrackHelper helper = app.getSavingTrackHelper();
+ final SavingTrackHelper.SaveGpxResult result = helper.saveDataToGpx(app.getAppCustomization().getTracksDir());
+ if (mapActivity != null && context != null) {
+ Snackbar snackbar = Snackbar.make(mapActivity.getLayout(),
+ getString(R.string.shared_string_file_is_saved, gpxFileName),
+ Snackbar.LENGTH_LONG)
+ .setAction(R.string.shared_string_undo, new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ final WeakReference mapActivityRef = new WeakReference<>(mapActivity);
+ final FragmentActivity fragmentActivity = mapActivityRef.get();
+ SaveGPXBottomSheetFragment.showInstance(fragmentActivity.getSupportFragmentManager(), result.getFilenames());
+ }
+ });
+ View view = snackbar.getView();
+ FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) view.getLayoutParams();
+ params.gravity = Gravity.TOP;
+ AndroidUtils.setMargins(params, 0, AndroidUtils.getStatusBarHeight(context), 0, 0);
+ view.setLayoutParams(params);
+ UiUtilities.setupSnackbar(snackbar, nightMode);
+ snackbar.show();
+ }
+ }
+
+ };
+
public void setSelectedGpxFile(SelectedGpxFile selectedGpxFile) {
this.selectedGpxFile = selectedGpxFile;
}
@@ -81,17 +137,46 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen
this.searchingGPS = searchingGPS;
}
+ public static void showInstance(@NonNull FragmentManager fragmentManager, SelectedGpxFile selectedGpxFile,
+ boolean wasTrackMonitored, boolean hasDataToSave, boolean searchingGPS) {
+ if (!fragmentManager.isStateSaved()) {
+ TripRecordingActiveBottomSheet fragment = new TripRecordingActiveBottomSheet();
+ fragment.setSelectedGpxFile(selectedGpxFile);
+ fragment.setWasTrackMonitored(wasTrackMonitored);
+ fragment.setHasDataToSave(hasDataToSave);
+ fragment.setSearchingGPS(searchingGPS);
+ fragment.show(fragmentManager, TAG);
+ }
+ }
+
@Override
public void createMenuItems(Bundle savedInstanceState) {
app = requiredMyApplication();
settings = app.getSettings();
LayoutInflater inflater = UiUtilities.getInflater(getContext(), nightMode);
+ final FragmentManager fragmentManager = getFragmentManager();
+ final Fragment targetFragment = getTargetFragment();
View itemView = inflater.inflate(R.layout.trip_recording_active_fragment, null, false);
items.add(new BottomSheetItemWithDescription.Builder()
.setCustomView(itemView)
.create());
+ long timeTrackSaved = app.getSavingTrackHelper().getLastTimeUpdated();
+ SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy HH:mm:ss:SSS Z");
+ sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
+ Date resultDate = new Date(timeTrackSaved);
+ String sdfFormatted = sdf.format(resultDate);
+ CharSequence formattedTimeTrackSaved = null;
+ try {
+ long time = sdf.parse(sdfFormatted).getTime();
+ long now = System.currentTimeMillis();
+ formattedTimeTrackSaved =
+ DateUtils.getRelativeTimeSpanString(time, now, DateUtils.MINUTE_IN_MILLIS);
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+
View buttonClear = itemView.findViewById(R.id.button_clear);
View buttonStart = itemView.findViewById(R.id.button_start);
View buttonSave = itemView.findViewById(R.id.button_save);
@@ -100,7 +185,7 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen
createItem(buttonClear, ItemType.CLEAR_DATA, hasDataToSave, null);
createItem(buttonStart, ItemType.START_SEGMENT, wasTrackMonitored, null);
- createItem(buttonSave, ItemType.SAVE, hasDataToSave, "...");
+ createItem(buttonSave, ItemType.SAVE, hasDataToSave, (String) formattedTimeTrackSaved);
createItem(buttonPause, wasTrackMonitored ? ItemType.PAUSE : ItemType.RESUME, true, null);
createItem(buttonStop, ItemType.STOP, true, null);
@@ -179,6 +264,32 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen
createItem(additionalButton, ItemType.APPEARANCE, checked, null);
}
});
+
+ buttonSave.findViewById(R.id.button_container).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ final GPXUtilities.GPXFile gpxFile = app.getSavingTrackHelper().getCurrentTrack().getGpxFile();
+ new SaveCurrentTrackTask(app, gpxFile, saveGpxListener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+ });
+
+ buttonStop.findViewById(R.id.button_container).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (fragmentManager != null) {
+ StopTrackRecordingBottomFragment.showInstance(fragmentManager, targetFragment);
+ }
+ }
+ });
+
+ buttonClear.findViewById(R.id.button_container).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (fragmentManager != null) {
+ ClearRecordedDataBottomSheetFragment.showInstance(fragmentManager, targetFragment);
+ }
+ }
+ });
}
private void updateStatus() {
@@ -421,16 +532,4 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen
protected boolean useVerticalButtons() {
return true;
}
-
- public static void showInstance(@NonNull FragmentManager fragmentManager, SelectedGpxFile selectedGpxFile,
- boolean wasTrackMonitored, boolean hasDataToSave, boolean searchingGPS) {
- if (!fragmentManager.isStateSaved()) {
- TripRecordingActiveBottomSheet fragment = new TripRecordingActiveBottomSheet();
- fragment.setSelectedGpxFile(selectedGpxFile);
- fragment.setWasTrackMonitored(wasTrackMonitored);
- fragment.setHasDataToSave(hasDataToSave);
- fragment.setSearchingGPS(searchingGPS);
- fragment.show(fragmentManager, TAG);
- }
- }
}