From 16dd13e902ab080062ced6ffd0db02eb2202d820 Mon Sep 17 00:00:00 2001 From: fumiama Date: Fri, 14 May 2021 22:34:29 +0800 Subject: [PATCH] =?UTF-8?q?2.0.beta6=201.=20=E4=BF=AE=E5=A4=8D=E6=BC=AB?= =?UTF-8?q?=E7=94=BB=E5=B0=81=E9=9D=A2=E4=B8=BA=E7=A9=BA=E5=AF=BC=E8=87=B4?= =?UTF-8?q?=E7=9A=84=E4=B8=BB=E9=A1=B5=E9=97=AA=E9=80=80=202.=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=AF=A6=E6=83=85=E9=A1=B5=E5=AF=BC=E8=88=AA=E5=88=B0?= =?UTF-8?q?=E4=BD=9C=E8=80=85=E3=80=81=E6=A0=87=E7=AD=BE=203.=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E9=98=85=E8=A7=88=E7=BC=93=E5=AD=98=E3=80=81=E9=9F=B3?= =?UTF-8?q?=E9=87=8F=E9=94=AE=E9=A1=B5=E3=80=81=E5=8F=8C=E9=A1=B5=E5=88=87?= =?UTF-8?q?=E5=88=86=204.=20=E4=BC=98=E5=8C=96=E5=8D=B7=E8=BD=B4=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F=E3=80=81=E4=B8=8B=E8=BD=BD=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/dictionaries/rumia.xml | 1 + app/build.gradle | 4 +- .../copymanga/template/ui/StatusCardFlow.kt | 75 ++++ .../copymanga/template/ui/ThemeCardFlow.kt | 36 ++ .../copymanga/tools/http/DownloadTools.kt | 152 ++++--- .../copymanga/tools/http/MangaDlTools.kt | 4 +- .../fumiama/copymanga/ui/book/BookFragment.kt | 11 +- .../fumiama/copymanga/ui/book/BookHandler.kt | 79 ++-- .../ui/cardflow/author/AuthorFragment.kt | 7 + .../ui/cardflow/caption/CaptionFragment.kt | 7 + .../ui/cardflow/finish/FinishFragment.kt | 74 +--- .../copymanga/ui/comicdl/ComicDlHandler.kt | 25 +- .../fumiama/copymanga/ui/home/HomeHandler.kt | 4 +- .../fumiama/copymanga/ui/vm/PagesManager.kt | 2 +- .../top/fumiama/copymanga/ui/vm/VMHandler.kt | 82 ++-- .../copymanga/ui/vm/ViewMangaActivity.kt | 389 +++++++++++++----- ...finish.xml => fragment_statuscardflow.xml} | 0 app/src/main/res/layout/widget_infodrawer.xml | 14 +- .../main/res/navigation/mobile_navigation.xml | 44 +- app/src/main/res/values/strings.xml | 5 + build.gradle | 2 +- 21 files changed, 665 insertions(+), 352 deletions(-) create mode 100644 app/src/main/java/top/fumiama/copymanga/template/ui/StatusCardFlow.kt create mode 100644 app/src/main/java/top/fumiama/copymanga/template/ui/ThemeCardFlow.kt create mode 100644 app/src/main/java/top/fumiama/copymanga/ui/cardflow/author/AuthorFragment.kt create mode 100644 app/src/main/java/top/fumiama/copymanga/ui/cardflow/caption/CaptionFragment.kt rename app/src/main/res/layout/{fragment_finish.xml => fragment_statuscardflow.xml} (100%) diff --git a/.idea/dictionaries/rumia.xml b/.idea/dictionaries/rumia.xml index dff7651..b4964f2 100644 --- a/.idea/dictionaries/rumia.xml +++ b/.idea/dictionaries/rumia.xml @@ -4,6 +4,7 @@ copymanga fileprovider fumiama + statuscardflow \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index e01d39c..34788ed 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -28,8 +28,8 @@ android { applicationId 'top.fumiama.copymanga' minSdkVersion 23 targetSdkVersion 30 - versionCode 16 - versionName '2.0.beta5' + versionCode 17 + versionName '2.0.beta6' resConfigs "zh", "zh-rCN" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/app/src/main/java/top/fumiama/copymanga/template/ui/StatusCardFlow.kt b/app/src/main/java/top/fumiama/copymanga/template/ui/StatusCardFlow.kt new file mode 100644 index 0000000..cde09bf --- /dev/null +++ b/app/src/main/java/top/fumiama/copymanga/template/ui/StatusCardFlow.kt @@ -0,0 +1,75 @@ +package top.fumiama.copymanga.template.ui + +import android.animation.ObjectAnimator +import android.view.View +import kotlinx.android.synthetic.main.anchor_popular.view.* +import kotlinx.android.synthetic.main.line_finish.* +import kotlinx.android.synthetic.main.line_lazybooklines.* +import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference +import top.fumiama.dmzj.copymanga.R + +@ExperimentalStdlibApi +open class StatusCardFlow(private val api: Int, nav: Int) : InfoCardLoader(R.layout.fragment_statuscardflow, nav) { + val sortWay = listOf("datetime_updated", "-datetime_updated", "popular", "-popular") + var sortValue = 0 + + override fun getApiUrl() = + getString(api).let { + String.format( + it, + page * 21, + sortWay[sortValue] + ) + } + + override fun setListeners() { + super.setListeners() + setUpdate(line_finish_time) + setHot(line_finish_pop) + } + + override fun onLoadFinish() { + super.onLoadFinish() + mainWeakReference?.get()?.runOnUiThread { + mypl.visibility = View.GONE + } + } + + open fun setUpdate(that: View) { + that.apply { + apt.setText(R.string.menu_update_time) + setOnClickListener { + sortValue = if(apim.rotation == 0f) { + ObjectAnimator.ofFloat(apim, "rotation", 0f, 180f).setDuration(233).start() + 1 + }else{ + ObjectAnimator.ofFloat(apim, "rotation", 180f, 0f).setDuration(233).start() + 0 + } + Thread{ + Thread.sleep(400) + mh?.sendEmptyMessage(4) + }.start() + } + } + } + + open fun setHot(that: View) { + that.apply { + apt.setText(R.string.menu_hot) + setOnClickListener { + sortValue = if (apim.rotation == 0f) { + ObjectAnimator.ofFloat(apim, "rotation", 0f, 180f).setDuration(233).start() + 1 + } else { + ObjectAnimator.ofFloat(apim, "rotation", 180f, 0f).setDuration(233).start() + 0 + } + Thread { + Thread.sleep(400) + mh?.sendEmptyMessage(4) + }.start() + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/top/fumiama/copymanga/template/ui/ThemeCardFlow.kt b/app/src/main/java/top/fumiama/copymanga/template/ui/ThemeCardFlow.kt new file mode 100644 index 0000000..eaf590d --- /dev/null +++ b/app/src/main/java/top/fumiama/copymanga/template/ui/ThemeCardFlow.kt @@ -0,0 +1,36 @@ +package top.fumiama.copymanga.template.ui + +import android.os.Bundle +import kotlinx.android.synthetic.main.app_bar_main.* +import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference + +@ExperimentalStdlibApi +open class ThemeCardFlow(private val api: Int, nav: Int) : StatusCardFlow(0, nav) { + private var theme = "" + override fun getApiUrl() = + getString(api).let { + String.format( + it, + page * 21, + sortWay[sortValue], + theme + ) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + arguments?.apply { + getString("path")?.apply { theme = this } + getString("name")?.apply { + mainWeakReference?.get()?.toolbar?.title = this + } + } + } + + override fun onResume() { + super.onResume() + arguments?.getString("name")?.apply { + mainWeakReference?.get()?.toolbar?.title = this + } + } +} \ No newline at end of file diff --git a/app/src/main/java/top/fumiama/copymanga/tools/http/DownloadTools.kt b/app/src/main/java/top/fumiama/copymanga/tools/http/DownloadTools.kt index c4d46de..46359e1 100644 --- a/app/src/main/java/top/fumiama/copymanga/tools/http/DownloadTools.kt +++ b/app/src/main/java/top/fumiama/copymanga/tools/http/DownloadTools.kt @@ -3,7 +3,6 @@ package top.fumiama.copymanga.tools.http import android.util.Log import top.fumiama.copymanga.tools.ssl.AllTrustManager import top.fumiama.copymanga.tools.ssl.IgnoreHostNameVerifier -import java.io.File import java.net.HttpURLConnection import java.net.URL import java.security.SecureRandom @@ -25,24 +24,31 @@ object DownloadTools { HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.socketFactory) } + private fun getConnection(url: String?, method: String = "GET") = + url?.let { + val connection = URL(url).openConnection() as HttpURLConnection + connection.requestMethod = method + connection.connectTimeout = 20000 + connection.readTimeout = 20000 + connection + } + fun getHttpContent(Url: String, refer: String? = null, ua: String? = null): ByteArray? { Log.d("Mydl", "getHttp: $Url") var ret: ByteArray? = null val task = FutureTask(Callable { try { - val connection = URL(Url).openConnection() as HttpURLConnection - connection.requestMethod = "GET" - connection.connectTimeout = 20000 - connection.readTimeout = 20000 - refer?.let { connection.setRequestProperty("referer", it) } - connection.setRequestProperty("source", "copyApp") - connection.setRequestProperty("webp", "1") - connection.setRequestProperty("region", "1") - connection.setRequestProperty("platform", "3") - ua?.let { connection.setRequestProperty("User-agent", it) } + getConnection(Url)?.apply { + refer?.let { setRequestProperty("referer", it) } + setRequestProperty("source", "copyApp") + setRequestProperty("webp", "1") + setRequestProperty("region", "1") + setRequestProperty("platform", "3") + ua?.let { setRequestProperty("User-agent", it) } - ret = connection.inputStream.readBytes() - connection.disconnect() + ret = inputStream.readBytes() + disconnect() + } } catch (ex: Exception) { ex.printStackTrace() } @@ -56,78 +62,17 @@ object DownloadTools { null } } - fun downloadUsingUrlRet(Url: String?, f: File): Boolean { - Log.d("Mydl", "Ret Get Url: $Url, File: $f") - val task = FutureTask(Callable { - try { - val connection = URL(Url).openConnection() as HttpURLConnection - connection.requestMethod = "GET" - connection.connectTimeout = 20000 - connection.readTimeout = 20000 - connection.setRequestProperty("source", "copyApp") - connection.setRequestProperty("webp", "1") - connection.setRequestProperty("region", "1") - connection.setRequestProperty("platform", "3") - - if (f.exists()) f.delete() - else f.parentFile?.mkdirs() - f.parentFile?.let { - if (!it.canRead()) it.setReadable(true) - if (!it.canWrite()) it.setWritable(true) - } - connection.inputStream.buffered().copyTo(f.outputStream()) - connection.disconnect() - return@Callable true - } catch (ex: Exception) { - ex.printStackTrace() - return@Callable false - } - }) - Thread(task).start() - return try { - task.get() - } catch (ex: Exception) { - ex.printStackTrace() - false - } - } - fun downloadUsingUrl(Url: String?, f: File, refer: String? = null) { - Log.d("Mydl", "Get Url: $Url, File: $f") - Thread(Runnable { - try { - val connection = URL(Url).openConnection() as HttpURLConnection - connection.requestMethod = "GET" - connection.connectTimeout = 20000 - connection.readTimeout = 20000 - refer?.let { connection.setRequestProperty("referer", it) } - - if (f.exists()) f.delete() - else f.parentFile?.mkdirs() - f.parentFile?.let { - if (!it.canRead()) it.setReadable(true) - if (!it.canWrite()) it.setWritable(true) - } - connection.inputStream.buffered().copyTo(f.outputStream()) - connection.disconnect() - } catch (ex: Exception) { - ex.printStackTrace() - } - }).start() - } fun getHttpContent(Url: String, refer: String? = null): ByteArray? { Log.d("Mydl", "getHttp: $Url") var ret: ByteArray? = null val task = FutureTask(Callable { try { - val connection = URL(Url).openConnection() as HttpURLConnection - connection.requestMethod = "GET" - connection.connectTimeout = 20000 - connection.readTimeout = 20000 - refer?.let { connection.setRequestProperty("referer", it) } + val connection = getConnection(Url) + refer?.let { connection?.setRequestProperty("referer", it) } - ret = connection.inputStream.readBytes() - connection.disconnect() + ret = connection?.inputStream?.readBytes() + connection?.disconnect() } catch (ex: Exception) { ex.printStackTrace() } @@ -141,4 +86,55 @@ object DownloadTools { null } } + + fun getHttpContent(Url: String, readSize: Int? = null, refer: String? = "https://api.copymanga.com"): ByteArray? { + Log.d("Mydl", "getHttp: $Url") + var ret: ByteArray? = null + val task = FutureTask(Callable { + try { + val connection = getConnection(Url) + refer?.let { connection?.setRequestProperty("referer", it) } + + val ci = connection?.inputStream + if(readSize != null) { + ret = ByteArray(readSize) + ci?.read(ret, 0, readSize) + } else ret = ci?.readBytes() + ci?.close() + connection?.disconnect() + } catch (ex: Exception) { + ex.printStackTrace() + } + return@Callable ret + }) + Thread(task).start() + return try { + task.get() + } catch (ex: Exception) { + ex.printStackTrace() + null + } + } + + fun touch(url: String?, refer: String? = "https://www.dmzj1.com"): FutureTask? = + url?.let { + Log.d("Mydl", "touchHttp: $it") + var ret: ByteArray? = null + val task = FutureTask(Callable { + try { + val connection = getConnection(it) + refer?.let { connection?.setRequestProperty("referer", it) } + + val ci = connection?.inputStream + ret = ci?.readBytes() + ci?.close() + connection?.disconnect() + } catch (ex: Exception) { + ex.printStackTrace() + } + return@Callable ret + }) + Thread(task).start() + task + } } \ No newline at end of file diff --git a/app/src/main/java/top/fumiama/copymanga/tools/http/MangaDlTools.kt b/app/src/main/java/top/fumiama/copymanga/tools/http/MangaDlTools.kt index 33177f3..6d82d20 100644 --- a/app/src/main/java/top/fumiama/copymanga/tools/http/MangaDlTools.kt +++ b/app/src/main/java/top/fumiama/copymanga/tools/http/MangaDlTools.kt @@ -19,6 +19,7 @@ class MangaDlTools { private var comicFileRelative: String? = null var size = 0 var complete = false + var wait = false fun downloadChapterInVol(url: CharSequence, chapterName: CharSequence, group: CharSequence, index: Int){ comicFileRelative = "$group/$chapterName.zip" @@ -72,6 +73,8 @@ class MangaDlTools { zip.setLevel(9) var succeed = true for (i in urls.indices) { + while (wait && !exit) sleep(1000) + if (exit) break zip.putNextEntry(ZipEntry("$i.webp")) var tryTimes = 3 var s = false @@ -89,7 +92,6 @@ class MangaDlTools { if (!s && tryTimes <= 0) succeed = false onDownloadedListener?.handleMessage(s, i + 1) zip.flush() - if (exit) break } zip.close() onDownloadedListener?.handleMessage(succeed) 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 ce0edd1..ce5dc3c 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 @@ -5,6 +5,7 @@ import android.util.Log import android.view.Menu import android.view.View import androidx.navigation.Navigation +import kotlinx.android.synthetic.main.app_bar_main.* import top.fumiama.dmzj.copymanga.R import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference import top.fumiama.copymanga.template.general.NoBackRefreshFragment @@ -28,7 +29,10 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) { override fun onResume() { super.onResume() - mainWeakReference?.get()?.menuMain?.let { setMenuVisible(it) } + mainWeakReference?.get()?.apply { + menuMain?.let { setMenuVisible(it) } + toolbar.title = bookHandler.book?.results?.comic?.name + } } override fun onDestroy() { @@ -37,6 +41,11 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) { bookHandler.destroy() } + override fun onPause() { + super.onPause() + mainWeakReference?.get()?.menuMain?.let { setMenuInvisible(it) } + } + private fun setMenuInvisible(menu: Menu){ menu.findItem(R.id.action_download)?.isVisible = false } 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 1e3d085..21694aa 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 @@ -17,6 +17,7 @@ import kotlinx.android.synthetic.main.fragment_book.* import kotlinx.android.synthetic.main.line_2chapters.view.* import kotlinx.android.synthetic.main.line_bookinfo.* import kotlinx.android.synthetic.main.line_bookinfo_text.* +import kotlinx.android.synthetic.main.line_caption.view.* import kotlinx.android.synthetic.main.line_chapter.view.* import top.fumiama.dmzj.copymanga.R import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference @@ -52,7 +53,7 @@ class BookHandler(that: WeakReference, path: String) 1 -> setCover() 2 -> setTexts() 3 -> fbibinfo?.let { setInfoHeight(it) } - //4 -> setThemes() + 4 -> setThemes() 5 -> setOverScale() 6 -> endSetLayouts() } @@ -147,44 +148,60 @@ class BookHandler(that: WeakReference, path: String) } } - private fun setThemes(){ - book?.results?.groups?.let { - val keyIterator = it.keys.iterator() - for(i in 0 until it.size){ - if(i % 2 == 0){ - that?.fbl?.addView(if(i < it.size - 1){ - val line = that.layoutInflater.inflate(R.layout.line_2chapters, that.fbl, false) - val leftKey = keyIterator.next() - line?.l2cl?.lct?.text = it[leftKey]?.name - line?.l2cl?.setOnClickListener { _-> - loadVolume(it[leftKey]?.path_word?:"null") + private fun setTheme(caption: String, themeStructure: Array, nav: Int) { + that?.apply { + val t = layoutInflater.inflate(R.layout.line_caption, fbl, false) + t.tcptn.text = caption + fbl.addView(t) + fbl.addView(layoutInflater.inflate(R.layout.div_h, fbl, false)) + } + var line: View? = null + val last = themeStructure.size - 1 + themeStructure.onEachIndexed { i, it -> + if(line == null) { + if(i == last) { + line = that?.layoutInflater?.inflate(R.layout.line_chapter, that.fbl, false) + line?.lcc?.apply { + lct.text = it.name + setOnClickListener { _ -> + loadVolume(it.name, it.path_word, nav) } - val rightKey = keyIterator.next() - line?.l2cr?.lct?.text = it[rightKey]?.name - line?.l2cr?.setOnClickListener { _-> - loadVolume(it[rightKey]?.path_word?:"null") + } + that?.fbl?.addView(line) + } else { + line = that?.layoutInflater?.inflate(R.layout.line_2chapters, that.fbl, false) + line?.l2cl?.apply { + lct.text = it.name + setOnClickListener { _ -> + loadVolume(it.name, it.path_word, nav) } - line - }else{ - //Log.d("MyBH", "Add chapter: ${vol[i].volume_name}") - val line = that.layoutInflater.inflate(R.layout.line_chapter, that.fbl, false) - val key = keyIterator.next() - line?.lct?.text = it[key]?.name - line?.lcc?.setOnClickListener { _-> - loadVolume(it[key]?.path_word?:"null") - } - line - }) + } } + } else line?.l2cr?.apply { + lct.text = it.name + setOnClickListener { _ -> + loadVolume(it.name, it.path_word, nav) + } + that?.fbl?.addView(line) + line = null } } } - private fun loadVolume(gpw: String){ + private fun setThemes(){ + that?.apply { + book?.results?.comic?.apply { + author?.let { setTheme(getString(R.string.author), it, R.id.action_nav_book_to_nav_author) } + theme?.let { setTheme(getString(R.string.caption), it, R.id.action_nav_book_to_nav_caption) } + } + } + } + + private fun loadVolume(name: String, path: String, nav: Int){ Log.d("MyBH", "start to load chapter") val bundle = Bundle() - bundle.putString("group", gpw) - book?.results?.comic?.path_word?.let { bundle.putString("path", it) } - that?.rootView?.let { Navigation.findNavController(it).navigate(R.id.action_nav_book_to_nav_chapter, bundle) } + bundle.putString("name", name) + bundle.putString("path", path) + that?.rootView?.let { Navigation.findNavController(it).navigate(nav, bundle) } } } \ No newline at end of file diff --git a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/author/AuthorFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/author/AuthorFragment.kt new file mode 100644 index 0000000..9abb65e --- /dev/null +++ b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/author/AuthorFragment.kt @@ -0,0 +1,7 @@ +package top.fumiama.copymanga.ui.cardflow.author + +import top.fumiama.copymanga.template.ui.ThemeCardFlow +import top.fumiama.dmzj.copymanga.R + +@ExperimentalStdlibApi +class AuthorFragment : ThemeCardFlow(R.string.authorApiUrl, R.id.action_nav_author_to_nav_book) \ No newline at end of file diff --git a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/caption/CaptionFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/caption/CaptionFragment.kt new file mode 100644 index 0000000..da3e4bd --- /dev/null +++ b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/caption/CaptionFragment.kt @@ -0,0 +1,7 @@ +package top.fumiama.copymanga.ui.cardflow.caption + +import top.fumiama.copymanga.template.ui.ThemeCardFlow +import top.fumiama.dmzj.copymanga.R + +@ExperimentalStdlibApi +class CaptionFragment : ThemeCardFlow(R.string.captionApiUrl, R.id.action_nav_caption_to_nav_book) \ No newline at end of file diff --git a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/finish/FinishFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/finish/FinishFragment.kt index 62352ba..1b77baf 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/finish/FinishFragment.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/finish/FinishFragment.kt @@ -1,77 +1,7 @@ package top.fumiama.copymanga.ui.cardflow.finish -import android.animation.ObjectAnimator -import android.view.View -import kotlinx.android.synthetic.main.anchor_popular.view.* -import kotlinx.android.synthetic.main.line_finish.* -import kotlinx.android.synthetic.main.line_lazybooklines.* -import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference -import top.fumiama.copymanga.template.ui.InfoCardLoader +import top.fumiama.copymanga.template.ui.StatusCardFlow import top.fumiama.dmzj.copymanga.R -import java.lang.Thread.sleep @ExperimentalStdlibApi -class FinishFragment : InfoCardLoader(R.layout.fragment_finish, R.id.action_nav_finish_to_nav_book) { - private val sortWay = listOf("datetime_updated", "-datetime_updated", "popular", "-popular") - private var sortValue = 0 - - override fun getApiUrl() = - getString(R.string.finishApiUrl).let { - String.format( - it, - page * 21, - sortWay[sortValue] - ) - } - - override fun setListeners() { - super.setListeners() - setUpdate() - setHot() - } - - override fun onLoadFinish() { - super.onLoadFinish() - mainWeakReference?.get()?.runOnUiThread { - mypl.visibility = View.GONE - } - } - - private fun setUpdate() { - line_finish_time.apply { - apt.setText(R.string.menu_update_time) - setOnClickListener { - sortValue = if(apim.rotation == 0f) { - ObjectAnimator.ofFloat(apim, "rotation", 0f, 180f).setDuration(233).start() - 1 - }else{ - ObjectAnimator.ofFloat(apim, "rotation", 180f, 0f).setDuration(233).start() - 0 - } - Thread{ - sleep(400) - mh?.sendEmptyMessage(4) - }.start() - } - } - } - - private fun setHot() { - line_finish_pop.apply { - apt.setText(R.string.menu_hot) - setOnClickListener { - sortValue = if (apim.rotation == 0f) { - ObjectAnimator.ofFloat(apim, "rotation", 0f, 180f).setDuration(233).start() - 1 - } else { - ObjectAnimator.ofFloat(apim, "rotation", 180f, 0f).setDuration(233).start() - 0 - } - Thread { - sleep(400) - mh?.sendEmptyMessage(4) - }.start() - } - } - } -} \ No newline at end of file +class FinishFragment : StatusCardFlow(R.string.finishApiUrl, R.id.action_nav_finish_to_nav_book) \ No newline at end of file diff --git a/app/src/main/java/top/fumiama/copymanga/ui/comicdl/ComicDlHandler.kt b/app/src/main/java/top/fumiama/copymanga/ui/comicdl/ComicDlHandler.kt index d4e23f8..58b697f 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/comicdl/ComicDlHandler.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/comicdl/ComicDlHandler.kt @@ -60,7 +60,6 @@ class ComicDlHandler(looper: Looper, that: WeakReference, priva private var checkedChapter = 0 private var dldChapter = 0 private var haveDlStarted = false - private var canDl = false private var tbtnlist: Array = arrayOf() private var tbtncnt = 0 private var isNewTitle = false @@ -215,10 +214,12 @@ class ComicDlHandler(looper: Looper, that: WeakReference, priva setProgress2(dldChapter * 100 / checkedChapter, 233) } private fun updateProgressBar(pageNow: Int, size: Int) { - val delta = 100 / checkedChapter - val start = dldChapter * delta - val now = pageNow * delta / size - setProgress2(start + now, 64) + if(checkedChapter > 0) { + val delta = 100 / checkedChapter + val start = dldChapter * delta + val now = pageNow * delta / size + setProgress2(start + now, 64) + } } private fun setProgress2(end: Int, duration: Long) { ObjectAnimator.ofInt( @@ -259,10 +260,10 @@ class ComicDlHandler(looper: Looper, that: WeakReference, priva else if(checkedChapter == 0) hideDlCard() else{ that.pdwn.progress = 0 - if (canDl || checkedChapter == 0) canDl = false + if(haveDlStarted && checkedChapter != 0) mangaDlTools.wait = !mangaDlTools.wait else { haveDlStarted = true - canDl = true + mangaDlTools.wait = false Thread{ sendEmptyMessage(9) //set dl card color to green downloadMangas() @@ -291,16 +292,8 @@ class ComicDlHandler(looper: Looper, that: WeakReference, priva private fun downloadMangas(){ for (i in tbtnlist) { if (i.isChecked) downloadChapterPages(i) - if (!canDl) { - checkedChapter -= dldChapter - dldChapter = 0 - break - } - } - if (canDl) { - haveDlStarted = false - canDl = false } + haveDlStarted = false } private fun downloadChapterPages(i: ChapterToggleButton) { diff --git a/app/src/main/java/top/fumiama/copymanga/ui/home/HomeHandler.kt b/app/src/main/java/top/fumiama/copymanga/ui/home/HomeHandler.kt index d10766f..b01458a 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/home/HomeHandler.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/home/HomeHandler.kt @@ -310,7 +310,9 @@ class HomeHandler(that: WeakReference) : AutoDownloadHandler( private fun setCards(cv: CardView, pw: String, name: String, img: String, isFinal: Boolean, isTopic: Boolean) { cv.tic.text = name homeF?.let { - Glide.with(it).load(GlideUrl(img, CMApi.myGlideHeaders)).timeout(20000).into(cv.imic) + if(img.startsWith("http")) { + Glide.with(it).load(GlideUrl(img, CMApi.myGlideHeaders)).timeout(20000).into(cv.imic) + } } if (isFinal) cv.sgnic.visibility = View.VISIBLE cv.setOnClickListener { diff --git a/app/src/main/java/top/fumiama/copymanga/ui/vm/PagesManager.kt b/app/src/main/java/top/fumiama/copymanga/ui/vm/PagesManager.kt index 02c3a63..843d09a 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/vm/PagesManager.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/vm/PagesManager.kt @@ -21,7 +21,7 @@ class PagesManager(w: WeakReference) { toPage(v?.r2l!=true) } private fun judgePrevious() = v?.pageNum?:0 > 1 - private fun judgeNext() = v?.pageNum?:0 < v?.count?:0 + private fun judgeNext() = v?.pageNum?:0 < v?.realCount?:0 @ExperimentalStdlibApi fun toPage(goNext:Boolean){ if (v?.clicked == false) { diff --git a/app/src/main/java/top/fumiama/copymanga/ui/vm/VMHandler.kt b/app/src/main/java/top/fumiama/copymanga/ui/vm/VMHandler.kt index df650cc..02a4ed0 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/vm/VMHandler.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/vm/VMHandler.kt @@ -78,19 +78,19 @@ class VMHandler(activity: ViewMangaActivity, url: String) : AutoDownloadHandler( } 4 -> { val simg = msg.obj as ScaleImageView - wv.get()?.loadImgOn(simg, msg.arg1) - simg.setHeight2FitImgWidth() - if(msg.arg2 == 1) sendEmptyMessage(8) + wv.get()?.loadImgOn(simg, msg.arg1, msg.arg2) + //simg.setHeight2FitImgWidth() + //if(msg.arg2 == 1) sendEmptyMessage(8) } 5 -> wv.get()?.clearImgOn(msg.obj as ScaleImageView) 6 -> wv.get()?.prepareLastPage(msg.arg1, msg.arg2) 7 -> dl?.show() 8 -> Thread{ - sleep(233) - sendEmptyMessage(13) - }.start() - 9 -> loadThread(msg.arg1) - 10 -> loadThread() + sleep(233) + sendEmptyMessage(13) + }.start() + 9 -> loadScrollMode(msg.arg1) + 10 -> loadScrollMode() 11 -> loadImgsIntoLine(msg.arg1) 12 -> loadImgsIntoLine() 13 -> { @@ -98,10 +98,12 @@ class VMHandler(activity: ViewMangaActivity, url: String) : AutoDownloadHandler( wv.get()?.restorePN() } 14 -> { - val item = (pn - 1) / (wv.get()?.verticalLoadMaxCount?:40) * (wv.get()?.verticalLoadMaxCount?:40) - loadThread(item) + val item = (pn - 1) / (wv.get()?.verticalLoadMaxCount?:20) * (wv.get()?.verticalLoadMaxCount?:20) + loadScrollMode(item) Log.d("MyVMH", "Load page from $item") } + 15 -> dl?.hide() + //16 -> wv.get()?.prepareItems() 22 -> wv.get()?.idtime?.text = SimpleDateFormat("HH:mm").format(Date()) + week + wv.get()?.toolsBox?.netinfo } } @@ -128,7 +130,10 @@ class VMHandler(activity: ViewMangaActivity, url: String) : AutoDownloadHandler( fun loadFromFile(file: File): Boolean { return try { val jsonFile = File(file.parentFile, "${file.nameWithoutExtension}.json") - if(jsonFile.exists()) manga = Gson().fromJson(jsonFile.reader(), Chapter2Return::class.java) + if(jsonFile.exists()) { + manga = Gson().fromJson(jsonFile.reader(), Chapter2Return::class.java) + prepareManga() + } else{ manga = Chapter2Return() manga?.let { @@ -137,10 +142,12 @@ class VMHandler(activity: ViewMangaActivity, url: String) : AutoDownloadHandler( it.results.comic.name = file.parentFile?.name it.results.chapter = ChapterWithContent() it.results.chapter.name = file.nameWithoutExtension - it.results.chapter.size = countZipEntries(file) + wv.get()?.countZipEntries { c -> + it.results.chapter.size = c + prepareManga() + } } } - prepareManga() true }catch (e: Exception){ e.printStackTrace() @@ -149,23 +156,6 @@ class VMHandler(activity: ViewMangaActivity, url: String) : AutoDownloadHandler( } } - private fun countZipEntries(file: File): Int{ - var count = 0 - try { - val zip = ZipInputStream(file.inputStream().buffered()) - var entry = zip.nextEntry - while (entry != null) { - if (!entry.isDirectory) count++ - entry = zip.nextEntry - } - zip.closeEntry() - zip.close() - } catch (e: Exception) { - wv.get()?.toolsBox?.toastError("统计zip图片数错误!") - } - return count - } - @ExperimentalStdlibApi private fun prepareManga(){ comicName = manga?.results?.comic?.name @@ -174,29 +164,33 @@ class VMHandler(activity: ViewMangaActivity, url: String) : AutoDownloadHandler( wv.get()?.initManga() wv.get()?.vprog?.visibility = View.GONE } - private fun loadImgsIntoLine(item: Int = (wv.get()?.currentItem?:0), maxCount: Int = (wv.get()?.verticalLoadMaxCount?:40)){ - Log.d("MyVMH", "Fun: loadImgsIntoLine($item)") - val count = wv.get()?.count?.minus(1)?:0 - val notFull = item + maxCount > count - val loadCount = (if(notFull) count - item else maxCount) - 1 - Log.d("MyVMH", "loadCount: $loadCount") - if(loadCount >= 0) for(i in 0..loadCount) obtainMessage(4,item + i, if(i == loadCount - 1)1 else 0, wv.get()?.scrollImages?.get(i)).sendToTarget() - else sendEmptyMessage(8) - if(notFull) obtainMessage(6, loadCount + 1, maxCount).sendToTarget() - } + private fun loadImgsIntoLine(item: Int = (wv.get()?.currentItem?:0), maxCount: Int = (wv.get()?.verticalLoadMaxCount?:20)) /*= Thread*/{ + Log.d("MyVMH", "Fun: loadImgsIntoLine($item, $maxCount)") + wv.get()?.realCount?.let { count -> + if(count > 0){ + val notFull = item + maxCount > count + val loadCount = (if(notFull) count - item else maxCount) - 1 + Log.d("MyVMH", "count: $count, loadCount: $loadCount, notFull: $notFull") + if(loadCount >= 0) for(i in 0..loadCount) obtainMessage(4,item + i, if(i == loadCount - 1) 1 else 0, wv.get()?.scrollImages?.get(i)).sendToTarget() + else sendEmptyMessage(8) + if(notFull) obtainMessage(6, loadCount + 1, maxCount).sendToTarget() + wv.get()?.updateSeekBar() + } + } + }//.start() - private fun loadThread() = Thread{ + private fun loadScrollMode() { sendEmptyMessage(7) //sleep(233) sendEmptyMessage(12) - }.start() + } - private fun loadThread(item: Int) = Thread{ + private fun loadScrollMode(item: Int) { sendEmptyMessage(7) //sleep(233) Log.d("MyVMH", "loadImgsIntoLine($item)") obtainMessage(11, item, 0).sendToTarget() - }.start() + } private fun showInfCard() { Log.d("MyVMH", "Read info drawer delta: $delta") diff --git a/app/src/main/java/top/fumiama/copymanga/ui/vm/ViewMangaActivity.kt b/app/src/main/java/top/fumiama/copymanga/ui/vm/ViewMangaActivity.kt index b6f9086..b0e1959 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/vm/ViewMangaActivity.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/vm/ViewMangaActivity.kt @@ -2,8 +2,10 @@ package top.fumiama.copymanga.ui.vm import android.animation.ObjectAnimator import android.annotation.SuppressLint +import android.app.Service import android.graphics.Bitmap import android.graphics.BitmapFactory +import android.media.AudioManager import android.os.Bundle import android.os.Handler import android.util.Log @@ -14,6 +16,8 @@ import androidx.recyclerview.widget.RecyclerView import androidx.viewpager2.widget.ViewPager2 import com.bumptech.glide.Glide import com.bumptech.glide.load.model.GlideUrl +import com.bumptech.glide.request.target.SimpleTarget +import com.bumptech.glide.request.transition.Transition import com.liaoinstan.springview.widget.SpringView import kotlinx.android.synthetic.main.activity_viewmanga.* import kotlinx.android.synthetic.main.line_header.view.* @@ -28,6 +32,7 @@ import kotlinx.android.synthetic.main.widget_titlebar.view.* import kotlinx.android.synthetic.main.widget_viewmangainfo.* import top.fumiama.dmzj.copymanga.R import top.fumiama.copymanga.template.general.TitleActivityTemplate +import top.fumiama.copymanga.template.http.AutoDownloadThread import top.fumiama.copymanga.tools.api.CMApi import top.fumiama.copymanga.tools.http.DownloadTools import top.fumiama.copymanga.tools.thread.TimeThread @@ -35,8 +40,10 @@ import top.fumiama.copymanga.views.ScaleImageView import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.File +import java.io.InputStream import java.lang.ref.WeakReference import java.util.* +import java.util.concurrent.FutureTask import java.util.zip.ZipFile class ViewMangaActivity : TitleActivityTemplate() { @@ -49,23 +56,32 @@ class ViewMangaActivity : TitleActivityTemplate() { //private var progressLog: PropertiesTools? = null var scrollImages = arrayOf() //var zipFirst = false - private var useFullScreen = false + //private var useFullScreen = false var r2l = true var currentItem = 0 - var verticalLoadMaxCount = 40 + var verticalLoadMaxCount = 20 private var notUseVP = true private var isVertical = false - private var q = 90 - private val size get() = if(count / verticalLoadMaxCount > currentItem / verticalLoadMaxCount) verticalLoadMaxCount else count % verticalLoadMaxCount + private var q = 100 + private val size get() = if(realCount / verticalLoadMaxCount > currentItem / verticalLoadMaxCount) verticalLoadMaxCount else realCount % verticalLoadMaxCount var infoDrawerDelta = 0f var pageNum: Int get() = getPageNumber() set(value) = setPageNumber(value) //var pn = 0 private val isPnValid: Boolean get(){ - if(pn == -2) pn = count + if(pn == -2) pn = realCount return intent.getStringExtra("function") == "log" && pn > 0 } + private var tasks: Array?>? = null + private var destroy = false + private var cut = false + private var isCut = booleanArrayOf() + private var indexMap = intArrayOf() + private var volTurnPage = false + private var am: AudioManager? = null + private var pm: PagesManager? = null + val realCount get() = if(cut) indexMap.size else count @ExperimentalStdlibApi @SuppressLint("SetTextI18n") @@ -76,17 +92,19 @@ class ViewMangaActivity : TitleActivityTemplate() { //progressLog = PropertiesTools(File("$filesDir/progress/${chapter2Return?.results?.chapter?.comic_id}")) //dlZip2View = intent.getStringExtra("callFrom") == "Dl" || p["dlZip2View"] == "true" //zipFirst = intent.getStringExtra("callFrom") == "zipFirst" - useFullScreen = p["useFullScreen"] != "true" + cut = p["useCut"] == "true" r2l = p["r2l"] == "true" + verticalLoadMaxCount = if (p["verticalMax"] != "null") p["verticalMax"].toInt() else 20 isVertical = p["vertical"] == "true" notUseVP = p["noVP"] == "true" || isVertical //url = intent.getStringExtra("url") handler = VMHandler(this, if(urlArray.isNotEmpty()) urlArray[position] else "") if (p["quality"] != "null") q = p["quality"].toInt() - if (p["verticalMax"] != "null") verticalLoadMaxCount = p["verticalMax"].toInt() tt = TimeThread(handler, 22) tt.canDo = true tt.start() + volTurnPage = p["volturn"] == "true" + am = getSystemService(Service.AUDIO_SERVICE) as AudioManager Log.d("MyVM", "Now ZipFile is $zipFile") try { @@ -101,15 +119,33 @@ class ViewMangaActivity : TitleActivityTemplate() { override fun onWindowFocusChanged(hasFocus: Boolean) { super.onWindowFocusChanged(hasFocus) - if(useFullScreen) { - if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.R) - window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY - else { - window.setDecorFitsSystemWindows(false) - window.insetsController?.hide(WindowInsets.Type.statusBars()) - //window.insetsController?.hide(WindowInsets.Type.navigationBars()) + if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.R) + window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + else { + window.setDecorFitsSystemWindows(false) + window.insetsController?.hide(WindowInsets.Type.statusBars()) + //window.insetsController?.hide(WindowInsets.Type.navigationBars()) + } + } + + @ExperimentalStdlibApi + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + var flag = false + if(volTurnPage) when(keyCode) { + KeyEvent.KEYCODE_VOLUME_UP -> { + pm?.toPage(false) + flag = true + } + KeyEvent.KEYCODE_VOLUME_DOWN -> { + pm?.toPage(true) + flag = true } } + return if(flag) true else super.onKeyDown(keyCode, event) + } + + private fun alertCellar() { + toolsBox.buildInfo("注意", "要使用使用流量观看吗?", "确定", null, "取消", {handler.startLoad()}, null, {finish()}) } fun restorePN(){ @@ -121,30 +157,122 @@ class ViewMangaActivity : TitleActivityTemplate() { sendProgress() } + private fun preDownloadChapterPages() { + getImgUrlArray()?.let { + val mid = (if(pn in 1 until realCount) (if(cut) Math.abs(indexMap[pn]) else pn) else if(pn == -2 || pn >= realCount) it.size else 1) - 1 + val left = if(isVertical && mid > verticalLoadMaxCount) (mid / verticalLoadMaxCount) * verticalLoadMaxCount else (mid-1) + val right = if(isVertical) (mid / verticalLoadMaxCount + 1) * verticalLoadMaxCount else mid + tasks = arrayOfNulls(it.size) + Thread{ + for (i in right until it.size) { + if(destroy) break + tasks?.let { tasks -> + tasks[i] = DownloadTools.touch(it[i]) + Thread.sleep(1000) + } + } + }.start() + Thread.sleep(500) + Thread{ + for (i in left downTo 0) { + if(destroy) break + tasks?.let { tasks -> + tasks[i] = DownloadTools.touch(it[i]) + Thread.sleep(1000) + } + } + }.start() + } + } + + @ExperimentalStdlibApi + private fun doPrepareWebImg() { + getImgUrlArray()?.apply { + if(cut) { + handler.sendEmptyMessage(7) //showDl + isCut = BooleanArray(size) + val analyzedCnt = BooleanArray(size) + forEachIndexed{ i, it -> + if(it != null) { + Thread{ + DownloadTools.getHttpContent(it, 1024)?.inputStream()?.let { + isCut[i] = canCut(it) + analyzedCnt[i] = true + } + }.start() + Thread.sleep(22) + } + } + while (analyzedCnt.count { it } != size) Thread.sleep(233) + isCut.forEachIndexed { index, b -> + Log.d("MyVM", "[$index] cut: $b") + indexMap += index+1 + if(b) indexMap += -(index+1) + } + handler.sendEmptyMessage(15) //hideDl + } + count = size + runOnUiThread { prepareItems() } + preDownloadChapterPages() + } + } + @ExperimentalStdlibApi fun initManga(){ - prepareItems(count) + if (zipFile?.exists() != true) doPrepareWebImg() + else prepareItems() if (!isVertical) restorePN() } @ExperimentalStdlibApi private fun prepareImgFromWeb() { - handler.startLoad() + if(toolsBox.netinfo == "移动数据") alertCellar() + else handler.startLoad() } + private fun canCut(inputStream: InputStream): Boolean{ + val op = BitmapFactory.Options() + op.inJustDecodeBounds = true + BitmapFactory.decodeStream(inputStream, null, op) + Log.d("MyVM", "w: ${op.outWidth}, h: ${op.outHeight}") + return op.outWidth.toFloat() / op.outHeight.toFloat() > 1 + } + + @ExperimentalStdlibApi + fun countZipEntries(doWhenFinish : (count: Int) -> Unit) = Thread{ + if (zipFile != null) try { + Log.d("Myvm", "zip: $zipFile") + val zip = ZipFile(zipFile) + count = zip.size() + if(cut) zip.entries().toList().sortedBy{it.name.substringBefore('.').toInt()}.forEachIndexed { i, it -> + val useCut = canCut(zip.getInputStream(it)) + isCut += useCut + indexMap += i + 1 + if (useCut) indexMap += -(i + 1) + Log.d("Myvm", "[$i] 分析: ${it.name}, cut: $useCut") + } + } catch (e: Exception) { + runOnUiThread { toolsBox.toastError("统计zip图片数错误!") } + } + runOnUiThread { + Log.d("Myvm", "开始加载控件") + doWhenFinish(count) + } + }.start() + private fun getPageNumber(): Int { - return if (r2l && !notUseVP) count - vp.currentItem + return if (r2l && !notUseVP) realCount - vp.currentItem else (if (notUseVP) currentItem else vp.currentItem) + 1 } private fun setPageNumber(num: Int) { - if (r2l && !notUseVP) vp.currentItem = count - num + if (r2l && !notUseVP) vp.currentItem = realCount - num else if (notUseVP) { if(isVertical){ currentItem = num - 1 - val delta = currentItem % verticalLoadMaxCount - Log.d("MyVM", "Height: ${psivl.height}, scrollY: ${psivs.scrollY}") - if (!isInScroll || isInSeek) psivs.scrollY = psivl.height / size * delta + val offset = currentItem % verticalLoadMaxCount + Log.d("MyVM", "Current: $currentItem, Height: ${psivl.height}, scrollY: ${psivs.scrollY}") + if (!isInScroll || isInSeek) psivs.scrollY = psivl.height * offset / size updateSeekBar() } else { @@ -156,31 +284,86 @@ class ViewMangaActivity : TitleActivityTemplate() { toolsBox.toastError("页数${currentItem}不合法") } } - } else vp.currentItem = num - 1 + } else { + Log.d("MyVM", "Set vp current: ${num-1}") + var delta = num - 1 - vp.currentItem + if(delta >= 1) Thread{ + while (delta-- > 0){ + Thread.sleep(23) + runOnUiThread { + vp.currentItem++ + } + } + }.start() + else if(delta <= -1) Thread{ + while (delta++ < 0){ + Thread.sleep(23) + runOnUiThread { + vp.currentItem-- + } + } + }.start() + } } fun clearImgOn(imgView: ScaleImageView){ imgView.visibility = View.GONE } - private fun getTempFile(position: Int) = File(cacheDir, "$position") + //private fun getTempFile(position: Int) = File(cacheDir, "$position") private fun getImgUrl(position: Int) = handler.manga?.results?.chapter?.let { it.contents[it.words.indexOf(position)].url } - fun loadImgOn(imgView: ScaleImageView, position: Int){ - if (zipFile?.exists() == true) imgView.setImageBitmap(getImgBitmap(position)) - else if(isVertical) { - val f = getTempFile(position) - if(DownloadTools.downloadUsingUrlRet(getImgUrl(position), f)) - imgView.setImageBitmap(BitmapFactory.decodeFile(f.path)) - else Toast.makeText(this, "下载第${position}页失败", Toast.LENGTH_SHORT).show() + private fun getImgUrlArray() = handler.manga?.results?.chapter?.let{ + val re = arrayOfNulls(it.contents.size) + for(i in it.contents.indices) { + re[i] = getImgUrl(i) + } + re + } + + private fun cutBitmap(bitmap: Bitmap, isEnd: Boolean) = Bitmap.createBitmap(bitmap, if(!isEnd) 0 else (bitmap.width/2), 0, bitmap.width/2, bitmap.height) + + private fun loadImg(imgView: ScaleImageView, bitmap: Bitmap, isLast: Int = 0, useCut: Boolean, isLeft: Boolean){ + val bitmap2load = if(useCut) cutBitmap(bitmap, isLeft) else bitmap + runOnUiThread { + imgView.setImageBitmap(bitmap2load) + if(isVertical){ + imgView.setHeight2FitImgWidth() + if (isLast == 1) handler.sendEmptyMessage(8) + } + } + } + + private fun loadImgUrlInto(imgView: ScaleImageView, url: String, isLast: Int = 0, useCut: Boolean, isLeft: Boolean){ + Log.d("MyVM", "Load from adt: $url") + AutoDownloadThread(url) { + it?.let { loadImg(imgView, BitmapFactory.decodeByteArray(it, 0, it.size), isLast, useCut, isLeft) } + }.start() + } + + fun loadImgOn(imgView: ScaleImageView, position: Int, isLast: Int = 0){ + Log.d("MyVM", "Load img: $position") + val index2load = if(cut) Math.abs(indexMap[position]) -1 else position + val useCut = cut && isCut[index2load] + val isLeft = cut && indexMap[position] > 0 + if (zipFile?.exists() == true) getImgBitmap(index2load)?.let { + loadImg(imgView, it, isLast, useCut, isLeft) + } + else { + val re = tasks?.get(index2load) + if (re != null) Thread{ + val data = re.get() + if(data != null) { + loadImg(imgView, BitmapFactory.decodeByteArray(data, 0, data.size), isLast, useCut, isLeft) + Log.d("MyVM", "Load from task") + } + else getImgUrl(index2load)?.let { loadImgUrlInto(imgView, it, isLast, useCut, isLeft) } + }.start() + else getImgUrl(index2load)?.let { loadImgUrlInto(imgView, it, isLast, useCut, isLeft) } } - else Glide.with(this) - .load(GlideUrl(getImgUrl(position), CMApi.myGlideHeaders)) - .timeout(10000) - .into(imgView) imgView.visibility = View.VISIBLE } @@ -190,7 +373,7 @@ class ViewMangaActivity : TitleActivityTemplate() { } private fun initImgList(){ - for (i in 0..39) { + for (i in 0 until verticalLoadMaxCount) { val newImg = ScaleImageView(this) scrollImages += newImg psivl.addView(newImg) @@ -202,24 +385,21 @@ class ViewMangaActivity : TitleActivityTemplate() { handler.dl?.hide() } - private fun getImgBitmap(position: Int): Bitmap? { - Log.d("MyVM", "Get bitmap @$position, count is $count") - if (position >= count || position < 0) return null - else { + private fun getImgBitmap(position: Int): Bitmap? = + if (position >= count || position < 0) null + else try { val zip = ZipFile(zipFile) - if (q == 100) return BitmapFactory.decodeStream(zip.getInputStream(zip.getEntry("${position}.jpg"))) + if (q == 100) BitmapFactory.decodeStream(zip.getInputStream(zip.getEntry("${position}.webp"))) else { val out = ByteArrayOutputStream() - try { - BitmapFactory.decodeStream(zip.getInputStream(zip.getEntry("${position}.webp"))) - } catch (e: Exception) { - e.printStackTrace() - return null - }?.compress(Bitmap.CompressFormat.JPEG, q, out) - return BitmapFactory.decodeStream(ByteArrayInputStream(out.toByteArray())) + BitmapFactory.decodeStream(zip.getInputStream(zip.getEntry("${position}.webp")))?.compress(Bitmap.CompressFormat.JPEG, q, out) + BitmapFactory.decodeStream(ByteArrayInputStream(out.toByteArray())) } + } catch (e: Exception) { + e.printStackTrace() + Toast.makeText(this, "加载zip的${position}.webp错误", Toast.LENGTH_SHORT).show() + null } - } private fun setIdPosition(position: Int) { infoDrawerDelta = position.toFloat() @@ -229,19 +409,24 @@ class ViewMangaActivity : TitleActivityTemplate() { @ExperimentalStdlibApi @SuppressLint("SetTextI18n") - private fun prepareItems(size: Int) { - ttitle.text = handler.manga?.results?.chapter?.name - prepareVP() - prepareInfoBar(size) - if (notUseVP && !isVertical) loadOneImg() - prepareIdBtVH() - toolsBox.dp2px(67)?.let { setIdPosition(it) } - prepareIdBtFullScreen() - prepareIdBtVP() - prepareIdBtLR() - handler.progressLog?.let { - //it["uuid"] = handler.manga?.results?.comic?.uuid - it["name"] = inftitle.ttitle.text + private fun prepareItems() { + try { + prepareVP() + //if (!isVertical) restorePN() + prepareInfoBar() + if (notUseVP && !isVertical && !isPnValid) loadOneImg() + prepareIdBtVH() + toolsBox.dp2px(67)?.let { setIdPosition(it) } + prepareIdBtCut() + prepareIdBtVP() + prepareIdBtLR() + /*progressLog?.let { + it["chapterId"] = hm.chapterId.toString() + it["name"] = inftitle.ttitle.text + }*/ + }catch (e: Exception) { + e.printStackTrace() + toolsBox.toastError("准备控件错误") } } @@ -253,6 +438,14 @@ class ViewMangaActivity : TitleActivityTemplate() { } } + private fun prepareIdBtCut() { + idtbcut.isChecked = cut + idtbcut.setOnClickListener { + p["useCut"] = if (idtbcut.isChecked) "true" else "false" + Toast.makeText(this, "下次浏览生效", Toast.LENGTH_SHORT).show() + } + } + private fun prepareIdBtLR() { idtblr.isChecked = r2l idtblr.setOnClickListener { @@ -285,11 +478,11 @@ class ViewMangaActivity : TitleActivityTemplate() { super.onPageSelected(position) } }) - if (r2l) vp.currentItem = count - 1 + if (r2l && !isPnValid) vp.currentItem = realCount - 1 } } - private fun updateSeekBar() { + fun updateSeekBar() { if (!isInSeek) hideObjs() updateSeekText() updateSeekProgress() @@ -297,17 +490,18 @@ class ViewMangaActivity : TitleActivityTemplate() { } @SuppressLint("SetTextI18n") - private fun prepareInfoBar(size: Int) { + private fun prepareInfoBar() { oneinfo.alpha = 0F infseek.visibility = View.GONE isearch.visibility = View.GONE inftitle.ttitle.text = handler.manga?.results?.chapter?.name - inftxtprogress.text = "$pageNum/$size" + inftxtprogress.text = "$pageNum/$realCount" infseek.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { override fun onProgressChanged(p0: SeekBar?, p1: Int, isHuman: Boolean) { + Log.d("MyVM", "seek to ${p1 * realCount / 100}") if (isHuman) { - if (p1 >= (pageNum + 1) * 100 / size) scrollForward() - else if (p1 < (pageNum - 1) * 100 / size) scrollBack() + if (p1 >= (pageNum + 1) * 100 / realCount) scrollForward() + else if (p1 < (pageNum - 1) * 100 / realCount) scrollBack() } } override fun onStartTrackingTouch(p0: SeekBar?) { @@ -318,6 +512,7 @@ class ViewMangaActivity : TitleActivityTemplate() { isInSeek = false } }) + isearch.setImageResource(R.drawable.ic_author) isearch.setOnClickListener { handler.sendEmptyMessage(3) } @@ -330,16 +525,16 @@ class ViewMangaActivity : TitleActivityTemplate() { val vsps = vsp as SpringView vsps.footerView.lht.text = "更多" vsps.headerView.lht.text = "更多" - val pm = PagesManager(WeakReference(this)) + pm = PagesManager(WeakReference(this)) vsps.setListener(object :SpringView.OnFreshListener{ override fun onLoadmore() { //scrollForward() - pm.toPage(true) + pm?.toPage(true) vsps.onFinishFreshAndLoad() } override fun onRefresh() { //scrollBack() - pm.toPage(false) + pm?.toPage(false) vsps.onFinishFreshAndLoad() } }) @@ -350,8 +545,11 @@ class ViewMangaActivity : TitleActivityTemplate() { psivs.setOnScrollChangeListener { _, _, scrollY, _, _ -> isInScroll = true if(!isInSeek){ - val newCurrent = (scrollY.toFloat() * size.toFloat() / psivl.height.toFloat() + 0.5).toInt() - pageNum += newCurrent - currentItem % verticalLoadMaxCount + val delta = (scrollY.toFloat() * size.toFloat() / psivl.height.toFloat() + 0.5).toInt() - currentItem % verticalLoadMaxCount + if(delta != 0 && !(delta > 0 && pageNum == size)) { + pageNum += delta + Log.d("MyVM", "Scroll to offset $delta") + } } } } @@ -361,14 +559,6 @@ class ViewMangaActivity : TitleActivityTemplate() { } } - private fun prepareIdBtFullScreen() { - idtbfullscreen.isChecked = !useFullScreen - idtbfullscreen.setOnClickListener { - p["useFullScreen"] = if (idtbfullscreen.isChecked) "true" else "false" - Toast.makeText(this, "下次浏览生效", Toast.LENGTH_SHORT).show() - } - } - fun scrollBack() { isInScroll = false if(isVertical && (pageNum-1) % verticalLoadMaxCount == 0){ @@ -384,20 +574,19 @@ class ViewMangaActivity : TitleActivityTemplate() { if(isVertical && (pageNum-1) % verticalLoadMaxCount == 0) handler.sendEmptyMessage(10) } - - @SuppressLint("SetTextI18n") private fun updateSeekText() { - inftxtprogress.text = "$pageNum/$count" + inftxtprogress.text = "$pageNum/$realCount" } private fun updateSeekProgress() { - infseek.progress = pageNum * 100 / count + infseek.progress = pageNum * 100 / realCount } override fun onDestroy() { dlhandler?.sendEmptyMessage(0) tt.canDo = false + destroy = true dlhandler = null handler.destroy() super.onDestroy() @@ -415,22 +604,30 @@ class ViewMangaActivity : TitleActivityTemplate() { @SuppressLint("ClickableViewAccessibility", "SetTextI18n") override fun onBindViewHolder(holder: ViewData, position: Int) { - val pos = if (r2l) count - position - 1 else position - if (zipFile?.exists() == true) getImgBitmap(pos)?.let { - Glide.with(this@ViewMangaActivity).load(it) - //.thumbnail(Glide.with(this@ViewMangaActivity).load(R.drawable.load)) - .into(holder.itemView.onei) - //holder.itemView.onei.setImageBitmap(it) + val pos = if (r2l) realCount - position - 1 else position + val index2load = if(cut) Math.abs(indexMap[pos]) -1 else pos + val useCut = cut && isCut[index2load] + val isLeft = cut && indexMap[pos] > 0 + if (zipFile?.exists() == true) getImgBitmap(index2load)?.let { + //Glide.with(this@ViewMangaActivity).load(if(useCut) cutBitmap(it, isLeft) else it).into(holder.itemView.onei) + holder.itemView.onei.setImageBitmap(if(useCut) cutBitmap(it, isLeft) else it) + } + else getImgUrl(index2load)?.let{ + if(useCut){ + val thisOneI = holder.itemView.onei + Glide.with(this@ViewMangaActivity) + .asBitmap() + .load(GlideUrl(it, CMApi.myGlideHeaders) + ).into(object : SimpleTarget() { + override fun onResourceReady(resource: Bitmap, transition: Transition?) { + thisOneI.setImageBitmap(cutBitmap(resource, isLeft)) + } }) + } else Glide.with(this@ViewMangaActivity).load(GlideUrl(it, CMApi.myGlideHeaders)).into(holder.itemView.onei) } - else Glide.with(this@ViewMangaActivity).load( - GlideUrl(getImgUrl(pos), CMApi.myGlideHeaders)) - .timeout(10000) - //.thumbnail(Glide.with(this@ViewMangaActivity).load(R.drawable.load)) - .into(holder.itemView.onei) } override fun getItemCount(): Int { - return count + return realCount } } } diff --git a/app/src/main/res/layout/fragment_finish.xml b/app/src/main/res/layout/fragment_statuscardflow.xml similarity index 100% rename from app/src/main/res/layout/fragment_finish.xml rename to app/src/main/res/layout/fragment_statuscardflow.xml diff --git a/app/src/main/res/layout/widget_infodrawer.xml b/app/src/main/res/layout/widget_infodrawer.xml index 1cb0dcd..3f10e48 100644 --- a/app/src/main/res/layout/widget_infodrawer.xml +++ b/app/src/main/res/layout/widget_infodrawer.xml @@ -39,7 +39,7 @@ app:layout_constraintVertical_bias="0.0" /> + app:layout_constraintStart_toEndOf="@+id/idtbcut" + app:layout_constraintTop_toTopOf="@+id/idtbcut" /> + app:layout_constraintTop_toTopOf="@+id/idtbcut" /> + app:layout_constraintTop_toTopOf="@+id/idtbcut" /> \ No newline at end of file diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml index 9937e66..1c36912 100644 --- a/app/src/main/res/navigation/mobile_navigation.xml +++ b/app/src/main/res/navigation/mobile_navigation.xml @@ -134,6 +134,20 @@ app:exitAnim="@anim/slide_out_left" app:popEnterAnim="@anim/slide_out_left_exit" app:popExitAnim="@anim/slide_in_right_exit"/> + + + tools:layout="@layout/fragment_statuscardflow" > + + + + + + + + https://api.copymanga.com/api/v3/recs?pos=3200102&limit=21&offset=%1$d&platform=3 https://api.copymanga.com/api/v3/update/newest?limit=21&offset=%1$d&platform=3 https://api.copymanga.com/api/v3/comics?limit=21&offset=%1$d&ordering=%2$s&top=finish&platform=3 + https://api.copymanga.com/api/v3/comics?limit=21&offset=%1$d&ordering=%2$s&author=%3$s&platform=3 + https://api.copymanga.com/api/v3/comics?limit=21&offset=%1$d&ordering=%2$s&theme=%3$s&platform=3 已完结 @@ -75,4 +77,7 @@ 近七天 近三十天 总榜单 + + 作者 + 标签 \ No newline at end of file diff --git a/build.gradle b/build.gradle index 8dc9e1f..cca0720 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ buildscript { maven { url 'https://maven.google.com' } } dependencies { - classpath 'com.android.tools.build:gradle:4.2.0' + classpath 'com.android.tools.build:gradle:4.2.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.21'