From f2a7f8efda6508866a298bd1184dd7c8a090ed6f Mon Sep 17 00:00:00 2001 From: arkon Date: Tue, 21 Apr 2020 20:37:13 -0400 Subject: [PATCH] Move restore completed/error dialogs to notifications --- .../data/notification/NotificationReceiver.kt | 16 +++++ .../data/notification/Notifications.kt | 1 + .../ui/setting/SettingsBackupController.kt | 64 +----------------- .../ui/setting/backup/BackupNotifier.kt | 67 ++++++++++++++++--- app/src/main/res/values/strings.xml | 6 +- 5 files changed, 80 insertions(+), 74 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt index c10c4605e9..9a8d4ae406 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt @@ -483,5 +483,21 @@ class NotificationReceiver : BroadcastReceiver() { } 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) + } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt b/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt index 819344c4ba..9bf6cf1f3f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt @@ -50,6 +50,7 @@ object Notifications { */ const val CHANNEL_BACKUP_RESTORE = "backup_restore_channel" const val ID_BACKUP = -501 + const val ID_RESTORE = -502 /** * Creates the notification channels introduced in Android Oreo. diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt index 16358e1012..e4e5d94681 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt @@ -35,13 +35,10 @@ import eu.kanade.tachiyomi.util.preference.preference import eu.kanade.tachiyomi.util.preference.preferenceCategory import eu.kanade.tachiyomi.util.preference.summaryRes 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.registerLocalReceiver import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.unregisterLocalReceiver -import java.io.File -import java.util.concurrent.TimeUnit class SettingsBackupController : SettingsController() { @@ -199,7 +196,6 @@ class SettingsBackupController : SettingsController() { fun createBackup(flags: Int) { backupFlags = flags - // Setup custom file picker intent // Get dirs 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() { override fun onReceive(context: Context, intent: Intent) { when (intent.getStringExtra(BackupConst.ACTION)) { @@ -382,16 +326,14 @@ class SettingsBackupController : SettingsController() { BackupConst.ACTION_RESTORE_COMPLETED_DIALOG -> { router.popControllerWithTag(TAG_RESTORING_BACKUP_DIALOG) 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 file = intent.getStringExtra(BackupConst.EXTRA_ERROR_FILE) - if (errors > 0) { - RestoredBackupDialog(time, errors, path, file).showDialog(router) - } + notifier.showRestoreComplete(time, errorCount, path, file) } BackupConst.ACTION_ERROR_RESTORE_DIALOG -> { router.popControllerWithTag(TAG_RESTORING_BACKUP_DIALOG) - context.toast(intent.getStringExtra(BackupConst.EXTRA_ERROR_MESSAGE)) + notifier.showRestoreError(intent.getStringExtra(BackupConst.EXTRA_ERROR_MESSAGE)) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/backup/BackupNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/backup/BackupNotifier.kt index e3dd42c805..bf57becfdd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/backup/BackupNotifier.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/backup/BackupNotifier.kt @@ -7,13 +7,18 @@ import com.hippo.unifile.UniFile import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.notification.NotificationReceiver 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.notificationManager +import java.io.File +import java.util.concurrent.TimeUnit internal class BackupNotifier(private val context: Context) { private val notificationBuilder = context.notificationBuilder(Notifications.CHANNEL_BACKUP_RESTORE) { setLargeIcon(BitmapFactory.decodeResource(context.resources, R.mipmap.ic_launcher)) + setSmallIcon(R.drawable.ic_tachi) + setAutoCancel(false) } private fun NotificationCompat.Builder.show(id: Int) { @@ -22,9 +27,6 @@ internal class BackupNotifier(private val context: Context) { fun showBackupProgress() { with(notificationBuilder) { - setSmallIcon(R.drawable.ic_tachi) - setAutoCancel(false) - setContentTitle(context.getString(R.string.backup)) setContentText(context.getString(R.string.creating_backup)) @@ -34,11 +36,8 @@ internal class BackupNotifier(private val context: Context) { notificationBuilder.show(Notifications.ID_BACKUP) } - fun showBackupError(error: String) { + fun showBackupError(error: String?) { with(notificationBuilder) { - setSmallIcon(R.drawable.ic_tachi) - setAutoCancel(false) - setContentTitle(context.getString(R.string.creating_backup_error)) setContentText(error) @@ -51,9 +50,6 @@ internal class BackupNotifier(private val context: Context) { fun showBackupComplete(unifile: UniFile) { with(notificationBuilder) { - setSmallIcon(R.drawable.ic_tachi) - setAutoCancel(false) - setContentTitle(context.getString(R.string.backup_created)) if (unifile.filePath != null) { @@ -75,4 +71,55 @@ internal class BackupNotifier(private val context: Context) { 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) + } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c70734d445..d80cc824e4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -320,14 +320,14 @@ Restoring backup\n%1$s source not found Backup created Restore completed - Could not open log - Restore took %1$s.\n%2$s errors found. + Restore took %1$s with %2$s errors 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. File saved at %1$s What do you want to backup? - Restoring backup Creating backup Backup failed + Restoring backup + Restoring backup failed Clear chapter cache