mirror of
https://github.com/FossifyOrg/Clock.git
synced 2026-06-15 09:50:49 -04:00
moved to registerForActivityResult and added timers to exports
This commit is contained in:
@@ -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
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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 = ":"
|
||||
|
||||
@@ -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<Alarm>,
|
||||
timers: List<Timer>,
|
||||
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<Alarm>?): String {
|
||||
if (alarms.isNullOrEmpty()) {
|
||||
return "[]"
|
||||
@@ -40,4 +47,16 @@ object AlarmsExporter {
|
||||
return "[${jsonAlarms.joinToString(",")}]"
|
||||
}
|
||||
|
||||
private fun timersToJSON(timers: List<Timer>?): String {
|
||||
if (timers.isNullOrEmpty()) {
|
||||
return "[]"
|
||||
}
|
||||
|
||||
val jsonTimers = mutableListOf<String>()
|
||||
for (timer in timers) {
|
||||
jsonTimers.add(timer.toJSON())
|
||||
}
|
||||
|
||||
return "[${jsonTimers.joinToString(",")}]"
|
||||
}
|
||||
}
|
||||
@@ -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() }
|
||||
@@ -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(
|
||||
|
||||
@@ -283,6 +283,63 @@
|
||||
tools:text="1 minute" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<include
|
||||
android:id="@+id/settings_timer_tab_divider"
|
||||
layout="@layout/divider"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/settings_export_and_import"
|
||||
style="@style/SettingsSectionLabelStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/settings_export_and_import" />
|
||||
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_export_data_holder"
|
||||
style="@style/SettingsHolderTextViewStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<org.fossify.commons.views.MyTextView
|
||||
android:id="@+id/settings_export_data_label"
|
||||
style="@style/SettingsTextLabelStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/settings_export_data" />
|
||||
|
||||
<org.fossify.commons.views.MyTextView
|
||||
android:id="@+id/settings_export_data"
|
||||
style="@style/SettingsTextValueStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/settings_export_data_label"
|
||||
tools:text="@+string/settings_export_data_subtitle" />
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/settings_import_data_holder"
|
||||
style="@style/SettingsHolderTextViewStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<org.fossify.commons.views.MyTextView
|
||||
android:id="@+id/settings_import_data_label"
|
||||
style="@style/SettingsTextLabelStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/settings_import_data" />
|
||||
|
||||
<org.fossify.commons.views.MyTextView
|
||||
android:id="@+id/settings_import_data"
|
||||
style="@style/SettingsTextValueStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/settings_import_data_label"
|
||||
tools:text="@+string/settings_import_data_subtitle" />
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/export_alarms_holder"
|
||||
android:id="@+id/export_data_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
@@ -14,7 +14,7 @@
|
||||
android:paddingRight="@dimen/activity_margin">
|
||||
|
||||
<org.fossify.commons.views.MyTextView
|
||||
android:id="@+id/export_alarms_folder_label"
|
||||
android:id="@+id/export_data_folder_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/small_margin"
|
||||
@@ -22,7 +22,7 @@
|
||||
android:textSize="@dimen/smaller_text_size" />
|
||||
|
||||
<org.fossify.commons.views.MyTextView
|
||||
android:id="@+id/export_alarms_folder"
|
||||
android:id="@+id/export_data_folder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/small_margin"
|
||||
@@ -32,13 +32,13 @@
|
||||
android:paddingBottom="@dimen/activity_margin" />
|
||||
|
||||
<org.fossify.commons.views.MyTextInputLayout
|
||||
android:id="@+id/export_alarms_hint"
|
||||
android:id="@+id/export_data_hint"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/filename_without_json">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/export_alarms_filename"
|
||||
android:id="@+id/export_data_filename"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/activity_margin"
|
||||
@@ -11,14 +11,6 @@
|
||||
android:icon="@drawable/ic_settings_cog_vector"
|
||||
android:title="@string/settings"
|
||||
app:showAsAction="ifRoom" />
|
||||
<item
|
||||
android:id="@+id/export_alarms"
|
||||
android:title="@string/export_alarms"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/import_alarms"
|
||||
android:title="@string/import_alarms"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/about"
|
||||
android:icon="@drawable/ic_info_vector"
|
||||
|
||||
@@ -32,8 +32,7 @@
|
||||
<string name="add_timer">Add timer</string>
|
||||
<string name="upcoming_alarm">Upcoming alarm</string>
|
||||
<string name="early_alarm_dismissal">Early alarm dismissal</string>
|
||||
<string name="import_alarms">Import alarms</string>
|
||||
<string name="export_alarms">Export alarms</string>
|
||||
|
||||
<!-- Timer -->
|
||||
<string name="timers_notification_msg">Timers are running</string>
|
||||
<string name="timer_single_notification_label_msg">Timer for %s is running</string>
|
||||
@@ -51,6 +50,12 @@
|
||||
<string name="timer_tab">Timer tab</string>
|
||||
<string name="show_seconds">Show seconds</string>
|
||||
<string name="increase_volume_gradually">Increase volume gradually</string>
|
||||
<string name="settings_export_and_import">Export and import</string>
|
||||
<string name="settings_import_data">Import data</string>
|
||||
<string name="settings_import_data_subtitle">Import app data (Alarms and Timers)</string>
|
||||
<string name="settings_export_data">Export data</string>
|
||||
<string name="settings_export_data_subtitle">Export app data (Alarms and Timers)</string>
|
||||
<string name="exporting_aborted_by_user">Exporting aborted by user</string>
|
||||
|
||||
<!-- FAQ -->
|
||||
<string name="faq_1_title">How can I change lap sorting at the stopwatch tab?</string>
|
||||
|
||||
Reference in New Issue
Block a user