diff --git a/app/src/main/java/eu/kanade/tachiyomi/Constants.kt b/app/src/main/java/eu/kanade/tachiyomi/Constants.kt index 48fec85954..6b9a416826 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/Constants.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/Constants.kt @@ -1,10 +1,10 @@ package eu.kanade.tachiyomi object Constants { - const val NOTIFICATION_LIBRARY_ID = 1 - const val NOTIFICATION_UPDATER_ID = 2 - const val NOTIFICATION_DOWNLOAD_CHAPTER_ID = 3 - const val NOTIFICATION_DOWNLOAD_CHAPTER_ERROR_ID = 4 - const val NOTIFICATION_DOWNLOAD_IMAGE_ID = 5 - + const val NOTIFICATION_LIBRARY_PROGRESS_ID = 1 + const val NOTIFICATION_LIBRARY_RESULT_ID = 2 + const val NOTIFICATION_UPDATER_ID = 3 + const val NOTIFICATION_DOWNLOAD_CHAPTER_ID = 4 + const val NOTIFICATION_DOWNLOAD_CHAPTER_ERROR_ID = 5 + const val NOTIFICATION_DOWNLOAD_IMAGE_ID = 6 } 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 29a38e5966..e9a9d2e1bf 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt @@ -1,10 +1,12 @@ package eu.kanade.tachiyomi.data.library +import android.app.Notification import android.app.PendingIntent import android.app.Service import android.content.Context import android.content.Intent import android.graphics.BitmapFactory +import android.os.Build import android.os.IBinder import android.os.PowerManager import android.support.v4.app.NotificationCompat @@ -28,7 +30,9 @@ import eu.kanade.tachiyomi.util.* import rx.Observable import rx.Subscription import rx.schedulers.Schedulers -import uy.kohesive.injekt.injectLazy +import timber.log.Timber +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get import java.util.* import java.util.concurrent.atomic.AtomicInteger @@ -40,27 +44,12 @@ import java.util.concurrent.atomic.AtomicInteger * progress of the update, and if case of an unexpected error, this service will be silently * destroyed. */ -class LibraryUpdateService : Service() { - - /** - * Database helper. - */ - val db: DatabaseHelper by injectLazy() - - /** - * Source manager. - */ - val sourceManager: SourceManager by injectLazy() - - /** - * Preferences. - */ - val preferences: PreferencesHelper by injectLazy() - - /** - * Download Manager - */ - val downloadManager: DownloadManager by injectLazy() +class LibraryUpdateService( + val db: DatabaseHelper = Injekt.get(), + val sourceManager: SourceManager = Injekt.get(), + val preferences: PreferencesHelper = Injekt.get(), + val downloadManager: DownloadManager = Injekt.get() +) : Service() { /** * Wake lock that will be held until the service is destroyed. @@ -75,18 +64,27 @@ class LibraryUpdateService : Service() { /** * Pending intent of action that cancels the library update */ - private val cancelPendingIntent by lazy {NotificationReceiver.cancelLibraryUpdatePendingBroadcast(this)} + private val cancelIntent by lazy { + NotificationReceiver.cancelLibraryUpdatePendingBroadcast(this) + } /** - * Id of the library update notification. + * Bitmap of the app for notifications. */ - private val notificationId: Int - get() = Constants.NOTIFICATION_LIBRARY_ID - private val notificationBitmap by lazy { BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher) } + /** + * Cached progress notification to avoid creating a lot. + */ + private val progressNotification by lazy { NotificationCompat.Builder(this) + .setSmallIcon(R.drawable.ic_refresh_white_24dp_img) + .setLargeIcon(notificationBitmap) + .setOngoing(true) + .addAction(R.drawable.ic_clear_grey_24dp_img, getString(android.R.string.cancel), cancelIntent) + } + companion object { /** @@ -144,16 +142,20 @@ class LibraryUpdateService : Service() { */ override fun onCreate() { super.onCreate() - createAndAcquireWakeLock() + wakeLock = (getSystemService(Context.POWER_SERVICE) as PowerManager).newWakeLock( + PowerManager.PARTIAL_WAKE_LOCK, "LibraryUpdateService:WakeLock") + wakeLock.acquire() } /** - * Method called when the service is destroyed. It destroys the running subscription, resets - * the alarm and release the wake lock. + * Method called when the service is destroyed. It destroys subscriptions and releases the wake + * lock. */ override fun onDestroy() { subscription?.unsubscribe() - destroyWakeLock() + if (wakeLock.isHeld) { + wakeLock.release() + } super.onDestroy() } @@ -192,7 +194,7 @@ class LibraryUpdateService : Service() { .subscribeOn(Schedulers.io()) .subscribe({ }, { - showNotification(getString(R.string.notification_update_error), "") + Timber.e(it) stopSelf(startId) }, { stopSelf(startId) @@ -213,7 +215,7 @@ class LibraryUpdateService : Service() { var listToUpdate = if (categoryId != -1) db.getLibraryMangas().executeAsBlocking().filter { it.category == categoryId } else { - val categoriesToUpdate = preferences.libraryUpdateCategories().getOrDefault().map { it.toInt() } + val categoriesToUpdate = preferences.libraryUpdateCategories().getOrDefault().map(String::toInt) if (categoriesToUpdate.isNotEmpty()) db.getLibraryMangas().executeAsBlocking() .filter { it.category in categoriesToUpdate } @@ -255,7 +257,7 @@ class LibraryUpdateService : Service() { // Emit each manga and update it sequentially. return Observable.from(mangaToUpdate) // Notify manga that will update. - .doOnNext { showProgressNotification(it, count.andIncrement, mangaToUpdate.size, cancelPendingIntent) } + .doOnNext { showProgressNotification(it, count.andIncrement, mangaToUpdate.size) } // Update the chapters of the manga. .concatMap { manga -> updateManga(manga) @@ -267,11 +269,11 @@ class LibraryUpdateService : Service() { // Filter out mangas without new chapters (or failed). .filter { pair -> pair.first.isNotEmpty() } .doOnNext { - if (downloadNew) { - if (categoriesToDownload.isEmpty() || manga.category in categoriesToDownload) { - downloadChapters(manga, it.first) - hasDownloads = true - } + if (downloadNew && (categoriesToDownload.isEmpty() || + manga.category in categoriesToDownload)) { + + downloadChapters(manga, it.first) + hasDownloads = true } } // Convert to the manga that contains new chapters. @@ -287,16 +289,17 @@ class LibraryUpdateService : Service() { } // Notify result of the overall update. .doOnCompleted { - if (newUpdates.isEmpty()) { - cancelNotification() - } else { - showResultNotification(newUpdates, failedUpdates) - if (downloadNew) { - if (hasDownloads) { - DownloadService.start(this) - } + cancelProgressNotification() + if (newUpdates.isNotEmpty()) { + showResultNotification(newUpdates) + if (downloadNew && hasDownloads) { + DownloadService.start(this) } } + + if (failedUpdates.isNotEmpty()) { + Timber.e("Failed updating: ${failedUpdates.map { it.title }}") + } } } @@ -337,7 +340,7 @@ class LibraryUpdateService : Service() { // Emit each manga and update it sequentially. return Observable.from(mangaToUpdate) // Notify manga that will update. - .doOnNext { showProgressNotification(it, count.andIncrement, mangaToUpdate.size, cancelPendingIntent) } + .doOnNext { showProgressNotification(it, count.andIncrement, mangaToUpdate.size) } // Update the details of the manga. .concatMap { manga -> val source = sourceManager.get(manga.source) as? HttpSource @@ -352,73 +355,10 @@ class LibraryUpdateService : Service() { .onErrorReturn { manga } } .doOnCompleted { - cancelNotification() + cancelProgressNotification() } } - /** - * Returns the text that will be displayed in the notification when there are new chapters. - * - * @param updates a list of manga that contains new chapters. - * @param failedUpdates a list of manga that failed to update. - * @return the body of the notification to display. - */ - private fun getUpdatedMangasBody(updates: List, failedUpdates: List): String { - return buildString { - if (updates.isEmpty()) { - append(getString(R.string.notification_no_new_chapters)) - append("\n") - } else { - append(getString(R.string.notification_new_chapters)) - for (manga in updates) { - append("\n") - append(manga.title.chop(45)) - } - } - if (!failedUpdates.isEmpty()) { - append("\n\n") - append(getString(R.string.notification_manga_update_failed)) - for (manga in failedUpdates) { - append("\n") - append(manga.title.chop(45)) - } - } - } - } - - /** - * Creates and acquires a wake lock until the library is updated. - */ - private fun createAndAcquireWakeLock() { - wakeLock = (getSystemService(Context.POWER_SERVICE) as PowerManager).newWakeLock( - PowerManager.PARTIAL_WAKE_LOCK, "LibraryUpdateService:WakeLock") - wakeLock.acquire() - } - - /** - * Releases the wake lock if it's held. - */ - private fun destroyWakeLock() { - if (wakeLock.isHeld) { - wakeLock.release() - } - } - - /** - * Shows the notification with the given title and body. - * - * @param title the title of the notification. - * @param body the body of the notification. - */ - private fun showNotification(title: String, body: String) { - notificationManager.notify(notificationId, notification { - setSmallIcon(R.drawable.ic_refresh_white_24dp_img) - setLargeIcon(notificationBitmap) - setContentTitle(title) - setContentText(body) - }) - } - /** * Shows the notification containing the currently updating manga and the progress. * @@ -426,52 +366,60 @@ class LibraryUpdateService : Service() { * @param current the current progress. * @param total the total progress. */ - private fun showProgressNotification(manga: Manga, current: Int, total: Int, cancelIntent: PendingIntent) { - notificationManager.notify(notificationId, notification { - setSmallIcon(R.drawable.ic_refresh_white_24dp_img) - setLargeIcon(notificationBitmap) - setContentTitle(manga.title) - setProgress(total, current, false) - setOngoing(true) - addAction(R.drawable.ic_clear_grey_24dp_img, getString(android.R.string.cancel), cancelIntent) - }) + private fun showProgressNotification(manga: Manga, current: Int, total: Int) { + notificationManager.notify(Constants.NOTIFICATION_LIBRARY_PROGRESS_ID, progressNotification + .setContentTitle(manga.title) + .setProgress(total, current, false) + .build()) } - /** * Shows the notification containing the result of the update done by the service. * * @param updates a list of manga with new updates. - * @param failed a list of manga that failed to update. */ - private fun showResultNotification(updates: List, failed: List) { - val title = getString(R.string.notification_update_completed) - val body = getUpdatedMangasBody(updates, failed) + private fun showResultNotification(updates: List) { + val title = getString(R.string.notification_new_chapters) + val newUpdates = updates.map { it.title.chop(45) }.toMutableSet() - notificationManager.notify(notificationId, notification { - setSmallIcon(R.drawable.ic_refresh_white_24dp_img) + // Append new chapters from a previous, existing notification + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + val previousNotification = notificationManager.activeNotifications + .find { it.id == Constants.NOTIFICATION_LIBRARY_RESULT_ID } + + if (previousNotification != null) { + val oldUpdates = previousNotification.notification.extras + .getString(Notification.EXTRA_BIG_TEXT, "") + .split("\n") + + newUpdates += oldUpdates + } + } + + notificationManager.notify(Constants.NOTIFICATION_LIBRARY_RESULT_ID, notification { + setSmallIcon(R.drawable.ic_book_white_24dp) setLargeIcon(notificationBitmap) setContentTitle(title) - setStyle(NotificationCompat.BigTextStyle().bigText(body)) - setContentIntent(notificationIntent) + setStyle(NotificationCompat.BigTextStyle().bigText(newUpdates.joinToString("\n"))) + setContentIntent(getNotificationIntent()) setAutoCancel(true) }) } /** - * Cancels the notification. + * Cancels the progress notification. */ - private fun cancelNotification() { - notificationManager.cancel(notificationId) + private fun cancelProgressNotification() { + notificationManager.cancel(Constants.NOTIFICATION_LIBRARY_PROGRESS_ID) } /** - * Property that returns an intent to open the main activity. + * Returns an intent to open the main activity. */ - private val notificationIntent: PendingIntent - get() { - val intent = Intent(this, MainActivity::class.java) - intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP - return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) - } + private fun getNotificationIntent(): PendingIntent { + val intent = Intent(this, MainActivity::class.java) + intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP + return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) + } + } 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 e046510175..18007bd85d 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 @@ -45,7 +45,7 @@ class NotificationReceiver : BroadcastReceiver() { ACTION_DELETE_IMAGE -> deleteImage(context, intent.getStringExtra(EXTRA_FILE_LOCATION), intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1)) // Cancel library update and dismiss notification - ACTION_CANCEL_LIBRARY_UPDATE -> cancelLibraryUpdate(context, Constants.NOTIFICATION_LIBRARY_ID) + ACTION_CANCEL_LIBRARY_UPDATE -> cancelLibraryUpdate(context, Constants.NOTIFICATION_LIBRARY_PROGRESS_ID) // Open reader activity ACTION_OPEN_CHAPTER -> { openChapter(context, intent.getLongExtra(EXTRA_MANGA_ID, -1), diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryFragment.kt index 9160224392..0b6d92fe46 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryFragment.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryFragment.kt @@ -441,11 +441,11 @@ class LibraryFragment : BaseRxFragment(), ActionMode.Callback if (presenter.editCoverWithStream(it, manga)) { // TODO refresh cover } else { - context.toast(R.string.notification_manga_update_failed) + context.toast(R.string.notification_cover_update_failed) } } } catch (error: IOException) { - context.toast(R.string.notification_manga_update_failed) + context.toast(R.string.notification_cover_update_failed) Timber.e(error) } } diff --git a/app/src/main/res/drawable-hdpi/ic_book_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_book_white_24dp.png new file mode 100644 index 0000000000..0fd780e778 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_book_white_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_book_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_book_white_24dp.png new file mode 100644 index 0000000000..8b02f9ac2c Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_book_white_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_book_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_book_white_24dp.png new file mode 100644 index 0000000000..5a5ee30413 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_book_white_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_book_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_book_white_24dp.png new file mode 100644 index 0000000000..d181a32150 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_book_white_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_book_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_book_white_24dp.png new file mode 100644 index 0000000000..938eff46c5 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_book_white_24dp.png differ diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index 69c819c4fc..f8e4452e9e 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -331,11 +331,7 @@ Напредък: %1$d/%2$d - Обновяването завършено. - Възникна неочаквана грешка при обновяването на библиотеката. - Не бяха открити нови глави. Открити нови глави за: - Не успяха да се обновят: Грешка при обновяването на корицата. Моля, добавете мангата в библиотеката си, преди да направите това. Синхронизиране отказано diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index ff82bcd3e9..781a847fd5 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -265,11 +265,7 @@ Progreso de actualización: %1$d/%2$d - Actualización completa - Se ha producido un error inesperado al actualizar la librería - No se encontraron nuevos capítulos - Capítulos nuevos encontrados para: - Fallaron al actualizar: + Nuevos capítulos encontrados Por favor añada el manga a la librería antes de hacer esto Sincronización cancelada El dispositivo no está cargando diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index e9f448295a..acb93d103f 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -313,9 +313,7 @@ Progression mise à jour: %1$d/%2$d - Mise à jour terminée - Aucun nouveau chapitre trouvé - Des nouveaux chapitres ont été trouvés pour : + Des nouveaux chapitres ont été trouvés La mise à jour de la couverture a échoué Veuillez ajouter le manga dans votre bibliothèque avant de faire cela Non branché @@ -368,9 +366,7 @@ Du cinquième au dernier chapitre Connexion réussie Pas de titre - Impossible de mettre à jour le manga: Synchronisation annulée - Une erreur inattendue s\'est produite lors de la mise à jour de la bibliothèque Effacer le cache des chapitres Supprimer quand marqué comme lu Restauration de la sauvegarde. Veuillez patienter… diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index ab7da63cd3..5415b7c218 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -322,11 +322,7 @@ Progressione aggiornamento: %1$d/%2$d - Aggiornamento completato - Si è verificato un errore imprevisto durante l\'aggiornamento della libreria - Non sono stati trovati nuovi capitoli - Nuovi capitoli trovati per: - Impossibile aggiornare: + Nuovi capitoli trovati Impossibile aggiornare la copertina Prima di fare questo per favore aggiungi il manga alla libreria Sincronizzazione annullata diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 8bc775afab..3c4d015fa1 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -272,11 +272,7 @@ Progresso da atualização: %1$d/%2$d - Atualização completa - Ocorreu um erro inesperado ao atualizar a biblioteca - Sem novos capítulos encontrados - Novos capítulos encontrados para: - Falha ao atualizar a manga: + Novos capítulos encontrados Por favor adicione a manga à sua biblioteca antes de fazer isto Sincronização cancelada O dispositivo não está ligado ao carregador diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 6eb73b1283..40c432a9c1 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -171,15 +171,11 @@ Пожалуйста включите хотя бы один источник Не удалось обновить обложку Пожалуйста добавьте мангу в свою библиотеку, перед тем как делать это - Не удалось обновить мангу: Новые главы найдены для: Соединение не доступно Синхронизация отменена - Новые главы не найдены Не заряжается Синхронизация отменена - Обновление завершено - Неожиданная ошибка случилась пока обновлялась библиотека Статус обновления: %1$d/%2$d Заморожено Выпускается diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index ccaefadb8a..19deaec102 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -332,11 +332,7 @@ Tiến độ cập nhật: %1$d/%2$d - Cập nhật đã hoàn thành - Một lỗi không mong đợi đã xảy ra khi cập nhật thư viện - Không tìm thấy chương mới Đã tìm thấy các chương mới cho: - Cập nhật thất bại: Cập nhật ảnh bìa thất bại Hãy thêm truyện vào thư viện trước khi thực hiện Đã hủy đồng bộ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2f11f948df..f2c72db0f2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -339,11 +339,7 @@ Update progress: %1$d/%2$d - Update completed - An unexpected error occurred while updating the library - No new chapters found - New chapters found for: - Failed to update manga: + New chapters found Failed to update cover Please add the manga to your library before doing this Sync canceled