mirror of
https://github.com/mihonapp/mihon.git
synced 2024-11-15 15:02:49 +01:00
merge backup and sync screens
This commit is contained in:
parent
6d9f74d0bf
commit
a1e9d34bb8
@ -17,7 +17,6 @@ import androidx.compose.material.icons.outlined.Label
|
|||||||
import androidx.compose.material.icons.outlined.QueryStats
|
import androidx.compose.material.icons.outlined.QueryStats
|
||||||
import androidx.compose.material.icons.outlined.Settings
|
import androidx.compose.material.icons.outlined.Settings
|
||||||
import androidx.compose.material.icons.outlined.SettingsBackupRestore
|
import androidx.compose.material.icons.outlined.SettingsBackupRestore
|
||||||
import androidx.compose.material.icons.outlined.Sync
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
@ -47,7 +46,6 @@ fun MoreScreen(
|
|||||||
onClickCategories: () -> Unit,
|
onClickCategories: () -> Unit,
|
||||||
onClickStats: () -> Unit,
|
onClickStats: () -> Unit,
|
||||||
onClickBackupAndRestore: () -> Unit,
|
onClickBackupAndRestore: () -> Unit,
|
||||||
onClickSync: () -> Unit,
|
|
||||||
onClickSettings: () -> Unit,
|
onClickSettings: () -> Unit,
|
||||||
onClickAbout: () -> Unit,
|
onClickAbout: () -> Unit,
|
||||||
) {
|
) {
|
||||||
@ -143,18 +141,11 @@ fun MoreScreen(
|
|||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
TextPreferenceWidget(
|
TextPreferenceWidget(
|
||||||
title = stringResource(R.string.label_backup),
|
title = stringResource(R.string.label_backup_and_sync),
|
||||||
icon = Icons.Outlined.SettingsBackupRestore,
|
icon = Icons.Outlined.SettingsBackupRestore,
|
||||||
onPreferenceClick = onClickBackupAndRestore,
|
onPreferenceClick = onClickBackupAndRestore,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
|
||||||
TextPreferenceWidget(
|
|
||||||
title = stringResource(R.string.label_sync),
|
|
||||||
icon = Icons.Outlined.Sync,
|
|
||||||
onPreferenceClick = onClickSync,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
item { Divider() }
|
item { Divider() }
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import android.content.ActivityNotFoundException
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.text.format.DateUtils
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
@ -49,12 +50,15 @@ import eu.kanade.tachiyomi.data.backup.BackupCreateJob
|
|||||||
import eu.kanade.tachiyomi.data.backup.BackupFileValidator
|
import eu.kanade.tachiyomi.data.backup.BackupFileValidator
|
||||||
import eu.kanade.tachiyomi.data.backup.BackupRestoreJob
|
import eu.kanade.tachiyomi.data.backup.BackupRestoreJob
|
||||||
import eu.kanade.tachiyomi.data.backup.models.Backup
|
import eu.kanade.tachiyomi.data.backup.models.Backup
|
||||||
|
import eu.kanade.tachiyomi.data.sync.SyncDataJob
|
||||||
|
import eu.kanade.tachiyomi.data.sync.SyncManager
|
||||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||||
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
||||||
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
import eu.kanade.tachiyomi.util.system.copyToClipboard
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import tachiyomi.domain.backup.service.BackupPreferences
|
import tachiyomi.domain.backup.service.BackupPreferences
|
||||||
|
import tachiyomi.domain.sync.SyncPreferences
|
||||||
import tachiyomi.presentation.core.components.ScrollbarLazyColumn
|
import tachiyomi.presentation.core.components.ScrollbarLazyColumn
|
||||||
import tachiyomi.presentation.core.components.material.Divider
|
import tachiyomi.presentation.core.components.material.Divider
|
||||||
import tachiyomi.presentation.core.util.isScrolledToEnd
|
import tachiyomi.presentation.core.util.isScrolledToEnd
|
||||||
@ -74,11 +78,107 @@ object SettingsBackupScreen : SearchableSettings {
|
|||||||
val backupPreferences = Injekt.get<BackupPreferences>()
|
val backupPreferences = Injekt.get<BackupPreferences>()
|
||||||
|
|
||||||
DiskUtil.RequestStoragePermission()
|
DiskUtil.RequestStoragePermission()
|
||||||
|
val syncPreferences = remember { Injekt.get<SyncPreferences>() }
|
||||||
|
val syncService by syncPreferences.syncService().collectAsState()
|
||||||
|
|
||||||
return listOf(
|
return listOf(
|
||||||
getCreateBackupPref(),
|
getManualBackupGroup(),
|
||||||
getRestoreBackupPref(),
|
|
||||||
getAutomaticBackupGroup(backupPreferences = backupPreferences),
|
getAutomaticBackupGroup(backupPreferences = backupPreferences),
|
||||||
|
) + listOf(
|
||||||
|
Preference.PreferenceGroup(
|
||||||
|
title = stringResource(R.string.pref_backup_manual_category),
|
||||||
|
preferenceItems = listOf(
|
||||||
|
Preference.PreferenceItem.ListPreference(
|
||||||
|
pref = syncPreferences.syncService(),
|
||||||
|
title = stringResource(R.string.pref_sync_service),
|
||||||
|
entries = mapOf(
|
||||||
|
SyncManager.SyncService.NONE.value to stringResource(R.string.off),
|
||||||
|
SyncManager.SyncService.SYNCYOMI.value to stringResource(R.string.syncyomi),
|
||||||
|
),
|
||||||
|
onValueChanged = { true },
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
) + getSyncServicePreferences(syncPreferences, syncService)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun getManualBackupGroup(): Preference.PreferenceGroup {
|
||||||
|
return Preference.PreferenceGroup(
|
||||||
|
title = stringResource(R.string.pref_backup_manual_category),
|
||||||
|
preferenceItems = listOf(
|
||||||
|
getCreateBackupPref(),
|
||||||
|
getRestoreBackupPref(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun getAutomaticBackupGroup(
|
||||||
|
backupPreferences: BackupPreferences,
|
||||||
|
): Preference.PreferenceGroup {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val backupIntervalPref = backupPreferences.backupInterval()
|
||||||
|
val backupInterval by backupIntervalPref.collectAsState()
|
||||||
|
val backupDirPref = backupPreferences.backupsDirectory()
|
||||||
|
val backupDir by backupDirPref.collectAsState()
|
||||||
|
val pickBackupLocation = rememberLauncherForActivityResult(
|
||||||
|
contract = ActivityResultContracts.OpenDocumentTree(),
|
||||||
|
) { uri ->
|
||||||
|
if (uri != null) {
|
||||||
|
val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
|
||||||
|
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
|
|
||||||
|
context.contentResolver.takePersistableUriPermission(uri, flags)
|
||||||
|
|
||||||
|
val file = UniFile.fromUri(context, uri)
|
||||||
|
backupDirPref.set(file.uri.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Preference.PreferenceGroup(
|
||||||
|
title = stringResource(R.string.pref_backup_service_category),
|
||||||
|
preferenceItems = listOf(
|
||||||
|
Preference.PreferenceItem.ListPreference(
|
||||||
|
pref = backupIntervalPref,
|
||||||
|
title = stringResource(R.string.pref_backup_interval),
|
||||||
|
entries = mapOf(
|
||||||
|
0 to stringResource(R.string.off),
|
||||||
|
6 to stringResource(R.string.update_6hour),
|
||||||
|
12 to stringResource(R.string.update_12hour),
|
||||||
|
24 to stringResource(R.string.update_24hour),
|
||||||
|
48 to stringResource(R.string.update_48hour),
|
||||||
|
168 to stringResource(R.string.update_weekly),
|
||||||
|
),
|
||||||
|
onValueChanged = {
|
||||||
|
BackupCreateJob.setupTask(context, it)
|
||||||
|
true
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Preference.PreferenceItem.TextPreference(
|
||||||
|
title = stringResource(R.string.pref_backup_directory),
|
||||||
|
enabled = backupInterval != 0,
|
||||||
|
subtitle = remember(backupDir) {
|
||||||
|
(UniFile.fromUri(context, backupDir.toUri())?.filePath)?.let {
|
||||||
|
"$it/automatic"
|
||||||
|
}
|
||||||
|
} ?: stringResource(R.string.invalid_location, backupDir),
|
||||||
|
onClick = {
|
||||||
|
try {
|
||||||
|
pickBackupLocation.launch(null)
|
||||||
|
} catch (e: ActivityNotFoundException) {
|
||||||
|
context.toast(R.string.file_picker_error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Preference.PreferenceItem.ListPreference(
|
||||||
|
pref = backupPreferences.numberOfBackups(),
|
||||||
|
enabled = backupInterval != 0,
|
||||||
|
title = stringResource(R.string.pref_backup_slots),
|
||||||
|
entries = listOf(2, 3, 4, 5).associateWith { it.toString() },
|
||||||
|
),
|
||||||
|
Preference.PreferenceItem.InfoPreference(stringResource(R.string.backup_info)),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,73 +443,129 @@ object SettingsBackupScreen : SearchableSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun getAutomaticBackupGroup(
|
private fun getSyncServicePreferences(syncPreferences: SyncPreferences, syncService: Int): List<Preference> {
|
||||||
backupPreferences: BackupPreferences,
|
val syncServiceType = SyncManager.SyncService.fromInt(syncService)
|
||||||
): Preference.PreferenceGroup {
|
return when (syncServiceType) {
|
||||||
val context = LocalContext.current
|
SyncManager.SyncService.NONE -> emptyList()
|
||||||
val backupIntervalPref = backupPreferences.backupInterval()
|
SyncManager.SyncService.SYNCYOMI -> getSelfHostPreferences(syncPreferences)
|
||||||
val backupInterval by backupIntervalPref.collectAsState()
|
} +
|
||||||
val backupDirPref = backupPreferences.backupsDirectory()
|
if (syncServiceType == SyncManager.SyncService.NONE) {
|
||||||
val backupDir by backupDirPref.collectAsState()
|
emptyList()
|
||||||
val pickBackupLocation = rememberLauncherForActivityResult(
|
} else {
|
||||||
contract = ActivityResultContracts.OpenDocumentTree(),
|
listOf(getSyncNowPref(), getAutomaticSyncGroup(syncPreferences))
|
||||||
) { uri ->
|
|
||||||
if (uri != null) {
|
|
||||||
val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
|
|
||||||
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
|
||||||
|
|
||||||
context.contentResolver.takePersistableUriPermission(uri, flags)
|
|
||||||
|
|
||||||
val file = UniFile.fromUri(context, uri)
|
|
||||||
backupDirPref.set(file.uri.toString())
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun getSelfHostPreferences(syncPreferences: SyncPreferences): List<Preference> {
|
||||||
|
return listOf(
|
||||||
|
Preference.PreferenceItem.EditTextPreference(
|
||||||
|
title = stringResource(R.string.pref_sync_device_name),
|
||||||
|
subtitle = stringResource(R.string.pref_sync_device_name_summ),
|
||||||
|
pref = syncPreferences.deviceName(),
|
||||||
|
),
|
||||||
|
Preference.PreferenceItem.EditTextPreference(
|
||||||
|
title = stringResource(R.string.pref_sync_host),
|
||||||
|
subtitle = stringResource(R.string.pref_sync_host_summ),
|
||||||
|
pref = syncPreferences.syncHost(),
|
||||||
|
),
|
||||||
|
Preference.PreferenceItem.EditTextPreference(
|
||||||
|
title = stringResource(R.string.pref_sync_api_key),
|
||||||
|
subtitle = stringResource(R.string.pref_sync_api_key_summ),
|
||||||
|
pref = syncPreferences.syncAPIKey(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun getSyncNowPref(): Preference.PreferenceGroup {
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
var showDialog by remember { mutableStateOf(false) }
|
||||||
|
val context = LocalContext.current
|
||||||
|
if (showDialog) {
|
||||||
|
SyncConfirmationDialog(
|
||||||
|
onConfirm = {
|
||||||
|
showDialog = false
|
||||||
|
scope.launch {
|
||||||
|
if (!SyncDataJob.isAnyJobRunning(context)) {
|
||||||
|
SyncDataJob.startNow(context)
|
||||||
|
} else {
|
||||||
|
context.toast(R.string.sync_in_progress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onDismissRequest = { showDialog = false },
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
return Preference.PreferenceGroup(
|
||||||
|
title = stringResource(R.string.pref_sync_now_group_title),
|
||||||
|
preferenceItems = listOf(
|
||||||
|
Preference.PreferenceItem.TextPreference(
|
||||||
|
title = stringResource(R.string.pref_sync_now),
|
||||||
|
subtitle = stringResource(R.string.pref_sync_now_subtitle),
|
||||||
|
onClick = {
|
||||||
|
showDialog = true
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun getAutomaticSyncGroup(syncPreferences: SyncPreferences): Preference.PreferenceGroup {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val syncIntervalPref = syncPreferences.syncInterval()
|
||||||
|
val lastSync by syncPreferences.syncLastSync().collectAsState()
|
||||||
|
val formattedLastSync = DateUtils.getRelativeTimeSpanString(lastSync.toEpochMilli(), System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS)
|
||||||
|
|
||||||
return Preference.PreferenceGroup(
|
return Preference.PreferenceGroup(
|
||||||
title = stringResource(R.string.pref_backup_service_category),
|
title = stringResource(R.string.pref_sync_service_category),
|
||||||
preferenceItems = listOf(
|
preferenceItems = listOf(
|
||||||
Preference.PreferenceItem.ListPreference(
|
Preference.PreferenceItem.ListPreference(
|
||||||
pref = backupIntervalPref,
|
pref = syncIntervalPref,
|
||||||
title = stringResource(R.string.pref_backup_interval),
|
title = stringResource(R.string.pref_sync_interval),
|
||||||
entries = mapOf(
|
entries = mapOf(
|
||||||
0 to stringResource(R.string.off),
|
0 to stringResource(R.string.off),
|
||||||
6 to stringResource(R.string.update_6hour),
|
30 to stringResource(R.string.update_30min),
|
||||||
12 to stringResource(R.string.update_12hour),
|
60 to stringResource(R.string.update_1hour),
|
||||||
24 to stringResource(R.string.update_24hour),
|
180 to stringResource(R.string.update_3hour),
|
||||||
48 to stringResource(R.string.update_48hour),
|
360 to stringResource(R.string.update_6hour),
|
||||||
168 to stringResource(R.string.update_weekly),
|
720 to stringResource(R.string.update_12hour),
|
||||||
|
1440 to stringResource(R.string.update_24hour),
|
||||||
|
2880 to stringResource(R.string.update_48hour),
|
||||||
|
10080 to stringResource(R.string.update_weekly),
|
||||||
),
|
),
|
||||||
onValueChanged = {
|
onValueChanged = {
|
||||||
BackupCreateJob.setupTask(context, it)
|
SyncDataJob.setupTask(context, it)
|
||||||
true
|
true
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
Preference.PreferenceItem.TextPreference(
|
Preference.PreferenceItem.InfoPreference(stringResource(R.string.last_synchronization, formattedLastSync)),
|
||||||
title = stringResource(R.string.pref_backup_directory),
|
|
||||||
enabled = backupInterval != 0,
|
|
||||||
subtitle = remember(backupDir) {
|
|
||||||
(UniFile.fromUri(context, backupDir.toUri())?.filePath)?.let {
|
|
||||||
"$it/automatic"
|
|
||||||
}
|
|
||||||
} ?: stringResource(R.string.invalid_location, backupDir),
|
|
||||||
onClick = {
|
|
||||||
try {
|
|
||||||
pickBackupLocation.launch(null)
|
|
||||||
} catch (e: ActivityNotFoundException) {
|
|
||||||
context.toast(R.string.file_picker_error)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Preference.PreferenceItem.ListPreference(
|
|
||||||
pref = backupPreferences.numberOfBackups(),
|
|
||||||
enabled = backupInterval != 0,
|
|
||||||
title = stringResource(R.string.pref_backup_slots),
|
|
||||||
entries = listOf(2, 3, 4, 5).associateWith { it.toString() },
|
|
||||||
),
|
|
||||||
Preference.PreferenceItem.InfoPreference(stringResource(R.string.backup_info)),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SyncConfirmationDialog(
|
||||||
|
onConfirm: () -> Unit,
|
||||||
|
onDismissRequest: () -> Unit,
|
||||||
|
) {
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
title = { Text(text = stringResource(R.string.pref_sync_confirmation_title)) },
|
||||||
|
text = { Text(text = stringResource(R.string.pref_sync_confirmation_message)) },
|
||||||
|
dismissButton = {
|
||||||
|
TextButton(onClick = onDismissRequest) {
|
||||||
|
Text(text = stringResource(R.string.action_cancel))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
TextButton(onClick = onConfirm) {
|
||||||
|
Text(text = stringResource(android.R.string.ok))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class MissingRestoreComponents(
|
private data class MissingRestoreComponents(
|
@ -223,17 +223,11 @@ object SettingsMainScreen : Screen() {
|
|||||||
screen = SettingsBrowseScreen,
|
screen = SettingsBrowseScreen,
|
||||||
),
|
),
|
||||||
Item(
|
Item(
|
||||||
titleRes = R.string.label_backup,
|
titleRes = R.string.label_backup_and_sync,
|
||||||
subtitleRes = R.string.pref_backup_summary,
|
subtitleRes = R.string.pref_backup_and_sync_summary,
|
||||||
icon = Icons.Outlined.SettingsBackupRestore,
|
icon = Icons.Outlined.SettingsBackupRestore,
|
||||||
screen = SettingsBackupScreen,
|
screen = SettingsBackupScreen,
|
||||||
),
|
),
|
||||||
Item(
|
|
||||||
titleRes = R.string.label_sync,
|
|
||||||
subtitleRes = R.string.pref_sync_summary,
|
|
||||||
icon = Icons.Outlined.Sync,
|
|
||||||
screen = SettingsSyncScreen,
|
|
||||||
),
|
|
||||||
Item(
|
Item(
|
||||||
titleRes = R.string.pref_category_security,
|
titleRes = R.string.pref_category_security,
|
||||||
subtitleRes = R.string.pref_security_summary,
|
subtitleRes = R.string.pref_security_summary,
|
||||||
|
@ -291,7 +291,6 @@ private val settingScreens = listOf(
|
|||||||
SettingsTrackingScreen,
|
SettingsTrackingScreen,
|
||||||
SettingsBrowseScreen,
|
SettingsBrowseScreen,
|
||||||
SettingsBackupScreen,
|
SettingsBackupScreen,
|
||||||
SettingsSyncScreen,
|
|
||||||
SettingsSecurityScreen,
|
SettingsSecurityScreen,
|
||||||
SettingsAdvancedScreen,
|
SettingsAdvancedScreen,
|
||||||
)
|
)
|
||||||
|
@ -1,180 +0,0 @@
|
|||||||
package eu.kanade.presentation.more.settings.screen
|
|
||||||
|
|
||||||
import android.text.format.DateUtils
|
|
||||||
import androidx.annotation.StringRes
|
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.outlined.Cloud
|
|
||||||
import androidx.compose.material.icons.outlined.Devices
|
|
||||||
import androidx.compose.material.icons.outlined.Sync
|
|
||||||
import androidx.compose.material.icons.outlined.VpnKey
|
|
||||||
import androidx.compose.material3.AlertDialog
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.ReadOnlyComposable
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import eu.kanade.presentation.more.settings.Preference
|
|
||||||
import eu.kanade.presentation.util.collectAsState
|
|
||||||
import eu.kanade.tachiyomi.R
|
|
||||||
import eu.kanade.tachiyomi.data.sync.SyncDataJob
|
|
||||||
import eu.kanade.tachiyomi.data.sync.SyncManager.SyncService
|
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import tachiyomi.domain.sync.SyncPreferences
|
|
||||||
import uy.kohesive.injekt.Injekt
|
|
||||||
import uy.kohesive.injekt.api.get
|
|
||||||
|
|
||||||
object SettingsSyncScreen : SearchableSettings {
|
|
||||||
|
|
||||||
@ReadOnlyComposable
|
|
||||||
@Composable
|
|
||||||
@StringRes
|
|
||||||
override fun getTitleRes() = R.string.label_sync
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
override fun getPreferences(): List<Preference> {
|
|
||||||
val syncPreferences = remember { Injekt.get<SyncPreferences>() }
|
|
||||||
val syncService by syncPreferences.syncService().collectAsState()
|
|
||||||
|
|
||||||
return listOf(
|
|
||||||
Preference.PreferenceItem.ListPreference(
|
|
||||||
pref = syncPreferences.syncService(),
|
|
||||||
title = stringResource(R.string.pref_sync_service),
|
|
||||||
entries = mapOf(
|
|
||||||
SyncService.NONE.value to stringResource(R.string.off),
|
|
||||||
SyncService.SYNCYOMI.value to stringResource(R.string.syncyomi),
|
|
||||||
),
|
|
||||||
onValueChanged = { true },
|
|
||||||
),
|
|
||||||
) + getSyncServicePreferences(syncPreferences, syncService)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun getSyncServicePreferences(syncPreferences: SyncPreferences, syncService: Int): List<Preference> {
|
|
||||||
return when (SyncService.fromInt(syncService)) {
|
|
||||||
SyncService.NONE -> emptyList()
|
|
||||||
SyncService.SYNCYOMI -> getSelfHostPreferences(syncPreferences)
|
|
||||||
} + getSyncNowPref() + getAutomaticSyncGroup(syncPreferences)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun getSelfHostPreferences(syncPreferences: SyncPreferences): List<Preference> {
|
|
||||||
return listOf(
|
|
||||||
Preference.PreferenceItem.EditTextPreference(
|
|
||||||
title = stringResource(R.string.pref_sync_device_name),
|
|
||||||
subtitle = stringResource(R.string.pref_sync_device_name_summ),
|
|
||||||
icon = Icons.Outlined.Devices,
|
|
||||||
pref = syncPreferences.deviceName(),
|
|
||||||
),
|
|
||||||
Preference.PreferenceItem.EditTextPreference(
|
|
||||||
title = stringResource(R.string.pref_sync_host),
|
|
||||||
subtitle = stringResource(R.string.pref_sync_host_summ),
|
|
||||||
icon = Icons.Outlined.Cloud,
|
|
||||||
pref = syncPreferences.syncHost(),
|
|
||||||
),
|
|
||||||
Preference.PreferenceItem.EditTextPreference(
|
|
||||||
title = stringResource(R.string.pref_sync_api_key),
|
|
||||||
subtitle = stringResource(R.string.pref_sync_api_key_summ),
|
|
||||||
icon = Icons.Outlined.VpnKey,
|
|
||||||
pref = syncPreferences.syncAPIKey(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun getSyncNowPref(): Preference.PreferenceGroup {
|
|
||||||
val scope = rememberCoroutineScope()
|
|
||||||
var showDialog by remember { mutableStateOf(false) }
|
|
||||||
val context = LocalContext.current
|
|
||||||
if (showDialog) {
|
|
||||||
SyncConfirmationDialog(
|
|
||||||
onConfirm = {
|
|
||||||
showDialog = false
|
|
||||||
scope.launch {
|
|
||||||
if (!SyncDataJob.isAnyJobRunning(context)) {
|
|
||||||
SyncDataJob.startNow(context)
|
|
||||||
} else {
|
|
||||||
context.toast(R.string.sync_in_progress)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onDismissRequest = { showDialog = false },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return Preference.PreferenceGroup(
|
|
||||||
title = stringResource(R.string.pref_sync_now_group_title),
|
|
||||||
preferenceItems = listOf(
|
|
||||||
Preference.PreferenceItem.TextPreference(
|
|
||||||
title = stringResource(R.string.pref_sync_now),
|
|
||||||
subtitle = stringResource(R.string.pref_sync_now_subtitle),
|
|
||||||
onClick = {
|
|
||||||
showDialog = true
|
|
||||||
},
|
|
||||||
icon = Icons.Outlined.Sync,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun getAutomaticSyncGroup(syncPreferences: SyncPreferences): Preference.PreferenceGroup {
|
|
||||||
val context = LocalContext.current
|
|
||||||
val syncIntervalPref = syncPreferences.syncInterval()
|
|
||||||
val lastSync by syncPreferences.syncLastSync().collectAsState()
|
|
||||||
val formattedLastSync = DateUtils.getRelativeTimeSpanString(lastSync.toEpochMilli(), System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS)
|
|
||||||
|
|
||||||
return Preference.PreferenceGroup(
|
|
||||||
title = stringResource(R.string.pref_sync_service_category),
|
|
||||||
preferenceItems = listOf(
|
|
||||||
Preference.PreferenceItem.ListPreference(
|
|
||||||
pref = syncIntervalPref,
|
|
||||||
title = stringResource(R.string.pref_sync_interval),
|
|
||||||
entries = mapOf(
|
|
||||||
0 to stringResource(R.string.off),
|
|
||||||
30 to stringResource(R.string.update_30min),
|
|
||||||
60 to stringResource(R.string.update_1hour),
|
|
||||||
180 to stringResource(R.string.update_3hour),
|
|
||||||
360 to stringResource(R.string.update_6hour),
|
|
||||||
720 to stringResource(R.string.update_12hour),
|
|
||||||
1440 to stringResource(R.string.update_24hour),
|
|
||||||
2880 to stringResource(R.string.update_48hour),
|
|
||||||
10080 to stringResource(R.string.update_weekly),
|
|
||||||
),
|
|
||||||
onValueChanged = {
|
|
||||||
SyncDataJob.setupTask(context, it)
|
|
||||||
true
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Preference.PreferenceItem.InfoPreference(stringResource(R.string.last_synchronization, formattedLastSync)),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun SyncConfirmationDialog(
|
|
||||||
onConfirm: () -> Unit,
|
|
||||||
onDismissRequest: () -> Unit,
|
|
||||||
) {
|
|
||||||
AlertDialog(
|
|
||||||
onDismissRequest = onDismissRequest,
|
|
||||||
title = { Text(text = stringResource(R.string.pref_sync_confirmation_title)) },
|
|
||||||
text = { Text(text = stringResource(R.string.pref_sync_confirmation_message)) },
|
|
||||||
dismissButton = {
|
|
||||||
TextButton(onClick = onDismissRequest) {
|
|
||||||
Text(text = stringResource(R.string.action_cancel))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
confirmButton = {
|
|
||||||
TextButton(onClick = onConfirm) {
|
|
||||||
Text(text = stringResource(android.R.string.ok))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
@ -72,7 +72,6 @@ object MoreTab : Tab {
|
|||||||
onClickCategories = { navigator.push(CategoryScreen()) },
|
onClickCategories = { navigator.push(CategoryScreen()) },
|
||||||
onClickStats = { navigator.push(StatsScreen()) },
|
onClickStats = { navigator.push(StatsScreen()) },
|
||||||
onClickBackupAndRestore = { navigator.push(SettingsScreen.toBackupScreen()) },
|
onClickBackupAndRestore = { navigator.push(SettingsScreen.toBackupScreen()) },
|
||||||
onClickSync = { navigator.push(SettingsScreen.toSyncScreen()) },
|
|
||||||
onClickSettings = { navigator.push(SettingsScreen.toMainScreen()) },
|
onClickSettings = { navigator.push(SettingsScreen.toMainScreen()) },
|
||||||
onClickAbout = { navigator.push(SettingsScreen.toAboutScreen()) },
|
onClickAbout = { navigator.push(SettingsScreen.toAboutScreen()) },
|
||||||
)
|
)
|
||||||
|
@ -16,7 +16,6 @@ import eu.kanade.presentation.more.settings.screen.AboutScreen
|
|||||||
import eu.kanade.presentation.more.settings.screen.SettingsAppearanceScreen
|
import eu.kanade.presentation.more.settings.screen.SettingsAppearanceScreen
|
||||||
import eu.kanade.presentation.more.settings.screen.SettingsBackupScreen
|
import eu.kanade.presentation.more.settings.screen.SettingsBackupScreen
|
||||||
import eu.kanade.presentation.more.settings.screen.SettingsMainScreen
|
import eu.kanade.presentation.more.settings.screen.SettingsMainScreen
|
||||||
import eu.kanade.presentation.more.settings.screen.SettingsSyncScreen
|
|
||||||
import eu.kanade.presentation.util.DefaultNavigatorScreenTransition
|
import eu.kanade.presentation.util.DefaultNavigatorScreenTransition
|
||||||
import eu.kanade.presentation.util.LocalBackPress
|
import eu.kanade.presentation.util.LocalBackPress
|
||||||
import eu.kanade.presentation.util.Screen
|
import eu.kanade.presentation.util.Screen
|
||||||
@ -25,7 +24,6 @@ import tachiyomi.presentation.core.components.TwoPanelBox
|
|||||||
|
|
||||||
class SettingsScreen private constructor(
|
class SettingsScreen private constructor(
|
||||||
val toBackup: Boolean,
|
val toBackup: Boolean,
|
||||||
val toSync: Boolean,
|
|
||||||
val toAbout: Boolean,
|
val toAbout: Boolean,
|
||||||
) : Screen() {
|
) : Screen() {
|
||||||
|
|
||||||
@ -36,8 +34,6 @@ class SettingsScreen private constructor(
|
|||||||
Navigator(
|
Navigator(
|
||||||
screen = if (toBackup) {
|
screen = if (toBackup) {
|
||||||
SettingsBackupScreen
|
SettingsBackupScreen
|
||||||
} else if (toSync) {
|
|
||||||
SettingsSyncScreen
|
|
||||||
} else if (toAbout) {
|
} else if (toAbout) {
|
||||||
AboutScreen
|
AboutScreen
|
||||||
} else {
|
} else {
|
||||||
@ -60,8 +56,6 @@ class SettingsScreen private constructor(
|
|||||||
Navigator(
|
Navigator(
|
||||||
screen = if (toBackup) {
|
screen = if (toBackup) {
|
||||||
SettingsBackupScreen
|
SettingsBackupScreen
|
||||||
} else if (toSync) {
|
|
||||||
SettingsSyncScreen
|
|
||||||
} else if (toAbout) {
|
} else if (toAbout) {
|
||||||
AboutScreen
|
AboutScreen
|
||||||
} else {
|
} else {
|
||||||
@ -85,12 +79,10 @@ class SettingsScreen private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun toMainScreen() = SettingsScreen(toBackup = false, toSync = false, toAbout = false)
|
fun toMainScreen() = SettingsScreen(toBackup = false, toAbout = false)
|
||||||
|
|
||||||
fun toBackupScreen() = SettingsScreen(toBackup = true, toSync = false, toAbout = false)
|
fun toBackupScreen() = SettingsScreen(toBackup = true, toAbout = false)
|
||||||
|
|
||||||
fun toSyncScreen() = SettingsScreen(toBackup = false, toSync = true, toAbout = false)
|
fun toAboutScreen() = SettingsScreen(toBackup = false, toAbout = true)
|
||||||
|
|
||||||
fun toAboutScreen() = SettingsScreen(toBackup = false, toSync = false, toAbout = true)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,8 @@
|
|||||||
<string name="label_recent_updates">Updates</string>
|
<string name="label_recent_updates">Updates</string>
|
||||||
<string name="label_recent_manga">History</string>
|
<string name="label_recent_manga">History</string>
|
||||||
<string name="label_sources">Sources</string>
|
<string name="label_sources">Sources</string>
|
||||||
<string name="label_backup">Backup and restore</string>
|
<string name="label_backup">Backup</string>
|
||||||
|
<string name="label_backup_and_sync">Backup and Sync</string>
|
||||||
<string name="label_sync">Sync</string>
|
<string name="label_sync">Sync</string>
|
||||||
<string name="label_stats">Statistics</string>
|
<string name="label_stats">Statistics</string>
|
||||||
<string name="label_migration">Migrate</string>
|
<string name="label_migration">Migrate</string>
|
||||||
@ -179,7 +180,7 @@
|
|||||||
<string name="pref_downloads_summary">Automatic download, download ahead</string>
|
<string name="pref_downloads_summary">Automatic download, download ahead</string>
|
||||||
<string name="pref_tracking_summary">One-way progress sync, enhanced sync</string>
|
<string name="pref_tracking_summary">One-way progress sync, enhanced sync</string>
|
||||||
<string name="pref_browse_summary">Sources, extensions, global search</string>
|
<string name="pref_browse_summary">Sources, extensions, global search</string>
|
||||||
<string name="pref_backup_summary">Manual & automatic backups</string>
|
<string name="pref_backup_and_sync_summary">Manual & automatic backups and sync</string>
|
||||||
<string name="pref_security_summary">App lock, secure screen</string>
|
<string name="pref_security_summary">App lock, secure screen</string>
|
||||||
<string name="pref_advanced_summary">Dump crash logs, battery optimizations</string>
|
<string name="pref_advanced_summary">Dump crash logs, battery optimizations</string>
|
||||||
|
|
||||||
@ -499,6 +500,7 @@
|
|||||||
<string name="pref_restore_backup_summ">Restore library from backup file</string>
|
<string name="pref_restore_backup_summ">Restore library from backup file</string>
|
||||||
<string name="pref_backup_directory">Backup location</string>
|
<string name="pref_backup_directory">Backup location</string>
|
||||||
<string name="pref_backup_service_category">Automatic backups</string>
|
<string name="pref_backup_service_category">Automatic backups</string>
|
||||||
|
<string name="pref_backup_manual_category">Manual backups</string>
|
||||||
<string name="pref_backup_interval">Backup frequency</string>
|
<string name="pref_backup_interval">Backup frequency</string>
|
||||||
<string name="pref_backup_slots">Maximum backups</string>
|
<string name="pref_backup_slots">Maximum backups</string>
|
||||||
<string name="backup_created">Backup created</string>
|
<string name="backup_created">Backup created</string>
|
||||||
@ -537,7 +539,6 @@
|
|||||||
<string name="pref_sync_host_summ">Enter the host address for synchronizing your library</string>
|
<string name="pref_sync_host_summ">Enter the host address for synchronizing your library</string>
|
||||||
<string name="pref_sync_api_key">API key</string>
|
<string name="pref_sync_api_key">API key</string>
|
||||||
<string name="pref_sync_api_key_summ">Enter the API key to synchronize your library</string>
|
<string name="pref_sync_api_key_summ">Enter the API key to synchronize your library</string>
|
||||||
<string name="pref_sync_summary">Sync your library with a remote server</string>
|
|
||||||
<string name="pref_sync_now_group_title">Sync Actions</string>
|
<string name="pref_sync_now_group_title">Sync Actions</string>
|
||||||
<string name="pref_sync_now">Sync now</string>
|
<string name="pref_sync_now">Sync now</string>
|
||||||
<string name="pref_sync_confirmation_title">Sync confirmation</string>
|
<string name="pref_sync_confirmation_title">Sync confirmation</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user