Move restore completed/error dialogs to notifications

This commit is contained in:
arkon 2020-04-21 20:37:13 -04:00
parent e6c172ac22
commit f2a7f8efda
5 changed files with 80 additions and 74 deletions

View File

@ -483,5 +483,21 @@ class NotificationReceiver : BroadcastReceiver() {
} }
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
} }
/**
* Returns [PendingIntent] that opens the error log file in an external viewer
*
* @param context context of application
* @param uri uri of error log file
* @return [PendingIntent]
*/
internal fun openErrorLog(context: Context, uri: Uri): PendingIntent {
val intent = Intent().apply {
action = Intent.ACTION_VIEW
setDataAndType(uri, "text/plain")
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
}
return PendingIntent.getActivity(context, 0, intent, 0)
}
} }
} }

View File

@ -50,6 +50,7 @@ object Notifications {
*/ */
const val CHANNEL_BACKUP_RESTORE = "backup_restore_channel" const val CHANNEL_BACKUP_RESTORE = "backup_restore_channel"
const val ID_BACKUP = -501 const val ID_BACKUP = -501
const val ID_RESTORE = -502
/** /**
* Creates the notification channels introduced in Android Oreo. * Creates the notification channels introduced in Android Oreo.

View File

@ -35,13 +35,10 @@ import eu.kanade.tachiyomi.util.preference.preference
import eu.kanade.tachiyomi.util.preference.preferenceCategory import eu.kanade.tachiyomi.util.preference.preferenceCategory
import eu.kanade.tachiyomi.util.preference.summaryRes import eu.kanade.tachiyomi.util.preference.summaryRes
import eu.kanade.tachiyomi.util.preference.titleRes import eu.kanade.tachiyomi.util.preference.titleRes
import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.system.getFilePicker import eu.kanade.tachiyomi.util.system.getFilePicker
import eu.kanade.tachiyomi.util.system.registerLocalReceiver import eu.kanade.tachiyomi.util.system.registerLocalReceiver
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.system.unregisterLocalReceiver import eu.kanade.tachiyomi.util.system.unregisterLocalReceiver
import java.io.File
import java.util.concurrent.TimeUnit
class SettingsBackupController : SettingsController() { class SettingsBackupController : SettingsController() {
@ -199,7 +196,6 @@ class SettingsBackupController : SettingsController() {
fun createBackup(flags: Int) { fun createBackup(flags: Int) {
backupFlags = flags backupFlags = flags
// Setup custom file picker intent
// Get dirs // Get dirs
val currentDir = preferences.backupsDirectory().getOrDefault() val currentDir = preferences.backupsDirectory().getOrDefault()
@ -309,58 +305,6 @@ class SettingsBackupController : SettingsController() {
} }
} }
class RestoredBackupDialog(bundle: Bundle? = null) : DialogController(bundle) {
constructor(time: Long, errorCount: Int, path: String, file: String) : this(Bundle().apply {
putLong(KEY_TIME, time)
putInt(KEY_ERROR_COUNT, errorCount)
putString(KEY_PATH, path)
putString(KEY_FILE, file)
})
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
val activity = activity!!
val time = args.getLong(KEY_TIME)
val errors = args.getInt(KEY_ERROR_COUNT)
val path = args.getString(KEY_PATH)
val file = args.getString(KEY_FILE)
val timeString = String.format("%02d min, %02d sec",
TimeUnit.MILLISECONDS.toMinutes(time),
TimeUnit.MILLISECONDS.toSeconds(time) - TimeUnit.MINUTES.toSeconds(
TimeUnit.MILLISECONDS.toMinutes(time))
)
return MaterialDialog.Builder(activity)
.title(R.string.restore_completed)
.content(activity.getString(R.string.restore_completed_content, timeString,
if (errors > 0) "$errors" else activity.getString(android.R.string.cancel)))
.positiveText(R.string.action_close)
.negativeText(R.string.action_open_log)
.onNegative { _, _ ->
val context = applicationContext ?: return@onNegative
if (!path.isNullOrEmpty()) {
val destFile = File(path, file)
val uri = destFile.getUriCompat(context)
val sendIntent = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(uri, "text/plain")
flags = Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_GRANT_READ_URI_PERMISSION
}
startActivity(sendIntent)
} else {
context.toast(context.getString(R.string.error_opening_log))
}
}
.build()
}
private companion object {
const val KEY_TIME = "RestoredBackupDialog.time"
const val KEY_ERROR_COUNT = "RestoredBackupDialog.errors"
const val KEY_PATH = "RestoredBackupDialog.path"
const val KEY_FILE = "RestoredBackupDialog.file"
}
}
inner class BackupBroadcastReceiver : BroadcastReceiver() { inner class BackupBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
when (intent.getStringExtra(BackupConst.ACTION)) { when (intent.getStringExtra(BackupConst.ACTION)) {
@ -382,16 +326,14 @@ class SettingsBackupController : SettingsController() {
BackupConst.ACTION_RESTORE_COMPLETED_DIALOG -> { BackupConst.ACTION_RESTORE_COMPLETED_DIALOG -> {
router.popControllerWithTag(TAG_RESTORING_BACKUP_DIALOG) router.popControllerWithTag(TAG_RESTORING_BACKUP_DIALOG)
val time = intent.getLongExtra(BackupConst.EXTRA_TIME, 0) val time = intent.getLongExtra(BackupConst.EXTRA_TIME, 0)
val errors = intent.getIntExtra(BackupConst.EXTRA_ERRORS, 0) val errorCount = intent.getIntExtra(BackupConst.EXTRA_ERRORS, 0)
val path = intent.getStringExtra(BackupConst.EXTRA_ERROR_FILE_PATH) val path = intent.getStringExtra(BackupConst.EXTRA_ERROR_FILE_PATH)
val file = intent.getStringExtra(BackupConst.EXTRA_ERROR_FILE) val file = intent.getStringExtra(BackupConst.EXTRA_ERROR_FILE)
if (errors > 0) { notifier.showRestoreComplete(time, errorCount, path, file)
RestoredBackupDialog(time, errors, path, file).showDialog(router)
}
} }
BackupConst.ACTION_ERROR_RESTORE_DIALOG -> { BackupConst.ACTION_ERROR_RESTORE_DIALOG -> {
router.popControllerWithTag(TAG_RESTORING_BACKUP_DIALOG) router.popControllerWithTag(TAG_RESTORING_BACKUP_DIALOG)
context.toast(intent.getStringExtra(BackupConst.EXTRA_ERROR_MESSAGE)) notifier.showRestoreError(intent.getStringExtra(BackupConst.EXTRA_ERROR_MESSAGE))
} }
} }
} }

View File

@ -7,13 +7,18 @@ import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.notification.NotificationReceiver import eu.kanade.tachiyomi.data.notification.NotificationReceiver
import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.system.notificationBuilder import eu.kanade.tachiyomi.util.system.notificationBuilder
import eu.kanade.tachiyomi.util.system.notificationManager import eu.kanade.tachiyomi.util.system.notificationManager
import java.io.File
import java.util.concurrent.TimeUnit
internal class BackupNotifier(private val context: Context) { internal class BackupNotifier(private val context: Context) {
private val notificationBuilder = context.notificationBuilder(Notifications.CHANNEL_BACKUP_RESTORE) { private val notificationBuilder = context.notificationBuilder(Notifications.CHANNEL_BACKUP_RESTORE) {
setLargeIcon(BitmapFactory.decodeResource(context.resources, R.mipmap.ic_launcher)) setLargeIcon(BitmapFactory.decodeResource(context.resources, R.mipmap.ic_launcher))
setSmallIcon(R.drawable.ic_tachi)
setAutoCancel(false)
} }
private fun NotificationCompat.Builder.show(id: Int) { private fun NotificationCompat.Builder.show(id: Int) {
@ -22,9 +27,6 @@ internal class BackupNotifier(private val context: Context) {
fun showBackupProgress() { fun showBackupProgress() {
with(notificationBuilder) { with(notificationBuilder) {
setSmallIcon(R.drawable.ic_tachi)
setAutoCancel(false)
setContentTitle(context.getString(R.string.backup)) setContentTitle(context.getString(R.string.backup))
setContentText(context.getString(R.string.creating_backup)) setContentText(context.getString(R.string.creating_backup))
@ -34,11 +36,8 @@ internal class BackupNotifier(private val context: Context) {
notificationBuilder.show(Notifications.ID_BACKUP) notificationBuilder.show(Notifications.ID_BACKUP)
} }
fun showBackupError(error: String) { fun showBackupError(error: String?) {
with(notificationBuilder) { with(notificationBuilder) {
setSmallIcon(R.drawable.ic_tachi)
setAutoCancel(false)
setContentTitle(context.getString(R.string.creating_backup_error)) setContentTitle(context.getString(R.string.creating_backup_error))
setContentText(error) setContentText(error)
@ -51,9 +50,6 @@ internal class BackupNotifier(private val context: Context) {
fun showBackupComplete(unifile: UniFile) { fun showBackupComplete(unifile: UniFile) {
with(notificationBuilder) { with(notificationBuilder) {
setSmallIcon(R.drawable.ic_tachi)
setAutoCancel(false)
setContentTitle(context.getString(R.string.backup_created)) setContentTitle(context.getString(R.string.backup_created))
if (unifile.filePath != null) { if (unifile.filePath != null) {
@ -75,4 +71,55 @@ internal class BackupNotifier(private val context: Context) {
notificationBuilder.show(Notifications.ID_BACKUP) notificationBuilder.show(Notifications.ID_BACKUP)
} }
fun showRestoreProgress() {
// TODO
}
fun showRestoreError(error: String?) {
with(notificationBuilder) {
setContentTitle(context.getString(R.string.restoring_backup_error))
setContentText(error)
// Remove progress bar
setProgress(0, 0, false)
}
notificationBuilder.show(Notifications.ID_RESTORE)
}
fun showRestoreComplete(time: Long, errorCount: Int, path: String?, file: String?) {
val timeString = String.format("%02d min, %02d sec",
TimeUnit.MILLISECONDS.toMinutes(time),
TimeUnit.MILLISECONDS.toSeconds(time) - TimeUnit.MINUTES.toSeconds(
TimeUnit.MILLISECONDS.toMinutes(time))
)
with(notificationBuilder) {
setSmallIcon(R.drawable.ic_tachi)
setAutoCancel(false)
setContentTitle(context.getString(R.string.restore_completed))
setContentText(context.getString(R.string.restore_completed_content, timeString, errorCount))
// Remove progress bar
setProgress(0, 0, false)
// Clear old actions if they exist
if (mActions.isNotEmpty()) {
mActions.clear()
}
if (errorCount > 0 && !path.isNullOrEmpty() && !file.isNullOrEmpty()) {
val destFile = File(path, file)
val uri = destFile.getUriCompat(context)
addAction(R.drawable.nnf_ic_file_folder,
context.getString(R.string.action_open_log),
NotificationReceiver.openErrorLog(context, uri))
}
}
notificationBuilder.show(Notifications.ID_RESTORE)
}
} }

View File

@ -320,14 +320,14 @@
<string name="dialog_restoring_source_not_found">Restoring backup\n%1$s source not found</string> <string name="dialog_restoring_source_not_found">Restoring backup\n%1$s source not found</string>
<string name="backup_created">Backup created</string> <string name="backup_created">Backup created</string>
<string name="restore_completed">Restore completed</string> <string name="restore_completed">Restore completed</string>
<string name="error_opening_log">Could not open log</string> <string name="restore_completed_content">Restore took %1$s with %2$s errors</string>
<string name="restore_completed_content">Restore took %1$s.\n%2$s errors found.</string>
<string name="backup_restore_content">Restore uses sources to fetch data, carrier costs may apply.\n\nMake sure you have installed all necessary extensions and are logged in to sources and tracking services before restoring.</string> <string name="backup_restore_content">Restore uses sources to fetch data, carrier costs may apply.\n\nMake sure you have installed all necessary extensions and are logged in to sources and tracking services before restoring.</string>
<string name="file_saved">File saved at %1$s</string> <string name="file_saved">File saved at %1$s</string>
<string name="backup_choice">What do you want to backup?</string> <string name="backup_choice">What do you want to backup?</string>
<string name="restoring_backup">Restoring backup</string>
<string name="creating_backup">Creating backup</string> <string name="creating_backup">Creating backup</string>
<string name="creating_backup_error">Backup failed</string> <string name="creating_backup_error">Backup failed</string>
<string name="restoring_backup">Restoring backup</string>
<string name="restoring_backup_error">Restoring backup failed</string>
<!-- Advanced section --> <!-- Advanced section -->
<string name="pref_clear_chapter_cache">Clear chapter cache</string> <string name="pref_clear_chapter_cache">Clear chapter cache</string>