From 06dd2ac2c1a10aaab5e678c52b30f89f7ec75032 Mon Sep 17 00:00:00 2001 From: lhjgege <1079947827@qq.com> Date: Fri, 11 Jul 2025 13:40:10 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8C=E6=AD=A5=E4=B8=8A=E6=B8=B8=E6=9B=B4?= =?UTF-8?q?=E6=94=B9:=20@lhjgege=20=E6=96=B0=E6=BC=AB=E7=94=BB=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=A2=A8=E6=B0=B4=E5=B1=8F=E6=A8=A1=E5=BC=8F=20(#5181?= =?UTF-8?q?)=20*=20=E6=96=B0=E6=BC=AB=E7=94=BB=E5=A2=9E=E5=8A=A0=E5=A2=A8?= =?UTF-8?q?=E6=B0=B4=E5=B1=8F=E6=A8=A1=E5=BC=8F=20*=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=B0=B4=E5=B9=B3=E6=BB=9A=E5=8A=A8=E5=8A=A8=E7=94=BB=E5=BC=80?= =?UTF-8?q?=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/legato/kazusa/constant/PreferKey.kt | 5 ++ .../io/legato/kazusa/help/config/AppConfig.kt | 27 ++++++- .../java/io/legato/kazusa/model/BookCover.kt | 21 +++-- .../io/legato/kazusa/ui/about/UpdateDialog.kt | 12 +++ .../kazusa/ui/book/manga/ReadMangaActivity.kt | 57 ++++++++++++- .../ui/book/manga/config/MangaEpaperDialog.kt | 49 ++++++++++++ .../manga/entities/EpaperTransformation.kt | 80 +++++++++++++++++++ .../manga/entities/GrayscaleTransformation.kt | 57 +++++++++++++ .../book/manga/recyclerview/MangaAdapter.kt | 44 ++++++++-- .../ui/book/manga/recyclerview/MangaVH.kt | 10 ++- .../res/layout/dialog_manga_color_filter.xml | 2 +- .../main/res/layout/dialog_manga_epaper.xml | 29 +++++++ app/src/main/res/layout/dialog_update.xml | 55 ++++++++++--- app/src/main/res/menu/book_manga.xml | 28 +++++++ app/src/main/res/values-zh/strings.xml | 10 +++ app/src/main/res/values/strings.xml | 6 ++ 16 files changed, 463 insertions(+), 29 deletions(-) create mode 100644 app/src/main/java/io/legato/kazusa/ui/book/manga/config/MangaEpaperDialog.kt create mode 100644 app/src/main/java/io/legato/kazusa/ui/book/manga/entities/EpaperTransformation.kt create mode 100644 app/src/main/java/io/legato/kazusa/ui/book/manga/entities/GrayscaleTransformation.kt create mode 100644 app/src/main/res/layout/dialog_manga_epaper.xml diff --git a/app/src/main/java/io/legato/kazusa/constant/PreferKey.kt b/app/src/main/java/io/legato/kazusa/constant/PreferKey.kt index 36e1b23c9..c04a39dd7 100644 --- a/app/src/main/java/io/legato/kazusa/constant/PreferKey.kt +++ b/app/src/main/java/io/legato/kazusa/constant/PreferKey.kt @@ -104,6 +104,11 @@ object PreferKey { const val enableMangaHorizontalScroll = "enableMangaHorizontalScroll" const val hideMangaTitle = "hideMangaTitle" const val mangaColorFilter = "mangaColorFilter" + const val enableMangaEInk = "enableMangaEInk" + const val mangaEInkThreshold = "mangaEInkThreshold" + const val disableHorizontalAnimator = "disableHorizontalAnimator" + const val enableMangaGray = "enableMangaGray" + const val autoRefresh = "auto_refresh" const val defaultToRead = "defaultToRead" const val exportCharset = "exportCharset" diff --git a/app/src/main/java/io/legato/kazusa/help/config/AppConfig.kt b/app/src/main/java/io/legato/kazusa/help/config/AppConfig.kt index e835073d1..81810a9ce 100644 --- a/app/src/main/java/io/legato/kazusa/help/config/AppConfig.kt +++ b/app/src/main/java/io/legato/kazusa/help/config/AppConfig.kt @@ -496,7 +496,7 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener { val defaultHomePage get() = appCtx.getPrefString(PreferKey.defaultHomePage, "bookshelf") - val updateToVariant get() = appCtx.getPrefString(PreferKey.updateToVariant, "default_version") + val updateToVariant get() = appCtx.getPrefString(PreferKey.updateToVariant, "official_version") val streamReadAloudAudio get() = appCtx.getPrefBoolean(PreferKey.streamReadAloudAudio, false) @@ -676,5 +676,30 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener { set(value) { appCtx.putPrefBoolean(PreferKey.hideMangaTitle, value) } + + //开启墨水屏模式 + var enableMangaEInk + get() = appCtx.getPrefBoolean(PreferKey.enableMangaEInk, false) + set(value) { + appCtx.putPrefBoolean(PreferKey.enableMangaEInk, value) + } + + var mangaEInkThreshold + get() = appCtx.getPrefInt(PreferKey.mangaEInkThreshold, 150) + set(value) { + appCtx.putPrefInt(PreferKey.mangaEInkThreshold, value) + } + + var disableHorizontalAnimator + get() = appCtx.getPrefBoolean(PreferKey.disableHorizontalAnimator, false) + set(value) { + appCtx.putPrefBoolean(PreferKey.disableHorizontalAnimator, value) + } + + var enableMangaGray + get() = appCtx.getPrefBoolean(PreferKey.enableMangaGray, false) + set(value) { + appCtx.putPrefBoolean(PreferKey.enableMangaGray, value) + } } diff --git a/app/src/main/java/io/legato/kazusa/model/BookCover.kt b/app/src/main/java/io/legato/kazusa/model/BookCover.kt index 91c101d2d..27af20416 100644 --- a/app/src/main/java/io/legato/kazusa/model/BookCover.kt +++ b/app/src/main/java/io/legato/kazusa/model/BookCover.kt @@ -2,12 +2,14 @@ package io.legato.kazusa.model import android.annotation.SuppressLint import android.content.Context -import android.graphics.drawable.BitmapDrawable +import android.graphics.Bitmap import android.graphics.drawable.Drawable import androidx.annotation.Keep +import androidx.core.graphics.drawable.toDrawable import com.bumptech.glide.Glide import com.bumptech.glide.RequestBuilder import com.bumptech.glide.load.DataSource +import com.bumptech.glide.load.Transformation import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.load.engine.GlideException import com.bumptech.glide.load.resource.bitmap.CenterCrop @@ -74,7 +76,7 @@ object BookCover { return } defaultDrawable = kotlin.runCatching { - BitmapDrawable(appCtx.resources, BitmapUtils.decodeBitmap(path, 600, 900)) + BitmapUtils.decodeBitmap(path, 600, 900).toDrawable(appCtx.resources) }.getOrDefault(appCtx.resources.getDrawable(R.drawable.image_cover_default, null)) } @@ -87,7 +89,7 @@ object BookCover { path: String?, loadOnlyWifi: Boolean = false, sourceOrigin: String? = null, - onLoadFinish: (() -> Unit)? = null + onLoadFinish: (() -> Unit)? = null, ): RequestBuilder { if (AppConfig.useDefaultCover) { return ImageLoader.load(context, defaultDrawable) @@ -105,7 +107,7 @@ object BookCover { e: GlideException?, model: Any?, target: Target, - isFirstResource: Boolean + isFirstResource: Boolean, ): Boolean { onLoadFinish.invoke() return false @@ -116,7 +118,7 @@ object BookCover { model: Any, target: Target?, dataSource: DataSource, - isFirstResource: Boolean + isFirstResource: Boolean, ): Boolean { onLoadFinish.invoke() return false @@ -133,11 +135,13 @@ object BookCover { /** * 加载漫画图片 */ + @SuppressLint("CheckResult") fun loadManga( context: Context, path: String?, loadOnlyWifi: Boolean = false, sourceOrigin: String? = null, + transformation: Transformation? = null, ): RequestBuilder { var options = RequestOptions().set(OkHttpModelLoader.loadOnlyWifiOption, loadOnlyWifi) .set(OkHttpModelLoader.mangaOption, true) @@ -148,7 +152,12 @@ object BookCover { .apply(options) .override(context.resources.displayMetrics.widthPixels, SIZE_ORIGINAL) .diskCacheStrategy(DiskCacheStrategy.ALL) - .skipMemoryCache(true) + .skipMemoryCache(true).let { + if (transformation != null) { + it.transform(transformation) + } + it + } } fun preloadManga( diff --git a/app/src/main/java/io/legato/kazusa/ui/about/UpdateDialog.kt b/app/src/main/java/io/legato/kazusa/ui/about/UpdateDialog.kt index 97ea0daa9..a61e026fc 100644 --- a/app/src/main/java/io/legato/kazusa/ui/about/UpdateDialog.kt +++ b/app/src/main/java/io/legato/kazusa/ui/about/UpdateDialog.kt @@ -6,8 +6,11 @@ import android.view.View import io.legato.kazusa.BuildConfig import io.legato.kazusa.R import io.legato.kazusa.base.BaseBottomSheetDialogFragment +import io.legato.kazusa.constant.AppConst import io.legato.kazusa.databinding.DialogUpdateBinding +import io.legato.kazusa.help.config.AppConfig import io.legato.kazusa.help.update.AppUpdate +import io.legato.kazusa.help.update.AppVariant import io.legato.kazusa.model.Download import io.legato.kazusa.utils.toastOnUi import io.legato.kazusa.utils.viewbindingdelegate.viewBinding @@ -27,6 +30,14 @@ class UpdateDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_update) { } } + private val checkVariant: AppVariant + get() = when (AppConfig.updateToVariant) { + "official_version" -> AppVariant.OFFICIAL + "beta_release_version" -> AppVariant.BETA_RELEASE + "beta_releaseA_version" -> AppVariant.BETA_RELEASEA + else -> AppConst.appInfo.appVariant + } + val binding by viewBinding(DialogUpdateBinding::bind) override fun onStart() { @@ -41,6 +52,7 @@ class UpdateDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_update) { binding.tvAbi.text = Build.SUPPORTED_ABIS.firstOrNull() ?: "unknown" binding.tvUrl.text = arguments?.getString("url") + binding.tvVariable.text = checkVariant.toString() val updateBody = arguments?.getString("updateBody") if (updateBody == null) { diff --git a/app/src/main/java/io/legato/kazusa/ui/book/manga/ReadMangaActivity.kt b/app/src/main/java/io/legato/kazusa/ui/book/manga/ReadMangaActivity.kt index 7c716faff..3a1aa7f8b 100644 --- a/app/src/main/java/io/legato/kazusa/ui/book/manga/ReadMangaActivity.kt +++ b/app/src/main/java/io/legato/kazusa/ui/book/manga/ReadMangaActivity.kt @@ -5,7 +5,6 @@ import android.content.Intent import android.os.Build import android.os.Bundle import android.os.Looper -import android.os.PersistableBundle import android.view.KeyEvent import android.view.Menu import android.view.MenuItem @@ -44,6 +43,7 @@ import io.legato.kazusa.ui.book.changesource.ChangeBookSourceDialog import io.legato.kazusa.ui.book.info.BookInfoActivity import io.legato.kazusa.ui.book.manga.config.MangaColorFilterConfig import io.legato.kazusa.ui.book.manga.config.MangaColorFilterDialog +import io.legato.kazusa.ui.book.manga.config.MangaEpaperDialog import io.legato.kazusa.ui.book.manga.config.MangaFooterConfig import io.legato.kazusa.ui.book.manga.config.MangaFooterSettingDialog import io.legato.kazusa.ui.book.manga.entities.BaseMangaPage @@ -63,7 +63,6 @@ import io.legato.kazusa.utils.canScroll import io.legato.kazusa.utils.fastBinarySearch import io.legato.kazusa.utils.findCenterViewPosition import io.legato.kazusa.utils.fromJsonObject -import io.legato.kazusa.utils.getCompatColor import io.legato.kazusa.utils.gone import io.legato.kazusa.utils.observeEvent import io.legato.kazusa.utils.showDialogFragment @@ -79,7 +78,7 @@ import kotlin.math.ceil class ReadMangaActivity : VMBaseActivity(), ReadManga.Callback, ChangeBookSourceDialog.CallBack, MangaMenu.CallBack, - MangaColorFilterDialog.Callback, ScrollTimer.ScrollCallback { + MangaColorFilterDialog.Callback, ScrollTimer.ScrollCallback, MangaEpaperDialog.Callback { private val mLayoutManager by lazy { MangaLayoutManager(this) @@ -191,6 +190,8 @@ class ReadMangaActivity : VMBaseActivity { item.isChecked = !item.isChecked AppConfig.enableMangaHorizontalScroll = item.isChecked + mMenu?.findItem(R.id.menu_disable_horizontal_animation)?.isVisible = item.isChecked setHorizontalScroll(item.isChecked) mAdapter.notifyDataSetChanged() } @@ -570,6 +572,38 @@ class ReadMangaActivity : VMBaseActivity { + item.isChecked = !item.isChecked + AppConfig.enableMangaEInk = item.isChecked + mMenu?.findItem(R.id.menu_gray_manga)?.isChecked = false + AppConfig.enableMangaGray = false + mMenu?.findItem(R.id.menu_epaper_manga_setting)?.isVisible = item.isChecked + mAdapter.enableMangaEInk(item.isChecked, AppConfig.mangaEInkThreshold) + } + + R.id.menu_epaper_manga_setting -> { + showDialogFragment(MangaEpaperDialog()) + } + + R.id.menu_disable_horizontal_animation -> { + item.isChecked = !item.isChecked + AppConfig.disableHorizontalAnimator = item.isChecked + if (item.isChecked) { + mPagerSnapHelper.attachToRecyclerView(null) + } else { + mPagerSnapHelper.attachToRecyclerView(binding.recyclerView) + } + } + + R.id.menu_gray_manga -> { + item.isChecked = !item.isChecked + AppConfig.enableMangaGray = item.isChecked + mMenu?.findItem(R.id.menu_epaper_manga)?.isChecked = false + AppConfig.enableMangaEInk = false + mMenu?.findItem(R.id.menu_epaper_manga_setting)?.isVisible = false + mAdapter.enableGray(item.isChecked) + } } return super.onCompatOptionsItemSelected(item) } @@ -626,6 +660,11 @@ class ReadMangaActivity : VMBaseActivity 0 && item.index == item.imageCount - 1 loadImageWithRetry( - item.mImageUrl, isHorizontal, isLastImage + item.mImageUrl, isHorizontal, isLastImage, mTransformation ) } } @@ -100,7 +106,7 @@ class MangaAdapter(private val context: Context) : fun onBind(item: MangaPage) { setImageColorFilter() val isLastImage = item.imageCount > 0 && item.index == item.imageCount - 1 - loadImageWithRetry(item.mImageUrl, isHorizontal, isLastImage) + loadImageWithRetry(item.mImageUrl, isHorizontal, isLastImage, mTransformation) } fun setImageColorFilter() { @@ -167,7 +173,7 @@ class MangaAdapter(private val context: Context) : } } - fun getFooterCount() = footerItems.size() + fun getFooterCount() = footerItems.size private fun isFooter(position: Int) = position >= getActualItemCount() @@ -199,8 +205,8 @@ class MangaAdapter(private val context: Context) : @Synchronized fun addFooterView(footer: ((parent: ViewGroup) -> ViewBinding)) { kotlin.runCatching { - val index = getActualItemCount() + footerItems.size() - footerItems.put(TYPE_FOOTER_VIEW + footerItems.size(), footer) + val index = getActualItemCount() + footerItems.size + footerItems.put(TYPE_FOOTER_VIEW + footerItems.size, footer) notifyItemInserted(index) } } @@ -244,4 +250,32 @@ class MangaAdapter(private val context: Context) : notifyItemRangeChanged(0, itemCount) } + fun enableMangaEInk(enable: Boolean, value: Int) { + if (enable) { + currentMangaEInkThreshold = value + mTransformation = EpaperTransformation(currentMangaEInkThreshold) + } else { + mTransformation = null + } + notifyItemRangeChanged(0, itemCount) + } + + fun updateThreshold(mangaEInkThreshold: Int) { + if (currentMangaEInkThreshold != mangaEInkThreshold) { + currentMangaEInkThreshold = mangaEInkThreshold + mTransformation = EpaperTransformation(currentMangaEInkThreshold) + notifyItemRangeChanged(0, itemCount) + } + } + + //开启灰色图片 + fun enableGray(enable: Boolean) { + mTransformation = if (enable) { + GrayscaleTransformation() + } else { + null + } + notifyItemRangeChanged(0, itemCount) + } + } \ No newline at end of file diff --git a/app/src/main/java/io/legato/kazusa/ui/book/manga/recyclerview/MangaVH.kt b/app/src/main/java/io/legato/kazusa/ui/book/manga/recyclerview/MangaVH.kt index cc34cf15b..1e4cdc5aa 100644 --- a/app/src/main/java/io/legato/kazusa/ui/book/manga/recyclerview/MangaVH.kt +++ b/app/src/main/java/io/legato/kazusa/ui/book/manga/recyclerview/MangaVH.kt @@ -2,6 +2,7 @@ package io.legato.kazusa.ui.book.manga.recyclerview import android.annotation.SuppressLint import android.content.Context +import android.graphics.Bitmap import android.graphics.drawable.Drawable import android.view.Gravity import android.view.ViewGroup @@ -17,6 +18,7 @@ import androidx.core.view.updateLayoutParams import androidx.recyclerview.widget.RecyclerView import androidx.viewbinding.ViewBinding import com.bumptech.glide.load.DataSource +import com.bumptech.glide.load.Transformation import com.bumptech.glide.load.engine.GlideException import com.bumptech.glide.request.RequestListener import com.bumptech.glide.request.target.Target @@ -51,7 +53,12 @@ open class MangaVH(val binding: VB, private val context: Conte } @SuppressLint("CheckResult") - fun loadImageWithRetry(imageUrl: String, isHorizontal: Boolean, isLastImage: Boolean) { + fun loadImageWithRetry( + imageUrl: String, + isHorizontal: Boolean, + isLastImage: Boolean, + transformation: Transformation? + ) { mFlProgress.isVisible = true mLoading.isVisible = true mRetry?.isGone = true @@ -67,6 +74,7 @@ open class MangaVH(val binding: VB, private val context: Conte context, imageUrl, sourceOrigin = ReadManga.book?.origin, + transformation = transformation ).addListener(object : RequestListener { override fun onLoadFailed( e: GlideException?, diff --git a/app/src/main/res/layout/dialog_manga_color_filter.xml b/app/src/main/res/layout/dialog_manga_color_filter.xml index a5c30f553..1e3edd368 100644 --- a/app/src/main/res/layout/dialog_manga_color_filter.xml +++ b/app/src/main/res/layout/dialog_manga_color_filter.xml @@ -14,7 +14,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingBottom="8dp" - android:text="滤镜" + android:text="@string/manga_color_filter" android:textSize="18sp" /> + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_update.xml b/app/src/main/res/layout/dialog_update.xml index bd2b23ee2..5ce954e40 100644 --- a/app/src/main/res/layout/dialog_update.xml +++ b/app/src/main/res/layout/dialog_update.xml @@ -98,20 +98,51 @@ - - + + - + app:cardBackgroundColor="?attr/colorPrimaryContainer" + app:strokeWidth="0dp"> + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 521bb7110..4f6590f25 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -1217,8 +1217,18 @@ 滤镜 隐藏漫画列表标题 刷新发现 + 未分组 + 动态取色 图标已修改 + 配置替换规则 + 更多设置 共 %d 章 已读 %d 章 + 墨水屏 + 墨水屏设置 + 阈值 + 禁用水平滚动动画 + 开启图片灰色 + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b4545e5f8..59a3aef5c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1226,4 +1226,10 @@ 共 %d 章 已读 %d 章 + 墨水屏 + 墨水屏设置 + 阈值 + 禁用水平滚动动画 + 开启图片灰色 +