1
0
mirror of https://github.com/fumiama/copymanga.git synced 2026-06-04 23:10:23 +08:00
新增
1. CardFlow页面加载进度
修复
1. 进入漫画详情后,立即返回闪退
2. 分类切换标签闪退 (fix #56)
3. 我的下载某些漫画排序错误
4. 下载页缺失的图无法自动补齐
优化
1. 我的下载的加载速度
2. 进一步协程化(MPFT)
This commit is contained in:
源文雨
2024-03-12 18:26:00 +09:00
parent f13c2d32e6
commit 3dff5312ba
17 changed files with 325 additions and 261 deletions

View File

@@ -8,8 +8,8 @@ android {
applicationId 'top.fumiama.copymanga'
minSdkVersion 23
targetSdkVersion 34
versionCode 50
versionName '2.2.2'
versionCode 51
versionName '2.2.3'
resourceConfigurations += ['zh', 'zh-rCN']
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

View File

@@ -54,12 +54,8 @@ class Book(val path: String, private val getString: (Int) -> String, private val
val json get() = mJsonString
constructor(name: String, getString: (Int) -> String, exDir: File): this(
Gson().fromJson(File(File(exDir, name), "info.json").readText(), Array<VolumeStructure>::class.java).let{
if (it.isEmpty() || it[0].results.list.isEmpty()) {
throw IllegalArgumentException("$name/info.json无效")
}
it[0].results.list[0].comic_path_word
}, getString, exDir, true, name
Reader.getComicPathWordInFolder(File(exDir, name)),
getString, exDir, true, name
)
/**
@@ -119,6 +115,7 @@ class Book(val path: String, private val getString: (Int) -> String, private val
saveVolumes(volumes)
mVolumes = volumes
}
goSaveHead(isDownload)
whenFinish()
}
}
@@ -130,10 +127,18 @@ class Book(val path: String, private val getString: (Int) -> String, private val
mJsonString = Gson().toJson(volumes)
File(mangaFolder, "info.json").writeText(mJsonString)
File(mangaFolder, "grps.json").writeText(Gson().toJson(mKeys))
(cover?.let { CMApi.imageProxy?.wrap(it) } ?:cover)?.let {
}
}
private fun goSaveHead(force: Boolean) {
name?.let { name ->
val mangaFolder = File(exDir, name)
if(!mangaFolder.exists()) mangaFolder.mkdirs()
val f = File(mangaFolder, "head.jpg")
if(force || !f.exists()) (cover?.let { CMApi.imageProxy?.wrap(it) } ?:cover)?.let {
Thread {
DownloadTools.getHttpContent(it, -1)?.let { data ->
File(mangaFolder, "head.jpg").writeBytes(data)
f.writeBytes(data)
}
}.start()
}

View File

@@ -11,7 +11,7 @@ import top.fumiama.copymanga.ui.vm.ViewMangaActivity
import java.io.File
object Reader {
fun viewMangaAt(name: String, pos: Int, urlArray: Array<String>, fromFirstPage: Boolean = false) {
fun start2viewManga(name: String, pos: Int, urlArray: Array<String>, fromFirstPage: Boolean = false) {
Log.d("MyR", "viewMangaAt name $name, pos $pos")
mainWeakReference?.get()?.apply {
getPreferences(Context.MODE_PRIVATE)?.edit {
@@ -39,7 +39,7 @@ object Reader {
}
}
}
fun getComicPathWordInFile(file: File): String {
fun getComicPathWordInFolder(file: File): String {
if(!file.exists()) {
return "N/A:!file.exists()"
}

View File

@@ -4,22 +4,26 @@ import android.annotation.SuppressLint
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import com.liaoinstan.springview.widget.SpringView
import kotlinx.android.synthetic.main.line_header.view.*
import kotlinx.android.synthetic.main.line_lazybooklines.*
import top.fumiama.copymanga.MainActivity
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import top.fumiama.copymanga.template.ui.CardList
import top.fumiama.copymanga.tools.ui.UITools
import top.fumiama.dmzj.copymanga.R
import java.lang.Thread.sleep
import java.lang.ref.WeakReference
open class MangaPagesFragmentTemplate(inflateRes:Int, val isLazy: Boolean = true, val forceLoad: Boolean = false) : NoBackRefreshFragment(inflateRes) {
open class MangaPagesFragmentTemplate(inflateRes:Int, private val isLazy: Boolean = true, val forceLoad: Boolean = false) : NoBackRefreshFragment(inflateRes) {
var cardPerRow = 3
var cardWidth = 0
var cardHeight = 0
@@ -64,12 +68,12 @@ open class MangaPagesFragmentTemplate(inflateRes:Int, val isLazy: Boolean = true
findNavController().popBackStack()
return
}
Thread {
sleep(600)
activity?.runOnUiThread {
lifecycleScope.launch {
withContext(Dispatchers.IO) {
delay(600)
setLayouts()
}
}.start()
}
}
}
@@ -80,60 +84,88 @@ open class MangaPagesFragmentTemplate(inflateRes:Int, val isLazy: Boolean = true
//jsonReaderNow = null
}
open fun setLayouts() {
val toolsBox = this.context?.let { UITools(it) }
open suspend fun setLayouts() = withContext(Dispatchers.IO) {
val toolsBox = this@MangaPagesFragmentTemplate.context?.let { UITools(it) }
val widthData = toolsBox?.calcWidthFromDp(8, 135)
cardPerRow = widthData?.get(0) ?: 3
cardWidth = widthData?.get(2) ?: 128
cardHeight = (cardWidth / 0.75 + 0.5).toInt()
mysp.footerView.lht.text = "加载"
mysp.headerView.lht.text = "刷新"
withContext(Dispatchers.Main){
mysp.footerView.lht.text = "加载"
mysp.headerView.lht.text = "刷新"
mydll?.setPadding(0, 0, 0, navBarHeight)
}
Log.d("MyMPAT", "Card per row: $cardPerRow")
Log.d("MyMPAT", "Card width: $cardWidth")
mydll?.setPadding(0, 0, 0, navBarHeight)
initCardList(WeakReference(this))
initCardList(WeakReference(this@MangaPagesFragmentTemplate))
managePage()
setListeners()
//mypl.visibility = View.GONE
}
private fun managePage() {
addPage()
if (isLazy) mysp.setListener(object : SpringView.OnFreshListener {
override fun onLoadmore() {
addPage()
lifecycleScope.launch { addPage() }
if (isLazy) {
mysp.apply {
post {
setListener(object : SpringView.OnFreshListener {
override fun onLoadmore() {
lifecycleScope.launch {
addPage()
}
}
override fun onRefresh() {
lifecycleScope.launch {
withContext(Dispatchers.IO) {
reset()
delay(600)
}
addPage()
}
}
})
}
}
override fun onRefresh() {
reset()
Thread {
sleep(600)
activity?.runOnUiThread {
addPage()
}
}.start()
}
})
}
}
open fun addPage() {}
open suspend fun addPage() {}
open fun onLoadFinish() {
//myp?.visibility = View.GONE
open suspend fun onLoadFinish() = withContext(Dispatchers.Main) {
mypc?.visibility = View.GONE
mysp?.onFinishFreshAndLoad()
//mys?.fullScroll(ScrollView.FOCUS_UP)
}
open fun reset() {
open suspend fun reset() = withContext(Dispatchers.Main) {
mydll.removeAllViews()
isEnd = false
page = 0
cardList?.reset()
mypl?.visibility = View.VISIBLE
mypc?.visibility = View.VISIBLE
mypl?.progress = 0
}
open fun initCardList(weakReference: WeakReference<Fragment>) {}
open fun setListeners() {}
}
fun setProgress(p: Int) {
var newP = p
mypl?.post {
if (p == mypl?.progress) return@post
if (newP >= 100) {
Log.d("MyMPFT", "set 100, hide")
mypc?.visibility = View.GONE
return@post
}
else if (newP < 0) newP = 0
mypl?.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
setProgress(newP, true)
} else progress = newP
invalidate()
Log.d("MyMPFT", "set ${mypl?.progress}")
}
}
}
}

View File

@@ -108,7 +108,7 @@ class CardList(
val file = File(that?.context?.getExternalFilesDir(""), card.name)
if(exitCardList) return@withIO
cardFrame.let {
withContext(Dispatchers.Main) { it.tic.text = name }
it.tic.apply { post { text = name } }
if(!file.exists()) {
if(head != null) {
that?.context?.let { context ->
@@ -119,33 +119,35 @@ class CardList(
if (exitCardList) return@GlideHideLottieViewListener
cardLoadingWaits.decrementAndGet()
})
withContext(Dispatchers.Main) {
if (waitMillis > 0) it.imic.postDelayed({
if (exitCardList) return@postDelayed
g.into(it.imic)
}, waitMillis) else g.into(it.imic)
if (waitMillis > 0) it.imic.postDelayed({
if (exitCardList) return@postDelayed
g.into(it.imic)
}, waitMillis) else it.imic.post { g.into(it.imic) }
}
} else {
it.laic.apply {
post {
pauseAnimation()
visibility = View.GONE
}
}
} else withContext(Dispatchers.Main) {
it.laic.pauseAnimation()
it.laic.visibility = View.GONE
it.imic.setImageResource(R.drawable.img_defmask)
it.imic.apply { post { setImageResource(R.drawable.img_defmask) } }
}
} else {
val img = File(file, "head.jpg")
withContext(Dispatchers.Main) {
it.laic.pauseAnimation()
it.laic.visibility = View.GONE
it.laic.apply {
post {
pauseAnimation()
visibility = View.GONE
}
}
if(img.exists()) {
withContext(Dispatchers.Main) {
it.imic.setImageURI(Uri.fromFile(img))
it.imic.apply {
post {
setImageURI(Uri.fromFile(img))
}
}
} else {
withContext(Dispatchers.Main) {
it.imic.setImageResource(R.drawable.img_defmask)
}
}
} else it.imic.apply { post { setImageResource(R.drawable.img_defmask) } }
}
withContext(Dispatchers.Main) {
if(card.isFinish) it.sgnic.visibility = View.VISIBLE

View File

@@ -7,8 +7,10 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import com.google.gson.Gson
import kotlinx.android.synthetic.main.line_lazybooklines.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import top.fumiama.copymanga.json.BookListStructure
import top.fumiama.copymanga.json.HistoryBookListStructure
import top.fumiama.copymanga.json.ShelfStructure
@@ -24,8 +26,9 @@ open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isT
private val subUrl get() = getApiUrl()
var ad: PausableDownloader? = null
override fun addPage() {
override suspend fun addPage(): Unit = withContext(Dispatchers.IO) {
super.addPage()
setProgress(20)
ad = PausableDownloader(subUrl) { data ->
if(isRefresh) {
page = 0
@@ -37,15 +40,18 @@ open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isT
Log.d("MyICL", "offset:${results.offset}, total:${results.total}")
if(results.offset < results.total) {
if(code == 200) {
results.list.forEach { book ->
val size = results?.list?.size?:0
results.list.forEachIndexed { i, book ->
Log.d("MyICL", "load @ $i")
if(ad?.exit == true) return@PausableDownloader
cardList?.addCard(
book?.comic?.name?:"null", null, book?.comic?.cover,
book?.comic?.path_word, null, null,
isFinish = false, isNew = false
)
setProgress(20+80*i/size)
}
offset += results.list.size
offset += size
}
}
page++
@@ -56,15 +62,18 @@ open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isT
Log.d("MyICL", "offset:${results?.offset}, total:${results?.total}")
if(results.offset < results.total) {
if(code == 200) {
results?.list?.forEach{ book ->
val size = results?.list?.size?:0
results?.list?.forEachIndexed { i, book ->
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?.path_word, null, null,
book?.comic?.status==1
)
setProgress(20+80*i/size)
}
offset += results.list.size
offset += size
}
}
page++
@@ -75,7 +84,9 @@ open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isT
Log.d("MyICL", "offset:${results?.offset}, total:${results?.total}")
if(results.offset < results.total) {
if(code == 200) {
results?.list?.forEach{ book ->
val size = results?.list?.size?:0
results?.list?.forEachIndexed { i, book ->
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,
@@ -83,8 +94,9 @@ open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isT
book?.comic?.status==1,
book.comic?.browse?.chapter_uuid != book.comic?.last_chapter_id
)
setProgress(20+80*i/size)
}
offset += results.list.size
offset += size
}
}
page++
@@ -95,11 +107,14 @@ open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isT
Log.d("MyICL", "offset:${results?.offset}, total:${results?.total}")
if(results.offset < results.total) {
if(code == 200) {
results?.list?.forEach{ book ->
val size = results?.list?.size?:0
results?.list?.forEachIndexed { i, book ->
Log.d("MyICL", "load @ $i")
if(ad?.exit == true) return@PausableDownloader
cardList?.addCard(book?.name?:"null", null, book?.cover, book?.path_word, null, null, false)
setProgress(20+80*i/size)
}
offset += results.list.size
offset += size
}
}
page++
@@ -107,17 +122,18 @@ open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isT
}
onLoadFinish()
}
lifecycleScope.launch {
try {
ad?.run()
} catch (e: Exception) {
e.printStackTrace()
try {
ad?.run()
} catch (e: Exception) {
e.printStackTrace()
try {
withContext(Dispatchers.Main) {
findNavController().popBackStack()
} catch (_: Exception) {}
}
}
} catch (_: Exception) {}
}
}
override fun initCardList(weakReference: WeakReference<Fragment>) {
super.initCardList(weakReference)
cardList = CardList(weakReference, cardWidth, cardHeight, cardPerRow)
@@ -136,14 +152,11 @@ open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isT
return ""
}
override fun onLoadFinish() {
super.onLoadFinish()
activity?.runOnUiThread {
if(ad?.exit != true) mypl.visibility = View.GONE
}
override suspend fun onLoadFinish() {
if(ad?.exit != true) super.onLoadFinish()
}
override fun reset() {
override suspend fun reset() {
super.reset()
offset = 0
}
@@ -162,4 +175,14 @@ open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isT
super.onDestroy()
ad?.exit = true
}
fun delayedRefresh(timeMillis: Long) {
lifecycleScope.launch {
withContext(Dispatchers.IO) {
delay(timeMillis)
reset()
addPage()
}
}
}
}

View File

@@ -3,6 +3,8 @@ package top.fumiama.copymanga.template.ui
import android.animation.ObjectAnimator
import android.view.View
import kotlinx.android.synthetic.main.anchor_popular.view.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import top.fumiama.copymanga.tools.api.CMApi
import top.fumiama.dmzj.copymanga.R
@@ -25,40 +27,32 @@ open class StatusCardFlow(private val api: Int, nav: Int, inflateRes: Int,
override fun setListeners() {
super.setListeners()
lineUpdate?.let { setUpdate(it) }
lineHot?.let { setHot(it) }
lineUpdate?.alpha = 1f
lineHot?.alpha = 0.5f
lineUpdate?.apply { post {
setUpdate(this)
alpha = 1f
} }
lineHot?.apply { post {
setHot(this)
alpha = 0.5f
} }
}
open fun setUpdate(that: View) {
private fun setUpdate(that: View) {
that.apply {
apt.setText(R.string.menu_update_time)
setOnClickListener {
sortValue = triggerLine(false)
Thread{
Thread.sleep(400)
activity?.runOnUiThread {
reset()
addPage()
}
}.start()
delayedRefresh(400)
}
}
}
open fun setHot(that: View) {
private fun setHot(that: View) {
that.apply {
apt.setText(R.string.menu_hot)
setOnClickListener {
sortValue = triggerLine(true)
Thread {
Thread.sleep(400)
activity?.runOnUiThread {
reset()
addPage()
}
}.start()
delayedRefresh(400)
}
}
}

View File

@@ -68,6 +68,7 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) {
book?.updateInfo()
} catch (e: Exception) {
e.printStackTrace()
if(mBookHandler?.exit != false) return@launch
Toast.makeText(context, R.string.null_book, Toast.LENGTH_SHORT).show()
findNavController().popBackStack()
return@launch
@@ -82,6 +83,7 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) {
}
} catch (e: Exception) {
e.printStackTrace()
if(mBookHandler?.exit != false) return@launch
Toast.makeText(context, R.string.null_volume, Toast.LENGTH_SHORT).show()
findNavController().popBackStack()
return@launch
@@ -126,7 +128,7 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) {
}
setOnClickListener {
mBookHandler?.urlArray?.let {
Reader.viewMangaAt(name, i, it)
Reader.start2viewManga(name, i, it)
}
}
}

View File

@@ -210,7 +210,7 @@ class BookHandler(private val th: WeakReference<BookFragment>): Handler(Looper.m
if (f.exists()) lci.setBackgroundResource(R.drawable.ic_success)
Log.d("MyBH", "add last single chapter ${it.name}")
val index = i
setOnClickListener { Reader.viewMangaAt(comicName, index, urlArray) }
setOnClickListener { Reader.start2viewManga(comicName, index, urlArray) }
}
line?.let { l -> addVolumesView(fbl, l) }
} else {
@@ -219,14 +219,14 @@ class BookHandler(private val th: WeakReference<BookFragment>): Handler(Looper.m
lct.text = it.name
if (f.exists()) lci.setBackgroundResource(R.drawable.ic_success)
val index = i
setOnClickListener { Reader.viewMangaAt(comicName, index, urlArray) }
setOnClickListener { Reader.start2viewManga(comicName, index, urlArray) }
}
}
} else line?.l2cr?.apply {
lct.text = it.name
if (f.exists()) lci.setBackgroundResource(R.drawable.ic_success)
val index = i
setOnClickListener { Reader.viewMangaAt(comicName, index, urlArray) }
setOnClickListener { Reader.start2viewManga(comicName, index, urlArray) }
line?.let { l -> addVolumesView(fbl, l) }
line = null
}

View File

@@ -1,19 +1,15 @@
package top.fumiama.copymanga.ui.cardflow.rank
import android.os.Bundle
import androidx.lifecycle.lifecycleScope
import com.google.android.material.tabs.TabLayout
import kotlinx.android.synthetic.main.fragment_rank.*
import kotlinx.android.synthetic.main.line_rank.view.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import top.fumiama.copymanga.template.ui.InfoCardLoader
import top.fumiama.copymanga.tools.api.CMApi
import top.fumiama.copymanga.tools.ui.UITools
import top.fumiama.dmzj.copymanga.R
import java.lang.Thread.sleep
import java.lang.ref.WeakReference
@ExperimentalStdlibApi
@@ -45,7 +41,7 @@ class RankFragment : InfoCardLoader(R.layout.fragment_rank, R.id.action_nav_rank
ad?.exit = true
}
override fun onLoadFinish() {
override suspend fun onLoadFinish() {
super.onLoadFinish()
isLoading = false
}
@@ -65,43 +61,36 @@ class RankFragment : InfoCardLoader(R.layout.fragment_rank, R.id.action_nav_rank
override fun onTabSelected(tab: TabLayout.Tab?) {
sortValue = tab?.position?:0
if(!isLoading) delayedRefresh()
if(!isLoading) {
isLoading = true
delayedRefresh(400)
}
}
override fun onTabUnselected(tab: TabLayout.Tab?) {}
})
}
private fun delayedRefresh() {
lifecycleScope.launch {
isLoading = true
withContext(Dispatchers.IO) {
delay(400)
withContext(Dispatchers.Main) {
reset()
addPage()
}
}
}
}
fun showSexInfo(toolsBox: UITools) {
if (ad?.exit != false) return
toolsBox.buildInfo("切换类型", "选择一种想筛选的漫画类型",
"男频", "全部", "女频", {
if(!isLoading) {
audience = 1
delayedRefresh()
isLoading = true
delayedRefresh(400)
}
}, {
if(!isLoading) {
audience = 0
delayedRefresh()
isLoading = true
delayedRefresh(400)
}
}, {
if(!isLoading) {
audience = 2
delayedRefresh()
isLoading = true
delayedRefresh(400)
}
})
}

View File

@@ -1,8 +1,5 @@
package top.fumiama.copymanga.ui.cardflow.recommend
import android.view.View
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.tools.api.CMApi
import top.fumiama.dmzj.copymanga.R

View File

@@ -3,19 +3,15 @@ package top.fumiama.copymanga.ui.cardflow.shelf
import android.animation.ObjectAnimator
import android.os.Bundle
import android.view.View
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import kotlinx.android.synthetic.main.anchor_popular.view.*
import kotlinx.android.synthetic.main.line_shelf.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import top.fumiama.copymanga.MainActivity
import top.fumiama.copymanga.template.ui.InfoCardLoader
import top.fumiama.copymanga.tools.api.CMApi
import top.fumiama.dmzj.copymanga.R
import java.lang.Thread.sleep
@ExperimentalStdlibApi
class ShelfFragment : InfoCardLoader(R.layout.fragment_shelf, R.id.action_nav_sub_to_nav_book, isShelfBook = true) {
@@ -56,7 +52,7 @@ class ShelfFragment : InfoCardLoader(R.layout.fragment_shelf, R.id.action_nav_su
val same = sortValue in 0..1
sortValue = rotate(it.apim, same, 0)
if (!same) fade()
resetDelayed()
delayedRefresh(400)
}
}
@@ -67,7 +63,7 @@ class ShelfFragment : InfoCardLoader(R.layout.fragment_shelf, R.id.action_nav_su
val same = sortValue in 2..3
sortValue = rotate(it.apim, same, 2)
if (!same) fade()
resetDelayed()
delayedRefresh(400)
}
}
@@ -78,7 +74,7 @@ class ShelfFragment : InfoCardLoader(R.layout.fragment_shelf, R.id.action_nav_su
val same = sortValue>=4
sortValue = rotate(it.apim, same, 4)
if (!same) fade()
resetDelayed()
delayedRefresh(400)
}
}
@@ -119,16 +115,4 @@ class ShelfFragment : InfoCardLoader(R.layout.fragment_shelf, R.id.action_nav_su
}
}
}
private fun resetDelayed() {
lifecycleScope.launch {
withContext(Dispatchers.IO) {
delay(400)
withContext(Dispatchers.Main) {
reset()
addPage()
}
}
}
}
}

View File

@@ -8,7 +8,6 @@ import com.google.gson.Gson
import kotlinx.android.synthetic.main.anchor_popular.view.*
import kotlinx.android.synthetic.main.line_sort.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import top.fumiama.copymanga.json.FilterStructure
@@ -17,7 +16,6 @@ import top.fumiama.copymanga.template.http.PausableDownloader
import top.fumiama.copymanga.template.ui.StatusCardFlow
import top.fumiama.copymanga.tools.api.CMApi
import top.fumiama.dmzj.copymanga.R
import java.lang.Thread.sleep
@ExperimentalStdlibApi
class SortFragment : StatusCardFlow(0, R.id.action_nav_sort_to_nav_book, R.layout.fragment_sort) {
@@ -30,8 +28,8 @@ class SortFragment : StatusCardFlow(0, R.id.action_nav_sort_to_nav_book, R.layou
CMApi.myHostApiUrl,
page * 21,
sortWay[sortValue],
if(theme >= 0) (filter?.results?.theme?.get(theme)?.path_word ?: "") else "",
if(region >= 0) (filter?.results?.top?.get(region)?.path_word ?: "") else "",
if(theme >= 0 && theme < (filter?.results?.theme?.size ?: 0)) (filter?.results?.theme?.get(theme)?.path_word ?: "") else "",
if(region >= 0 && region < (filter?.results?.top?.size ?: 0)) (filter?.results?.top?.get(region)?.path_word ?: "") else "",
)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -60,26 +58,18 @@ class SortFragment : StatusCardFlow(0, R.id.action_nav_sort_to_nav_book, R.layou
private fun setClasses() {
filter?.results?.top?.let { items ->
setMenu(items, line_sort_region)
setMenu(items, line_sort_region) {
region = it
}
}
filter?.results?.theme?.let { items ->
setMenu(items, line_sort_class)
}
}
private fun suspendReset() {
lifecycleScope.launch {
withContext(Dispatchers.IO) {
delay(400)
withContext(Dispatchers.Main) {
reset()
addPage()
}
setMenu(items, line_sort_class) {
theme = it
}
}
}
private fun setMenu(items: Array<out ThemeStructure>, line: View) {
private fun setMenu(items: Array<out ThemeStructure>, line: View, setIndex: (Int) -> Unit) {
if(ad?.exit == true) return
line.apt.text = "全部"
line.setOnClickListener {
@@ -90,9 +80,9 @@ class SortFragment : StatusCardFlow(0, R.id.action_nav_sort_to_nav_book, R.layou
label = "全部"
labelColor = it.apt.currentTextColor
callback = {
region = -1
setIndex(-1)
it.apt.text = "全部"
suspendReset()
delayedRefresh(400)
}
}
for(i in items.indices) item {
@@ -100,8 +90,8 @@ class SortFragment : StatusCardFlow(0, R.id.action_nav_sort_to_nav_book, R.layou
labelColor = it.apt.currentTextColor
callback = { //optional
it.apt.text = label
region = i
suspendReset()
setIndex(i)
delayedRefresh(400)
}
}
}

View File

@@ -8,8 +8,8 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.preference.PreferenceManager
import kotlinx.android.synthetic.main.line_lazybooklines.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import top.fumiama.copymanga.MainActivity
@@ -19,10 +19,8 @@ import top.fumiama.copymanga.template.ui.CardList
import top.fumiama.copymanga.tools.file.FileUtils
import top.fumiama.copymanga.tools.ui.Navigate
import top.fumiama.copymanga.tools.ui.UITools
import top.fumiama.copymanga.ui.comicdl.ComicDlFragment
import top.fumiama.dmzj.copymanga.R
import java.io.File
import java.lang.Thread.sleep
import java.lang.ref.WeakReference
@OptIn(ExperimentalStdlibApi::class)
@@ -57,59 +55,89 @@ class NewDownloadFragment: MangaPagesFragmentTemplate(R.layout.fragment_newdownl
exit = true
}
override fun addPage() {
override suspend fun addPage(): Unit = withContext(Dispatchers.IO) {
super.addPage()
if(isRefresh){
page = 0
isRefresh = false
}
lifecycleScope.launch {
withContext(Dispatchers.IO) {
if(!isEnd) {
if(sortedBookList == null || isContentChanged) {
Log.d("MyNDF", "Sorting books...")
sortedBookList = extDir?.listFiles()?.sortedBy {
return@sortedBy Reader.getComicPathWordInFile(it)
}
if (isReverse) {
Log.d("MyNDF", "reversed...")
sortedBookList = sortedBookList?.asReversed()
}
if (!showAll) {
sortedBookList = sortedBookList?.filter {
return@filter FileUtils.sizeOf(it) / 1048576 > 0
if (isEnd) {
onLoadFinish()
return@withContext
}
setProgress(20)
if(sortedBookList == null || isContentChanged) {
Log.d("MyNDF", "Sorting books...")
sortedBookList = extDir?.listFiles()?.toList()
var size = sortedBookList?.size?:0
if (size > 0) {
if (isReverse) {
Log.d("MyNDF", "reversed...")
sortedBookList = sortedBookList?.asReversed()
}
setProgress(40)
if (!showAll) {
val cache = hashMapOf<String, Boolean>()
sortedBookList = sortedBookList?.filter {
setProgress(40+20*cache.size/size)
it.absolutePath.let { path ->
if (cache.containsKey(path)) cache[path]!!
else {
val b = (it.listFiles { f ->
return@listFiles f.isDirectory && f.listFiles()?.isNotEmpty() ?: false
}?.size ?: 0) > 0
cache[path] = b
b
}
}
isContentChanged = false
}
Log.d("MyNDF", "Start drawing cards")
cardList?.addCard(oldDlCardName, path = oldDlCardName)
var cnt = 1
sortedBookList?.let {
for(i in it.listIterator(page)) {
if(cardList?.exitCardList != false) return@withContext
page++ // page is actually count
val chosenJson = File(i, "info.bin")
val newJson = File(i, "info.json")
val bookSize = (FileUtils.sizeOf(i)/1048576).toInt()
when {
chosenJson.exists() -> continue // unsupported old folder
newJson.exists() -> {
if(cardList?.exitCardList != false) return@withContext
cardList?.addCard(i.name, "\n${bookSize}MB")
cnt++
}
}
if (cnt >= 21) break
}
if(page >= it.size) {
isEnd = true
}
}
}
onLoadFinish()
setProgress(60)
size = sortedBookList?.size?:0
val cache = hashMapOf<String, String>()
sortedBookList = sortedBookList?.sortedBy {
setProgress(60+20*cache.size/size)
return@sortedBy it.absolutePath.let { path ->
if (cache.containsKey(path)) cache[path]!!
else {
val s = Reader.getComicPathWordInFolder(it).lowercase()
cache[path] = s
s
}
}
}
setProgress(80)
}
isContentChanged = false
}
Log.d("MyNDF", "Start drawing cards")
cardList?.addCard(oldDlCardName, path = oldDlCardName)
var cnt = 1
val size = sortedBookList?.size?:0
sortedBookList?.let {
for(i in it.listIterator(page)) {
if(cardList?.exitCardList != false) return@withContext
page++ // page is actually count
val chosenJson = File(i, "info.bin")
val newJson = File(i, "info.json")
val bookSize = (FileUtils.sizeOf(i)/1048576).toInt()
when {
chosenJson.exists() -> continue // unsupported old folder
newJson.exists() -> {
if(cardList?.exitCardList != false) return@withContext
cardList?.addCard(i.name, "\n${bookSize}MB")
cnt++
}
}
setProgress(80+20*(cnt-1)/size)
if (cnt >= 21) break
}
if(page >= it.size) {
isEnd = true
}
}
setProgress(99)
onLoadFinish()
}
override fun initCardList(weakReference: WeakReference<Fragment>) {
@@ -184,22 +212,17 @@ class NewDownloadFragment: MangaPagesFragmentTemplate(R.layout.fragment_newdownl
"确定", null, "取消", {
isReverse = !isReverse
isContentChanged = true
reset()
Thread {
sleep(600)
addPage()
}.start()
lifecycleScope.launch {
withContext(Dispatchers.IO) {
reset()
delay(600)
addPage()
}
}
}
)
}
override fun onLoadFinish() {
super.onLoadFinish()
activity?.runOnUiThread {
mypl.visibility = View.GONE
}
}
companion object {
var wn: WeakReference<NewDownloadFragment>? = null
}

View File

@@ -24,7 +24,7 @@ class PagesManager(private val w: WeakReference<ViewMangaActivity>) {
@ExperimentalStdlibApi
fun toPage(goNext:Boolean) {
v?.let { v ->
if (v.clicked) {
if (v.clicked == 1) {
v.hideDrawer()
return
}
@@ -48,7 +48,7 @@ class PagesManager(private val w: WeakReference<ViewMangaActivity>) {
//if(v.zipFirst) intent.putExtra("callFrom", "zipFirst")
v.tt.canDo = false
//ViewMangaActivity.dlhandler = null
comicName?.let { Reader.viewMangaAt(it, chapterPosition, v.urlArray, goNext) }
comicName?.let { Reader.start2viewManga(it, chapterPosition, v.urlArray, goNext) }
v.finish()
return
}
@@ -59,6 +59,11 @@ class PagesManager(private val w: WeakReference<ViewMangaActivity>) {
}
}
fun toggleDrawer() {
if (v?.clicked == false) v?.showDrawer() else v?.hideDrawer()
v?.apply {
when(clicked) {
0 -> showDrawer()
1 -> hideDrawer()
}
}
}
}

View File

@@ -66,7 +66,7 @@ class ViewMangaActivity : TitleActivityTemplate() {
var count = 0
private lateinit var handler: VMHandler
lateinit var tt: TimeThread
var clicked = false
var clicked = 0
private var isInSeek = false
private var isInScroll = true
//private var progressLog: PropertiesTools? = null
@@ -884,28 +884,38 @@ class ViewMangaActivity : TitleActivityTemplate() {
}
fun showDrawer() {
infseek.visibility = View.VISIBLE
isearch.visibility = View.VISIBLE
ObjectAnimator.ofFloat(
oneinfo,
"alpha",
oneinfo.alpha,
1F
).setDuration(233).start()
clicked = true
clicked = 2 // loading
infseek.post {
infseek.visibility = View.VISIBLE
isearch.post {
isearch.visibility = View.VISIBLE
infseek.invalidate()
isearch.invalidate()
ObjectAnimator.ofFloat(
oneinfo,
"alpha",
oneinfo.alpha,
1F
).setDuration(300).start()
clicked = 1 // true
}
}
}
fun hideDrawer() {
clicked = 2 // loading
ObjectAnimator.ofFloat(
oneinfo,
"alpha",
oneinfo.alpha,
0F
).setDuration(233).start()
clicked = false
).setDuration(300).start()
infseek.postDelayed({
infseek.visibility = View.GONE
isearch.visibility = View.GONE
infseek.invalidate()
isearch.invalidate()
clicked = 0 // false
}, 300)
handler.sendEmptyMessage(if (fullyHideInfo) VMHandler.HIDE_INFO_CARD_FULL else VMHandler.HIDE_INFO_CARD)
}

View File

@@ -25,18 +25,26 @@
android:id="@+id/mydll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
android:orientation="vertical" />
</androidx.core.widget.NestedScrollView>
</com.liaoinstan.springview.widget.SpringView>
<ProgressBar
android:id="@+id/mypl"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
<androidx.cardview.widget.CardView
android:id="@+id/mypc"
android:layout_width="@dimen/book_card_width"
android:layout_height="@dimen/icon_size_middle"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toTopOf="parent">
<ProgressBar
android:id="@+id/mypl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="16dp"
style="?android:attr/progressBarStyleHorizontal"/>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>