Version 0.9.2

Fixes to notification text when there are multiple chapters
Simplified errors now show after restoring a backup on the popup dialog
Fixed last updated sorting being in a jumbled order after restoring (Note: if the list is still jumbled after restore, refersh your library)
Fixed notifcations not expanding on older devices
This commit is contained in:
Jay 2019-12-14 12:17:20 -08:00
parent 74644ec54e
commit cebed39b20
10 changed files with 87 additions and 17 deletions

View File

@ -38,8 +38,8 @@ android {
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 29 targetSdkVersion 29
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
versionCode 43 versionCode 44
versionName "0.9.1" versionName '0.9.2'
buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\"" buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\""
buildConfigField "String", "COMMIT_SHA", "\"${getGitSha()}\"" buildConfigField "String", "COMMIT_SHA", "\"${getGitSha()}\""

View File

@ -20,4 +20,5 @@ object BackupConst {
const val EXTRA_TIME = "$ID.$INTENT_FILTER.EXTRA_TIME" const val EXTRA_TIME = "$ID.$INTENT_FILTER.EXTRA_TIME"
const val EXTRA_ERROR_FILE_PATH = "$ID.$INTENT_FILTER.EXTRA_ERROR_FILE_PATH" const val EXTRA_ERROR_FILE_PATH = "$ID.$INTENT_FILTER.EXTRA_ERROR_FILE_PATH"
const val EXTRA_ERROR_FILE = "$ID.$INTENT_FILTER.EXTRA_ERROR_FILE" const val EXTRA_ERROR_FILE = "$ID.$INTENT_FILTER.EXTRA_ERROR_FILE"
const val EXTRA_MINI_ERROR= "$ID.$INTENT_FILTER.EXTRA_MINI_ERROR"
} }

View File

@ -23,6 +23,7 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.* import eu.kanade.tachiyomi.data.database.models.*
import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceNotFoundException
import eu.kanade.tachiyomi.util.chop import eu.kanade.tachiyomi.util.chop
import eu.kanade.tachiyomi.util.isServiceRunning import eu.kanade.tachiyomi.util.isServiceRunning
import eu.kanade.tachiyomi.util.sendLocalBroadcast import eu.kanade.tachiyomi.util.sendLocalBroadcast
@ -104,6 +105,17 @@ class BackupRestoreService : Service() {
*/ */
private val errors = mutableListOf<Pair<Date, String>>() private val errors = mutableListOf<Pair<Date, String>>()
/**
* List containing distinct errors
*/
private val errorsMini = mutableListOf<String>()
/**
* List containing missing sources
*/
private val sourcesMissing = mutableListOf<Long>()
/** /**
* Backup manager * Backup manager
*/ */
@ -203,6 +215,7 @@ class BackupRestoreService : Service() {
restoreAmount = mangasJson.size() + 1 // +1 for categories restoreAmount = mangasJson.size() + 1 // +1 for categories
restoreProgress = 0 restoreProgress = 0
errors.clear() errors.clear()
errorsMini.clear()
// Restore categories // Restore categories
json.get(CATEGORIES)?.let { json.get(CATEGORIES)?.let {
@ -243,6 +256,14 @@ class BackupRestoreService : Service() {
putExtra(BackupConst.EXTRA_ERRORS, errors.size) putExtra(BackupConst.EXTRA_ERRORS, errors.size)
putExtra(BackupConst.EXTRA_ERROR_FILE_PATH, logFile.parent) putExtra(BackupConst.EXTRA_ERROR_FILE_PATH, logFile.parent)
putExtra(BackupConst.EXTRA_ERROR_FILE, logFile.name) putExtra(BackupConst.EXTRA_ERROR_FILE, logFile.name)
val sourceMissingCount = sourcesMissing.distinct().size
val sourceErrors = getString(R.string.sources_missing, sourceMissingCount)
val otherErrors = errorsMini.distinct().joinToString("\n")
putExtra(BackupConst.EXTRA_MINI_ERROR,
if (sourceMissingCount > 0) sourceErrors + "\n" + otherErrors
else otherErrors
)
putExtra(BackupConst.EXTRA_ERRORS, errors.size)
putExtra(BackupConst.ACTION, BackupConst.ACTION_RESTORE_COMPLETED_DIALOG) putExtra(BackupConst.ACTION, BackupConst.ACTION_RESTORE_COMPLETED_DIALOG)
} }
sendLocalBroadcast(completeIntent) sendLocalBroadcast(completeIntent)
@ -323,6 +344,12 @@ class BackupRestoreService : Service() {
return backupManager.restoreMangaFetchObservable(source, manga) return backupManager.restoreMangaFetchObservable(source, manga)
.onErrorReturn { .onErrorReturn {
errors.add(Date() to "${manga.title} - ${it.message}") errors.add(Date() to "${manga.title} - ${it.message}")
if (it is SourceNotFoundException) {
sourcesMissing.add(it.id)
}
else {
errorsMini.add(it.message ?: "")
}
manga manga
} }
.filter { it.id != null } .filter { it.id != null }
@ -395,6 +422,7 @@ class BackupRestoreService : Service() {
// If there's any error, return empty update and continue. // If there's any error, return empty update and continue.
.onErrorReturn { .onErrorReturn {
errors.add(Date() to "${manga.title} - ${it.message}") errors.add(Date() to "${manga.title} - ${it.message}")
errorsMini.add(it.message ?: "")
Pair(emptyList(), emptyList()) Pair(emptyList(), emptyList())
} }
} }
@ -414,10 +442,13 @@ class BackupRestoreService : Service() {
.doOnNext { db.insertTrack(it).executeAsBlocking() } .doOnNext { db.insertTrack(it).executeAsBlocking() }
.onErrorReturn { .onErrorReturn {
errors.add(Date() to "${manga.title} - ${it.message}") errors.add(Date() to "${manga.title} - ${it.message}")
errorsMini.add(it.message ?: "")
track track
} }
} else { } else {
errors.add(Date() to "${manga.title} - ${service?.name} not logged in") val notLoggedIn = getString(R.string.not_logged_into, service?.name)
errors.add(Date() to "${manga.title} - $notLoggedIn")
errorsMini.add(notLoggedIn)
Observable.empty() Observable.empty()
} }
} }

