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 index 9b2b395ccb..3d2d1bbab1 100644 --- a/OsmAnd/res/layout/bottom_sheet_item_button_with_icon.xml +++ b/OsmAnd/res/layout/bottom_sheet_item_button_with_icon.xml @@ -34,7 +34,6 @@ android:layout_height="wrap_content" android:duplicateParentState="true" android:textSize="@dimen/default_desc_text_size" - osmand:letterSpacing="@dimen/description_letter_spacing" osmand:typeface="@string/font_roboto_medium" tools:text="Title" tools:textColor="@color/text_color_secondary_light" /> @@ -47,7 +46,7 @@ android:textColor="@color/text_color_secondary_light" android:textSize="@dimen/default_desc_text_size" android:visibility="gone" - osmand:letterSpacing="@dimen/description_letter_spacing" + android:letterSpacing="@dimen/description_letter_spacing" osmand:typeface="@string/font_roboto_medium" tools:text="Description" tools:visibility="visible" /> diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 905a947661..b2a92f75c2 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -11,7 +11,7 @@ Thx - Hardy --> - + On pause Are you sure you want to stop recording?\nAll unsaved data will be lost. Track recording stopped Save and stop recording 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/OsmandMonitoringPlugin.java b/OsmAnd/src/net/osmand/plus/monitoring/OsmandMonitoringPlugin.java index 1ddb443891..65538733b0 100644 --- a/OsmAnd/src/net/osmand/plus/monitoring/OsmandMonitoringPlugin.java +++ b/OsmAnd/src/net/osmand/plus/monitoring/OsmandMonitoringPlugin.java @@ -43,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; @@ -318,9 +319,7 @@ public class OsmandMonitoringPlugin extends OsmandPlugin { } public void controlDialog(final Activity activity, final boolean showTrackSelection) { - FragmentActivity fragmentActivity = (FragmentActivity) activity; - TripRecordingActiveBottomSheet.showInstance(fragmentActivity.getSupportFragmentManager()); - /*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(); @@ -329,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); @@ -417,7 +418,7 @@ public class OsmandMonitoringPlugin extends OsmandPlugin { run.run(); } }); - bld.show(); +// bld.show(); } } @@ -538,7 +539,7 @@ public class OsmandMonitoringPlugin extends OsmandPlugin { } public static LinearLayout createIntervalChooseLayout(final OsmandApplication app, - final Context uiCtx, + final Context uiCtx, final String patternMsg, final int[] seconds, final int[] minutes, final ValueHolder choice, final ValueHolder v, @@ -598,7 +599,7 @@ public class OsmandMonitoringPlugin extends OsmandPlugin { } } } - + ll.setOrientation(LinearLayout.VERTICAL); ll.addView(tv); ll.addView(sliderContainer); diff --git a/OsmAnd/src/net/osmand/plus/monitoring/TripRecordingActiveBottomSheet.java b/OsmAnd/src/net/osmand/plus/monitoring/TripRecordingActiveBottomSheet.java index 6234d58b18..3e3fad8b75 100644 --- a/OsmAnd/src/net/osmand/plus/monitoring/TripRecordingActiveBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/monitoring/TripRecordingActiveBottomSheet.java @@ -4,8 +4,10 @@ import android.app.Activity; import android.app.Dialog; import android.content.Context; import android.graphics.drawable.Drawable; +import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; +import android.text.format.DateUtils; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; @@ -21,34 +23,84 @@ 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 com.google.android.material.snackbar.Snackbar; + +import net.osmand.GPXUtilities; import net.osmand.plus.GpxSelectionHelper; 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.myplaces.SaveCurrentTrackTask; import net.osmand.plus.settings.backend.OsmandSettings; +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.TimeZone; + import static net.osmand.plus.UiUtilities.CompoundButtonType.PROFILE_DEPENDENT; public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragment { public static final String TAG = TripRecordingActiveBottomSheet.class.getSimpleName(); - private OsmandApplication app; - private OsmandSettings settings; + 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(); + SavingTrackHelper helper = app.getSavingTrackHelper(); + final SavingTrackHelper.SaveGpxResult result = helper.saveDataToGpx(app.getAppCustomization().getTracksDir()); + if (mapActivity != 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()); + } + }); + UiUtilities.setupSnackbar(snackbar, nightMode); + snackbar.show(); + dismiss(); + } + } + + }; + + public static void showInstance(@NonNull FragmentManager fragmentManager) { + if (!fragmentManager.isStateSaved()) { + TripRecordingActiveBottomSheet fragment = new TripRecordingActiveBottomSheet(); + fragment.show(fragmentManager, TAG); + } + } @Override public void createMenuItems(Bundle savedInstanceState) { app = requiredMyApplication(); - settings = app.getSettings(); + OsmandSettings settings = app.getSettings(); Context context = requireContext(); LayoutInflater inflater = UiUtilities.getInflater(context, nightMode); @@ -67,6 +119,19 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen ); statusIcon.setImageDrawable(statusDrawable); + String timeTrackSaved = String.valueOf(app.getSavingTrackHelper().getLastTimeUpdated()); + SimpleDateFormat sdf = new SimpleDateFormat("MMM dd,yyyy HH:mm"); + sdf.setTimeZone(TimeZone.getTimeZone("GMT")); + CharSequence formattedTimeTrackSaved = null; + try { + long time = sdf.parse(timeTrackSaved).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); @@ -75,7 +140,7 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen createButton(buttonClear, ItemType.CLEAR_DATA, true, null); createButton(buttonStart, ItemType.START_SEGMENT, true, null); - createButton(buttonSave, ItemType.SAVE, true, "17 min. ago"); + createButton(buttonSave, ItemType.SAVE, true, (String) formattedTimeTrackSaved); createButton(buttonPause, ItemType.PAUSE, true, null); createButton(buttonStop, ItemType.STOP, true, null); @@ -116,6 +181,25 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen }); UiUtilities.setupCompoundButton(showTrackOnMapButton, nightMode, PROFILE_DEPENDENT); + buttonSave.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.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + FragmentManager fragmentManager = getFragmentManager(); + Fragment targetFragment = getTargetFragment(); + if (fragmentManager != null && targetFragment != null) { + StopTrackRecordingBottomFragment.showInstance(fragmentManager, targetFragment); + } + } + }); } private void createButton(View view, ItemType type, boolean enabled, @Nullable String description) { @@ -150,35 +234,6 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen desc.setText(description); } - enum ItemType { - SEARCHING_GPS(R.string.searching_gps, R.drawable.ic_action_gps_info), - RECORDING(R.string.recording_default_name, R.drawable.ic_action_track_recordable), - ON_PAUSE(R.string.on_pause, R.drawable.ic_pause), - CLEAR_DATA(R.string.clear_recorded_data, R.drawable.ic_action_delete_dark), - START_SEGMENT(R.string.gpx_start_new_segment, R.drawable.ic_action_new_segment), - SAVE(R.string.shared_string_save, R.drawable.ic_action_save_to_file), - PAUSE(R.string.shared_string_pause, R.drawable.ic_pause), - STOP(R.string.shared_string_control_stop, R.drawable.ic_action_rec_stop); - - @StringRes - private int titleId; - @DrawableRes - private int iconId; - - ItemType(@StringRes int titleId, @DrawableRes int iconId) { - this.titleId = titleId; - this.iconId = iconId; - } - - public int getTitleId() { - return titleId; - } - - public int getIconId() { - return iconId; - } - } - @ColorRes protected int getActiveTextColorId() { return nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light; @@ -235,10 +290,32 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen } } - public static void showInstance(@NonNull FragmentManager fragmentManager) { - if (!fragmentManager.isStateSaved()) { - TripRecordingActiveBottomSheet fragment = new TripRecordingActiveBottomSheet(); - fragment.show(fragmentManager, TAG); + enum ItemType { + SEARCHING_GPS(R.string.searching_gps, R.drawable.ic_action_gps_info), + RECORDING(R.string.recording_default_name, R.drawable.ic_action_track_recordable), + ON_PAUSE(R.string.on_pause, R.drawable.ic_pause), + CLEAR_DATA(R.string.clear_recorded_data, R.drawable.ic_action_delete_dark), + START_SEGMENT(R.string.gpx_start_new_segment, R.drawable.ic_action_new_segment), + SAVE(R.string.shared_string_save, R.drawable.ic_action_save_to_file), + PAUSE(R.string.shared_string_pause, R.drawable.ic_pause), + STOP(R.string.shared_string_control_stop, R.drawable.ic_action_rec_stop); + + @StringRes + private int titleId; + @DrawableRes + private int iconId; + + ItemType(@StringRes int titleId, @DrawableRes int iconId) { + this.titleId = titleId; + this.iconId = iconId; + } + + public int getTitleId() { + return titleId; + } + + public int getIconId() { + return iconId; } } }