mirror of
https://github.com/fumiama/copymanga.git
synced 2026-06-04 23:10:23 +08:00
v2.3.6
新增 1. 漫画详情页加载进度条 修复 1. 本地记录的章节数超过云端现有章节数时闪退(fix #97) 优化 1. 卡片流加载进度条增加动画 2. 下载页底部下载按钮上移规避导航栏(fix #96) 升级 1. net.java.dev.jna -> 5.15.0
This commit is contained in:
@@ -11,8 +11,8 @@ android {
|
||||
applicationId 'top.fumiama.copymanga'
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 34
|
||||
versionCode 63
|
||||
versionName '2.3.5'
|
||||
versionCode 64
|
||||
versionName '2.3.6'
|
||||
resourceConfigurations += ['zh', 'zh-rCN']
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
@@ -95,5 +95,5 @@ dependencies {
|
||||
//noinspection GradleDependency
|
||||
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0'
|
||||
implementation 'com.airbnb.android:lottie:6.5.2'
|
||||
implementation 'net.java.dev.jna:jna:5.14.0@aar'
|
||||
implementation 'net.java.dev.jna:jna:5.15.0@aar'
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ import kotlinx.coroutines.withContext
|
||||
import top.fumiama.copymanga.manga.Shelf
|
||||
import top.fumiama.copymanga.tools.ui.UITools
|
||||
import top.fumiama.copymanga.ui.book.BookFragment.Companion.bookHandler
|
||||
import top.fumiama.copymanga.ui.book.BookHandler
|
||||
import top.fumiama.copymanga.ui.cardflow.rank.RankFragment
|
||||
import top.fumiama.copymanga.ui.comicdl.ComicDlFragment
|
||||
import top.fumiama.copymanga.ui.download.DownloadFragment
|
||||
@@ -189,7 +190,7 @@ class MainActivity : AppCompatActivity() {
|
||||
true
|
||||
}
|
||||
R.id.action_download -> {
|
||||
bookHandler.get()?.sendEmptyMessage(6)
|
||||
bookHandler.get()?.sendEmptyMessage(BookHandler.NAVIGATE_TO_DOWNLOAD)
|
||||
true
|
||||
}
|
||||
R.id.action_sort -> {
|
||||
|
||||
@@ -97,14 +97,16 @@ class Book(val path: String, private val getString: (Int) -> String, private val
|
||||
/**
|
||||
* 更新云端最新章节信息并缓存到本地
|
||||
*/
|
||||
suspend fun updateVolumes(whenFinish: suspend () -> Unit) = withContext(Dispatchers.IO) withIO@ {
|
||||
suspend fun updateVolumes(setProgress: (Int) -> Unit, whenFinish: suspend () -> Unit) = withContext(Dispatchers.IO) withIO@ {
|
||||
var isDownload = false
|
||||
var volumes = if(loadCache && loadVolumes()) mVolumes else emptyArray<VolumeStructure>()
|
||||
if(mGroupPathWords.isEmpty()) return@withIO
|
||||
if(volumes.isEmpty()) {
|
||||
isDownload = true
|
||||
val delta = 100/mGroupPathWords.size
|
||||
mGroupPathWords.forEachIndexed { i, g ->
|
||||
Volume(path, g, getString) {
|
||||
return@Volume exit
|
||||
Volume(path, g, getString, { return@Volume exit }) { p ->
|
||||
setProgress(i*delta+100*p/delta)
|
||||
}.updateChapters(mCounts[i])?.let {
|
||||
volumes += it
|
||||
}
|
||||
@@ -116,6 +118,7 @@ class Book(val path: String, private val getString: (Int) -> String, private val
|
||||
mVolumes = volumes
|
||||
}
|
||||
goSaveHead(isDownload)
|
||||
setProgress(100)
|
||||
whenFinish()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import top.fumiama.copymanga.template.http.PausableDownloader
|
||||
import top.fumiama.copymanga.tools.api.CMApi
|
||||
import top.fumiama.dmzj.copymanga.R
|
||||
|
||||
class Volume(private val path: String, private val groupPathWord: String, getString: (Int) -> String, private val isExit: ()->Boolean) {
|
||||
class Volume(private val path: String, private val groupPathWord: String, getString: (Int) -> String, private val isExit: ()->Boolean, private val setProgress: ((Int) -> Unit)? = null) {
|
||||
private val mGroupInfoApiUrlTemplate = getString(R.string.groupInfoApiUrl)
|
||||
private val exit: Boolean
|
||||
get() {
|
||||
@@ -21,12 +21,20 @@ class Volume(private val path: String, private val groupPathWord: String, getStr
|
||||
}
|
||||
private var mDownloaders = arrayOf<PausableDownloader>()
|
||||
private var mVolume: VolumeStructure? = null
|
||||
private var mProgress = 0
|
||||
set(value) {
|
||||
setProgress?.let { it(field) }
|
||||
field = value
|
||||
}
|
||||
private var mDelta = 0
|
||||
suspend fun updateChapters(count: Int): VolumeStructure? = withContext(Dispatchers.IO) {
|
||||
val times = count / 100
|
||||
val remain = count % 100
|
||||
val re = arrayOfNulls<VolumeStructure>(if(remain != 0) (times+1) else (times))
|
||||
if (re.isEmpty()) return@withContext null
|
||||
Log.d("MyV", "${groupPathWord}卷共需加载${if(times == 0) 1 else times}次")
|
||||
mProgress = 0
|
||||
mDelta = 100/re.size
|
||||
download(re, 0, count)
|
||||
return@withContext mVolume
|
||||
}
|
||||
@@ -40,6 +48,7 @@ class Volume(private val path: String, private val groupPathWord: String, getStr
|
||||
mDownloaders += ad
|
||||
ad.run()
|
||||
}
|
||||
mProgress += mDelta
|
||||
}
|
||||
private fun whenFinish(re: Array<VolumeStructure?>, c: Int, offset: Int): suspend (ByteArray) -> Unit = lambda@ { result: ByteArray ->
|
||||
try {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package top.fumiama.copymanga.template.general
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.net.ConnectivityManager
|
||||
@@ -8,6 +9,7 @@ import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import androidx.core.animation.doOnEnd
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
@@ -157,18 +159,31 @@ open class MangaPagesFragmentTemplate(inflateRes:Int, private val isLazy: Boolea
|
||||
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
|
||||
}
|
||||
if (newP >= 100) newP = 100
|
||||
else if (newP < 0) newP = 0
|
||||
if (mypl?.progress == 0) {
|
||||
Log.d("MyMPFT", "set from 0, show")
|
||||
mypc?.apply {
|
||||
visibility = View.VISIBLE
|
||||
invalidate()
|
||||
ObjectAnimator.ofFloat(this, "alpha", 0f, 1f)
|
||||
.setDuration(300)
|
||||
.start()
|
||||
}
|
||||
}
|
||||
if(newP == 100) {
|
||||
Log.d("MyMPFT", "set to 100, hide")
|
||||
mypc?.apply {
|
||||
val oa = ObjectAnimator.ofFloat(this, "alpha", 1f, 0f).setDuration(300)
|
||||
oa.doOnEnd { visibility = View.GONE }
|
||||
oa.start()
|
||||
}
|
||||
}
|
||||
mypl?.apply {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
setProgress(newP, true)
|
||||
} else progress = newP
|
||||
invalidate()
|
||||
Log.d("MyMPFT", "set ${mypl?.progress}")
|
||||
val oa = ObjectAnimator.ofInt(this, "progress", newP).setDuration(100)
|
||||
oa.addUpdateListener { invalidate() }
|
||||
oa.start()
|
||||
Log.d("MyMPFT", "set $progress")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isT
|
||||
book?.comic?.path_word, null, null,
|
||||
isFinish = false, isNew = false
|
||||
)
|
||||
setProgress(20+80*i/size)
|
||||
setProgress(20+80*(i+1)/size)
|
||||
}
|
||||
offset += size
|
||||
}
|
||||
@@ -71,7 +71,7 @@ open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isT
|
||||
book?.comic?.path_word, null, null,
|
||||
book?.comic?.status==1
|
||||
)
|
||||
setProgress(20+80*i/size)
|
||||
setProgress(20+80*(i+1)/size)
|
||||
}
|
||||
offset += size
|
||||
}
|
||||
@@ -94,7 +94,7 @@ 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)
|
||||
setProgress(20+80*(i+1)/size)
|
||||
}
|
||||
offset += size
|
||||
}
|
||||
@@ -112,7 +112,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?.name?:"null", null, book?.cover, book?.path_word, null, null, false)
|
||||
setProgress(20+80*i/size)
|
||||
setProgress(20+80*(i+1)/size)
|
||||
}
|
||||
offset += size
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package top.fumiama.copymanga.ui.book
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context.MODE_PRIVATE
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.core.animation.addListener
|
||||
import androidx.core.animation.doOnEnd
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import kotlinx.android.synthetic.main.app_bar_main.*
|
||||
@@ -42,6 +45,12 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) {
|
||||
lifecycleScope.launch {
|
||||
prepareHandler()
|
||||
try {
|
||||
fbloading?.apply {
|
||||
post {
|
||||
progress = 0
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
book?.updateInfo()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
@@ -52,12 +61,25 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) {
|
||||
}
|
||||
Log.d("MyBF", "read path: ${book?.path}")
|
||||
for (i in 1..3) {
|
||||
mBookHandler?.sendEmptyMessageDelayed(i, (i*100).toLong())
|
||||
mBookHandler?.sendEmptyMessage(i)
|
||||
}
|
||||
try {
|
||||
book?.updateVolumes {
|
||||
delay(300)
|
||||
mBookHandler?.sendEmptyMessage(10)
|
||||
fbc?.apply {
|
||||
alpha = 0f
|
||||
visibility = View.VISIBLE
|
||||
invalidate()
|
||||
ObjectAnimator.ofFloat(this, "alpha", 0f, 1f)
|
||||
.setDuration(300)
|
||||
.start()
|
||||
}
|
||||
book?.updateVolumes({ fbloading?.apply { post {
|
||||
val oa = ObjectAnimator.ofInt(this, "progress", 20 + it*8/10)
|
||||
.setDuration(128)
|
||||
oa.addUpdateListener { invalidate() }
|
||||
oa.start()
|
||||
Log.d("MyBF", "set progress $it")
|
||||
} } }) {
|
||||
mBookHandler?.sendEmptyMessage(BookHandler.SET_VOLUMES)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
@@ -95,14 +117,15 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) {
|
||||
}
|
||||
|
||||
fun setStartRead() {
|
||||
if(mBookHandler?.chapterNames?.isNotEmpty() == true) activity?.apply {
|
||||
if(mBookHandler?.chapterNames?.isNotEmpty() != true) return
|
||||
activity?.apply {
|
||||
book?.name?.let { name ->
|
||||
getPreferences(MODE_PRIVATE).getInt(name, -1).let { p ->
|
||||
this@BookFragment.lbbstart.apply {
|
||||
var i = 0
|
||||
if(p >= 0) {
|
||||
text = mBookHandler!!.chapterNames[p]
|
||||
i = p
|
||||
if(p >= 0) mBookHandler!!.chapterNames.let {
|
||||
i = if (p >= it.size) it.size-1 else p
|
||||
text = it[i]
|
||||
}
|
||||
setOnClickListener {
|
||||
mBookHandler?.apply {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package top.fumiama.copymanga.ui.book
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
@@ -10,6 +11,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.animation.doOnEnd
|
||||
import androidx.core.widget.NestedScrollView
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
@@ -70,9 +72,10 @@ class BookHandler(private val th: WeakReference<BookFragment>): Handler(Looper.m
|
||||
|
||||
private fun endSetLayouts() {
|
||||
if (exit) return
|
||||
that?.fbloading?.apply {
|
||||
pauseAnimation()
|
||||
visibility = View.GONE
|
||||
that?.fbc?.apply {
|
||||
val oa = ObjectAnimator.ofFloat(this, "alpha", 1f, 0f).setDuration(300)
|
||||
oa.doOnEnd { visibility = View.GONE }
|
||||
oa.start()
|
||||
}
|
||||
complete = true
|
||||
that?.setStartRead()
|
||||
@@ -291,7 +294,7 @@ class BookHandler(private val th: WeakReference<BookFragment>): Handler(Looper.m
|
||||
}
|
||||
}
|
||||
}
|
||||
sendEmptyMessage(9) // end set layout
|
||||
sendEmptyMessage(END_SET_LAYOUTS)
|
||||
}
|
||||
|
||||
private fun loadVolume(name: String, path: String, nav: Int){
|
||||
@@ -331,4 +334,10 @@ class BookHandler(private val th: WeakReference<BookFragment>): Handler(Looper.m
|
||||
override fun getItemCount(): Int = that?.book?.keys?.size?:0
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val NAVIGATE_TO_DOWNLOAD = 6
|
||||
const val END_SET_LAYOUTS = 9
|
||||
const val SET_VOLUMES = 10
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.google.gson.Gson
|
||||
import kotlinx.android.synthetic.main.fragment_dlcomic.*
|
||||
import kotlinx.android.synthetic.main.widget_downloadbar.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -24,6 +25,7 @@ class ComicDlFragment: NoBackRefreshFragment(R.layout.fragment_dlcomic) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
exit = false
|
||||
ldwn?.setPadding(0, 0, 0, navBarHeight)
|
||||
dlsdwn?.translationY = -navBarHeight.toFloat()
|
||||
if(isFirstInflate) lifecycleScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
when {
|
||||
|
||||
@@ -199,8 +199,11 @@ class ComicDlHandler(looper: Looper, private val th: WeakReference<ComicDlFragme
|
||||
dl?.setContentView(R.layout.dialog_unzipping)
|
||||
that?.dlsdwn?.viewTreeObserver?.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener{
|
||||
override fun onGlobalLayout() {
|
||||
cdwnWidth = that!!.dlsdwn.width
|
||||
Log.d("MyDl", "Get dlsdwn height: $cdwnWidth")
|
||||
that!!.apply {
|
||||
cdwnWidth = dlsdwn.width
|
||||
Log.d("MyDl", "Get dlsdwn width: $cdwnWidth")
|
||||
ldwn?.setPadding(0, 0, 0, dlsdwn.height+navBarHeight)
|
||||
}
|
||||
that!!.dlsdwn.viewTreeObserver.removeOnGlobalLayoutListener(this)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -44,12 +44,29 @@
|
||||
app:layout_constraintTop_toBottomOf="@+id/fbiinf"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
|
||||
|
||||
<com.airbnb.lottie.LottieAnimationView
|
||||
android:id="@+id/fbloading"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/fbc"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:alpha="0.5"
|
||||
app:lottie_autoPlay="true"
|
||||
app:lottie_loop="true"
|
||||
app:lottie_rawRes="@raw/lottie_loading" />
|
||||
android:alpha="0">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
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">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/fbloading"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:padding="16dp" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
@@ -34,17 +35,20 @@
|
||||
android:id="@+id/mypc"
|
||||
android:layout_width="@dimen/book_card_width"
|
||||
android:layout_height="@dimen/icon_size_middle"
|
||||
android:alpha="0"
|
||||
android:visibility="gone"
|
||||
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"
|
||||
tools:visibility="visible">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/mypl"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:padding="16dp"
|
||||
style="?android:attr/progressBarStyleHorizontal"/>
|
||||
android:padding="16dp" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
Reference in New Issue
Block a user