Library updates are now in groups, tapping on them take you directly to the chapter to read

Fixes to lollipop snackbar and webview
This commit is contained in:
Jay 2019-11-05 00:07:20 -08:00
parent 1b545c9e4d
commit 1291adf821
11 changed files with 89 additions and 71 deletions

View File

@ -11,7 +11,6 @@ import eu.kanade.tachiyomi.data.notification.NotificationHandler
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.util.chop
import eu.kanade.tachiyomi.util.getResourceColor
import eu.kanade.tachiyomi.util.notificationManager
import java.util.regex.Pattern
@ -170,8 +169,8 @@ internal class DownloadNotifier(private val context: Context) {
setSmallIcon(android.R.drawable.stat_sys_download_done)
setAutoCancel(true)
clearActions()
setContentIntent(NotificationReceiver.openChapterPendingBroadcast(context, download
.manga, download.chapter, Notifications.ID_DOWNLOAD_CHAPTER))
setContentIntent(NotificationReceiver.openChapterPendingActivity(context, download
.manga, download.chapter))
setProgress(0, 0, false)
}

View File

@ -10,6 +10,7 @@ import android.os.Build
import android.os.IBinder
import android.os.PowerManager
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
@ -30,8 +31,6 @@ import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.ui.recent_updates.RecentChapterItem
import eu.kanade.tachiyomi.util.*
import rx.Observable
import rx.Subscription
@ -274,7 +273,7 @@ class LibraryUpdateService(
// Initialize the variables holding the progress of the updates.
val count = AtomicInteger(0)
// List containing new updates
val newUpdates = ArrayList<Manga>()
val newUpdates = ArrayList<Pair<Manga, Chapter>>()
// list containing failed updates
val failedUpdates = ArrayList<Manga>()
// List containing categories that get included in downloads.
@ -307,7 +306,7 @@ class LibraryUpdateService(
}
}
// Convert to the manga that contains new chapters.
.map { manga }
.map { Pair(manga, (it.first.minBy { ch -> ch.chapter_number }!!)) }
}
// Add manga with new chapters to the list.
.doOnNext { manga ->
@ -329,6 +328,7 @@ class LibraryUpdateService(
cancelProgressNotification()
}
.map { manga -> manga.first }
}
fun downloadChapters(manga: Manga, chapters: List<Chapter>) {
@ -442,53 +442,50 @@ class LibraryUpdateService(
*
* @param updates a list of manga with new updates.
*/
private fun showResultNotification(updates: List<Manga>) {
val newUpdates = updates.map { it.title.chop(45) }.toMutableSet()
// Append new chapters from a previous, existing notification
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val previousNotification = notificationManager.activeNotifications
.find { it.id == Notifications.ID_NEW_CHAPTERS }
if (previousNotification != null) {
val oldUpdates = previousNotification.notification.extras
.getString(Notification.EXTRA_BIG_TEXT)
if (!oldUpdates.isNullOrEmpty()) {
newUpdates += oldUpdates.split("\n")
}
}
private fun showResultNotification(updates: List<Pair<Manga, Chapter>>) {
val notifications = ArrayList<Pair<Notification, Int>>()
updates.forEach {
val manga = it.first
val chapter = it.second
notifications.add(Pair(notification(Notifications.CHANNEL_NEW_CHAPTERS) {
setSmallIcon(R.drawable.ic_book_white_24dp)
setLargeIcon(notificationBitmap)
setContentTitle(manga.title.chop(45))
color = ContextCompat.getColor(applicationContext, R.color.colorAccentLight)
setContentText(chapter.name)
priority = NotificationCompat.PRIORITY_HIGH
setGroup(Notifications.GROUP_NEW_CHAPTERS)
setContentIntent(
NotificationReceiver.openChapterPendingActivity(
this@LibraryUpdateService, manga, chapter
)
)
setAutoCancel(true)
}, manga.id.hashCode()))
}
notificationManager.notify(Notifications.ID_NEW_CHAPTERS, notification(Notifications.CHANNEL_NEW_CHAPTERS) {
NotificationManagerCompat.from(this).apply {
notifications.forEach {
notify(it.second, it.first)
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N || notificationManager
.activeNotifications.find { it.groupKey == Notifications.GROUP_NEW_CHAPTERS } == null) {
notify(Notifications.ID_NEW_CHAPTERS, notification(Notifications.CHANNEL_NEW_CHAPTERS) {
setSmallIcon(R.drawable.ic_book_white_24dp)
setLargeIcon(notificationBitmap)
setContentTitle(getString(R.string.notification_new_chapters))
color = ContextCompat.getColor(applicationContext, R.color.colorAccentLight)
if (newUpdates.size > 1) {
setContentText(getString(R.string.notification_new_chapters_text, newUpdates.size))
setStyle(NotificationCompat.BigTextStyle().bigText(newUpdates.joinToString("\n")))
setNumber(newUpdates.size)
} else {
val onlyManga = updates.first()
val id = onlyManga.id ?: 0
setContentText(newUpdates.first())
val context = applicationContext
val db = DatabaseHelper(context)
val chapters = db.getChapters(onlyManga).executeAsBlocking()
val chapter = chapters.sortedByDescending { it.source_order }.find { !it.read }
if (chapter != null) {
addAction(R.drawable.ic_in_library_24dp, getString(R.string.action_start_reading),
NotificationReceiver.openChapterPendingBroadcast(context, onlyManga,
chapter, Notifications.ID_NEW_CHAPTERS))
}
}
setContentText(getString(R.string.notification_new_chapters_text, updates.size))
priority = NotificationCompat.PRIORITY_HIGH
setGroup(Notifications.GROUP_NEW_CHAPTERS)
setGroupSummary(true)
setContentIntent(getNotificationIntent())
setAutoCancel(true)
})
}
}
}
/**
* Cancels the progress notification.

View File

@ -300,10 +300,11 @@ class NotificationReceiver : BroadcastReceiver() {
* @param manga manga of chapter
* @param chapter chapter that needs to be opened
*/
internal fun openChapterPendingBroadcast(context: Context, manga: Manga, chapter:
Chapter, notificationId: Int): PendingIntent {
val newIntent = ReaderActivity.newIntent(context, manga, chapter, notificationId)
return PendingIntent.getActivity(context, 0, newIntent, PendingIntent.FLAG_UPDATE_CURRENT)
internal fun openChapterPendingActivity(context: Context, manga: Manga, chapter:
Chapter): PendingIntent {
val newIntent = ReaderActivity.newIntent(context, manga, chapter)
return PendingIntent.getActivity(context, manga.id.hashCode(), newIntent, PendingIntent
.FLAG_UPDATE_CURRENT)
}
/**

View File

@ -36,7 +36,8 @@ object Notifications {
* Notification channel and ids used by the library updater.
*/
const val CHANNEL_NEW_CHAPTERS = "new_chapters_channel"
const val ID_NEW_CHAPTERS = 301
const val ID_NEW_CHAPTERS = -301
const val GROUP_NEW_CHAPTERS = "eu.kanade.tachiyomi.NEW_CHAPTERS"
/**
* Creates the notification channels introduced in Android Oreo.

View File

@ -508,15 +508,14 @@ open class BrowseCatalogueController(bundle: Bundle) :
presenter.changeMangaFavorite(manga)
adapter?.notifyItemChanged(position)
snack =
catalogue_view?.snack(activity.getString(R.string.manga_removed_library), 5000) {
catalouge_layout?.snack(R.string.manga_removed_library, 5000) {
setAction(R.string.action_undo) {
if (!manga.favorite) addManga(manga, position)
}
}
} else {
addManga(manga, position)
snack =
catalogue_view?.snack(activity.getString(R.string.manga_added_library))
snack = catalouge_layout?.snack(R.string.manga_added_library)
}
}

View File

@ -7,6 +7,7 @@ import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.widget.FrameLayout
import com.google.android.material.snackbar.Snackbar
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.SelectableAdapter
import eu.kanade.tachiyomi.R
@ -98,7 +99,8 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
swipe_refresh.setOnRefreshListener {
if (!LibraryUpdateService.isRunning(context)) {
LibraryUpdateService.start(context, category)
swipe_refresh.snack(R.string.updating_category)
controller.snack?.dismiss()
controller.snack = swipe_refresh.snack(R.string.updating_category)
}
// It can be a very long operation, so we disable swipe refresh and show a toast.
swipe_refresh.isRefreshing = false

View File

@ -18,6 +18,7 @@ import androidx.core.view.GravityCompat
import com.bluelinelabs.conductor.ControllerChangeHandler
import com.bluelinelabs.conductor.ControllerChangeType
import com.f2prateek.rx.preferences.Preference
import com.google.android.material.snackbar.Snackbar
import com.jakewharton.rxbinding.support.v4.view.pageSelections
import com.jakewharton.rxbinding.support.v7.widget.queryTextChanges
import com.jakewharton.rxrelay.BehaviorRelay
@ -121,6 +122,8 @@ class LibraryController(
private var searchViewSubscription: Subscription? = null
var snack: Snackbar? = null
init {
setHasOptionsMenu(true)
retainViewMode = RetainViewMode.RETAIN_DETACH
@ -176,6 +179,12 @@ class LibraryController(
super.onDestroyView(view)
}
override fun onDetach(view: View) {
snack?.dismiss()
snack = null
super.onDetach(view)
}
override fun createSecondaryDrawer(drawer: androidx.drawerlayout.widget.DrawerLayout): ViewGroup {
val view = drawer.inflate(R.layout.library_drawer) as LibraryNavigationView
navView = view
@ -476,7 +485,8 @@ class LibraryController(
val mangas = selectedMangas.toList()
presenter.removeMangaFromLibrary(mangas, true)
destroyActionModeIfNeeded()
view?.snack(activity?.getString(R.string.manga_removed_library) ?: "", 5000) {
snack?.dismiss()
snack = view?.snack(activity?.getString(R.string.manga_removed_library) ?: "", 5000) {
setAction(R.string.action_undo) {
presenter.addMangas(mangas)
}

View File

@ -27,7 +27,8 @@ class MangaWebViewController(bundle: Bundle? = null) : BaseController(bundle) {
})
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
return inflater.inflate(R.layout.manga_info_web_controller, container, false)
return WebView(applicationContext)// inflater.inflate(R.layout.manga_info_web_controller, container,
// false)
}
override fun onViewCreated(view: View) {

View File

@ -19,6 +19,7 @@ import android.widget.LinearLayout
import android.widget.SeekBar
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.notification.Notifications
@ -120,13 +121,13 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>(),
const val VERTICAL = 3
const val WEBTOON = 4
fun newIntent(context: Context, manga: Manga, chapter: Chapter, notificationId:Int? =
null):
fun newIntent(context: Context, manga: Manga, chapter: Chapter):
Intent {
val intent = Intent(context, ReaderActivity::class.java)
intent.putExtra("manga", manga.id)
intent.putExtra("chapter", chapter.id)
intent.putExtra("notificationId", notificationId)
intent.putExtra("chapterUrl", chapter.url)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
return intent
}
}
@ -146,17 +147,14 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>(),
if (presenter.needsInit()) {
val manga = intent.extras!!.getLong("manga", -1)
val chapter = intent.extras!!.getLong("chapter", -1)
val notificationId = intent.extras!!.getInt("notificationId", -1)
if (notificationId > 0) {
applicationContext.notificationManager.cancel(notificationId)
}
if (manga == -1L || chapter == -1L) {
val chapterUrl = intent.extras!!.getString("chapterUrl", "")
if (manga == -1L || chapterUrl == "" && chapter == -1L) {
finish()
return
}
presenter.init(manga, chapter)
if (chapterUrl.isEmpty()) presenter.init(manga, chapter)
else presenter.init(manga, chapterUrl)
}
if (savedState != null) {

View File

@ -185,6 +185,15 @@ class ReaderPresenter(
}, ReaderActivity::setInitialChapterError)
}
fun init(mangaId: Long, chapterUrl: String) {
if (!needsInit()) return
val context = Injekt.get<Application>()
val db = DatabaseHelper(context)
val chapterId = db.getChapter(chapterUrl).executeAsBlocking()?.id
if (chapterId != null)
init(mangaId, chapterId)
}
/**
* Initializes this presenter with the given [manga] and [initialChapterId]. This method will
* set the chapter loader, view subscriptions and trigger an initial load.

View File

@ -3,6 +3,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:id="@+id/catalouge_layout"
android:layout_height="match_parent">
<LinearLayout