From 680fc66f214da5d29d583f3f5c20fcd0a1ac6383 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Wed, 3 Jun 2020 18:52:00 +0300 Subject: [PATCH] Tracker fixes --- .../org/koitharu/kotatsu/domain/MangaUtils.kt | 3 ++ .../domain/tracking/TrackingRepository.kt | 8 +-- .../ui/common/list/BaseRecyclerAdapter.kt | 15 ++++-- .../kotatsu/ui/common/list/BaseViewHolder.kt | 38 ++++++------- .../categories/CategoriesAdapter.kt | 7 ++- .../select/CategoriesSelectAdapter.kt | 7 ++- .../kotatsu/ui/tracker/TrackWorker.kt | 54 ++++++++++++------- .../res/layout/dialog_favorite_categories.xml | 4 +- app/src/main/res/layout/item_category.xml | 3 +- .../res/layout/item_manga_list_details.xml | 4 +- app/src/main/res/layout/item_page.xml | 5 +- app/src/main/res/layout/item_page_webtoon.xml | 4 +- .../main/res/layout/item_search_complete.xml | 5 +- app/src/main/res/menu/popup_chapter.xml | 17 ------ app/src/main/res/values-ru/strings.xml | 3 -- app/src/main/res/values/strings.xml | 3 -- 16 files changed, 98 insertions(+), 82 deletions(-) delete mode 100644 app/src/main/res/menu/popup_chapter.xml diff --git a/app/src/main/java/org/koitharu/kotatsu/domain/MangaUtils.kt b/app/src/main/java/org/koitharu/kotatsu/domain/MangaUtils.kt index 7033f4c59..03323a620 100644 --- a/app/src/main/java/org/koitharu/kotatsu/domain/MangaUtils.kt +++ b/app/src/main/java/org/koitharu/kotatsu/domain/MangaUtils.kt @@ -3,6 +3,7 @@ package org.koitharu.kotatsu.domain import android.graphics.BitmapFactory import android.net.Uri import android.util.Size +import androidx.annotation.WorkerThread import okhttp3.OkHttpClient import okhttp3.Request import org.koin.core.KoinComponent @@ -21,6 +22,8 @@ object MangaUtils : KoinComponent { * Automatic determine type of manga by page size * @return ReaderMode.WEBTOON if page is wide */ + @WorkerThread + @Suppress("BlockingMethodInNonBlockingContext") suspend fun determineReaderMode(pages: List): ReaderMode? { try { val page = pages.medianOrNull() ?: return null diff --git a/app/src/main/java/org/koitharu/kotatsu/domain/tracking/TrackingRepository.kt b/app/src/main/java/org/koitharu/kotatsu/domain/tracking/TrackingRepository.kt index 30090d180..b4b26bced 100644 --- a/app/src/main/java/org/koitharu/kotatsu/domain/tracking/TrackingRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/domain/tracking/TrackingRepository.kt @@ -49,7 +49,7 @@ class TrackingRepository : KoinComponent { knownChaptersCount: Int, lastChapterId: Long, newChapters: List, - lastNotifiedChapterId: Long + previousTrackChapterId: Long ) { db.withTransaction { val entity = TrackEntity( @@ -58,13 +58,15 @@ class TrackingRepository : KoinComponent { lastCheck = System.currentTimeMillis(), lastChapterId = lastChapterId, totalChapters = knownChaptersCount, - lastNotifiedChapterId = lastNotifiedChapterId + lastNotifiedChapterId = newChapters.lastOrNull()?.id ?: previousTrackChapterId ) db.tracksDao.upsert(entity) if (newChapters.isNotEmpty()) { val logEntity = TrackLogEntity( mangaId = mangaId, - chapters = newChapters.joinToString("\n") { x -> x.name }, + chapters = newChapters + .takeLastWhile { x -> x.id != previousTrackChapterId } + .joinToString("\n") { x -> x.name }, createdAt = System.currentTimeMillis() ) db.trackLogsDao.insert(logEntity) diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/common/list/BaseRecyclerAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/common/list/BaseRecyclerAdapter.kt index 686873a91..073a23af5 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/common/list/BaseRecyclerAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/common/list/BaseRecyclerAdapter.kt @@ -87,16 +87,23 @@ abstract class BaseRecyclerAdapter(private val onItemClickListener: OnRecy final override fun getItemCount() = dataSet.size final override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder { - return onCreateViewHolder(parent).setOnItemClickListener(onItemClickListener) - .also(this::onViewHolderCreated) + return onCreateViewHolder(parent) + } + + override fun onViewDetachedFromWindow(holder: BaseViewHolder) { + holder.setOnItemClickListener(null) + super.onViewDetachedFromWindow(holder) + } + + override fun onViewAttachedToWindow(holder: BaseViewHolder) { + super.onViewAttachedToWindow(holder) + holder.setOnItemClickListener(onItemClickListener) } protected open fun onDataSetChanged() = Unit protected abstract fun getExtra(item: T, position: Int): E - protected open fun onViewHolderCreated(holder: BaseViewHolder) = Unit - protected abstract fun onCreateViewHolder(parent: ViewGroup): BaseViewHolder protected abstract fun onGetItemId(item: T): Long diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/common/list/BaseViewHolder.kt b/app/src/main/java/org/koitharu/kotatsu/ui/common/list/BaseViewHolder.kt index ffe70af85..37f82fbf0 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/common/list/BaseViewHolder.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/common/list/BaseViewHolder.kt @@ -1,6 +1,5 @@ package org.koitharu.kotatsu.ui.common.list -import android.os.Build import android.view.View import android.view.ViewGroup import androidx.annotation.LayoutRes @@ -27,26 +26,29 @@ abstract class BaseViewHolder protected constructor(view: View) : onBind(data, extra) } - fun requireData() = boundData ?: throw IllegalStateException("Calling requireData() before bind()") - - fun setOnItemClickListener(listener: OnRecyclerItemClickListener?): BaseViewHolder { - if (listener != null) { - itemView.setOnClickListener { - listener.onItemClick(boundData ?: return@setOnClickListener, bindingAdapterPosition, it) - } - itemView.setOnLongClickListener { - listener.onItemLongClick(boundData ?: return@setOnLongClickListener false, bindingAdapterPosition, it) - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - itemView.setOnContextClickListener { - listener.onItemLongClick(boundData ?: return@setOnContextClickListener false, bindingAdapterPosition, it) - } - } - } - return this + fun requireData(): T { + return boundData ?: throw IllegalStateException("Calling requireData() before bind()") + } + + fun setOnItemClickListener(listener: OnRecyclerItemClickListener?) { + val listenersAdapter = listener?.let { HolderListenersAdapter(it) } + itemView.setOnClickListener(listenersAdapter) + itemView.setOnLongClickListener(listenersAdapter) } open fun onRecycled() = Unit abstract fun onBind(data: T, extra: E) + + private inner class HolderListenersAdapter(private val listener: OnRecyclerItemClickListener) : + View.OnClickListener, View.OnLongClickListener { + + override fun onClick(v: View) { + listener.onItemClick(boundData ?: return, bindingAdapterPosition, v) + } + + override fun onLongClick(v: View): Boolean { + return listener.onItemLongClick(boundData ?: return false, bindingAdapterPosition, v) + } + } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/list/favourites/categories/CategoriesAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/list/favourites/categories/CategoriesAdapter.kt index 3f8921199..0ee108091 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/list/favourites/categories/CategoriesAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/list/favourites/categories/CategoriesAdapter.kt @@ -19,7 +19,7 @@ class CategoriesAdapter(private val onItemClickListener: OnRecyclerItemClickList override fun getExtra(item: FavouriteCategory, position: Int) = Unit @SuppressLint("ClickableViewAccessibility") - override fun onViewHolderCreated(holder: BaseViewHolder) { + override fun onViewAttachedToWindow(holder: BaseViewHolder) { holder.imageView_more.setOnClickListener { v -> onItemClickListener.onItemClick(holder.requireData(), holder.bindingAdapterPosition, v) } @@ -32,6 +32,11 @@ class CategoriesAdapter(private val onItemClickListener: OnRecyclerItemClickList } } + override fun onViewDetachedFromWindow(holder: BaseViewHolder) { + holder.imageView_more.setOnClickListener(null) + holder.imageView_handle.setOnTouchListener(null) + } + fun moveItem(oldPos: Int, newPos: Int) { val item = dataSet.removeAt(oldPos) dataSet.add(newPos, item) diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/list/favourites/categories/select/CategoriesSelectAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/ui/list/favourites/categories/select/CategoriesSelectAdapter.kt index fbd82eaa5..1385be8b7 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/list/favourites/categories/select/CategoriesSelectAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/list/favourites/categories/select/CategoriesSelectAdapter.kt @@ -31,8 +31,11 @@ class CategoriesSelectAdapter(private val listener: OnCategoryCheckListener) : override fun onGetItemId(item: FavouriteCategory) = item.id - override fun onViewHolderCreated(holder: BaseViewHolder) { - super.onViewHolderCreated(holder) + override fun onViewDetachedFromWindow(holder: BaseViewHolder) { + holder.itemView.setOnClickListener(null) + } + + override fun onViewAttachedToWindow(holder: BaseViewHolder) { holder.itemView.setOnClickListener { if (it !is Checkable) return@setOnClickListener it.toggle() diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/tracker/TrackWorker.kt b/app/src/main/java/org/koitharu/kotatsu/ui/tracker/TrackWorker.kt index c5e3fab78..dd154a95e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/tracker/TrackWorker.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/tracker/TrackWorker.kt @@ -55,7 +55,7 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) : mangaId = track.manga.id, knownChaptersCount = chapters.size, lastChapterId = chapters.lastOrNull()?.id ?: 0L, - lastNotifiedChapterId = 0L, + previousTrackChapterId = 0L, newChapters = emptyList() ) } @@ -64,7 +64,7 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) : mangaId = track.manga.id, knownChaptersCount = track.knownChaptersCount, lastChapterId = 0L, - lastNotifiedChapterId = chapters.lastOrNull()?.id ?: 0L, + previousTrackChapterId = track.lastNotifiedChapterId, newChapters = chapters ) showNotification(track.manga, chapters) @@ -82,7 +82,7 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) : mangaId = track.manga.id, knownChaptersCount = chapters.size, lastChapterId = chapters.lastOrNull()?.id ?: 0L, - lastNotifiedChapterId = chapters.lastOrNull()?.id ?: 0L, + previousTrackChapterId = track.lastNotifiedChapterId, newChapters = emptyList() ) } else { @@ -91,12 +91,13 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) : mangaId = track.manga.id, knownChaptersCount = knownChapter + 1, lastChapterId = track.lastChapterId, - lastNotifiedChapterId = chapters.lastOrNull()?.id ?: 0L, + previousTrackChapterId = track.lastNotifiedChapterId, newChapters = newChapters ) - if (chapters.lastOrNull()?.id != track.lastNotifiedChapterId) { - showNotification(track.manga, newChapters) - } + showNotification( + track.manga, + newChapters.takeLastWhile { x -> x.id != track.lastNotifiedChapterId } + ) } } } @@ -106,12 +107,13 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) : mangaId = track.manga.id, knownChaptersCount = track.knownChaptersCount, lastChapterId = track.lastChapterId, - lastNotifiedChapterId = chapters.lastOrNull()?.id ?: 0L, + previousTrackChapterId = track.lastNotifiedChapterId, newChapters = newChapters ) - if (chapters.lastOrNull()?.id != track.lastNotifiedChapterId) { - showNotification(track.manga, newChapters) - } + showNotification( + track.manga, + newChapters.takeLastWhile { x -> x.id != track.lastNotifiedChapterId } + ) } } success++ @@ -130,15 +132,21 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) : val id = manga.url.hashCode() val colorPrimary = ContextCompat.getColor(applicationContext, R.color.blue_primary) val builder = NotificationCompat.Builder(applicationContext, CHANNEL_ID) - val summary = applicationContext.resources.getQuantityString(R.plurals.new_chapters, - newChapters.size, newChapters.size) + val summary = applicationContext.resources.getQuantityString( + R.plurals.new_chapters, + newChapters.size, newChapters.size + ) with(builder) { setContentText(summary) setContentTitle(manga.title) setNumber(newChapters.size) - setLargeIcon(Coil.execute(GetRequestBuilder(applicationContext) - .data(manga.coverUrl) - .build()).toBitmapOrNull()) + setLargeIcon( + Coil.execute( + GetRequestBuilder(applicationContext) + .data(manga.coverUrl) + .build() + ).toBitmapOrNull() + ) setSmallIcon(R.drawable.ic_stat_book_plus) val style = NotificationCompat.InboxStyle(this) for (chapter in newChapters) { @@ -148,8 +156,12 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) : style.setBigContentTitle(summary) setStyle(style) val intent = MangaDetailsActivity.newIntent(applicationContext, manga) - setContentIntent(PendingIntent.getActivity(applicationContext, id, - intent, PendingIntent.FLAG_UPDATE_CURRENT)) + setContentIntent( + PendingIntent.getActivity( + applicationContext, id, + intent, PendingIntent.FLAG_UPDATE_CURRENT + ) + ) setAutoCancel(true) color = colorPrimary setShortcutId(manga.id.toString()) @@ -182,9 +194,11 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) : val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager if (manager.getNotificationChannel(CHANNEL_ID) == null) { - val channel = NotificationChannel(CHANNEL_ID, + val channel = NotificationChannel( + CHANNEL_ID, context.getString(R.string.new_chapters), - NotificationManager.IMPORTANCE_DEFAULT) + NotificationManager.IMPORTANCE_DEFAULT + ) channel.setShowBadge(true) channel.lightColor = ContextCompat.getColor(context, R.color.blue_primary) channel.enableLights(true) diff --git a/app/src/main/res/layout/dialog_favorite_categories.xml b/app/src/main/res/layout/dialog_favorite_categories.xml index bb45c4550..785ae6552 100644 --- a/app/src/main/res/layout/dialog_favorite_categories.xml +++ b/app/src/main/res/layout/dialog_favorite_categories.xml @@ -40,12 +40,12 @@ android:layout_width="match_parent" android:layout_height="?android:listPreferredItemHeightSmall" android:background="?android:selectableItemBackground" - android:drawableEnd="@drawable/ic_add" android:gravity="start|center_vertical" android:paddingStart="?android:listPreferredItemPaddingStart" android:paddingEnd="?android:listPreferredItemPaddingEnd" android:text="@string/add_new_category" android:textAppearance="@style/TextAppearance.MaterialComponents.Body1" - android:textColor="?android:textColorPrimary" /> + android:textColor="?android:textColorPrimary" + app:drawableEndCompat="@drawable/ic_add" /> \ No newline at end of file diff --git a/app/src/main/res/layout/item_category.xml b/app/src/main/res/layout/item_category.xml index 024889453..bae9f8155 100644 --- a/app/src/main/res/layout/item_category.xml +++ b/app/src/main/res/layout/item_category.xml @@ -6,7 +6,8 @@ android:layout_height="?android:listPreferredItemHeightSmall" android:background="?android:windowBackground" android:gravity="center_vertical" - android:orientation="horizontal"> + android:orientation="horizontal" + tools:ignore="Overdraw"> + tools:text="10/10" + app:drawableStartCompat="@drawable/ic_star_rating" /> diff --git a/app/src/main/res/layout/item_page.xml b/app/src/main/res/layout/item_page.xml index 9be300434..cf4798de0 100644 --- a/app/src/main/res/layout/item_page.xml +++ b/app/src/main/res/layout/item_page.xml @@ -1,6 +1,7 @@ + tools:text="@tools:sample/lorem[6]" + app:drawableTopCompat="@drawable/ic_error_large" /> + tools:text="@tools:sample/lorem[6]" + app:drawableTopCompat="@drawable/ic_error_large" /> \ No newline at end of file + tools:text="@tools:sample/full_names" + app:drawableStartCompat="@drawable/ic_history" /> \ No newline at end of file diff --git a/app/src/main/res/menu/popup_chapter.xml b/app/src/main/res/menu/popup_chapter.xml deleted file mode 100644 index 09cb4ccaa..000000000 --- a/app/src/main/res/menu/popup_chapter.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index cab7c4605..d8dec4d26 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -38,9 +38,6 @@ Обработка… Загрузка завершена Загрузки - Сохранить предыдущие главы - Сохранить следующие главы - Сохранить эту главу По имени Популярная Обновлённая diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8cb973dc5..42f75e1dd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -39,9 +39,6 @@ Processing… Download complete Downloads - Save this chapter and prev. - Save this chapter and next - Save this chapter By name Popular Updated