View File

@ -465,12 +465,12 @@ class LibraryUpdateService(
catch (e: Exception) { } catch (e: Exception) { }
setContentTitle(manga.title.chop(45)) setContentTitle(manga.title.chop(45))
color = ContextCompat.getColor(this@LibraryUpdateService, R.color.colorAccentLight) color = ContextCompat.getColor(this@LibraryUpdateService, R.color.colorAccentLight)
setContentText(chapterNames.first()) val chaptersNames = if (chapterNames.size > 5) {
setStyle(NotificationCompat.BigTextStyle().bigText(
if (chapterNames.size > 5) {
"${chapterNames.take(4).joinToString(", ")}, " + "${chapterNames.take(4).joinToString(", ")}, " +
getString(R.string.notification_and_n_more, (chapterNames.size - 4)) getString(R.string.notification_and_n_more, (chapterNames.size - 4))
} else chapterNames.joinToString(", "))) } else chapterNames.joinToString(", ")
setContentText(chaptersNames)
setStyle(NotificationCompat.BigTextStyle().bigText(chaptersNames))
priority = NotificationCompat.PRIORITY_HIGH priority = NotificationCompat.PRIORITY_HIGH
setGroup(Notifications.GROUP_NEW_CHAPTERS) setGroup(Notifications.GROUP_NEW_CHAPTERS)
setContentIntent( setContentIntent(
@ -498,7 +498,15 @@ class LibraryUpdateService(
setLargeIcon(notificationBitmap) setLargeIcon(notificationBitmap)
setContentTitle(getString(R.string.notification_new_chapters)) setContentTitle(getString(R.string.notification_new_chapters))
color = ContextCompat.getColor(applicationContext, R.color.colorAccentLight) color = ContextCompat.getColor(applicationContext, R.color.colorAccentLight)
if (updates.size > 1) {
setContentText(getString(R.string.notification_new_chapters_text, updates.size)) setContentText(getString(R.string.notification_new_chapters_text, updates.size))
setStyle(NotificationCompat.BigTextStyle().bigText(updates.joinToString("\n") {
it.first.title.chop(45)
}))
}
else {
setContentText(updates.first().first.title.chop(45))
}
priority = NotificationCompat.PRIORITY_HIGH priority = NotificationCompat.PRIORITY_HIGH
setGroup(Notifications.GROUP_NEW_CHAPTERS) setGroup(Notifications.GROUP_NEW_CHAPTERS)
setGroupSummary(true) setGroupSummary(true)

View File

@ -68,7 +68,10 @@ open class SourceManager(private val context: Context) {
} }
private fun getSourceNotInstalledException(): Exception { private fun getSourceNotInstalledException(): Exception {
return Exception(context.getString(R.string.source_not_installed, id.toString())) return SourceNotFoundException(context.getString(R.string.source_not_installed, id
.toString()), id)
} }
} }
} }
class SourceNotFoundException(message: String, val id: Long) : Exception(message)

