From 2a381a3ee6bf3dd3a06de12c2abc055cc502628a Mon Sep 17 00:00:00 2001 From: ronniedroid Date: Thu, 18 Apr 2024 13:05:54 +0300 Subject: [PATCH] moved to registerForActivityResult and added timers to exports --- .../fossify/clock/activities/MainActivity.kt | 137 ---------------- .../clock/activities/SettingsActivity.kt | 147 +++++++++++++++++- ...ortAlarmsDialog.kt => ExportDataDialog.kt} | 30 ++-- .../org/fossify/clock/helpers/Config.kt | 6 +- .../org/fossify/clock/helpers/Constants.kt | 4 +- .../{AlarmsExporter.kt => DataExporter.kt} | 25 ++- .../{AlarmsImporter.kt => DataImporter.kt} | 4 +- .../kotlin/org/fossify/clock/models/Timer.kt | 18 ++- app/src/main/res/layout/activity_settings.xml | 57 +++++++ ...port_alarms.xml => dialog_export_data.xml} | 10 +- app/src/main/res/menu/menu.xml | 8 - app/src/main/res/values/strings.xml | 9 +- 12 files changed, 271 insertions(+), 184 deletions(-) rename app/src/main/kotlin/org/fossify/clock/dialogs/{ExportAlarmsDialog.kt => ExportDataDialog.kt} (68%) rename app/src/main/kotlin/org/fossify/clock/helpers/{AlarmsExporter.kt => DataExporter.kt} (61%) rename app/src/main/kotlin/org/fossify/clock/helpers/{AlarmsImporter.kt => DataImporter.kt} (96%) rename app/src/main/res/layout/{dialog_export_alarms.xml => dialog_export_data.xml} (88%) diff --git a/app/src/main/kotlin/org/fossify/clock/activities/MainActivity.kt b/app/src/main/kotlin/org/fossify/clock/activities/MainActivity.kt index 48bf8bb2..cd03f294 100644 --- a/app/src/main/kotlin/org/fossify/clock/activities/MainActivity.kt +++ b/app/src/main/kotlin/org/fossify/clock/activities/MainActivity.kt @@ -1,16 +1,13 @@ package org.fossify.clock.activities import android.annotation.SuppressLint -import android.content.ActivityNotFoundException import android.content.Intent import android.content.pm.ShortcutInfo import android.graphics.drawable.ColorDrawable import android.graphics.drawable.Icon import android.graphics.drawable.LayerDrawable -import android.net.Uri import android.os.Bundle import android.view.WindowManager -import android.widget.Toast import me.grantland.widget.AutofitHelper import org.fossify.clock.BuildConfig import org.fossify.clock.R @@ -22,10 +19,6 @@ import org.fossify.commons.databinding.BottomTablayoutItemBinding import org.fossify.commons.extensions.* import org.fossify.commons.helpers.* import org.fossify.commons.models.FAQItem -import org.fossify.clock.dialogs.ExportAlarmsDialog -import org.fossify.commons.dialogs.FilePickerDialog -import java.io.FileOutputStream -import java.io.OutputStream class MainActivity : SimpleActivity() { private var storedTextColor = 0 @@ -33,11 +26,6 @@ class MainActivity : SimpleActivity() { private var storedPrimaryColor = 0 private val binding: ActivityMainBinding by viewBinding(ActivityMainBinding::inflate) - private companion object { - private const val PICK_IMPORT_SOURCE_INTENT = 11 - private const val PICK_EXPORT_FILE_INTENT = 21 - } - override fun onCreate(savedInstanceState: Bundle?) { isMaterialActivity = true super.onCreate(savedInstanceState) @@ -142,8 +130,6 @@ class MainActivity : SimpleActivity() { R.id.more_apps_from_us -> launchMoreAppsFromUsIntent() R.id.settings -> launchSettings() R.id.about -> launchAbout() - R.id.export_alarms -> tryExportAlarms() - R.id.import_alarms -> tryImportAlarms() else -> return@setOnMenuItemClickListener false } return@setOnMenuItemClickListener true @@ -153,8 +139,6 @@ class MainActivity : SimpleActivity() { private fun refreshMenuItems() { binding.mainToolbar.menu.apply { findItem(R.id.sort).isVisible = binding.viewPager.currentItem == TAB_ALARM - findItem(R.id.export_alarms).isVisible = binding.viewPager.currentItem == TAB_ALARM - findItem(R.id.import_alarms).isVisible = binding.viewPager.currentItem == TAB_ALARM findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(org.fossify.commons.R.bool.hide_google_relations) } } @@ -188,13 +172,6 @@ class MainActivity : SimpleActivity() { requestCode == PICK_AUDIO_FILE_INTENT_ID && resultCode == RESULT_OK && resultData != null -> { storeNewAlarmSound(resultData) } - requestCode == PICK_EXPORT_FILE_INTENT && resultCode == RESULT_OK && resultData != null && resultData.data != null -> { - val outputStream = contentResolver.openOutputStream(resultData.data!!) - exportAlarmsTo(outputStream) - } - requestCode == PICK_IMPORT_SOURCE_INTENT && resultCode == RESULT_OK && resultData != null && resultData.data != null -> { - tryImportAlarmsFromFile(resultData.data!!) - } } } @@ -320,118 +297,4 @@ class MainActivity : SimpleActivity() { startAboutActivity(R.string.app_name, licenses, BuildConfig.VERSION_NAME, faqItems, true) } - - private fun exportAlarmsTo(outputStream: OutputStream?) { - ensureBackgroundThread { - val alarms = dbHelper.getAlarms() - if (alarms.isEmpty()) { - toast(org.fossify.commons.R.string.no_entries_for_exporting) - } else { - AlarmsExporter.exportAlarms(alarms, outputStream) { - toast( - when (it) { - ExportResult.EXPORT_OK -> org.fossify.commons.R.string.exporting_successful - else -> org.fossify.commons.R.string.exporting_failed - } - ) - } - } - } - } - - private fun tryExportAlarms() { - if (isQPlus()) { - ExportAlarmsDialog(this, config.lastAlarmsExportPath, true) { file -> - Intent(Intent.ACTION_CREATE_DOCUMENT).apply { - type = "application/json" - putExtra(Intent.EXTRA_TITLE, file.name) - addCategory(Intent.CATEGORY_OPENABLE) - - try { - startActivityForResult(this, PICK_EXPORT_FILE_INTENT) - } catch (e: ActivityNotFoundException) { - toast(org.fossify.commons.R.string.system_service_disabled, Toast.LENGTH_LONG) - } catch (e: Exception) { - showErrorToast(e) - } - } - } - } else { - handlePermission(PERMISSION_WRITE_STORAGE) { isAllowed -> - if (isAllowed) { - ExportAlarmsDialog(this, config.lastAlarmsExportPath, false) { file -> - getFileOutputStream(file.toFileDirItem(this), true) { out -> - exportAlarmsTo(out) - } - } - } - } - } - } - - private fun tryImportAlarms() { - if (isQPlus()) { - Intent(Intent.ACTION_GET_CONTENT).apply { - addCategory(Intent.CATEGORY_OPENABLE) - type = "application/json" - - try { - startActivityForResult(this, PICK_IMPORT_SOURCE_INTENT) - } catch (e: ActivityNotFoundException) { - toast(org.fossify.commons.R.string.system_service_disabled, Toast.LENGTH_LONG) - } catch (e: Exception) { - showErrorToast(e) - } - } - } else { - handlePermission(PERMISSION_READ_STORAGE) { isAllowed -> - if (isAllowed) { - pickFileToImportAlarms() - } - } - } - } - - private fun pickFileToImportAlarms() { - FilePickerDialog(this) { - importAlarms(it) - } - } - - private fun tryImportAlarmsFromFile(uri: Uri) { - when (uri.scheme) { - "file" -> importAlarms(uri.path!!) - "content" -> { - val tempFile = getTempFile("alarms", "alarms.json") - if (tempFile == null) { - toast(org.fossify.commons.R.string.unknown_error_occurred) - return - } - - try { - val inputStream = contentResolver.openInputStream(uri) - val out = FileOutputStream(tempFile) - inputStream!!.copyTo(out) - importAlarms(tempFile.absolutePath) - } catch (e: Exception) { - showErrorToast(e) - } - } - - else -> toast(org.fossify.commons.R.string.invalid_file_format) - } - } - - private fun importAlarms(path: String) { - ensureBackgroundThread { - val result = AlarmsImporter(this, DBHelper.dbInstance!!).importAlarms(path) - toast( - when (result) { - AlarmsImporter.ImportResult.IMPORT_OK -> - org.fossify.commons.R.string.importing_successful - AlarmsImporter.ImportResult.IMPORT_FAIL -> org.fossify.commons.R.string.no_items_found - } - ) - } - } } diff --git a/app/src/main/kotlin/org/fossify/clock/activities/SettingsActivity.kt b/app/src/main/kotlin/org/fossify/clock/activities/SettingsActivity.kt index 79413d6b..a95f2da3 100644 --- a/app/src/main/kotlin/org/fossify/clock/activities/SettingsActivity.kt +++ b/app/src/main/kotlin/org/fossify/clock/activities/SettingsActivity.kt @@ -1,16 +1,22 @@ package org.fossify.clock.activities +import android.content.ActivityNotFoundException import android.content.Intent import android.os.Bundle +import android.widget.Toast +import androidx.activity.result.contract.ActivityResultContracts import org.fossify.clock.databinding.ActivitySettingsBinding +import org.fossify.clock.dialogs.ExportDataDialog import org.fossify.clock.extensions.config -import org.fossify.clock.helpers.DEFAULT_MAX_ALARM_REMINDER_SECS -import org.fossify.clock.helpers.DEFAULT_MAX_TIMER_REMINDER_SECS +import org.fossify.clock.extensions.dbHelper +import org.fossify.clock.extensions.timerDb +import org.fossify.clock.extensions.timerHelper +import org.fossify.clock.helpers.* +import org.fossify.commons.R +import org.fossify.clock.R as CR import org.fossify.commons.extensions.* -import org.fossify.commons.helpers.IS_CUSTOMIZING_COLORS -import org.fossify.commons.helpers.MINUTE_SECONDS -import org.fossify.commons.helpers.NavigationIcon -import org.fossify.commons.helpers.isTiramisuPlus +import org.fossify.commons.helpers.* +import java.io.OutputStream import java.util.Locale import kotlin.system.exitProcess @@ -42,6 +48,7 @@ class SettingsActivity : SimpleActivity() { setupTimerMaxReminder() setupIncreaseVolumeGradually() setupCustomizeWidgetColors() + setupExportData() updateTextColors(binding.settingsHolder) arrayOf( @@ -170,4 +177,132 @@ class SettingsActivity : SimpleActivity() { } } } + + private fun setupExportData() { + binding.settingsExportDataHolder.setOnClickListener { + tryExportData() + } + } + + private val exportActivityResultLauncher = registerForActivityResult(ActivityResultContracts.CreateDocument("application/json")) { uri -> + try { + val outputStream = uri?.let { contentResolver.openOutputStream(it) } + if (outputStream != null) { + exportDataTo(outputStream) + } else { + toast(CR.string.exporting_aborted_by_user) + } + } catch (e: Exception) { + showErrorToast(e) + } + } + + private fun exportDataTo(outputStream: OutputStream?) { + ensureBackgroundThread { + val alarms = dbHelper.getAlarms() + val timers = timerDb.getTimers() + if (alarms.isEmpty()) { + toast(R.string.no_entries_for_exporting) + } else { + DataExporter.exportData(alarms, timers, outputStream) { + toast( + when (it) { + ExportResult.EXPORT_OK -> R.string.exporting_successful + else -> R.string.exporting_failed + } + ) + } + } + } + } + + private fun tryExportData() { + if (isQPlus()) { + ExportDataDialog(this, config.lastDataExportPath, true) { file -> + Intent(Intent.ACTION_CREATE_DOCUMENT).apply { + putExtra(Intent.EXTRA_TITLE, file.name) + addCategory(Intent.CATEGORY_OPENABLE) + + + try { + exportActivityResultLauncher.launch(file.name) + } catch (e: ActivityNotFoundException) { + toast(R.string.system_service_disabled, Toast.LENGTH_LONG) + } catch (e: Exception) { + showErrorToast(e) + } + + + } + } + } else { + handlePermission(PERMISSION_WRITE_STORAGE) { isAllowed -> + if (isAllowed) { + ExportDataDialog(this, config.lastDataExportPath, false) { file -> + getFileOutputStream(file.toFileDirItem(this), true) { out -> + exportDataTo(out) + } + } + } + } + } + } + +// private fun tryImportData() { +// if (isQPlus()) { +// Intent(Intent.ACTION_GET_CONTENT).apply { +// addCategory(Intent.CATEGORY_OPENABLE) +// type = "application/json" +// } +// } else { +// handlePermission(PERMISSION_READ_STORAGE) { isAllowed -> +// if (isAllowed) { +// pickFileToImportData() +// } +// } +// } +// } +// +// private fun pickFileToImportData() { +// FilePickerDialog(this) { +// importData(it) +// } +// } +// +// private fun tryImportDataFromFile(uri: Uri) { +// when (uri.scheme) { +// "file" -> importData(uri.path!!) +// "content" -> { +// val tempFile = getTempFile("fossify_clock_data", "fossify_clock_data.json") +// if (tempFile == null) { +// toast(R.string.unknown_error_occurred) +// return +// } +// +// try { +// val inputStream = contentResolver.openInputStream(uri) +// val out = FileOutputStream(tempFile) +// inputStream!!.copyTo(out) +// importData(tempFile.absolutePath) +// } catch (e: Exception) { +// showErrorToast(e) +// } +// } +// +// else -> toast(R.string.invalid_file_format) +// } +// } +// +// private fun importData(path: String) { +// ensureBackgroundThread { +// val result = AlarmsImporter(this, DBHelper.dbInstance!!).importAlarms(path) +// toast( +// when (result) { +// AlarmsImporter.ImportResult.IMPORT_OK -> +// R.string.importing_successful +// AlarmsImporter.ImportResult.IMPORT_FAIL -> R.string.no_items_found +// } +// ) +// } +// } } diff --git a/app/src/main/kotlin/org/fossify/clock/dialogs/ExportAlarmsDialog.kt b/app/src/main/kotlin/org/fossify/clock/dialogs/ExportDataDialog.kt similarity index 68% rename from app/src/main/kotlin/org/fossify/clock/dialogs/ExportAlarmsDialog.kt rename to app/src/main/kotlin/org/fossify/clock/dialogs/ExportDataDialog.kt index de48d2e4..6ab79fb9 100644 --- a/app/src/main/kotlin/org/fossify/clock/dialogs/ExportAlarmsDialog.kt +++ b/app/src/main/kotlin/org/fossify/clock/dialogs/ExportDataDialog.kt @@ -6,12 +6,12 @@ import org.fossify.commons.dialogs.FilePickerDialog import org.fossify.commons.extensions.* import org.fossify.commons.helpers.ensureBackgroundThread import org.fossify.clock.R -import org.fossify.clock.databinding.DialogExportAlarmsBinding +import org.fossify.clock.databinding.DialogExportDataBinding import org.fossify.clock.extensions.config -import org.fossify.clock.helpers.ALARMS_EXPORT_EXTENSION +import org.fossify.clock.helpers.DATA_EXPORT_EXTENSION import java.io.File -class ExportAlarmsDialog( +class ExportDataDialog( val activity: BaseSimpleActivity, val path: String, val hidePath: Boolean, @@ -21,17 +21,17 @@ class ExportAlarmsDialog( private val config = activity.config init { - val view = DialogExportAlarmsBinding.inflate(activity.layoutInflater, null, false).apply { - exportAlarmsFolder.text = activity.humanizePath(realPath) - exportAlarmsFilename.setText("${activity.getString(R.string.export_alarms)}_${activity.getCurrentFormattedDateTime()}") + val view = DialogExportDataBinding.inflate(activity.layoutInflater, null, false).apply { + exportDataFolder.text = activity.humanizePath(realPath) + exportDataFilename.setText("${activity.getString(R.string.settings_export_data)}_${activity.getCurrentFormattedDateTime()}") if (hidePath) { - exportAlarmsFolderLabel.beGone() - exportAlarmsFolder.beGone() + exportDataFolderLabel.beGone() + exportDataFolder.beGone() } else { - exportAlarmsFolder.setOnClickListener { + exportDataFolder.setOnClickListener { FilePickerDialog(activity, realPath, false, showFAB = true) { - exportAlarmsFolder.text = activity.humanizePath(it) + exportDataFolder.text = activity.humanizePath(it) realPath = it } } @@ -42,21 +42,21 @@ class ExportAlarmsDialog( .setPositiveButton(org.fossify.commons.R.string.ok, null) .setNegativeButton(org.fossify.commons.R.string.cancel, null) .apply { - activity.setupDialogStuff(view.root, this, R.string.export_alarms) { alertDialog -> - alertDialog.showKeyboard(view.exportAlarmsFilename) + activity.setupDialogStuff(view.root, this, R.string.settings_export_data) { alertDialog -> + alertDialog.showKeyboard(view.exportDataFilename) alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener { - val filename = view.exportAlarmsFilename.value + val filename = view.exportDataFilename.value when { filename.isEmpty() -> activity.toast(org.fossify.commons.R.string.empty_name) filename.isAValidFilename() -> { - val file = File(realPath, "$filename$ALARMS_EXPORT_EXTENSION") + val file = File(realPath, "$filename$DATA_EXPORT_EXTENSION") if (!hidePath && file.exists()) { activity.toast(org.fossify.commons.R.string.name_taken) return@setOnClickListener } ensureBackgroundThread { - config.lastAlarmsExportPath = file.absolutePath.getParentPath() + config.lastDataExportPath = file.absolutePath.getParentPath() callback(file) alertDialog.dismiss() } diff --git a/app/src/main/kotlin/org/fossify/clock/helpers/Config.kt b/app/src/main/kotlin/org/fossify/clock/helpers/Config.kt index 94d7a75c..f069d578 100644 --- a/app/src/main/kotlin/org/fossify/clock/helpers/Config.kt +++ b/app/src/main/kotlin/org/fossify/clock/helpers/Config.kt @@ -105,7 +105,7 @@ class Config(context: Context) : BaseConfig(context) { get() = prefs.getBoolean(WAS_INITIAL_WIDGET_SET_UP, false) set(wasInitialWidgetSetUp) = prefs.edit().putBoolean(WAS_INITIAL_WIDGET_SET_UP, wasInitialWidgetSetUp).apply() - var lastAlarmsExportPath: String - get() = prefs.getString(LAST_ALARMS_EXPORT_PATH, "")!! - set(lastBlockedNumbersExportPath) = prefs.edit().putString(LAST_ALARMS_EXPORT_PATH, lastBlockedNumbersExportPath).apply() + var lastDataExportPath: String + get() = prefs.getString(LAST_DATA_EXPORT_PATH, "")!! + set(lastDataExportPath) = prefs.edit().putString(LAST_DATA_EXPORT_PATH, lastDataExportPath).apply() } diff --git a/app/src/main/kotlin/org/fossify/clock/helpers/Constants.kt b/app/src/main/kotlin/org/fossify/clock/helpers/Constants.kt index 214926cc..9bf9748e 100644 --- a/app/src/main/kotlin/org/fossify/clock/helpers/Constants.kt +++ b/app/src/main/kotlin/org/fossify/clock/helpers/Constants.kt @@ -26,8 +26,8 @@ const val INCREASE_VOLUME_GRADUALLY = "increase_volume_gradually" const val ALARMS_SORT_BY = "alarms_sort_by" const val STOPWATCH_LAPS_SORT_BY = "stopwatch_laps_sort_by" const val WAS_INITIAL_WIDGET_SET_UP = "was_initial_widget_set_up" -const val ALARMS_EXPORT_EXTENSION = ".json" -const val LAST_ALARMS_EXPORT_PATH = "last_alarms_export_path" +const val DATA_EXPORT_EXTENSION = ".json" +const val LAST_DATA_EXPORT_PATH = "last_alarms_export_path" const val TABS_COUNT = 4 const val EDITED_TIME_ZONE_SEPARATOR = ":" diff --git a/app/src/main/kotlin/org/fossify/clock/helpers/AlarmsExporter.kt b/app/src/main/kotlin/org/fossify/clock/helpers/DataExporter.kt similarity index 61% rename from app/src/main/kotlin/org/fossify/clock/helpers/AlarmsExporter.kt rename to app/src/main/kotlin/org/fossify/clock/helpers/DataExporter.kt index 28e4896e..fdca4fdc 100644 --- a/app/src/main/kotlin/org/fossify/clock/helpers/AlarmsExporter.kt +++ b/app/src/main/kotlin/org/fossify/clock/helpers/DataExporter.kt @@ -1,12 +1,15 @@ package org.fossify.clock.helpers import org.fossify.clock.models.Alarm +import org.fossify.clock.models.Timer import org.fossify.commons.helpers.ExportResult import java.io.OutputStream -object AlarmsExporter { - fun exportAlarms( +object DataExporter { + + fun exportData( alarms: ArrayList, + timers: List, outputStream: OutputStream?, callback: (result: ExportResult) -> Unit, ) { @@ -16,10 +19,13 @@ object AlarmsExporter { } val alarmsToExport = alarmsToJSON(alarms) + val timersToExport = timersToJSON(timers) + + val dataToExport = "{\"alarms\": $alarmsToExport, \"timers\": $timersToExport" try { outputStream.bufferedWriter().use { out -> - out.write(alarmsToExport) + out.write(dataToExport) } callback.invoke(ExportResult.EXPORT_OK) } catch (e: Exception) { @@ -27,6 +33,7 @@ object AlarmsExporter { } } + // Replace with a generic later private fun alarmsToJSON(alarms: List?): String { if (alarms.isNullOrEmpty()) { return "[]" @@ -40,4 +47,16 @@ object AlarmsExporter { return "[${jsonAlarms.joinToString(",")}]" } + private fun timersToJSON(timers: List?): String { + if (timers.isNullOrEmpty()) { + return "[]" + } + + val jsonTimers = mutableListOf() + for (timer in timers) { + jsonTimers.add(timer.toJSON()) + } + + return "[${jsonTimers.joinToString(",")}]" + } } diff --git a/app/src/main/kotlin/org/fossify/clock/helpers/AlarmsImporter.kt b/app/src/main/kotlin/org/fossify/clock/helpers/DataImporter.kt similarity index 96% rename from app/src/main/kotlin/org/fossify/clock/helpers/AlarmsImporter.kt rename to app/src/main/kotlin/org/fossify/clock/helpers/DataImporter.kt index 7c97f8fd..e7262eb1 100644 --- a/app/src/main/kotlin/org/fossify/clock/helpers/AlarmsImporter.kt +++ b/app/src/main/kotlin/org/fossify/clock/helpers/DataImporter.kt @@ -8,7 +8,7 @@ import org.json.JSONObject import java.io.File -class AlarmsImporter( +class DataImporter( private val activity: Activity, private val dbHelper: DBHelper, ) { @@ -16,7 +16,7 @@ class AlarmsImporter( IMPORT_FAIL, IMPORT_OK } - fun importAlarms(path: String): ImportResult { + fun importData(path: String): ImportResult { return try { val inputStream = File(path).inputStream() val jsonString = inputStream.bufferedReader().use { it.readText().trimEnd() } diff --git a/app/src/main/kotlin/org/fossify/clock/models/Timer.kt b/app/src/main/kotlin/org/fossify/clock/models/Timer.kt index f20dbe18..3f237049 100644 --- a/app/src/main/kotlin/org/fossify/clock/models/Timer.kt +++ b/app/src/main/kotlin/org/fossify/clock/models/Timer.kt @@ -3,6 +3,7 @@ package org.fossify.clock.models import androidx.annotation.Keep import androidx.room.Entity import androidx.room.PrimaryKey +import org.json.JSONObject @Entity(tableName = "timers") @Keep @@ -17,7 +18,22 @@ data class Timer( var createdAt: Long, var channelId: String? = null, var oneShot: Boolean = false, -) +) { + @Keep + fun toJSON(): String { + val jsonObject = JSONObject() + jsonObject.put("id", id) + jsonObject.put("state", state) + jsonObject.put("vibrate", vibrate) + jsonObject.put("soundUri", soundUri) + jsonObject.put("soundTitle", soundTitle) + jsonObject.put("label", label) + jsonObject.put("createdAt", createdAt) + jsonObject.put("channelId", channelId) + jsonObject.put("oneShot", oneShot) + return jsonObject.toString() + } +} @Keep data class ObfuscatedTimer( diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index 159fb86b..dba596ab 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -283,6 +283,63 @@ tools:text="1 minute" /> + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/dialog_export_alarms.xml b/app/src/main/res/layout/dialog_export_data.xml similarity index 88% rename from app/src/main/res/layout/dialog_export_alarms.xml rename to app/src/main/res/layout/dialog_export_data.xml index dac0d742..f85c98c0 100644 --- a/app/src/main/res/layout/dialog_export_alarms.xml +++ b/app/src/main/res/layout/dialog_export_data.xml @@ -5,7 +5,7 @@ android:layout_height="match_parent"> - - Add timer Upcoming alarm Early alarm dismissal - Import alarms - Export alarms + Timers are running Timer for %s is running @@ -51,6 +50,12 @@ Timer tab Show seconds Increase volume gradually + Export and import + Import data + Import app data (Alarms and Timers) + Export data + Export app data (Alarms and Timers) + Exporting aborted by user How can I change lap sorting at the stopwatch tab?