diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt index adcceeb06..0722165ee 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt @@ -6,6 +6,7 @@ import android.content.Context import android.content.Intent import android.graphics.Bitmap import android.graphics.BitmapFactory +import android.net.Uri import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import com.bumptech.glide.Glide @@ -80,6 +81,39 @@ class LibraryUpdateNotifier(private val context: Context) { ) } + /** + * Shows notification containing update entries that failed with action to open full log. + * + * @param errors List of entry titles that failed to update. + * @param uri Uri for error log file containing all titles that failed. + */ + fun showUpdateErrorNotification(errors: List, uri: Uri) { + if (errors.isEmpty()) { + return + } + + context.notificationManager.notify( + Notifications.ID_LIBRARY_ERROR, + context.notificationBuilder(Notifications.CHANNEL_LIBRARY) { + setContentTitle(context.resources.getQuantityString(R.plurals.notification_update_error, errors.size, errors.size)) + setStyle( + NotificationCompat.BigTextStyle().bigText( + errors.joinToString("\n") { + it.chop(NOTIF_TITLE_MAX_LEN) + } + ) + ) + setSmallIcon(R.drawable.ic_tachi) + addAction( + R.drawable.nnf_ic_file_folder, + context.getString(R.string.action_open_log), + NotificationReceiver.openErrorLogPendingActivity(context, uri) + ) + } + .build() + ) + } + /** * Shows the notification containing the result of the update done by the service. * diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt index 764c53ca4..01d31a72e 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt @@ -23,9 +23,11 @@ import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource import eu.kanade.tachiyomi.util.prepUpdateCover +import eu.kanade.tachiyomi.util.storage.getUriCompat import eu.kanade.tachiyomi.util.system.acquireWakeLock import eu.kanade.tachiyomi.util.system.isServiceRunning import exh.LIBRARY_UPDATE_EXCLUDED_SOURCES +import java.io.File import java.util.ArrayList import java.util.concurrent.atomic.AtomicInteger import rx.Observable @@ -254,7 +256,7 @@ class LibraryUpdateService( // List containing new updates val newUpdates = ArrayList>>() // List containing failed updates - val failedUpdates = ArrayList() + val failedUpdates = ArrayList>() // List containing categories that get included in downloads. val categoriesToDownload = preferences.downloadNewCategories().get().map(String::toInt) // Boolean to determine if user wants to automatically download new chapters. @@ -266,7 +268,7 @@ class LibraryUpdateService( return Observable.from(mangaToUpdate) // Notify manga that will update. .doOnNext { notifier.showProgressNotification(it, count.andIncrement, mangaToUpdate.size) } - // Update the chapters of the manga. + // Update the chapters of the manga .concatMap { manga -> if (manga.source in LIBRARY_UPDATE_EXCLUDED_SOURCES) { // Ignore EXH manga, updating chapters for every manga will get you banned @@ -275,7 +277,7 @@ class LibraryUpdateService( updateManga(manga) // If there's any error, return empty update and continue. .onErrorReturn { - failedUpdates.add(manga) + failedUpdates.add(Pair(manga, it.message)) Pair(emptyList(), emptyList()) } // Filter out mangas without new chapters (or failed). @@ -295,7 +297,10 @@ class LibraryUpdateService( .map { Pair( manga, - (it.first.sortedByDescending { ch -> ch.source_order }.toTypedArray()) + ( + it.first.sortedByDescending { ch -> ch.source_order } + .toTypedArray() + ) ) } } @@ -306,6 +311,8 @@ class LibraryUpdateService( } // Notify result of the overall update. .doOnCompleted { + notifier.cancelProgressNotification() + if (newUpdates.isNotEmpty()) { notifier.showUpdateNotifications(newUpdates) if (downloadNew && hasDownloads) { @@ -314,10 +321,12 @@ class LibraryUpdateService( } if (failedUpdates.isNotEmpty()) { - Timber.e("Failed updating: ${failedUpdates.map { it.title }}") + val errorFile = writeErrorFile(failedUpdates) + notifier.showUpdateErrorNotification( + failedUpdates.map { it.first.title }, + errorFile.getUriCompat(this) + ) } - - notifier.cancelProgressNotification() } .map { manga -> manga.first } } @@ -420,4 +429,25 @@ class LibraryUpdateService( notifier.cancelProgressNotification() } } + + /** + * Writes basic file of update errors to cache dir. + */ + private fun writeErrorFile(errors: List>): File { + try { + if (errors.isNotEmpty()) { + val destFile = File(externalCacheDir, "tachiyomi_update_errors.txt") + + destFile.bufferedWriter().use { out -> + errors.forEach { (manga, error) -> + out.write("${manga.title}: $error\n") + } + } + return destFile + } + } catch (e: Exception) { + // Empty + } + return File("") + } } 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 31ea4c6b8..cd8132fac 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 @@ -25,7 +25,7 @@ object Notifications { */ const val CHANNEL_LIBRARY = "library_channel" const val ID_LIBRARY_PROGRESS = -101 - const val ID_OLD_LIBRARY_RESULT = -101 + const val ID_LIBRARY_ERROR = -102 /** * Notification channel and ids used by the downloader. @@ -45,7 +45,7 @@ object Notifications { * Notification channel and ids used by the library updater. */ const val CHANNEL_UPDATES_TO_EXTS = "updates_ext_channel" - const val ID_UPDATES_TO_EXTS = -501 + const val ID_UPDATES_TO_EXTS = -401 /** * Notification channel and ids used by the backup/restore system. diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index abbe8504a..35afaff76 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -579,6 +579,10 @@ Chapters %1$s and 1 more Chapters %1$s and %2$d more + + 1 update failed + %1$d updates failed + Failed to update cover Please add the manga to your library before doing this Sync canceled