From ad11e61eabc919fdd6a4086fdc0b3d6664ce5c19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Tue, 13 May 2025 17:29:28 +0900 Subject: [PATCH] =?UTF-8?q?v2.4.3=20=E6=96=B0=E5=A2=9E=201.=20=E6=9B=B4?= =?UTF-8?q?=E6=94=B9=E9=BB=98=E8=AE=A4=20API=20(fix=20#131)=202.=20?= =?UTF-8?q?=E6=8C=89=E9=92=AE=E9=A2=9C=E8=89=B2=E9=9A=8F=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E6=94=B9=E5=8F=98=20(close=20#123)=20=E4=BF=AE=E5=A4=8D=201.?= =?UTF-8?q?=20=E2=80=9C=E6=88=91=E7=9A=84=E8=AE=A2=E9=98=85=E2=80=9D?= =?UTF-8?q?=E4=B8=AD=E5=B7=B2=E9=98=85=E8=AF=BB=E7=9A=84=E8=AF=9D=E6=95=B0?= =?UTF-8?q?=E5=8F=AF=E8=83=BD=E4=BC=9A=E6=98=BE=E7=A4=BA=E4=B8=BA=E4=B9=B1?= =?UTF-8?q?=E7=A0=81=20(fix=20#128)=202.=20=E6=90=9C=E7=B4=A2=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E6=98=BE=E7=A4=BA=E8=BD=AC=E7=A0=81=E5=90=8E=E7=BB=93?= =?UTF-8?q?=E6=9E=9C=203.=20=E6=90=9C=E7=B4=A2=E6=A1=86=E8=BE=93=E5=85=A5?= =?UTF-8?q?=E5=85=B3=E9=94=AE=E8=AF=8D=E5=BC=82=E5=B8=B8=E5=9B=9E=E6=98=BE?= =?UTF-8?q?=20(fix=20#109)=20=E4=BC=98=E5=8C=96=201.=20=E8=AF=A6=E6=83=85?= =?UTF-8?q?=E9=A1=B5=E6=8E=92=E7=89=88=20(fix=20#124)=20=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=201.=20gson=20->=202.13.1=202.=20lottie=20->=206.6.6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 8 +-- .../java/top/fumiama/copymanga/api/Config.kt | 2 +- .../top/fumiama/copymanga/strings/Chinese.kt | 36 +++++++++++ .../fumiama/copymanga/ui/book/BookFragment.kt | 59 ++++++++++++++----- .../fumiama/copymanga/ui/book/BookHandler.kt | 3 +- .../ui/cardflow/search/SearchFragment.kt | 4 +- .../fumiama/copymanga/ui/home/HomeFragment.kt | 8 ++- .../copymanga/view/template/InfoCardLoader.kt | 5 +- app/src/main/res/values/strings.xml | 5 +- 9 files changed, 101 insertions(+), 29 deletions(-) create mode 100644 app/src/main/java/top/fumiama/copymanga/strings/Chinese.kt diff --git a/app/build.gradle b/app/build.gradle index 20fb6a4..46a7a25 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ android { applicationId 'top.fumiama.copymanga' minSdkVersion 23 targetSdkVersion 34 - versionCode 69 - versionName '2.4.2' + versionCode 70 + versionName '2.4.3' resourceConfigurations += ['zh', 'zh-rCN'] testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -114,13 +114,13 @@ dependencies { implementation 'com.github.bumptech.glide:glide:4.16.0' //noinspection KaptUsageInsteadOfKsp kapt 'com.github.bumptech.glide:compiler:4.16.0' - implementation 'com.google.code.gson:gson:2.12.1' + implementation 'com.google.code.gson:gson:2.13.1' implementation 'com.github.vovaksenov99:OverscrollableScrollView:1.0' implementation 'com.github.liaoinstan.SpringView:library:0a24d3e9dd' implementation 'com.github.zawadz88:MaterialPopupMenu:4.1.0' implementation files('libs/com.lapism/search-2.4.1.aar') // https://stackoverflow.com/a/63029110/28801553 //noinspection GradleDependency implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0' - implementation 'com.airbnb.android:lottie:6.6.4' + implementation 'com.airbnb.android:lottie:6.6.6' implementation 'net.java.dev.jna:jna:5.17.0@aar' } diff --git a/app/src/main/java/top/fumiama/copymanga/api/Config.kt b/app/src/main/java/top/fumiama/copymanga/api/Config.kt index 4b7df18..4a15f07 100644 --- a/app/src/main/java/top/fumiama/copymanga/api/Config.kt +++ b/app/src/main/java/top/fumiama/copymanga/api/Config.kt @@ -29,7 +29,7 @@ object Config { if (field != null) return field field = Proxy( R.string.apiProxyApiUrl, - Regex("^https://(api|www)\\.(copymanga|mangacopy|copy-manga)\\.\\w+/api/"), + Regex("^https://(api|www)\\.(copymanga|mangacopy|copy-manga|copy20)\\.\\w+/api/"), ) return field } diff --git a/app/src/main/java/top/fumiama/copymanga/strings/Chinese.kt b/app/src/main/java/top/fumiama/copymanga/strings/Chinese.kt new file mode 100644 index 0000000..ede19ec --- /dev/null +++ b/app/src/main/java/top/fumiama/copymanga/strings/Chinese.kt @@ -0,0 +1,36 @@ +package top.fumiama.copymanga.strings + +object Chinese { + /** + * 如果输入字符串中已包含汉字,直接返回。 + * 否则尝试以 UTF8 重新解码。 + */ + fun fixEncodingIfNeeded(input: String): String { + // 如果本身包含汉字,直接返回 + if (containsChinese(input)) { + return input + } + + return try { + val decoded = input.toByteArray(Charsets.ISO_8859_1).decodeToString() + + // 检测解码后的是否包含汉字 + if (containsChinese(decoded)) { + decoded + } else { + input // 解码后也没有汉字,说明可能不是编码问题 + } + } catch (e: Exception) { + input + } + } + + /** + * 简单检测字符串是否包含常见 CJK(中日韩)汉字。 + */ + fun containsChinese(text: String): Boolean { + val regex = Regex("[\u4E00-\u9FFF]") + return regex.containsMatchIn(text) + } + +} \ No newline at end of file diff --git a/app/src/main/java/top/fumiama/copymanga/ui/book/BookFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/book/BookFragment.kt index d01024c..38c94eb 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/book/BookFragment.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/book/BookFragment.kt @@ -3,15 +3,18 @@ package top.fumiama.copymanga.ui.book import android.animation.ObjectAnimator import android.annotation.SuppressLint import android.content.Context.MODE_PRIVATE +import android.content.res.ColorStateList import android.os.Bundle import android.util.Log import android.view.View import android.widget.Toast import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController +import com.google.android.material.color.MaterialColors import kotlinx.android.synthetic.main.app_bar_main.* import kotlinx.android.synthetic.main.card_book.* import kotlinx.android.synthetic.main.fragment_book.* +import kotlinx.android.synthetic.main.line_bookinfo_text.* import kotlinx.android.synthetic.main.line_booktandb.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -19,6 +22,7 @@ import kotlinx.coroutines.withContext import top.fumiama.copymanga.MainActivity import top.fumiama.copymanga.api.manga.Book import top.fumiama.copymanga.api.manga.Reader +import top.fumiama.copymanga.strings.Chinese import top.fumiama.copymanga.view.template.NoBackRefreshFragment import top.fumiama.copymanga.view.interaction.Navigate import top.fumiama.copymanga.ui.comicdl.ComicDlFragment @@ -98,6 +102,7 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) { activity?.apply { toolbar.title = book?.name } + setReadTo() setStartRead() } @@ -118,16 +123,13 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) { activity?.apply { book?.name?.let { name -> getPreferences(MODE_PRIVATE).getInt(name, -1).let { p -> - this@BookFragment.lbbstart.apply { - var i = 0 - if(p >= 0) mBookHandler!!.chapterNames.let { - i = if (p >= it.size) it.size-1 else p - text = it[i] - } - setOnClickListener { - mBookHandler?.apply { - Reader.start2viewManga(name, i, urlArray, uuidArray) - } + var i = 0 + if(p >= 0) mBookHandler!!.chapterNames.let { + i = if (p >= it.size) it.size-1 else p + } + this@BookFragment.lbbstart.setOnClickListener { + mBookHandler?.apply { + Reader.start2viewManga(name, i, urlArray, uuidArray) } } } @@ -135,6 +137,23 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) { } } + fun setReadTo() { + var chapter = "未读" + if(!mBookHandler?.chapterNames.isNullOrEmpty()) { + activity?.apply { + book?.name?.let { name -> + getPreferences(MODE_PRIVATE).getInt(name, -1).let { p -> + if(p >= 0) mBookHandler!!.chapterNames.let { + chapter = it[if (p >= it.size) it.size-1 else p] + } + } + } + } + } + chapter = "读至 $chapter" + this@BookFragment.bttag.text = chapter + } + private suspend fun prepareHandler() = withContext(Dispatchers.IO) { arguments?.apply { if (getBoolean("loadJson")) { @@ -175,7 +194,7 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) { mBookHandler?.collect = b.results?.collect?:-2 Log.d("MyBF", "get collect of ${book?.path} = ${mBookHandler?.collect}") tic.text = b.results?.browse?.chapter_name?.let { name -> - getString(R.string.text_format_cloud_read_to).format(name) + getString(R.string.text_format_cloud_read_to).format(Chinese.fixEncodingIfNeeded(name)) } } } @@ -187,7 +206,11 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) { queryCollect() mBookHandler?.collect?.let { collect -> if (collect > 0) { - this@BookFragment.lbbsub.setText(R.string.button_sub_subscribed) + this@BookFragment.lbbsub.apply { + setText(R.string.button_sub_subscribed) + val color = MaterialColors.getColor(this, R.attr.colorButtonNormal) + backgroundTintList = ColorStateList.valueOf(color) + } } } book?.uuid?.let { uuid -> @@ -199,7 +222,11 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) { val re = MainActivity.shelf?.del(collect) Toast.makeText(context, re, Toast.LENGTH_SHORT).show() if (re == "请求成功") { - this@BookFragment.lbbsub.setText(R.string.button_sub) + this@BookFragment.lbbsub.apply { + setText(R.string.button_sub) + val color = MaterialColors.getColor(this, R.attr.colorPrimarySurface) + backgroundTintList = ColorStateList.valueOf(color) + } } } return@clickLaunch @@ -208,7 +235,11 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) { Toast.makeText(context, re, Toast.LENGTH_SHORT).show() if (re == "修改成功") { queryCollect() - this@BookFragment.lbbsub.setText(R.string.button_sub_subscribed) + this@BookFragment.lbbsub.apply { + setText(R.string.button_sub_subscribed) + val color = MaterialColors.getColor(this, R.attr.colorButtonNormal) + backgroundTintList = ColorStateList.valueOf(color) + } } } } diff --git a/app/src/main/java/top/fumiama/copymanga/ui/book/BookHandler.kt b/app/src/main/java/top/fumiama/copymanga/ui/book/BookHandler.kt index 47eae81..73de754 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/book/BookHandler.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/book/BookHandler.kt @@ -78,6 +78,7 @@ class BookHandler(private val th: WeakReference): Handler(Looper.m oa.start() } complete = true + that?.setReadTo() that?.setStartRead() that?.setAddToShelf() Log.d("MyBH", "Set complete: true") @@ -126,7 +127,7 @@ class BookHandler(private val th: WeakReference): Handler(Looper.m // tic?.visibility = View.GONE activity?.toolbar?.title = book?.name btauth?.text = that?.getString(R.string.text_format_region)?.format(book?.region?:"未知") - bttag?.text = that?.getString(R.string.text_format_img_type)?.format(book?.imageType?:"未知") + // bttag?.text = that?.getString(R.string.text_format_img_type)?.format(book?.imageType?:"未知") bthit?.text = that?.getString(R.string.text_format_hit)?.format(book?.popular?:-1) btsub?.text = that?.getString(R.string.text_format_stat)?.format(book?.status?:"未知") bttime?.text = book?.updateTime?:"未知" diff --git a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/search/SearchFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/search/SearchFragment.kt index f98cc99..fc9ed73 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/search/SearchFragment.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/search/SearchFragment.kt @@ -5,6 +5,8 @@ import android.util.Log import top.fumiama.copymanga.view.template.InfoCardLoader import top.fumiama.copymanga.api.Config import top.fumiama.dmzj.copymanga.R +import java.net.URLEncoder +import java.nio.charset.Charset @ExperimentalStdlibApi class SearchFragment : InfoCardLoader(R.layout.fragment_search, R.id.action_nav_search_to_nav_book) { @@ -16,7 +18,7 @@ class SearchFragment : InfoCardLoader(R.layout.fragment_search, R.id.action_nav_ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (isFirstInflate) { - query = arguments?.getCharSequence("query")?.toString() + query = arguments?.getCharSequence("query")?.toString()?.let { q -> URLEncoder.encode(q, Charset.defaultCharset().name()) } type = arguments?.getString("type") Log.d("MySF", "get query=$query, type=$type") } diff --git a/app/src/main/java/top/fumiama/copymanga/ui/home/HomeFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/home/HomeFragment.kt index 41f189a..6347ec3 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/home/HomeFragment.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/home/HomeFragment.kt @@ -96,13 +96,14 @@ class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) { var lastChangeTime = 0L override fun onQueryTextChange(newText: CharSequence): Boolean { if (newText.contentEquals("__notice_focus_change__") || newText.contentEquals(lastSearch)) return true + lastSearch = newText.toString() postDelayed({ lifecycleScope.launch { + if (!newText.contentEquals(lastSearch)) return@launch val diff = System.currentTimeMillis() - lastChangeTime if(diff > 500) { if (newText.isNotEmpty()) { Log.d("MyHF", "new text: $newText") - lastSearch = newText.toString() adapter.refresh(newText) } } @@ -295,9 +296,10 @@ class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) { override fun getItemCount() = (results?.results?.list?.size?:0) + if (query?.isNotEmpty() == true) 1 else 0 suspend fun refresh(q: CharSequence) = withContext(Dispatchers.IO) { - query = URLEncoder.encode(q.toString(), Charset.defaultCharset().name()) + query = q.toString() activity?.apply { - PausableDownloader(getString(R.string.searchApiUrl).format(Config.myHostApiUrl.value, 0, query, type)) { + PausableDownloader(getString(R.string.searchApiUrl).format(Config.myHostApiUrl.value, 0, + URLEncoder.encode(q.toString(), Charset.defaultCharset().name()), type)) { results = Gson().fromJson(it.decodeToString(), BookListStructure::class.java) count = results?.results?.total?:0 withContext(Dispatchers.Main) { diff --git a/app/src/main/java/top/fumiama/copymanga/view/template/InfoCardLoader.kt b/app/src/main/java/top/fumiama/copymanga/view/template/InfoCardLoader.kt index 15ddfe6..0ca63b2 100644 --- a/app/src/main/java/top/fumiama/copymanga/view/template/InfoCardLoader.kt +++ b/app/src/main/java/top/fumiama/copymanga/view/template/InfoCardLoader.kt @@ -16,6 +16,7 @@ import top.fumiama.copymanga.json.HistoryBookListStructure import top.fumiama.copymanga.json.ShelfStructure import top.fumiama.copymanga.json.TypeBookListStructure import top.fumiama.copymanga.net.template.PausableDownloader +import top.fumiama.copymanga.strings.Chinese import top.fumiama.copymanga.view.interaction.Navigate import java.lang.ref.WeakReference @@ -66,7 +67,7 @@ open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isT Log.d("MyICL", "load @ $i") if(ad?.exit == true) return@PausableDownloader cardList?.addCard( - book?.comic?.name?:"null", "\n云读至${book?.last_chapter_name}", book?.comic?.cover, + book?.comic?.name?:"null", "\n云读至${book?.last_chapter_name?.let { Chinese.fixEncodingIfNeeded(it) }}", book?.comic?.cover, book?.comic?.path_word, null, null, book?.comic?.status==1 ) @@ -88,7 +89,7 @@ open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isT Log.d("MyICL", "load @ $i") if(ad?.exit == true) return@PausableDownloader cardList?.addCard( - book?.comic?.name?:"null", "\n${book?.last_browse?.last_browse_name?.let { "读到$it" }?:"未读"}", book?.comic?.cover, + book?.comic?.name?:"null", "\n${book?.last_browse?.last_browse_name?.let { "读到${Chinese.fixEncodingIfNeeded(it)}" }?:"未读"}", book?.comic?.cover, book?.comic?.path_word, null, null, book?.comic?.status==1, book.comic?.browse?.chapter_uuid != book.comic?.last_chapter_id diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 11a8b4e..d3ee1d6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,7 +1,7 @@ - + + ]> 拷贝漫画 @@ -123,7 +123,6 @@ 热度 %1$d 状态 %1$s 区域 %1$s - 画幅 %1$s 云读至%1$s 专题系列