View File

@ -360,11 +360,13 @@ class SettingsBackupController : SettingsController() {
} }
class RestoredBackupDialog(bundle: Bundle? = null) : DialogController(bundle) { class RestoredBackupDialog(bundle: Bundle? = null) : DialogController(bundle) {
constructor(time: Long, errorCount: Int, path: String, file: String) : this(Bundle().apply { constructor(time: Long, errorCount: Int, path: String, file: String, errors: String) : this
(Bundle().apply {
putLong(KEY_TIME, time) putLong(KEY_TIME, time)
putInt(KEY_ERROR_COUNT, errorCount) putInt(KEY_ERROR_COUNT, errorCount)
putString(KEY_PATH, path) putString(KEY_PATH, path)
putString(KEY_FILE, file) putString(KEY_FILE, file)
putString(KEY_MINI_ERRORS, errors)
}) })
override fun onCreateDialog(savedViewState: Bundle?): Dialog { override fun onCreateDialog(savedViewState: Bundle?): Dialog {
@ -373,16 +375,22 @@ class SettingsBackupController : SettingsController() {
val errors = args.getInt(KEY_ERROR_COUNT) val errors = args.getInt(KEY_ERROR_COUNT)
val path = args.getString(KEY_PATH) val path = args.getString(KEY_PATH)
val file = args.getString(KEY_FILE) val file = args.getString(KEY_FILE)
val miniErrors = args.getString(KEY_MINI_ERRORS)
val timeString = String.format("%02d min, %02d sec", val timeString = String.format("%02d min, %02d sec",
TimeUnit.MILLISECONDS.toMinutes(time), TimeUnit.MILLISECONDS.toMinutes(time),
TimeUnit.MILLISECONDS.toSeconds(time) - TimeUnit.MINUTES.toSeconds( TimeUnit.MILLISECONDS.toSeconds(time) - TimeUnit.MINUTES.toSeconds(
TimeUnit.MILLISECONDS.toMinutes(time)) TimeUnit.MILLISECONDS.toMinutes(time))
) )
var errorString = activity.getString(R.string.restore_completed_content, timeString,
if (errors > 0) "$errors" else activity.getString(android.R.string
.no))
if (errors > 0)
errorString = errorString.trimEnd('.') + ":"
return MaterialDialog.Builder(activity) return MaterialDialog.Builder(activity)
.title(R.string.restore_completed) .title(R.string.restore_completed)
.content(activity.getString(R.string.restore_completed_content, timeString, .content("$errorString\n$miniErrors")
if (errors > 0) "$errors" else activity.getString(android.R.string.no)))
.positiveText(R.string.action_close) .positiveText(R.string.action_close)
.negativeText(R.string.action_open_log) .negativeText(R.string.action_open_log)
.onNegative { _, _ -> .onNegative { _, _ ->
@ -408,6 +416,7 @@ class SettingsBackupController : SettingsController() {
const val KEY_ERROR_COUNT = "RestoredBackupDialog.errors" const val KEY_ERROR_COUNT = "RestoredBackupDialog.errors"
const val KEY_PATH = "RestoredBackupDialog.path" const val KEY_PATH = "RestoredBackupDialog.path"
const val KEY_FILE = "RestoredBackupDialog.file" const val KEY_FILE = "RestoredBackupDialog.file"
const val KEY_MINI_ERRORS = "RestoredBackupDialog.miniErrors"
} }
} }
@ -432,8 +441,9 @@ class SettingsBackupController : SettingsController() {
val errors = intent.getIntExtra(BackupConst.EXTRA_ERRORS, 0) val errors = intent.getIntExtra(BackupConst.EXTRA_ERRORS, 0)
val path = intent.getStringExtra(BackupConst.EXTRA_ERROR_FILE_PATH) val path = intent.getStringExtra(BackupConst.EXTRA_ERROR_FILE_PATH)
val file = intent.getStringExtra(BackupConst.EXTRA_ERROR_FILE) val file = intent.getStringExtra(BackupConst.EXTRA_ERROR_FILE)
val miniErrors = intent.getStringExtra(BackupConst.EXTRA_MINI_ERROR)
if (errors > 0) { if (errors > 0) {
RestoredBackupDialog(time, errors, path, file).showDialog(router) RestoredBackupDialog(time, errors, path, file, miniErrors).showDialog(router)
} }
} }
BackupConst.ACTION_ERROR_BACKUP_DIALOG -> { BackupConst.ACTION_ERROR_BACKUP_DIALOG -> {

View File

@ -84,6 +84,11 @@ fun syncChaptersWithSource(db: DatabaseHelper,
// Return if there's nothing to add, delete or change, avoiding unnecessary db transactions. // Return if there's nothing to add, delete or change, avoiding unnecessary db transactions.
if (toAdd.isEmpty() && toDelete.isEmpty() && toChange.isEmpty()) { if (toAdd.isEmpty() && toDelete.isEmpty() && toChange.isEmpty()) {
val newestDate = dbChapters.maxBy { it.date_upload }?.date_upload ?: 0L
if (newestDate != 0L && newestDate != manga.last_update) {
manga.last_update = newestDate
db.updateLastUpdated(manga).executeAsBlocking()
}
return Pair(emptyList(), emptyList()) return Pair(emptyList(), emptyList())
} }
@ -129,7 +134,9 @@ fun syncChaptersWithSource(db: DatabaseHelper,
db.fixChaptersSourceOrder(sourceChapters).executeAsBlocking() db.fixChaptersSourceOrder(sourceChapters).executeAsBlocking()
// Set this manga as updated since chapters were changed // Set this manga as updated since chapters were changed
manga.last_update = Date().time val newestChaper = db.getChapters(manga).executeAsBlocking().maxBy { it.date_fetch }
val dateFetch = newestChaper?.date_fetch ?: Date().time
manga.last_update = if (dateFetch == 0L) Date().time else dateFetch
db.updateLastUpdated(manga).executeAsBlocking() db.updateLastUpdated(manga).executeAsBlocking()
} }
return Pair(toAdd.subtract(readded).toList(), toDelete.subtract(readded).toList()) return Pair(toAdd.subtract(readded).toList(), toDelete.subtract(readded).toList())

View File

@ -1,5 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<changelog bulletedList="true"> <changelog bulletedList="true">
<changelogversion versionName="v0.9.2" changeDate="">
<changelogtext>Fixes notification text when there are multiple chapters</changelogtext>
<changelogtext>Simplified errors now show after restoring a backup on the popup dialog</changelogtext>
<changelogtext>Fixed last updated sorting being in a jumbled order after restoring (Note:
if the list is still jumbled after restore, refersh your library)</changelogtext>
<changelogtext>Fixed notifcations not expanding on older devices</changelogtext>
</changelogversion>
<changelogversion versionName="v0.9.1" changeDate=""> <changelogversion versionName="v0.9.1" changeDate="">
<changelogtext>Range Select for Library and Chapters: long Press on an item <changelogtext>Range Select for Library and Chapters: long Press on an item
then long press on another to select everything in between</changelogtext> then long press on another to select everything in between</changelogtext>

View File

@ -374,6 +374,8 @@
<string name="delete_downloads_for_manga">Delete downloaded chapters?</string> <string name="delete_downloads_for_manga">Delete downloaded chapters?</string>
<string name="copied_to_clipboard">%1$s copied to clipboard</string> <string name="copied_to_clipboard">%1$s copied to clipboard</string>
<string name="source_not_installed">Source not installed: %1$s</string> <string name="source_not_installed">Source not installed: %1$s</string>
<string name="sources_missing">Sources missing: %1$d</string>
<string name="not_logged_into">Not logged into %1$s</string>
<!-- Manga chapters fragment --> <!-- Manga chapters fragment -->
<string name="manga_chapters_tab">Chapters</string> <string name="manga_chapters_tab">Chapters</string>

View File

@ -7,7 +7,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.5.2' classpath 'com.android.tools.build:gradle:3.5.3'
classpath 'com.github.ben-manes:gradle-versions-plugin:0.22.0' classpath 'com.github.ben-manes:gradle-versions-plugin:0.22.0'
classpath 'com.github.zellius:android-shortcut-gradle-plugin:0.1.2' classpath 'com.github.zellius:android-shortcut-gradle-plugin:0.1.2'
classpath 'com.google.gms:google-services:4.3.2' classpath 'com.google.gms:google-services:4.3.2'