[DO NOT USE] Introduce LauncherPreference
This commit is contained in:
1 parent
3d16151bd2
commit
bb77c4ecfc
2 files changed
+79
-64
No files matched your search
@@ -6,7 +6,6 @@ import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS
|
||||
import android.provider.Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
@@ -41,12 +40,10 @@ import com.hippo.ehviewer.client.EhEngine
|
||||
import com.hippo.ehviewer.client.data.FavListUrlBuilder
|
||||
import com.hippo.ehviewer.client.systemDns
|
||||
import com.hippo.ehviewer.ui.compose.observed
|
||||
import com.hippo.ehviewer.ui.legacy.BaseDialogBuilder
|
||||
import com.hippo.ehviewer.ui.legacy.EditTextDialogBuilder
|
||||
import com.hippo.ehviewer.ui.login.LocalNavController
|
||||
import com.hippo.ehviewer.util.LogCat
|
||||
import com.hippo.ehviewer.util.ReadableTime
|
||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -92,39 +89,38 @@ fun AdvancedScreen() {
|
||||
value = Settings::saveCrashLog,
|
||||
)
|
||||
val dumpLogError = stringResource(id = R.string.settings_advanced_dump_logcat_failed)
|
||||
val dumpLogcatLauncher = rememberLauncherForActivityResult(ActivityResultContracts.CreateDocument("application/zip")) { uri ->
|
||||
LauncherPreference(
|
||||
title = stringResource(id = R.string.settings_advanced_dump_logcat),
|
||||
summary = stringResource(id = R.string.settings_advanced_dump_logcat_summary),
|
||||
contract = ActivityResultContracts.CreateDocument("application/zip"),
|
||||
key = "log-" + ReadableTime.getFilenamableTime(System.currentTimeMillis()) + ".zip",
|
||||
) { uri ->
|
||||
uri?.run {
|
||||
coroutineScope.launch {
|
||||
context.runCatching {
|
||||
grantUriPermission(BuildConfig.APPLICATION_ID, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||
contentResolver.openOutputStream(uri)?.use { outputStream ->
|
||||
val files = ArrayList<File>()
|
||||
AppConfig.externalParseErrorDir?.listFiles()?.let { files.addAll(it) }
|
||||
AppConfig.externalCrashDir?.listFiles()?.let { files.addAll(it) }
|
||||
ZipOutputStream(outputStream).use { zipOs ->
|
||||
files.forEach { file ->
|
||||
if (!file.isFile) return@forEach
|
||||
val entry = ZipEntry(file.name)
|
||||
zipOs.putNextEntry(entry)
|
||||
file.inputStream().use { it.copyTo(zipOs) }
|
||||
}
|
||||
val logcatEntry = ZipEntry("logcat-" + ReadableTime.getFilenamableTime(System.currentTimeMillis()) + ".txt")
|
||||
zipOs.putNextEntry(logcatEntry)
|
||||
LogCat.save(zipOs)
|
||||
context.runCatching {
|
||||
grantUriPermission(BuildConfig.APPLICATION_ID, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||
contentResolver.openOutputStream(uri)?.use { outputStream ->
|
||||
val files = ArrayList<File>()
|
||||
AppConfig.externalParseErrorDir?.listFiles()?.let { files.addAll(it) }
|
||||
AppConfig.externalCrashDir?.listFiles()?.let { files.addAll(it) }
|
||||
ZipOutputStream(outputStream).use { zipOs ->
|
||||
files.forEach { file ->
|
||||
if (!file.isFile) return@forEach
|
||||
val entry = ZipEntry(file.name)
|
||||
zipOs.putNextEntry(entry)
|
||||
file.inputStream().use { it.copyTo(zipOs) }
|
||||
}
|
||||
launchSnackBar(getString(R.string.settings_advanced_dump_logcat_to, uri.toString()))
|
||||
val logcatEntry = ZipEntry("logcat-" + ReadableTime.getFilenamableTime(System.currentTimeMillis()) + ".txt")
|
||||
zipOs.putNextEntry(logcatEntry)
|
||||
LogCat.save(zipOs)
|
||||
}
|
||||
}.onFailure {
|
||||
launchSnackBar(dumpLogError)
|
||||
it.printStackTrace()
|
||||
launchSnackBar(getString(R.string.settings_advanced_dump_logcat_to, uri.toString()))
|
||||
}
|
||||
}.onFailure {
|
||||
launchSnackBar(dumpLogError)
|
||||
it.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
Preference(
|
||||
title = stringResource(id = R.string.settings_advanced_dump_logcat),
|
||||
summary = stringResource(id = R.string.settings_advanced_dump_logcat_summary),
|
||||
) { dumpLogcatLauncher.launch("log-" + ReadableTime.getFilenamableTime(System.currentTimeMillis()) + ".zip") }
|
||||
SimpleMenuPreferenceInt(
|
||||
title = stringResource(id = R.string.settings_advanced_read_cache_size),
|
||||
entry = R.array.read_cache_size_entries,
|
||||
@@ -173,49 +169,42 @@ fun AdvancedScreen() {
|
||||
value = Settings::preloadThumbAggressively,
|
||||
)
|
||||
val exportFailed = stringResource(id = R.string.settings_advanced_export_data_failed)
|
||||
val exportLauncher = rememberLauncherForActivityResult(ActivityResultContracts.CreateDocument("application/vnd.sqlite3")) { uri ->
|
||||
uri?.let {
|
||||
coroutineScope.launch {
|
||||
val alertDialog = withUIContext { BaseDialogBuilder(context).setCancelable(false).setView(R.layout.preference_dialog_task).show() }
|
||||
context.runCatching {
|
||||
grantUriPermission(BuildConfig.APPLICATION_ID, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||
EhDB.exportDB(context, uri)
|
||||
launchSnackBar(getString(R.string.settings_advanced_export_data_to, uri.toString()))
|
||||
}.onFailure {
|
||||
it.printStackTrace()
|
||||
launchSnackBar(exportFailed)
|
||||
}
|
||||
if (alertDialog.isShowing) alertDialog.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
Preference(
|
||||
LauncherPreference(
|
||||
title = stringResource(id = R.string.settings_advanced_export_data),
|
||||
summary = stringResource(id = R.string.settings_advanced_export_data_summary),
|
||||
) { exportLauncher.launch(ReadableTime.getFilenamableTime(System.currentTimeMillis()) + ".db") }
|
||||
|
||||
val importFailed = stringResource(id = R.string.cant_read_the_file)
|
||||
val importSucceed = stringResource(id = R.string.settings_advanced_import_data_successfully)
|
||||
val importLauncher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri ->
|
||||
contract = ActivityResultContracts.CreateDocument("application/vnd.sqlite3"),
|
||||
key = ReadableTime.getFilenamableTime(System.currentTimeMillis()) + ".db",
|
||||
) { uri ->
|
||||
uri?.let {
|
||||
coroutineScope.launch {
|
||||
val alertDialog = withUIContext { BaseDialogBuilder(context).setCancelable(false).setView(R.layout.preference_dialog_task).show() }
|
||||
context.runCatching {
|
||||
grantUriPermission(BuildConfig.APPLICATION_ID, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
EhDB.importDB(context, uri)
|
||||
launchSnackBar(importSucceed)
|
||||
}.onFailure {
|
||||
it.printStackTrace()
|
||||
launchSnackBar(importFailed)
|
||||
}
|
||||
if (alertDialog.isShowing) alertDialog.dismiss()
|
||||
context.runCatching {
|
||||
grantUriPermission(BuildConfig.APPLICATION_ID, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||
EhDB.exportDB(context, uri)
|
||||
launchSnackBar(getString(R.string.settings_advanced_export_data_to, uri.toString()))
|
||||
}.onFailure {
|
||||
it.printStackTrace()
|
||||
launchSnackBar(exportFailed)
|
||||
}
|
||||
}
|
||||
}
|
||||
Preference(
|
||||
val importFailed = stringResource(id = R.string.cant_read_the_file)
|
||||
val importSucceed = stringResource(id = R.string.settings_advanced_import_data_successfully)
|
||||
LauncherPreference(
|
||||
title = stringResource(id = R.string.settings_advanced_import_data),
|
||||
summary = stringResource(id = R.string.settings_advanced_import_data_summary),
|
||||
) { importLauncher.launch("application/octet-stream") }
|
||||
contract = ActivityResultContracts.GetContent(),
|
||||
key = "application/octet-stream",
|
||||
) { uri ->
|
||||
uri?.let {
|
||||
context.runCatching {
|
||||
grantUriPermission(BuildConfig.APPLICATION_ID, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
EhDB.importDB(context, uri)
|
||||
launchSnackBar(importSucceed)
|
||||
}.onFailure {
|
||||
it.printStackTrace()
|
||||
launchSnackBar(importFailed)
|
||||
}
|
||||
}
|
||||
}
|
||||
val backupNothing = stringResource(id = R.string.settings_advanced_backup_favorite_nothing)
|
||||
val backupFailed = stringResource(id = R.string.settings_advanced_backup_favorite_failed)
|
||||
val backupSucceed = stringResource(id = R.string.settings_advanced_backup_favorite_success)
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package com.hippo.ehviewer.ui.settings
|
||||
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContract
|
||||
import androidx.annotation.ArrayRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
@@ -30,6 +33,7 @@ import androidx.compose.ui.res.stringArrayResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.unit.dp
|
||||
import arrow.atomic.Atomic
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.ui.legacy.BaseDialogBuilder
|
||||
import com.hippo.ehviewer.ui.login.LocalNavController
|
||||
@@ -40,9 +44,12 @@ import com.jamal.composeprefs3.ui.prefs.SliderPref
|
||||
import com.jamal.composeprefs3.ui.prefs.SpannedTextPref
|
||||
import com.jamal.composeprefs3.ui.prefs.SwitchPref
|
||||
import com.jamal.composeprefs3.ui.prefs.TextPref
|
||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.reflect.KMutableProperty0
|
||||
|
||||
@@ -137,3 +144,22 @@ fun WorkPreference(title: String, summary: String? = null, work: suspend Corouti
|
||||
coroutineScope.launch(block = work).invokeOnCompletion { if (alertDialog.isShowing) alertDialog.dismiss() }
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun <I, O> LauncherPreference(title: String, summary: String? = null, contract: ActivityResultContract<I, O>, key: I, work: suspend CoroutineScope.(O) -> Unit) {
|
||||
val coroutineScope = rememberCoroutineScope { Dispatchers.IO }
|
||||
val context = LocalContext.current
|
||||
val callback = remember { Atomic<(O) -> Unit> {} }
|
||||
val launcher = rememberLauncherForActivityResult(contract = contract) { callback.getAndSet { }.invoke(it) }
|
||||
Preference(title = title, summary = summary) {
|
||||
var alertDialog: AlertDialog? = null
|
||||
coroutineScope.launch {
|
||||
val o = suspendCoroutine { cont ->
|
||||
callback.set { cont.resume(it) }
|
||||
launcher.launch(key)
|
||||
}
|
||||
alertDialog = withUIContext { BaseDialogBuilder(context).setCancelable(false).setView(R.layout.preference_dialog_task).show() }
|
||||
work(o)
|
||||
}.invokeOnCompletion { alertDialog?.dismiss() }
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user