|
|
|
@ -1,20 +1,25 @@
|
|
|
|
package org.koitharu.kotatsu.backups.ui
|
|
|
|
package org.koitharu.kotatsu.backups.ui
|
|
|
|
|
|
|
|
|
|
|
|
import android.app.Notification
|
|
|
|
import android.net.Uri
|
|
|
|
import androidx.core.app.NotificationChannelCompat
|
|
|
|
import androidx.core.app.NotificationChannelCompat
|
|
|
|
import androidx.core.app.NotificationCompat
|
|
|
|
import androidx.core.app.NotificationCompat
|
|
|
|
import androidx.core.app.NotificationManagerCompat
|
|
|
|
import androidx.core.app.NotificationManagerCompat
|
|
|
|
import androidx.core.app.PendingIntentCompat
|
|
|
|
import androidx.core.app.PendingIntentCompat
|
|
|
|
|
|
|
|
import androidx.core.app.ShareCompat
|
|
|
|
import org.koitharu.kotatsu.R
|
|
|
|
import org.koitharu.kotatsu.R
|
|
|
|
import org.koitharu.kotatsu.core.ErrorReporterReceiver
|
|
|
|
import org.koitharu.kotatsu.core.ErrorReporterReceiver
|
|
|
|
import org.koitharu.kotatsu.core.nav.AppRouter
|
|
|
|
import org.koitharu.kotatsu.core.nav.AppRouter
|
|
|
|
import org.koitharu.kotatsu.core.ui.CoroutineIntentService
|
|
|
|
import org.koitharu.kotatsu.core.ui.CoroutineIntentService
|
|
|
|
|
|
|
|
import org.koitharu.kotatsu.core.util.CompositeResult
|
|
|
|
import org.koitharu.kotatsu.core.util.ext.checkNotificationPermission
|
|
|
|
import org.koitharu.kotatsu.core.util.ext.checkNotificationPermission
|
|
|
|
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
|
|
|
|
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
|
|
|
|
|
|
|
|
import org.koitharu.kotatsu.core.util.ext.getFileDisplayName
|
|
|
|
|
|
|
|
import androidx.appcompat.R as appcompatR
|
|
|
|
|
|
|
|
|
|
|
|
abstract class BaseBackupRestoreService : CoroutineIntentService() {
|
|
|
|
abstract class BaseBackupRestoreService : CoroutineIntentService() {
|
|
|
|
|
|
|
|
|
|
|
|
protected abstract val notificationTag: String
|
|
|
|
protected abstract val notificationTag: String
|
|
|
|
|
|
|
|
protected abstract val isRestoreService: Boolean
|
|
|
|
|
|
|
|
|
|
|
|
protected lateinit var notificationManager: NotificationManagerCompat
|
|
|
|
protected lateinit var notificationManager: NotificationManagerCompat
|
|
|
|
private set
|
|
|
|
private set
|
|
|
|
@ -26,10 +31,7 @@ abstract class BaseBackupRestoreService : CoroutineIntentService() {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
override fun IntentJobContext.onError(error: Throwable) {
|
|
|
|
override fun IntentJobContext.onError(error: Throwable) {
|
|
|
|
if (applicationContext.checkNotificationPermission(CHANNEL_ID)) {
|
|
|
|
showResultNotification(null, CompositeResult.failure(error))
|
|
|
|
val notification = createErrorNotification(error)
|
|
|
|
|
|
|
|
notificationManager.notify(notificationTag, startId, notification)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private fun createNotificationChannel() {
|
|
|
|
private fun createNotificationChannel() {
|
|
|
|
@ -43,33 +45,93 @@ abstract class BaseBackupRestoreService : CoroutineIntentService() {
|
|
|
|
notificationManager.createNotificationChannel(channel)
|
|
|
|
notificationManager.createNotificationChannel(channel)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected fun createErrorNotification(error: Throwable): Notification {
|
|
|
|
protected fun IntentJobContext.showResultNotification(
|
|
|
|
|
|
|
|
fileUri: Uri?,
|
|
|
|
|
|
|
|
result: CompositeResult,
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
if (!applicationContext.checkNotificationPermission(CHANNEL_ID)) {
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
val notification = NotificationCompat.Builder(applicationContext, CHANNEL_ID)
|
|
|
|
val notification = NotificationCompat.Builder(applicationContext, CHANNEL_ID)
|
|
|
|
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
|
|
|
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
|
|
|
.setDefaults(0)
|
|
|
|
.setDefaults(0)
|
|
|
|
.setSilent(true)
|
|
|
|
.setSilent(true)
|
|
|
|
.setAutoCancel(true)
|
|
|
|
.setAutoCancel(true)
|
|
|
|
.setContentText(error.getDisplayMessage(resources))
|
|
|
|
.setSubText(fileUri?.let { contentResolver.getFileDisplayName(it) })
|
|
|
|
.setSmallIcon(android.R.drawable.stat_notify_error)
|
|
|
|
when {
|
|
|
|
ErrorReporterReceiver.getPendingIntent(applicationContext, error)?.let { reportIntent ->
|
|
|
|
result.isAllSuccess -> {
|
|
|
|
notification.addAction(
|
|
|
|
if (isRestoreService) {
|
|
|
|
R.drawable.ic_alert_outline,
|
|
|
|
notification
|
|
|
|
applicationContext.getString(R.string.report),
|
|
|
|
.setContentTitle(getString(R.string.restoring_backup))
|
|
|
|
reportIntent,
|
|
|
|
.setContentText(getString(R.string.data_restored_success))
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
|
|
|
|
notification
|
|
|
|
|
|
|
|
.setContentTitle(getString(R.string.backup_saved))
|
|
|
|
|
|
|
|
.setContentText(fileUri?.let { contentResolver.getFileDisplayName(it) })
|
|
|
|
|
|
|
|
.setSubText(null)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
notification.setSmallIcon(R.drawable.ic_stat_done)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result.isAllFailed || !isRestoreService -> {
|
|
|
|
|
|
|
|
val title = getString(if (isRestoreService) R.string.data_not_restored else R.string.error_occurred)
|
|
|
|
|
|
|
|
val message = result.failures.joinToString("\n") {
|
|
|
|
|
|
|
|
it.getDisplayMessage(applicationContext.resources)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
notification
|
|
|
|
|
|
|
|
.setContentText(if (isRestoreService) getString(R.string.data_not_restored_text) else message)
|
|
|
|
|
|
|
|
.setBigText(title, message)
|
|
|
|
|
|
|
|
.setSmallIcon(android.R.drawable.stat_notify_error)
|
|
|
|
|
|
|
|
result.failures.firstNotNullOfOrNull { error ->
|
|
|
|
|
|
|
|
ErrorReporterReceiver.getPendingIntent(applicationContext, error)
|
|
|
|
|
|
|
|
}?.let { reportIntent ->
|
|
|
|
|
|
|
|
notification.addAction(
|
|
|
|
|
|
|
|
R.drawable.ic_alert_outline,
|
|
|
|
|
|
|
|
applicationContext.getString(R.string.report),
|
|
|
|
|
|
|
|
reportIntent,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
else -> {
|
|
|
|
|
|
|
|
notification
|
|
|
|
|
|
|
|
.setContentTitle(getString(R.string.restoring_backup))
|
|
|
|
|
|
|
|
.setContentText(getString(R.string.data_restored_with_errors))
|
|
|
|
|
|
|
|
.setSmallIcon(R.drawable.ic_stat_done)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
notification.setContentIntent(
|
|
|
|
notification.setContentIntent(
|
|
|
|
PendingIntentCompat.getActivity(
|
|
|
|
PendingIntentCompat.getActivity(
|
|
|
|
applicationContext,
|
|
|
|
applicationContext,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
AppRouter.homeIntent(this),
|
|
|
|
AppRouter.homeIntent(this@BaseBackupRestoreService),
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
return notification.build()
|
|
|
|
if (!isRestoreService && fileUri != null) {
|
|
|
|
|
|
|
|
val shareIntent = ShareCompat.IntentBuilder(this@BaseBackupRestoreService)
|
|
|
|
|
|
|
|
.setStream(fileUri)
|
|
|
|
|
|
|
|
.setType("application/zip")
|
|
|
|
|
|
|
|
.setChooserTitle(R.string.share_backup)
|
|
|
|
|
|
|
|
.createChooserIntent()
|
|
|
|
|
|
|
|
notification.addAction(
|
|
|
|
|
|
|
|
appcompatR.drawable.abc_ic_menu_share_mtrl_alpha,
|
|
|
|
|
|
|
|
getString(R.string.share),
|
|
|
|
|
|
|
|
PendingIntentCompat.getActivity(this@BaseBackupRestoreService, 0, shareIntent, 0, false),
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
notificationManager.notify(notificationTag, startId, notification.build())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected fun NotificationCompat.Builder.setBigText(title: String, text: CharSequence) = setStyle(
|
|
|
|
|
|
|
|
NotificationCompat.BigTextStyle()
|
|
|
|
|
|
|
|
.bigText(text)
|
|
|
|
|
|
|
|
.setSummaryText(text)
|
|
|
|
|
|
|
|
.setBigContentTitle(title),
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
protected companion object {
|
|
|
|
protected companion object {
|
|
|
|
|
|
|
|
|
|
|
|
const val CHANNEL_ID = "backup_restore"
|
|
|
|
const val CHANNEL_ID = "backup_restore"
|
|
|
|
|