From 54d875ff2de8e48bb2a5432a69dc417342b70884 Mon Sep 17 00:00:00 2001 From: y20k Date: Mon, 9 Mar 2020 15:39:48 +0100 Subject: [PATCH] option to delete all recordings that are not starred --- app/build.gradle | 2 +- app/src/main/java/org/y20k/trackbook/Keys.kt | 3 +- .../org/y20k/trackbook/SettingsFragment.kt | 59 +++++++++++++++++-- .../java/org/y20k/trackbook/TrackFragment.kt | 6 +- .../org/y20k/trackbook/TracklistFragment.kt | 6 +- .../org/y20k/trackbook/helpers/FileHelper.kt | 29 ++++++++- app/src/main/res/values-fr/strings.xml | 4 +- app/src/main/res/values-it/strings.xml | 4 +- app/src/main/res/values-nb-rNO/strings.xml | 4 +- app/src/main/res/values-nl/strings.xml | 4 +- app/src/main/res/values-zh-rCN/strings.xml | 4 +- app/src/main/res/values/strings.xml | 9 ++- 12 files changed, 107 insertions(+), 27 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 78a4184..ea80b54 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -81,7 +81,7 @@ dependencies { implementation "com.google.android.material:material:1.1.0-beta01" implementation "com.google.code.gson:gson:2.8.6" - implementation "org.osmdroid:osmdroid-android:6.1.5" + implementation "org.osmdroid:osmdroid-android:6.1.6" } androidExtensions { diff --git a/app/src/main/java/org/y20k/trackbook/Keys.kt b/app/src/main/java/org/y20k/trackbook/Keys.kt index 02991fb..8eb0ae7 100644 --- a/app/src/main/java/org/y20k/trackbook/Keys.kt +++ b/app/src/main/java/org/y20k/trackbook/Keys.kt @@ -69,7 +69,8 @@ object Keys { // dialog types const val DIALOG_EMPTY_RECORDING: Int = 0 - const val DIALOG_REMOVE_TRACK: Int = 1 + const val DIALOG_DELETE_TRACK: Int = 1 + const val DIALOG_DELETE_NON_STARRED: Int = 2 // dialog results const val DIALOG_EMPTY_PAYLOAD_STRING: String = "" diff --git a/app/src/main/java/org/y20k/trackbook/SettingsFragment.kt b/app/src/main/java/org/y20k/trackbook/SettingsFragment.kt index 8ae239f..1507088 100644 --- a/app/src/main/java/org/y20k/trackbook/SettingsFragment.kt +++ b/app/src/main/java/org/y20k/trackbook/SettingsFragment.kt @@ -18,11 +18,15 @@ package org.y20k.trackbook +import YesNoDialog import android.content.Context import android.os.Bundle import android.view.View import androidx.preference.* +import kotlinx.coroutines.* +import org.y20k.trackbook.core.Tracklist import org.y20k.trackbook.helpers.AppThemeHelper +import org.y20k.trackbook.helpers.FileHelper import org.y20k.trackbook.helpers.LengthUnitHelper import org.y20k.trackbook.helpers.LogHelper @@ -30,7 +34,7 @@ import org.y20k.trackbook.helpers.LogHelper /* * SettingsFragment class */ -class SettingsFragment : PreferenceFragmentCompat() { +class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogListener { /* Define log tag */ private val TAG: String = LogHelper.makeLogTag(SettingsFragment::class.java) @@ -88,12 +92,16 @@ class SettingsFragment : PreferenceFragmentCompat() { return@setOnPreferenceChangeListener false } } -// preferenceThemeSelection.setOnPreferenceClickListener { -// preferenceThemeSelection.summary = "${getString(R.string.pref_theme_selection_theme_summary)} ${AppThemeHelper.getCurrentTheme(activity as Context)}" -// return@setOnPreferenceClickListener true -// } - + // set up "Delete Non-Starred" preference + val preferenceDeleteNonStarred: Preference = Preference(activity as Context) + preferenceDeleteNonStarred.title = getString(R.string.pref_delete_non_starred_title) + preferenceDeleteNonStarred.setIcon(R.drawable.ic_delete_24dp) + preferenceDeleteNonStarred.summary = getString(R.string.pref_delete_non_starred_summary) + preferenceDeleteNonStarred.setOnPreferenceClickListener{ + YesNoDialog(this as YesNoDialog.YesNoDialogListener).show(context = activity as Context, type = Keys.DIALOG_DELETE_NON_STARRED, message = R.string.dialog_yes_no_message_delete_non_starred, yesButton = R.string.dialog_yes_no_positive_button_delete_non_starred) + return@setOnPreferenceClickListener true + } // set up "Accuracy Threshold" preference val preferenceAccuracyThreshold: SeekBarPreference = SeekBarPreference(activity as Context) @@ -120,6 +128,10 @@ class SettingsFragment : PreferenceFragmentCompat() { preferenceCategoryGeneral.title = getString(R.string.pref_general_title) preferenceCategoryGeneral.contains(preferenceImperialMeasurementUnits) preferenceCategoryGeneral.contains(preferenceGpsOnly) + val preferenceCategoryMaintenance: PreferenceCategory = PreferenceCategory(activity as Context) + preferenceCategoryMaintenance.title = getString(R.string.pref_maintenance_title) + preferenceCategoryMaintenance.contains(preferenceDeleteNonStarred) + val preferenceCategoryAdvanced: PreferenceCategory = PreferenceCategory(activity as Context) preferenceCategoryAdvanced.title = getString(R.string.pref_advanced_title) preferenceCategoryAdvanced.contains(preferenceAccuracyThreshold) @@ -130,10 +142,45 @@ class SettingsFragment : PreferenceFragmentCompat() { screen.addPreference(preferenceGpsOnly) screen.addPreference(preferenceImperialMeasurementUnits) screen.addPreference(preferenceThemeSelection) + screen.addPreference(preferenceCategoryMaintenance) + screen.addPreference(preferenceDeleteNonStarred) screen.addPreference(preferenceCategoryAdvanced) screen.addPreference(preferenceAccuracyThreshold) screen.addPreference(preferenceResetAdvanced) preferenceScreen = screen } + + /* Overrides onYesNoDialog from YesNoDialogListener */ + override fun onYesNoDialog(type: Int, dialogResult: Boolean, payload: Int, payloadString: String) { + when (type) { + Keys.DIALOG_DELETE_NON_STARRED -> { + when (dialogResult) { + // user tapped delete + true -> { + deleteNonStarred(activity as Context) + } + } + } + else -> { + super.onYesNoDialog(type, dialogResult, payload, payloadString) + } + } + } + + + /* Removes track and track files for given position - used by TracklistFragment */ + fun deleteNonStarred(context: Context) { + val backgroundJob = Job() + val uiScope = CoroutineScope(Dispatchers.Main + backgroundJob) + uiScope.launch { + var tracklist: Tracklist = FileHelper.readTracklist(context) + val deferred: Deferred = async { FileHelper.deleteNonStarredSuspended(context, tracklist) } + // wait for result and store in tracklist + tracklist = deferred.await() + backgroundJob.cancel() + } + } + + } diff --git a/app/src/main/java/org/y20k/trackbook/TrackFragment.kt b/app/src/main/java/org/y20k/trackbook/TrackFragment.kt index b124ed7..2981ace 100644 --- a/app/src/main/java/org/y20k/trackbook/TrackFragment.kt +++ b/app/src/main/java/org/y20k/trackbook/TrackFragment.kt @@ -85,8 +85,8 @@ class TrackFragment : Fragment(), RenameTrackDialog.RenameTrackListener, YesNoDi } // set up delete button layout.deleteButton.setOnClickListener { - val dialogMessage: String = "${getString(R.string.dialog_yes_no_message_remove_recording)}\n\n- ${layout.trackNameView.text}" - YesNoDialog(this@TrackFragment as YesNoDialog.YesNoDialogListener).show(context = activity as Context, type = Keys.DIALOG_REMOVE_TRACK, messageString = dialogMessage, yesButton = R.string.dialog_yes_no_positive_button_remove_recording) + val dialogMessage: String = "${getString(R.string.dialog_yes_no_message_delete_recording)}\n\n- ${layout.trackNameView.text}" + YesNoDialog(this@TrackFragment as YesNoDialog.YesNoDialogListener).show(context = activity as Context, type = Keys.DIALOG_DELETE_TRACK, messageString = dialogMessage, yesButton = R.string.dialog_yes_no_positive_button_delete_recording) } // set up rename button layout.editButton.setOnClickListener { @@ -147,7 +147,7 @@ class TrackFragment : Fragment(), RenameTrackDialog.RenameTrackListener, YesNoDi /* Overrides onYesNoDialog from YesNoDialogListener */ override fun onYesNoDialog(type: Int, dialogResult: Boolean, payload: Int, payloadString: String) { when (type) { - Keys.DIALOG_REMOVE_TRACK -> { + Keys.DIALOG_DELETE_TRACK -> { when (dialogResult) { // user tapped remove track true -> { diff --git a/app/src/main/java/org/y20k/trackbook/TracklistFragment.kt b/app/src/main/java/org/y20k/trackbook/TracklistFragment.kt index fa3f544..7258e5f 100644 --- a/app/src/main/java/org/y20k/trackbook/TracklistFragment.kt +++ b/app/src/main/java/org/y20k/trackbook/TracklistFragment.kt @@ -77,8 +77,8 @@ class TracklistFragment : Fragment(), TracklistAdapter.TracklistAdapterListener, override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { // ask user val adapterPosition: Int = viewHolder.adapterPosition - val dialogMessage: String = "${getString(R.string.dialog_yes_no_message_remove_recording)}\n\n- ${tracklistAdapter.getTrackName(adapterPosition)}" - YesNoDialog(this@TracklistFragment as YesNoDialog.YesNoDialogListener).show(context = activity as Context, type = Keys.DIALOG_REMOVE_TRACK, messageString = dialogMessage, yesButton = R.string.dialog_yes_no_positive_button_remove_recording, payload = adapterPosition) + val dialogMessage: String = "${getString(R.string.dialog_yes_no_message_delete_recording)}\n\n- ${tracklistAdapter.getTrackName(adapterPosition)}" + YesNoDialog(this@TracklistFragment as YesNoDialog.YesNoDialogListener).show(context = activity as Context, type = Keys.DIALOG_DELETE_TRACK, messageString = dialogMessage, yesButton = R.string.dialog_yes_no_positive_button_delete_recording, payload = adapterPosition) } } val itemTouchHelper = ItemTouchHelper(swipeHandler) @@ -105,7 +105,7 @@ class TracklistFragment : Fragment(), TracklistAdapter.TracklistAdapterListener, /* Overrides onYesNoDialog from YesNoDialogListener */ override fun onYesNoDialog(type: Int, dialogResult: Boolean, payload: Int, payloadString: String) { when (type) { - Keys.DIALOG_REMOVE_TRACK -> { + Keys.DIALOG_DELETE_TRACK -> { when (dialogResult) { // user tapped remove track true -> { diff --git a/app/src/main/java/org/y20k/trackbook/helpers/FileHelper.kt b/app/src/main/java/org/y20k/trackbook/helpers/FileHelper.kt index 39e832a..c08f176 100644 --- a/app/src/main/java/org/y20k/trackbook/helpers/FileHelper.kt +++ b/app/src/main/java/org/y20k/trackbook/helpers/FileHelper.kt @@ -224,6 +224,20 @@ object FileHelper { } + /* Suspend function: Deletes tracks that are not starred using deleteTracks */ + suspend fun deleteNonStarredSuspended(context: Context, tracklist: Tracklist): Tracklist { + return suspendCoroutine { cont -> + val tracklistElements = mutableListOf() + tracklist.tracklistElements.forEach { tracklistElement -> + if (!tracklistElement.starred) { + tracklistElements.add(tracklistElement) + } + } + cont.resume(deleteTracks(context, tracklistElements, tracklist)) + } + } + + /* Suspend function: Wrapper for readTracklist */ suspend fun readTracklistSuspended(context: Context): Tracklist { return suspendCoroutine {cont -> @@ -314,7 +328,20 @@ object FileHelper { } - /* Deletes track */ + /* Deletes multiple tracks track */ + private fun deleteTracks(context: Context, tracklistElements: MutableList, tracklist: Tracklist): Tracklist { + tracklistElements.forEach { tracklistElement -> + // delete track files + tracklistElement.trackUriString.toUri().toFile().delete() + tracklistElement.gpxUriString.toUri().toFile().delete() + } + tracklist.tracklistElements.removeAll{ tracklistElements.contains(it) } + saveTracklist(context, tracklist, GregorianCalendar.getInstance().time) + return tracklist + } + + + /* Deletes one track */ private fun deleteTrack(context: Context, position: Int, tracklist: Tracklist): Tracklist { val tracklistElement: TracklistElement = tracklist.tracklistElements[position] // delete track files diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index ff974ae..5d9e5c7 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -65,8 +65,8 @@ Renommer Entrez un nouveau nom Oui - Supprimer - Supprimer cet enregistrement \? + Supprimer + Supprimer cet enregistrement \? Annuler les corrections d\'emplacement avec une précision supérieure à : Seuil de précision Avancé diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index a5daebc..192e8ce 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -65,8 +65,8 @@ Rinomina Inserisci un nuovo nome - Rimuovi - Rimuovere questa registrazione\? + Rimuovi + Rimuovere questa registrazione\? Elimina le correzioni di posizione con una precisione maggiore di: Soglia della precisione Avanzate diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index b7b6192..7f232d6 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -65,8 +65,8 @@ Gi nytt navn Skriv inn nytt navn Ja - Fjern - Fjern dette opptaket\? + Fjern + Fjern dette opptaket\? Forkast posisjonsendringer med nøyaktighet større enn Nøyaktighetsterskel Avansert diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 7e77370..b6482a6 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -65,8 +65,8 @@ Naam wijzigen Voer een naam in Ja - Verwijderen - Wil je deze opname verwijderen\? + Verwijderen + Wil je deze opname verwijderen\? Locatie-aanpassingen verwerpen indien nauwkeurigheid hoger is dan: Nauwkeurigheidsdrempelwaarde Geavanceerd diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 09dd8ca..0459398 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -34,8 +34,8 @@ 输入一个新名称 分享GPX文件到 - 删除 - 删除此记录? + 删除 + 删除此记录? 提示:海拔数据的准确性取决于您的设备.测量整个路线的上坡和下坡海拔. 请先安装一个文件管理器或GPX轨迹查看器. diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6b827f2..e32e2ad 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -34,8 +34,10 @@ Enter a new name Share GPX file with Yes - Remove - Remove this recording? + Delete + Delete + Delete all non-starred recordings? This action cannot be undone. + Delete this recording? Hint: The accuracy of elevation data depends on your device. The uphill and downhill elevation of the whole route is measured. Please install a file manager or a GPX track viewer first. @@ -69,7 +71,10 @@ Discard location fixes with an accuracy larger than: Accuracy Threshold Advanced + Delete all recordings in \"Tracks\" that are not starred. + Delete Non-Starred Recordings General + Maintenance Restrict to GPS Currently using GPS and Network for localization. Currently using only GPS for localization.