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 86085d0495..c10c4605e9 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 @@ -4,6 +4,7 @@ import android.app.PendingIntent import android.content.BroadcastReceiver import android.content.Context import android.content.Intent +import android.net.Uri import android.os.Build import android.os.Handler import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID @@ -57,6 +58,9 @@ class NotificationReceiver : BroadcastReceiver() { // Delete image from path and dismiss notification ACTION_DELETE_IMAGE -> deleteImage(context, intent.getStringExtra(EXTRA_FILE_LOCATION), intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1)) + // Share backup file + ACTION_SHARE_BACKUP -> shareBackup(context, intent.getParcelableExtra(EXTRA_URI), + intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1)) // Cancel library update and dismiss notification ACTION_CANCEL_LIBRARY_UPDATE -> cancelLibraryUpdate(context, Notifications.ID_LIBRARY_PROGRESS) // Open reader activity @@ -100,8 +104,8 @@ class NotificationReceiver : BroadcastReceiver() { val intent = Intent(Intent.ACTION_SEND).apply { val uri = File(path).getUriCompat(context) putExtra(Intent.EXTRA_STREAM, uri) - flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION type = "image/*" + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION } // Dismiss notification dismissNotification(context, notificationId) @@ -109,6 +113,25 @@ class NotificationReceiver : BroadcastReceiver() { context.startActivity(intent) } + /** + * Called to start share intent to share backup file + * + * @param context context of application + * @param path path of file + * @param notificationId id of notification + */ + private fun shareBackup(context: Context, uri: Uri, notificationId: Int) { + val sendIntent = Intent(Intent.ACTION_SEND).apply { + putExtra(Intent.EXTRA_STREAM, uri) + type = "application/json" + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION + } + // Dismiss notification + dismissNotification(context, notificationId) + // Launch share activity + context.startActivity(sendIntent) + } + /** * Starts reader activity * @@ -196,6 +219,9 @@ class NotificationReceiver : BroadcastReceiver() { // Called to delete image. private const val ACTION_DELETE_IMAGE = "$ID.$NAME.DELETE_IMAGE" + // Called to launch send intent. + private const val ACTION_SHARE_BACKUP = "$ID.$NAME.SEND_BACKUP" + // Called to cancel library update. private const val ACTION_CANCEL_LIBRARY_UPDATE = "$ID.$NAME.CANCEL_LIBRARY_UPDATE" @@ -220,6 +246,9 @@ class NotificationReceiver : BroadcastReceiver() { // Called to dismiss notification. private const val ACTION_DISMISS_NOTIFICATION = "$ID.$NAME.ACTION_DISMISS_NOTIFICATION" + // Value containing uri. + private const val EXTRA_URI = "$ID.$NAME.URI" + // Value containing notification id. private const val EXTRA_NOTIFICATION_ID = "$ID.$NAME.NOTIFICATION_ID" @@ -437,5 +466,22 @@ class NotificationReceiver : BroadcastReceiver() { } return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) } + + /** + * Returns [PendingIntent] that starts a share activity for a backup file. + * + * @param context context of application + * @param uri uri of backup file + * @param notificationId id of notification + * @return [PendingIntent] + */ + internal fun shareBackup(context: Context, uri: Uri, notificationId: Int): PendingIntent { + val intent = Intent(context, NotificationReceiver::class.java).apply { + action = ACTION_SHARE_BACKUP + putExtra(EXTRA_URI, uri) + putExtra(EXTRA_NOTIFICATION_ID, notificationId) + } + return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) + } } } 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 387af45e1a..16358e1012 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 @@ -182,7 +182,9 @@ class SettingsBackupController : SettingsController() { val file = UniFile.fromUri(activity, uri) - notifier.showBackupNotification() + activity.toast(R.string.creating_backup) + notifier.showBackupProgress() + BackupCreateService.makeBackup(activity, file.uri, backupFlags) } CODE_BACKUP_RESTORE -> if (data != null && resultCode == Activity.RESULT_OK) { @@ -247,35 +249,6 @@ class SettingsBackupController : SettingsController() { } } - class CreatedBackupDialog(bundle: Bundle? = null) : DialogController(bundle) { - constructor(uri: Uri) : this(Bundle().apply { - putParcelable(KEY_URI, uri) - }) - - override fun onCreateDialog(savedViewState: Bundle?): Dialog { - val activity = activity!! - val unifile = UniFile.fromUri(activity, args.getParcelable(KEY_URI)) - return MaterialDialog.Builder(activity).apply { - title(R.string.backup_created) - if (unifile.filePath != null) { - content(activity.getString(R.string.file_saved, unifile.filePath)) - } - positiveText(R.string.action_close) - negativeText(R.string.action_export) - onNegative { _, _ -> - val sendIntent = Intent(Intent.ACTION_SEND) - sendIntent.type = "application/json" - sendIntent.putExtra(Intent.EXTRA_STREAM, unifile.uri) - startActivity(Intent.createChooser(sendIntent, "")) - } - }.build() - } - - private companion object { - const val KEY_URI = "BackupCreatedDialog.uri" - } - } - class RestoreBackupDialog(bundle: Bundle? = null) : DialogController(bundle) { constructor(uri: Uri) : this(Bundle().apply { putParcelable(KEY_URI, uri) @@ -392,9 +365,12 @@ class SettingsBackupController : SettingsController() { override fun onReceive(context: Context, intent: Intent) { when (intent.getStringExtra(BackupConst.ACTION)) { BackupConst.ACTION_BACKUP_COMPLETED_DIALOG -> { - notifier.dismiss() val uri = Uri.parse(intent.getStringExtra(BackupConst.EXTRA_URI)) - CreatedBackupDialog(uri).showDialog(router) + val unifile = UniFile.fromUri(activity, uri) + notifier.showBackupComplete(unifile) + } + BackupConst.ACTION_ERROR_BACKUP_DIALOG -> { + notifier.showBackupError(intent.getStringExtra(BackupConst.EXTRA_ERROR_MESSAGE)) } BackupConst.ACTION_SET_PROGRESS_DIALOG -> { val progress = intent.getIntExtra(BackupConst.EXTRA_PROGRESS, 0) @@ -413,10 +389,6 @@ class SettingsBackupController : SettingsController() { RestoredBackupDialog(time, errors, path, file).showDialog(router) } } - BackupConst.ACTION_ERROR_BACKUP_DIALOG -> { - notifier.dismiss() - context.toast(intent.getStringExtra(BackupConst.EXTRA_ERROR_MESSAGE)) - } BackupConst.ACTION_ERROR_RESTORE_DIALOG -> { router.popControllerWithTag(TAG_RESTORING_BACKUP_DIALOG) context.toast(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 a72cde3763..e3dd42c805 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 @@ -3,7 +3,9 @@ package eu.kanade.tachiyomi.ui.setting.backup import android.content.Context import android.graphics.BitmapFactory import androidx.core.app.NotificationCompat +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.system.notificationBuilder import eu.kanade.tachiyomi.util.system.notificationManager @@ -14,15 +16,11 @@ internal class BackupNotifier(private val context: Context) { setLargeIcon(BitmapFactory.decodeResource(context.resources, R.mipmap.ic_launcher)) } - private fun NotificationCompat.Builder.show(id: Int = Notifications.ID_BACKUP) { + private fun NotificationCompat.Builder.show(id: Int) { context.notificationManager.notify(id, build()) } - fun dismiss() { - context.notificationManager.cancel(Notifications.ID_BACKUP) - } - - fun showBackupNotification() { + fun showBackupProgress() { with(notificationBuilder) { setSmallIcon(R.drawable.ic_tachi) setAutoCancel(false) @@ -33,6 +31,48 @@ internal class BackupNotifier(private val context: Context) { setProgress(0, 0, true) } - notificationBuilder.show() + notificationBuilder.show(Notifications.ID_BACKUP) + } + + fun showBackupError(error: String) { + with(notificationBuilder) { + setSmallIcon(R.drawable.ic_tachi) + setAutoCancel(false) + + setContentTitle(context.getString(R.string.creating_backup_error)) + setContentText(error) + + // Remove progress bar + setProgress(0, 0, false) + } + + notificationBuilder.show(Notifications.ID_BACKUP) + } + + fun showBackupComplete(unifile: UniFile) { + with(notificationBuilder) { + setSmallIcon(R.drawable.ic_tachi) + setAutoCancel(false) + + setContentTitle(context.getString(R.string.backup_created)) + + if (unifile.filePath != null) { + setContentText(context.getString(R.string.file_saved, unifile.filePath)) + } + + // Remove progress bar + setProgress(0, 0, false) + + // Clear old actions if they exist + if (mActions.isNotEmpty()) { + mActions.clear() + } + + addAction(R.drawable.ic_share_24dp, + context.getString(R.string.action_share), + NotificationReceiver.shareBackup(context, unifile.uri, Notifications.ID_BACKUP)) + } + + notificationBuilder.show(Notifications.ID_BACKUP) } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5410371a06..c70734d445 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -101,7 +101,6 @@ Save Reset Undo - Export Open log Create Restore @@ -328,6 +327,7 @@ What do you want to backup? Restoring backup Creating backup + Backup failed Clear chapter cache