Keep new chapters notification across updates

This commit is contained in:
len 2017-03-25 21:38:46 +01:00
parent e619870eec
commit de8fa09366
17 changed files with 102 additions and 186 deletions

View file

@ -1,10 +1,10 @@
package eu.kanade.tachiyomi package eu.kanade.tachiyomi
object Constants { object Constants {
const val NOTIFICATION_LIBRARY_ID = 1 const val NOTIFICATION_LIBRARY_PROGRESS_ID = 1
const val NOTIFICATION_UPDATER_ID = 2 const val NOTIFICATION_LIBRARY_RESULT_ID = 2
const val NOTIFICATION_DOWNLOAD_CHAPTER_ID = 3 const val NOTIFICATION_UPDATER_ID = 3
const val NOTIFICATION_DOWNLOAD_CHAPTER_ERROR_ID = 4 const val NOTIFICATION_DOWNLOAD_CHAPTER_ID = 4
const val NOTIFICATION_DOWNLOAD_IMAGE_ID = 5 const val NOTIFICATION_DOWNLOAD_CHAPTER_ERROR_ID = 5
const val NOTIFICATION_DOWNLOAD_IMAGE_ID = 6
} }

View file

@ -1,10 +1,12 @@
package eu.kanade.tachiyomi.data.library package eu.kanade.tachiyomi.data.library
import android.app.Notification
import android.app.PendingIntent import android.app.PendingIntent
import android.app.Service import android.app.Service
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.os.Build
import android.os.IBinder import android.os.IBinder
import android.os.PowerManager import android.os.PowerManager
import android.support.v4.app.NotificationCompat import android.support.v4.app.NotificationCompat
@ -28,7 +30,9 @@ import eu.kanade.tachiyomi.util.*
import rx.Observable import rx.Observable
import rx.Subscription import rx.Subscription
import rx.schedulers.Schedulers 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.*
import java.util.concurrent.atomic.AtomicInteger 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 * progress of the update, and if case of an unexpected error, this service will be silently
* destroyed. * destroyed.
*/ */
class LibraryUpdateService : Service() { class LibraryUpdateService(
val db: DatabaseHelper = Injekt.get(),
/** val sourceManager: SourceManager = Injekt.get(),
* Database helper. val preferences: PreferencesHelper = Injekt.get(),
*/ val downloadManager: DownloadManager = Injekt.get()
val db: DatabaseHelper by injectLazy() ) : Service() {
/**
* Source manager.
*/
val sourceManager: SourceManager by injectLazy()
/**
* Preferences.
*/
val preferences: PreferencesHelper by injectLazy()
/**
* Download Manager
*/
val downloadManager: DownloadManager by injectLazy()
/** /**
* Wake lock that will be held until the service is destroyed. * 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 * 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 { private val notificationBitmap by lazy {
BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher) 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 { companion object {
/** /**
@ -144,16 +142,20 @@ class LibraryUpdateService : Service() {
*/ */
override fun onCreate() { override fun onCreate() {
super.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 * Method called when the service is destroyed. It destroys subscriptions and releases the wake
* the alarm and release the wake lock. * lock.
*/ */
override fun onDestroy() { override fun onDestroy() {
subscription?.unsubscribe() subscription?.unsubscribe()
destroyWakeLock() if (wakeLock.isHeld) {
wakeLock.release()
}
super.onDestroy() super.onDestroy()
} }
@ -192,7 +194,7 @@ class LibraryUpdateService : Service() {
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.subscribe({ .subscribe({
}, { }, {
showNotification(getString(R.string.notification_update_error), "") Timber.e(it)
stopSelf(startId) stopSelf(startId)
}, { }, {
stopSelf(startId) stopSelf(startId)
@ -213,7 +215,7 @@ class LibraryUpdateService : Service() {
var listToUpdate = if (categoryId != -1) var listToUpdate = if (categoryId != -1)
db.getLibraryMangas().executeAsBlocking().filter { it.category == categoryId } db.getLibraryMangas().executeAsBlocking().filter { it.category == categoryId }
else { else {
val categoriesToUpdate = preferences.libraryUpdateCategories().getOrDefault().map { it.toInt() } val categoriesToUpdate = preferences.libraryUpdateCategories().getOrDefault().map(String::toInt)
if (categoriesToUpdate.isNotEmpty()) if (categoriesToUpdate.isNotEmpty())
db.getLibraryMangas().executeAsBlocking() db.getLibraryMangas().executeAsBlocking()
.filter { it.category in categoriesToUpdate } .filter { it.category in categoriesToUpdate }
@ -255,7 +257,7 @@ class LibraryUpdateService : Service() {
// Emit each manga and update it sequentially. // Emit each manga and update it sequentially.
return Observable.from(mangaToUpdate) return Observable.from(mangaToUpdate)
// Notify manga that will update. // 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. // Update the chapters of the manga.
.concatMap { manga -> .concatMap { manga ->
updateManga(manga) updateManga(manga)
@ -267,13 +269,13 @@ class LibraryUpdateService : Service() {
// Filter out mangas without new chapters (or failed). // Filter out mangas without new chapters (or failed).
.filter { pair -> pair.first.isNotEmpty() } .filter { pair -> pair.first.isNotEmpty() }
.doOnNext { .doOnNext {
if (downloadNew) { if (downloadNew && (categoriesToDownload.isEmpty() ||
if (categoriesToDownload.isEmpty() || manga.category in categoriesToDownload) { manga.category in categoriesToDownload)) {
downloadChapters(manga, it.first) downloadChapters(manga, it.first)
hasDownloads = true hasDownloads = true
} }
} }
}
// Convert to the manga that contains new chapters. // Convert to the manga that contains new chapters.
.map { manga } .map { manga }
} }
@ -287,15 +289,16 @@ class LibraryUpdateService : Service() {
} }
// Notify result of the overall update. // Notify result of the overall update.
.doOnCompleted { .doOnCompleted {
if (newUpdates.isEmpty()) { cancelProgressNotification()
cancelNotification() if (newUpdates.isNotEmpty()) {
} else { showResultNotification(newUpdates)
showResultNotification(newUpdates, failedUpdates) if (downloadNew && hasDownloads) {
if (downloadNew) {
if (hasDownloads) {
DownloadService.start(this) 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. // Emit each manga and update it sequentially.
return Observable.from(mangaToUpdate) return Observable.from(mangaToUpdate)
// Notify manga that will update. // 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. // Update the details of the manga.
.concatMap { manga -> .concatMap { manga ->
val source = sourceManager.get(manga.source) as? HttpSource val source = sourceManager.get(manga.source) as? HttpSource
@ -352,73 +355,10 @@ class LibraryUpdateService : Service() {
.onErrorReturn { manga } .onErrorReturn { manga }
} }
.doOnCompleted { .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<Manga>, failedUpdates: List<Manga>): 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. * Shows the notification containing the currently updating manga and the progress.
* *
@ -426,52 +366,60 @@ class LibraryUpdateService : Service() {
* @param current the current progress. * @param current the current progress.
* @param total the total progress. * @param total the total progress.
*/ */
private fun showProgressNotification(manga: Manga, current: Int, total: Int, cancelIntent: PendingIntent) { private fun showProgressNotification(manga: Manga, current: Int, total: Int) {
notificationManager.notify(notificationId, notification { notificationManager.notify(Constants.NOTIFICATION_LIBRARY_PROGRESS_ID, progressNotification
setSmallIcon(R.drawable.ic_refresh_white_24dp_img) .setContentTitle(manga.title)
setLargeIcon(notificationBitmap) .setProgress(total, current, false)
setContentTitle(manga.title) .build())
setProgress(total, current, false)
setOngoing(true)
addAction(R.drawable.ic_clear_grey_24dp_img, getString(android.R.string.cancel), cancelIntent)
})
} }
/** /**
* Shows the notification containing the result of the update done by the service. * Shows the notification containing the result of the update done by the service.
* *
* @param updates a list of manga with new updates. * @param updates a list of manga with new updates.
* @param failed a list of manga that failed to update.
*/ */
private fun showResultNotification(updates: List<Manga>, failed: List<Manga>) { private fun showResultNotification(updates: List<Manga>) {
val title = getString(R.string.notification_update_completed) val title = getString(R.string.notification_new_chapters)
val body = getUpdatedMangasBody(updates, failed) val newUpdates = updates.map { it.title.chop(45) }.toMutableSet()
notificationManager.notify(notificationId, notification { // Append new chapters from a previous, existing notification
setSmallIcon(R.drawable.ic_refresh_white_24dp_img) 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) setLargeIcon(notificationBitmap)
setContentTitle(title) setContentTitle(title)
setStyle(NotificationCompat.BigTextStyle().bigText(body)) setStyle(NotificationCompat.BigTextStyle().bigText(newUpdates.joinToString("\n")))
setContentIntent(notificationIntent) setContentIntent(getNotificationIntent())
setAutoCancel(true) setAutoCancel(true)
}) })
} }
/** /**
* Cancels the notification. * Cancels the progress notification.
*/ */
private fun cancelNotification() { private fun cancelProgressNotification() {
notificationManager.cancel(notificationId) 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 private fun getNotificationIntent(): PendingIntent {
get() {
val intent = Intent(this, MainActivity::class.java) val intent = Intent(this, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) return PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
} }
} }

View file

@ -45,7 +45,7 @@ class NotificationReceiver : BroadcastReceiver() {
ACTION_DELETE_IMAGE -> deleteImage(context, intent.getStringExtra(EXTRA_FILE_LOCATION), ACTION_DELETE_IMAGE -> deleteImage(context, intent.getStringExtra(EXTRA_FILE_LOCATION),
intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1)) intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1))
// Cancel library update and dismiss notification // 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 // Open reader activity
ACTION_OPEN_CHAPTER -> { ACTION_OPEN_CHAPTER -> {
openChapter(context, intent.getLongExtra(EXTRA_MANGA_ID, -1), openChapter(context, intent.getLongExtra(EXTRA_MANGA_ID, -1),

View file

@ -441,11 +441,11 @@ class LibraryFragment : BaseRxFragment<LibraryPresenter>(), ActionMode.Callback
if (presenter.editCoverWithStream(it, manga)) { if (presenter.editCoverWithStream(it, manga)) {
// TODO refresh cover // TODO refresh cover
} else { } else {
context.toast(R.string.notification_manga_update_failed) context.toast(R.string.notification_cover_update_failed)
} }
} }
} catch (error: IOException) { } catch (error: IOException) {
context.toast(R.string.notification_manga_update_failed) context.toast(R.string.notification_cover_update_failed)
Timber.e(error) Timber.e(error)
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

View file

@ -331,11 +331,7 @@
<!-- Library update service notifications --> <!-- Library update service notifications -->
<string name="notification_update_progress">Напредък: %1$d/%2$d</string> <string name="notification_update_progress">Напредък: %1$d/%2$d</string>
<string name="notification_update_completed">Обновяването завършено.</string>
<string name="notification_update_error">Възникна неочаквана грешка при обновяването на библиотеката.</string>
<string name="notification_no_new_chapters">Не бяха открити нови глави.</string>
<string name="notification_new_chapters">Открити нови глави за:</string> <string name="notification_new_chapters">Открити нови глави за:</string>
<string name="notification_manga_update_failed">Не успяха да се обновят:</string>
<string name="notification_cover_update_failed">Грешка при обновяването на корицата.</string> <string name="notification_cover_update_failed">Грешка при обновяването на корицата.</string>
<string name="notification_first_add_to_library">Моля, добавете мангата в библиотеката си, преди да направите това.</string> <string name="notification_first_add_to_library">Моля, добавете мангата в библиотеката си, преди да направите това.</string>
<string name="notification_not_connected_to_ac_title">Синхронизиране отказано</string> <string name="notification_not_connected_to_ac_title">Синхронизиране отказано</string>

View file

@ -265,11 +265,7 @@
<!-- Library update service notifications --> <!-- Library update service notifications -->
<string name="notification_update_progress">Progreso de actualización: %1$d/%2$d</string> <string name="notification_update_progress">Progreso de actualización: %1$d/%2$d</string>
<string name="notification_update_completed">Actualización completa</string> <string name="notification_new_chapters">Nuevos capítulos encontrados</string>
<string name="notification_update_error">Se ha producido un error inesperado al actualizar la librería</string>
<string name="notification_no_new_chapters">No se encontraron nuevos capítulos</string>
<string name="notification_new_chapters">Capítulos nuevos encontrados para:</string>
<string name="notification_manga_update_failed">Fallaron al actualizar:</string>
<string name="notification_first_add_to_library">Por favor añada el manga a la librería antes de hacer esto</string> <string name="notification_first_add_to_library">Por favor añada el manga a la librería antes de hacer esto</string>
<string name="notification_not_connected_to_ac_title">Sincronización cancelada</string> <string name="notification_not_connected_to_ac_title">Sincronización cancelada</string>
<string name="notification_not_connected_to_ac_body">El dispositivo no está cargando</string> <string name="notification_not_connected_to_ac_body">El dispositivo no está cargando</string>

View file

@ -313,9 +313,7 @@
<!-- Library update service notifications --> <!-- Library update service notifications -->
<string name="notification_update_progress">Progression mise à jour: %1$d/%2$d</string> <string name="notification_update_progress">Progression mise à jour: %1$d/%2$d</string>
<string name="notification_update_completed">Mise à jour terminée</string> <string name="notification_new_chapters">Des nouveaux chapitres ont été trouvés</string>
<string name="notification_no_new_chapters">Aucun nouveau chapitre trouvé</string>
<string name="notification_new_chapters">Des nouveaux chapitres ont été trouvés pour :</string>
<string name="notification_cover_update_failed">La mise à jour de la couverture a échoué</string> <string name="notification_cover_update_failed">La mise à jour de la couverture a échoué</string>
<string name="notification_first_add_to_library">Veuillez ajouter le manga dans votre bibliothèque avant de faire cela</string> <string name="notification_first_add_to_library">Veuillez ajouter le manga dans votre bibliothèque avant de faire cela</string>
<string name="notification_not_connected_to_ac_body">Non branché</string> <string name="notification_not_connected_to_ac_body">Non branché</string>
@ -368,9 +366,7 @@
<string name="fifth_to_last">Du cinquième au dernier chapitre</string> <string name="fifth_to_last">Du cinquième au dernier chapitre</string>
<string name="login_success">Connexion réussie</string> <string name="login_success">Connexion réussie</string>
<string name="manga_chapter_no_title">Pas de titre</string> <string name="manga_chapter_no_title">Pas de titre</string>
<string name="notification_manga_update_failed">Impossible de mettre à jour le manga:</string>
<string name="notification_not_connected_to_ac_title">Synchronisation annulée</string> <string name="notification_not_connected_to_ac_title">Synchronisation annulée</string>
<string name="notification_update_error">Une erreur inattendue s\'est produite lors de la mise à jour de la bibliothèque</string>
<string name="pref_clear_chapter_cache">Effacer le cache des chapitres</string> <string name="pref_clear_chapter_cache">Effacer le cache des chapitres</string>
<string name="pref_remove_after_marked_as_read">Supprimer quand marqué comme lu</string> <string name="pref_remove_after_marked_as_read">Supprimer quand marqué comme lu</string>
<string name="restore_please_wait">Restauration de la sauvegarde. Veuillez patienter…</string> <string name="restore_please_wait">Restauration de la sauvegarde. Veuillez patienter…</string>

View file

@ -322,11 +322,7 @@
<!-- Library update service notifications --> <!-- Library update service notifications -->
<string name="notification_update_progress">Progressione aggiornamento: %1$d/%2$d</string> <string name="notification_update_progress">Progressione aggiornamento: %1$d/%2$d</string>
<string name="notification_update_completed">Aggiornamento completato</string> <string name="notification_new_chapters">Nuovi capitoli trovati</string>
<string name="notification_update_error">Si è verificato un errore imprevisto durante l\'aggiornamento della libreria</string>
<string name="notification_no_new_chapters">Non sono stati trovati nuovi capitoli</string>
<string name="notification_new_chapters">Nuovi capitoli trovati per:</string>
<string name="notification_manga_update_failed">Impossibile aggiornare:</string>
<string name="notification_cover_update_failed">Impossibile aggiornare la copertina</string> <string name="notification_cover_update_failed">Impossibile aggiornare la copertina</string>
<string name="notification_first_add_to_library">Prima di fare questo per favore aggiungi il manga alla libreria</string> <string name="notification_first_add_to_library">Prima di fare questo per favore aggiungi il manga alla libreria</string>
<string name="notification_not_connected_to_ac_title">Sincronizzazione annullata</string> <string name="notification_not_connected_to_ac_title">Sincronizzazione annullata</string>

View file

@ -272,11 +272,7 @@
<!-- Library update service notifications --> <!-- Library update service notifications -->
<string name="notification_update_progress">Progresso da atualização: %1$d/%2$d</string> <string name="notification_update_progress">Progresso da atualização: %1$d/%2$d</string>
<string name="notification_update_completed">Atualização completa</string> <string name="notification_new_chapters">Novos capítulos encontrados</string>
<string name="notification_update_error">Ocorreu um erro inesperado ao atualizar a biblioteca</string>
<string name="notification_no_new_chapters">Sem novos capítulos encontrados</string>
<string name="notification_new_chapters">Novos capítulos encontrados para:</string>
<string name="notification_manga_update_failed">Falha ao atualizar a manga:</string>
<string name="notification_first_add_to_library">Por favor adicione a manga à sua biblioteca antes de fazer isto</string> <string name="notification_first_add_to_library">Por favor adicione a manga à sua biblioteca antes de fazer isto</string>
<string name="notification_not_connected_to_ac_title">Sincronização cancelada</string> <string name="notification_not_connected_to_ac_title">Sincronização cancelada</string>
<string name="notification_not_connected_to_ac_body">O dispositivo não está ligado ao carregador</string> <string name="notification_not_connected_to_ac_body">O dispositivo não está ligado ao carregador</string>

View file

@ -171,15 +171,11 @@
<string name="no_valid_sources">Пожалуйста включите хотя бы один источник</string> <string name="no_valid_sources">Пожалуйста включите хотя бы один источник</string>
<string name="notification_cover_update_failed">Не удалось обновить обложку</string> <string name="notification_cover_update_failed">Не удалось обновить обложку</string>
<string name="notification_first_add_to_library">Пожалуйста добавьте мангу в свою библиотеку, перед тем как делать это</string> <string name="notification_first_add_to_library">Пожалуйста добавьте мангу в свою библиотеку, перед тем как делать это</string>
<string name="notification_manga_update_failed">Не удалось обновить мангу:</string>
<string name="notification_new_chapters">Новые главы найдены для:</string> <string name="notification_new_chapters">Новые главы найдены для:</string>
<string name="notification_no_connection_body">Соединение не доступно</string> <string name="notification_no_connection_body">Соединение не доступно</string>
<string name="notification_no_connection_title">Синхронизация отменена</string> <string name="notification_no_connection_title">Синхронизация отменена</string>
<string name="notification_no_new_chapters">Новые главы не найдены</string>
<string name="notification_not_connected_to_ac_body">Не заряжается</string> <string name="notification_not_connected_to_ac_body">Не заряжается</string>
<string name="notification_not_connected_to_ac_title">Синхронизация отменена</string> <string name="notification_not_connected_to_ac_title">Синхронизация отменена</string>
<string name="notification_update_completed">Обновление завершено</string>
<string name="notification_update_error">Неожиданная ошибка случилась пока обновлялась библиотека</string>
<string name="notification_update_progress">Статус обновления: %1$d/%2$d</string> <string name="notification_update_progress">Статус обновления: %1$d/%2$d</string>
<string name="on_hold">Заморожено</string> <string name="on_hold">Заморожено</string>
<string name="ongoing">Выпускается</string> <string name="ongoing">Выпускается</string>

View file

@ -332,11 +332,7 @@
<!-- Library update service notifications --> <!-- Library update service notifications -->
<string name="notification_update_progress">Tiến độ cập nhật: %1$d/%2$d</string> <string name="notification_update_progress">Tiến độ cập nhật: %1$d/%2$d</string>
<string name="notification_update_completed">Cập nhật đã hoàn thành</string>
<string name="notification_update_error">Một lỗi không mong đợi đã xảy ra khi cập nhật thư viện</string>
<string name="notification_no_new_chapters">Không tìm thấy chương mới</string>
<string name="notification_new_chapters">Đã tìm thấy các chương mới cho:</string> <string name="notification_new_chapters">Đã tìm thấy các chương mới cho:</string>
<string name="notification_manga_update_failed">Cập nhật thất bại:</string>
<string name="notification_cover_update_failed">Cập nhật ảnh bìa thất bại</string> <string name="notification_cover_update_failed">Cập nhật ảnh bìa thất bại</string>
<string name="notification_first_add_to_library">Hãy thêm truyện vào thư viện trước khi thực hiện</string> <string name="notification_first_add_to_library">Hãy thêm truyện vào thư viện trước khi thực hiện</string>
<string name="notification_not_connected_to_ac_title">Đã hủy đồng bộ</string> <string name="notification_not_connected_to_ac_title">Đã hủy đồng bộ</string>

View file

@ -339,11 +339,7 @@
<!-- Library update service notifications --> <!-- Library update service notifications -->
<string name="notification_update_progress">Update progress: %1$d/%2$d</string> <string name="notification_update_progress">Update progress: %1$d/%2$d</string>
<string name="notification_update_completed">Update completed</string> <string name="notification_new_chapters">New chapters found</string>
<string name="notification_update_error">An unexpected error occurred while updating the library</string>
<string name="notification_no_new_chapters">No new chapters found</string>
<string name="notification_new_chapters">New chapters found for:</string>
<string name="notification_manga_update_failed">Failed to update manga:</string>
<string name="notification_cover_update_failed">Failed to update cover</string> <string name="notification_cover_update_failed">Failed to update cover</string>
<string name="notification_first_add_to_library">Please add the manga to your library before doing this</string> <string name="notification_first_add_to_library">Please add the manga to your library before doing this</string>
<string name="notification_not_connected_to_ac_title">Sync canceled</string> <string name="notification_not_connected_to_ac_title">Sync canceled</string>