1
0
mirror of https://github.com/fumiama/copymanga.git synced 2026-06-10 10:24:29 +08:00

2.0.beta11

修复
1. 返回漫画详情页时封面拉长
2. 有时一章只有五页
3. 我的下载显示不全
4. 搜索封面变形
5. 删除漫画闪退
新增
1. 多线程下载漫画
This commit is contained in:
源文雨
2022-03-13 21:35:13 +08:00
parent cb666cb104
commit 98d06b261d
19 changed files with 356 additions and 296 deletions

View File

@@ -0,0 +1,79 @@
package top.fumiama.copymanga.manga
import android.util.Log
import com.google.gson.Gson
import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference
import top.fumiama.copymanga.json.Chapter2Return
import top.fumiama.copymanga.template.http.AutoDownloadThread
import top.fumiama.copymanga.tools.http.DownloadPool
import java.io.File
class MangaDlTools {
private var pool: DownloadPool? = null
private var grp: CharSequence = ""
private var indexMap = hashMapOf<String, Int>()
var exit: Boolean
get() = pool?.exit?:false
set(value) { pool?.exit = value }
var wait
get() = pool?.wait
set(value) { if (value != null) { pool?.wait = value } }
fun downloadChapterInVol(url: CharSequence, chapterName: CharSequence, group: CharSequence, index: Int){
Log.d("MyMDT", "下载:$url, index$index")
AutoDownloadThread(url.toString()){
Gson().fromJson(it?.decodeToString(), Chapter2Return::class.java)?.let {
if(it.results.chapter.words.size != it.results.chapter.size) downloadChapterInVol(url, chapterName, group, index)
else getChapterInfo(it, index, chapterName, group)
}
}.start()
}
@Synchronized private fun setPool(comicName: String, group: CharSequence) {
if(pool == null || grp != group) {
pool = DownloadPool(File(
mainWeakReference?.get()?.getExternalFilesDir(""),
"$comicName/$group"
).absolutePath)
grp = group
}
}
@Synchronized private fun setIndexMap(f : String, index: Int) {
indexMap[f] = index
}
private fun getChapterInfo(chapter2Return: Chapter2Return, index: Int, chapterName: CharSequence, group: CharSequence) {
if(index >= 0){
val f = "$chapterName.zip"
setPool(chapter2Return.results.comic.name, group)
setIndexMap(f, index)
pool?.plusAssign(DownloadPool.Quest(f, getMangaUrls(chapter2Return)))
pool?.setOnDownloadListener { fileName: String, isSuccess: Boolean ->
indexMap[fileName]?.let { onDownloadedListener?.handleMessage(it, isSuccess) }
}
pool?.setOnPageDownloadListener { fileName: String, downloaded: Int, total: Int, isSuccess: Boolean ->
indexMap[fileName]?.let { onDownloadedListener?.handleMessage(it, downloaded, total, isSuccess) }
}
}
}
private fun getMangaUrls(chapter2Return: Chapter2Return): Array<String>{
var re: Array<String> = arrayOf()
val hm: HashMap<Int, String> = hashMapOf()
val chapter = chapter2Return.results.chapter
for(i in 0 until chapter.size) {
hm[chapter.words[i]] = chapter.contents[i].url
}
for(i in 0 until chapter.size){
re += hm[i]?:""
}
return re
}
var onDownloadedListener: OnDownloadedListener? = null
interface OnDownloadedListener{
fun handleMessage(index: Int, isSuccess: Boolean)
fun handleMessage(index: Int, downloaded: Int, total: Int, isSuccess: Boolean)
}
}

View File

@@ -7,6 +7,7 @@ import android.util.Log
import com.google.gson.Gson
import top.fumiama.dmzj.copymanga.R
import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference
import top.fumiama.copymanga.json.Chapter2Return
import top.fumiama.copymanga.json.ReturnBase
import top.fumiama.copymanga.tools.http.DownloadTools
import top.fumiama.copymanga.tools.thread.TimeThread
@@ -22,7 +23,7 @@ open class AutoDownloadHandler(private val url: String, private val jsonClass: C
0 -> setLayouts()
}
}
open fun setGsonItem(gsonObj: Any) {}
open fun setGsonItem(gsonObj: Any): Boolean = true
open fun getGsonItem(): ReturnBase? = null
open fun onError() {}
open fun doWhenFinishDownload() {}
@@ -33,22 +34,26 @@ open class AutoDownloadHandler(private val url: String, private val jsonClass: C
exit = true
}
private fun download(){
Thread{
DownloadTools.getHttpContent(url,
mainWeakReference?.get()?.getString(R.string.referUrl)!!,
mainWeakReference?.get()?.getString(R.string.pc_ua)!!
)?.let {
if(exit) return@Thread
val fi = it.inputStream()
setGsonItem(Gson().fromJson(fi.reader(), jsonClass))
fi.close()
}
}.start()
Thread{ dlThread() }.start()
checkTimes = 0
timeThread = TimeThread(this, callCheckMsg)
timeThread?.canDo = true
timeThread?.start()
}
private fun dlThread() {
DownloadTools.getHttpContent(url,
mainWeakReference?.get()?.getString(R.string.referUrl)!!,
mainWeakReference?.get()?.getString(R.string.pc_ua)!!
)?.let {
if(exit) return
val fi = it.inputStream()
val pass = setGsonItem(Gson().fromJson(fi.reader(), jsonClass))
fi.close()
if(!pass) {
dlThread()
}
}
}
private fun check(){
val g = getGsonItem()
if(g != null) {

View File

@@ -0,0 +1,85 @@
package top.fumiama.copymanga.tools.http
import android.util.Log
import java.io.File
import java.lang.Thread.sleep
import java.util.zip.CRC32
import java.util.zip.CheckedOutputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
class DownloadPool(folder: String) {
class Quest(val fileName: String, val imgUrl: Array<String>, val refer: String? = null)
var exit = false
set(value) {
if(value) {
mOnDownloadListener = null
mOnPageDownloadListener = null
}
field = value
}
var wait = false
private val saveFolder = File(folder)
//fileName: String, isSuccess: Boolean
private var mOnDownloadListener: ((String, Boolean) -> Unit)? = null
//fileName: String, downloaded: Int, total: Int, isSuccess: Boolean
private var mOnPageDownloadListener: ((String, Int, Int, Boolean) -> Unit)? = null
init {
if(!saveFolder.exists()) saveFolder.mkdirs()
}
operator fun plusAssign(quest: Quest) {
packZipFile(quest.fileName, quest.imgUrl, quest.refer?:"")
}
operator fun plusAssign(quests: Array<Quest>) {
Thread{
quests.forEach { quest ->
packZipFile(quest.fileName, quest.imgUrl, quest.refer?:"")
sleep(1000)
}
}.start()
}
fun setOnDownloadListener(onDownloadListener: (String, Boolean) -> Unit) {
mOnDownloadListener = onDownloadListener
}
fun setOnPageDownloadListener(onPageDownloadListener: (String, Int, Int, Boolean) -> Unit) {
mOnPageDownloadListener = onPageDownloadListener
}
private fun packZipFile(fileName: String, imgUrls: Array<String>, refer: String) {
Thread{
File(saveFolder, fileName).let { f ->
f.parentFile?.let { if(!it.exists()) it.mkdirs() }
if(f.exists()) f.delete()
f.createNewFile()
Log.d("MyDP", "Zip file: ${f.absolutePath}")
val zip = ZipOutputStream(CheckedOutputStream(f.outputStream(), CRC32()))
zip.setLevel(9)
var succeed = true
for(index in imgUrls.indices) {
while (wait && !exit) sleep(1000)
if(exit) break
zip.putNextEntry(ZipEntry("$index.jpg"))
var tryTimes = 3
var s = false
while (!s && tryTimes-- > 0){
s = (DownloadTools.getHttpContent(imgUrls[index], -1, refer)) ?.let { zip.write(it); true }?:false
if (!s) sleep(2000)
}
if(!s && tryTimes <= 0) {
succeed = false
mOnPageDownloadListener?.let { it(fileName, index + 1, imgUrls.size, false) }
break
} else mOnPageDownloadListener?.let { it(fileName, index + 1, imgUrls.size, true) }
//zip.flush()
}
zip.close()
mOnPageDownloadListener?.let { it(fileName, 0, 0, true) }
mOnDownloadListener?.let { it(fileName, succeed) }
}
}.start()
}
}

View File

@@ -3,8 +3,10 @@ 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.net.URLEncoder
import java.security.SecureRandom
import java.util.concurrent.Callable
import java.util.concurrent.FutureTask
@@ -87,7 +89,7 @@ object DownloadTools {
}
}
fun getHttpContent(Url: String, readSize: Int? = null, refer: String? = "https://api.copymanga.com"): ByteArray? {
fun getHttpContent(Url: String, readSize: Int, refer: String? = "https://api.copymanga.com"): ByteArray? {
Log.d("Mydl", "getHttp: $Url")
var ret: ByteArray? = null
val task = FutureTask(Callable {
@@ -96,7 +98,7 @@ object DownloadTools {
refer?.let { connection?.setRequestProperty("referer", it) }
val ci = connection?.inputStream
if(readSize != null) {
if(readSize > 0) {
ret = ByteArray(readSize)
ci?.read(ret, 0, readSize)
} else ret = ci?.readBytes()
@@ -116,7 +118,7 @@ object DownloadTools {
}
}
fun touch(url: String?, refer: String? = "https://www.dmzj1.com"): FutureTask<ByteArray?>? =
fun touch(url: String?, refer: String? = "https://api.copymanga.com"): FutureTask<ByteArray?>? =
url?.let {
Log.d("Mydl", "touchHttp: $it")
var ret: ByteArray? = null
@@ -137,4 +139,40 @@ object DownloadTools {
Thread(task).start()
task
}
private fun replaceChineseCharacters(string: String?) : String? {
if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.M) return string
else return string?.replace(Regex("(?<=/)[\\w\\s\\d\\u4e00-\\u9fa5.-]+(?=/?)")) { match ->
return@replace URLEncoder.encode(match.value, "UTF-8")
}
}
fun downloadUsingUrlRet(url: String?, f: File, refer: String?): Boolean {
Log.d("Mydl", "Ret Get url: $url, File: $f")
val task = FutureTask(Callable {
val connection = getConnection(replaceChineseCharacters(url))
if(refer != null) connection?.setRequestProperty("referer", refer)
if (f.exists()) f.delete()
else f.parentFile?.mkdirs()
f.parentFile?.let {
if (!it.canRead()) it.setReadable(true)
if (!it.canWrite()) it.setWritable(true)
}
val ci = connection?.inputStream
val fo = f.outputStream()
ci?.buffered()?.copyTo(fo)
fo.close()
ci?.close()
connection?.disconnect()
return@Callable true
})
Thread(task).start()
return try {
task.get()
} catch (ex: Exception) {
ex.printStackTrace()
false
}
}
}

View File

@@ -1,108 +0,0 @@
package top.fumiama.copymanga.tools.http
import android.util.Log
import com.google.gson.Gson
import top.fumiama.dmzj.copymanga.R
import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference
import top.fumiama.copymanga.json.Chapter2Return
import top.fumiama.copymanga.template.http.AutoDownloadThread
import top.fumiama.copymanga.tools.http.DownloadTools.getHttpContent
import java.io.File
import java.lang.Thread.sleep
import java.util.zip.CRC32
import java.util.zip.CheckedOutputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
class MangaDlTools {
var exit = false
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"
complete = false
getChapterInfo(url, index)
while (!complete) sleep(1000)
}
private fun getChapterInfo(chapter2Return: Chapter2Return, index: Int) {
if(index >= 0){
comicFileRelative?.let {
dlChapterAndPackIntoZip(
File(
mainWeakReference?.get()?.getExternalFilesDir(""),
"${chapter2Return.results.comic.name}/$it"
),
getMangaUrls(chapter2Return)
)
}
}
}
private fun getMangaUrls(chapter2Return: Chapter2Return): Array<String>{
var re: Array<String> = arrayOf()
val hm: HashMap<Int, String> = hashMapOf()
val chapter = chapter2Return.results.chapter
for(i in 0 until chapter.size) {
hm[chapter.words[i]] = chapter.contents[i].url
}
for(i in 0 until chapter.size){
re += hm[i]?:""
}
size = re.size
return re
}
private fun getChapterInfo(url: CharSequence, index: Int){
Log.d("MyMDT", "下载:$url, index$index")
AutoDownloadThread(url.toString()){
Gson().fromJson(it?.decodeToString(), Chapter2Return::class.java)?.let {
getChapterInfo(it, index)
}
}.start()
}
private fun dlChapterAndPackIntoZip(zipf: File, urls: Array<String>) {
zipf.parentFile?.let { if (!it.exists()) it.mkdirs() }
if (zipf.exists()) zipf.delete()
zipf.createNewFile()
val zip = ZipOutputStream(CheckedOutputStream(zipf.outputStream(), CRC32()))
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
while (!s && tryTimes-- > 0) {
s = getHttpContent(
urls[i],
mainWeakReference?.get()?.getString(R.string.referUrl),
mainWeakReference?.get()?.getString(R.string.pc_ua)
)?.let { zip.write(it); true } ?: false
if (!s) {
onDownloadedListener?.handleMessage(i + 1)
sleep(2000)
}
}
if (!s && tryTimes <= 0) succeed = false
onDownloadedListener?.handleMessage(s, i + 1)
zip.flush()
}
zip.close()
onDownloadedListener?.handleMessage(succeed)
complete = true
}
var onDownloadedListener: OnDownloadedListener? = null
interface OnDownloadedListener {
fun handleMessage(succeed: Boolean)
fun handleMessage(succeed: Boolean, pageNow: Int)
fun handleMessage(pageNow: Int)
}
}

View File

@@ -27,7 +27,6 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) {
bookHandler.startLoad()
}.start()
}
else bookHandler.fbibinfo?.layoutParams?.height = (bookHandler.fbibinfo?.width?:0 * 4.0 / 9.0 + 0.5).toInt()
}
override fun onResume() {
@@ -37,6 +36,7 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) {
toolbar.title = bookHandler.book?.results?.comic?.name
}
setStartRead()
bookHandler.fbibinfo?.layoutParams?.height = ((bookHandler.fbibinfo?.width?:0) * 4.0 / 9.0 + 0.5).toInt()
}
override fun onDestroy() {

View File

@@ -91,9 +91,10 @@ class BookHandler(that: WeakReference<BookFragment>, private val path: String)
}
}
override fun setGsonItem(gsonObj: Any) {
super.setGsonItem(gsonObj)
override fun setGsonItem(gsonObj: Any): Boolean {
val pass = super.setGsonItem(gsonObj)
book = gsonObj as BookInfoStructure
return pass
}
override fun getGsonItem() = book

View File

@@ -39,9 +39,10 @@ class ChapterHandler(that: WeakReference<ChapterFragment>, pw: String, gpw: Stri
}
override fun getGsonItem() = chapters
override fun setGsonItem(gsonObj: Any) {
super.setGsonItem(gsonObj)
override fun setGsonItem(gsonObj: Any) :Boolean {
val pass = super.setGsonItem(gsonObj)
chapters = gsonObj as VolumeStructure
return pass
}
override fun onError() {

View File

@@ -49,6 +49,7 @@ class ComicDlFragment: NoBackRefreshFragment(R.layout.fragment_dlcomic) {
override fun onDestroy() {
super.onDestroy()
//mainWeakReference?.get()?.menuMain?.let { setMenuInvisible(it) }
handler?.downloading = false
handler?.mangaDlTools?.exit = true
ads.forEach {
it.exit = true

View File

@@ -27,7 +27,7 @@ import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference
import top.fumiama.copymanga.json.ComicStructureOld
import top.fumiama.copymanga.json.VolumeStructure
import top.fumiama.copymanga.tools.api.CMApi
import top.fumiama.copymanga.tools.http.MangaDlTools
import top.fumiama.copymanga.manga.MangaDlTools
import top.fumiama.copymanga.tools.api.UITools
import top.fumiama.copymanga.ui.comicdl.ComicDlFragment.Companion.json
import top.fumiama.copymanga.ui.vm.ViewMangaActivity
@@ -48,46 +48,23 @@ class ComicDlHandler(looper: Looper, that: WeakReference<ComicDlFragment>, priva
private var btnw = 0
private var cdwnWidth = 0
private var dl: Dialog? = null
private var hasToastedError = false
get(){
val re = field
field = true
return re
}
private var haveSElectAll = false
private var checkedChapter = 0
private var dldChapter = 0
private var haveDlStarted = false
private val dldChapter: Int get() = finishMap.count { p -> return@count p == true }
private var tbtnlist: Array<ChapterToggleButton> = arrayOf()
private var tbtncnt = 0
private var isNewTitle = false
val mangaDlTools = MangaDlTools()
private var multiSelect = false
private var size = 0
private var refreshSize = true
private var ltbtn: View? = null
private var finishMap = arrayOf<Boolean?>()
var downloading = false
@SuppressLint("SetTextI18n")
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
when(msg.what){
0 -> dl?.hide()
1 -> {
tbtnlist[msg.arg1].setBackgroundResource(R.drawable.rndbg_checked)
tbtnlist[msg.arg1].isChecked = false
updateProgressBar()
}
-1 -> {
tbtnlist.get(msg.arg1).setBackgroundResource(R.drawable.rndbg_error)
dldChapter--
Toast.makeText(
that?.context,
"下载${tbtnlist[msg.arg1].chapterName}失败",
Toast.LENGTH_SHORT
).show()
updateProgressBar()
}
//2 -> scanHiddenChapters()
//3 ->
4 -> {
@@ -104,7 +81,6 @@ class ComicDlHandler(looper: Looper, that: WeakReference<ComicDlFragment>, priva
}
haveSElectAll = false
checkedChapter = 0
dldChapter = 0
} else {
for (i in tbtnlist) {
if (multiSelect || !i.isChecked && !isChapterExists(i.chapterName, i.caption ?: "null")) {
@@ -117,24 +93,12 @@ class ComicDlHandler(looper: Looper, that: WeakReference<ComicDlFragment>, priva
}
that?.tdwn?.text = "${dldChapter}/${checkedChapter}"
}
5 -> {
setSize(msg.arg2)
updateProgressBar(msg.arg2, size)
if (!(msg.obj as Boolean)) {
Toast.makeText(that?.context, "下载${tbtnlist.get(msg.arg1).chapterName}的第${msg.arg2}页失败", Toast.LENGTH_SHORT).show()
}else{
val progressTxt = that?.tdwn?.text.toString()
that?.tdwn?.text = "${progressTxt.substringBefore(' ')}${msg.arg2}/${size}"
}
}
6 -> that?.tdwn?.text = "${dldChapter}/${checkedChapter}"
7 -> deleteChapters(msg.obj as File, msg.arg1)
8 -> that?.cdwn?.setCardBackgroundColor(that.resources.getColor(R.color.colorBlue))
9 -> that?.cdwn?.setCardBackgroundColor(that.resources.getColor(R.color.colorGreen))
10 -> addTbtn(msg.obj as Array<String>)
11 -> addCaption(msg.obj as String)
12 -> addDiv()
13 -> that?.let { Toast.makeText(it.context, "下载${tbtnlist[msg.arg1].textOn}的第${msg.arg2}页失败,尝试重新下载...", Toast.LENGTH_SHORT).show() }
}
}
@@ -208,16 +172,8 @@ class ComicDlHandler(looper: Looper, that: WeakReference<ComicDlFragment>, priva
File(that?.context?.getExternalFilesDir(""),"$comicName/$caption/$chapter.zip").exists()
@SuppressLint("SetTextI18n")
private fun updateProgressBar() {
that?.tdwn?.text = "${++dldChapter}/$checkedChapter"
setProgress2(dldChapter * 100 / checkedChapter, 233)
}
private fun updateProgressBar(pageNow: Int, size: Int) {
if(checkedChapter > 0) {
val delta = 100 / checkedChapter
val start = dldChapter * delta
val now = pageNow * delta / size
setProgress2(start + now, 64)
}
that?.tdwn?.text = "$dldChapter/$checkedChapter"
setProgress2(dldChapter * 100 / (if(checkedChapter > 0) checkedChapter else 1), 233)
}
private fun setProgress2(end: Int, duration: Long) {
ObjectAnimator.ofInt(
@@ -227,12 +183,6 @@ class ComicDlHandler(looper: Looper, that: WeakReference<ComicDlFragment>, priva
end
).setDuration(duration).start()
}
private fun setSize(pageNow: Int){
if(refreshSize || size == 0) {
size = mangaDlTools.size
refreshSize = false
}else if(pageNow == size) refreshSize = true
}
private fun setComponents() {
val widthData = toolsBox.calcWidthFromDpRoot(8, 64)
btnNumPerRow = widthData[0]
@@ -258,23 +208,17 @@ class ComicDlHandler(looper: Looper, that: WeakReference<ComicDlFragment>, priva
else if(checkedChapter == 0) hideDlCard()
else{
that.pdwn.progress = 0
if(haveDlStarted && checkedChapter != 0) mangaDlTools.wait = !mangaDlTools.wait
else {
haveDlStarted = true
mangaDlTools.wait = false
Thread{
sendEmptyMessage(9) //set dl card color to green
downloadMangas()
sendEmptyMessage(8) //set dl card color to blue
if (!haveDlStarted) {
dldChapter = 0
checkedChapter = 0
this.postDelayed({
setProgress2(0, 233)
that.tdwn?.text = "0/0"
}, 400)
}
}.start()
if (downloading || checkedChapter == 0) {
mangaDlTools.wait = !mangaDlTools.wait!!
} else {
if(!downloading) {
downloading = true
Thread {
sendEmptyMessage(9)
finishMap = arrayOfNulls(tbtnlist.size)
downloadChapterPages()
}.start()
} else mangaDlTools.wait = false
}
}
}
@@ -282,46 +226,78 @@ class ComicDlHandler(looper: Looper, that: WeakReference<ComicDlFragment>, priva
Thread { sendEmptyMessage(4) }.start()
return@setOnLongClickListener true
}
mangaDlTools.onDownloadedListener = object :MangaDlTools.OnDownloadedListener{
override fun handleMessage(index: Int, isSuccess: Boolean) {
mainWeakReference?.get()?.runOnUiThread {
if(isSuccess) onZipDownloadFinish(index)
else onZipDownloadFailure(index)
}
}
override fun handleMessage(
index: Int,
downloaded: Int,
total: Int,
isSuccess: Boolean
) {
mainWeakReference?.get()?.runOnUiThread {
if(isSuccess) {
tbtnlist[index].text = if(downloaded == 0 && total == 0) tbtnlist[index].chapterName else "$downloaded/$total"
} else {
tbtnlist[index].text = "$downloaded/$total"
Toast.makeText(that?.context, "下载${tbtnlist[index].chapterName}的第${downloaded}页失败", Toast.LENGTH_SHORT).show()
}
}
}
}
}
fun showMultiSelectInfo() {
toolsBox.buildInfo("进入多选模式?", "之后可以对已下载漫画进行批量删除/重新下载",
"确定", null, "取消", { multiSelect = true })
}
private fun downloadMangas(){
for (i in tbtnlist) {
if (i.isChecked) downloadChapterPages(i)
}
haveDlStarted = false
}
private fun downloadChapterPages(i: ChapterToggleButton) {
mangaDlTools.onDownloadedListener =
object : MangaDlTools.OnDownloadedListener {
override fun handleMessage(succeed: Boolean) {
this@ComicDlHandler.obtainMessage(if (succeed) 1 else -1, i.index, 0)
.sendToTarget()
}
override fun handleMessage(succeed: Boolean, pageNow: Int) {
this@ComicDlHandler.obtainMessage(
5,
i.index,
pageNow,
succeed
).sendToTarget()
}
override fun handleMessage(pageNow: Int){
this@ComicDlHandler.obtainMessage(13, i.index, pageNow).sendToTarget()
private fun downloadChapterPages() {
tbtnlist.forEach { i ->
if(i.isChecked) {
i.url?.let {
mangaDlTools.downloadChapterInVol(
it,
i.chapterName,
i.caption?:"null",
i.index
)
}
}
i.url?.let {
mangaDlTools.downloadChapterInVol(
it,
i.chapterName,
i.caption?:"null",
i.index
)
}
}
private fun onZipDownloadFinish(index: Int) {
if(index >= 0 && index < tbtnlist.size) {
tbtnlist[index].setBackgroundResource(R.drawable.rndbg_checked)
tbtnlist[index].isChecked = false
finishMap[index] = true
updateProgressBar()
that?.apply {
cdwn.postDelayed({
if (dldChapter == checkedChapter) {
checkedChapter = 0
setProgress2(0, 233)
tdwn.text = "0/0"
cdwn.setCardBackgroundColor(resources.getColor(R.color.colorBlue))
finishMap = arrayOf()
downloading = false
}
}, 400)
}
}
}
private fun onZipDownloadFailure(index: Int) {
tbtnlist[index].setBackgroundResource(R.drawable.rndbg_error)
Toast.makeText(that?.context, "下载${tbtnlist[index].chapterName}失败", Toast.LENGTH_SHORT).show()
updateProgressBar()
}
private fun showDlCard(){
//ObjectAnimator.ofFloat(dlsdwn, "alpha", 0.3f, 0.9f).setDuration(233).start()
ObjectAnimator.ofFloat(that?.dlsdwn, "translationX", cdwnWidth.toFloat() * 0.9f, 0f).setDuration(233).start()

View File

@@ -1,19 +0,0 @@
package top.fumiama.copymanga.ui.download
import android.os.Handler
import android.os.Looper
import android.os.Message
import java.io.File
import java.lang.ref.WeakReference
class DlLHandler(looper: Looper, dl: DownloadFragment): Handler(looper) {
private val dll = WeakReference(dl)
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
when(msg.what){
1 -> dll.get()?.checkDir(msg.obj as File)
2 -> dll.get()?.rmrf(msg.obj as File)
3 -> dll.get()?.scanFile(msg.obj as File)
}
}
}

View File

@@ -22,16 +22,13 @@ import java.util.zip.ZipInputStream
class DownloadFragment: NoBackRefreshFragment(R.layout.fragment_download) {
private var nullZipDirStr = emptyArray<String>()
private var handler: DlLHandler? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if(isFirstInflate) {
arguments?.getString("title")?.let {
mainWeakReference?.get()?.toolbar?.title = it
}
handler = DlLHandler(Looper.myLooper()!!, this)
handler?.obtainMessage(3, currentDir)?.sendToTarget() //call scanFile
scanFile(currentDir)
}
}
@@ -71,15 +68,11 @@ class DownloadFragment: NoBackRefreshFragment(R.layout.fragment_download) {
setOnItemLongClickListener { _, _, position, _ ->
val chosenFile = File(cd, it[position])
AlertDialog.Builder(context)
.setIcon(R.drawable.ic_launcher_foreground).setMessage("在此执行删除/查错?")
.setTitle("提示").setPositiveButton("删除") { _, _ ->
if (chosenFile.exists()) handler?.obtainMessage(2, chosenFile)
?.sendToTarget() //call rmrf
handler?.obtainMessage(3, cd)?.sendToTarget() //call scanFile
.setIcon(R.drawable.ic_launcher_foreground).setMessage("删除?")
.setTitle("提示").setPositiveButton(android.R.string.ok) { _, _ ->
if (chosenFile.exists()) rmrf(chosenFile)
scanFile(cd)
}.setNegativeButton(android.R.string.cancel) { _, _ -> }
.setNeutralButton("查错") { _, _ ->
handler?.obtainMessage(1, chosenFile)?.sendToTarget()
} //call checkDir
.show()
true
}
@@ -98,13 +91,6 @@ class DownloadFragment: NoBackRefreshFragment(R.layout.fragment_download) {
f.delete()
}
fun checkDir(f: File){
nullZipDirStr = emptyArray()
findNullWebpZipFileInDir(f)
if(nullZipDirStr.isNotEmpty()) showErrorZip(nullZipDirStr.joinToString("\n"))
else Toast.makeText(context, "未发现错误", Toast.LENGTH_SHORT).show()
}
private fun callDownloadFragment(jsonFile: File, isNew: Boolean = false){
val bundle = Bundle()
Log.d("MyDF", "Call dl and is new: $isNew")

View File

@@ -201,6 +201,7 @@ class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) {
bundle.putString("path", path_word)
rootView?.let { r -> Navigation.findNavController(r).navigate(R.id.action_nav_home_to_nav_book, bundle) }
}
holder.itemView.lwc.layoutParams.height = fhs.width / 4
}
}

View File

@@ -78,8 +78,8 @@ class HomeHandler(that: WeakReference<HomeFragment>) : AutoDownloadHandler(
}
override fun getGsonItem() = index
override fun setGsonItem(gsonObj: Any) {
super.setGsonItem(gsonObj)
override fun setGsonItem(gsonObj: Any) :Boolean {
val pass = super.setGsonItem(gsonObj)
index = gsonObj as IndexStructure
var banners = arrayOf<IndexStructure.Results.Banners>()
index?.results?.banners?.forEach {
@@ -88,6 +88,7 @@ class HomeHandler(that: WeakReference<HomeFragment>) : AutoDownloadHandler(
}
}
index?.results?.banners = banners
return pass
}
override fun onError() {
super.onError()

View File

@@ -104,11 +104,15 @@ class VMHandler(activity: ViewMangaActivity, url: String) : AutoDownloadHandler(
22 -> wv.get()?.idtime?.text = SimpleDateFormat("HH:mm").format(Date()) + week + wv.get()?.toolsBox?.netinfo
}
}
override fun getGsonItem() = manga
override fun setGsonItem(gsonObj: Any) {
override fun setGsonItem(gsonObj: Any): Boolean {
super.setGsonItem(gsonObj)
manga = gsonObj as Chapter2Return
val m = gsonObj as Chapter2Return
if(m.results.chapter.words.size != m.results.chapter.size) {
return false
}
manga = m
return true
}
override fun onError() {
super.onError()

View File

@@ -390,18 +390,29 @@ class ViewMangaActivity : TitleActivityTemplate() {
private fun getImgBitmap(position: Int): Bitmap? =
if (position >= count || position < 0) null
else try {
else {
val zip = ZipFile(zipFile)
if (q == 100) BitmapFactory.decodeStream(zip.getInputStream(zip.getEntry("${position}.webp")))
else {
val out = ByteArrayOutputStream()
BitmapFactory.decodeStream(zip.getInputStream(zip.getEntry("${position}.webp")))?.compress(Bitmap.CompressFormat.JPEG, q, out)
BitmapFactory.decodeStream(ByteArrayInputStream(out.toByteArray()))
try {
if (q == 100) BitmapFactory.decodeStream(zip.getInputStream(zip.getEntry("${position}.jpg")))
else {
val out = ByteArrayOutputStream()
BitmapFactory.decodeStream(zip.getInputStream(zip.getEntry("${position}.jpg")))?.compress(Bitmap.CompressFormat.JPEG, q, out)
BitmapFactory.decodeStream(ByteArrayInputStream(out.toByteArray()))
}
} catch (e: Exception) {
try {
if (q == 100) BitmapFactory.decodeStream(zip.getInputStream(zip.getEntry("${position}.webp")))
else {
val out = ByteArrayOutputStream()
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}项错误", Toast.LENGTH_SHORT).show()
null
}
}
} catch (e: Exception) {
e.printStackTrace()
Toast.makeText(this, "加载zip的${position}.webp错误", Toast.LENGTH_SHORT).show()
null
}
private fun setIdPosition(position: Int) {

View File

@@ -1,11 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:fillViewport="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/mylv">
</ListView>
</androidx.core.widget.NestedScrollView>
android:layout_height="wrap_content"
android:id="@+id/mylv">
</ListView>

View File

@@ -14,6 +14,7 @@
layout="@layout/card_book_plain"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/lwl"
app:layout_constraintHorizontal_weight="1"
@@ -23,7 +24,8 @@
<LinearLayout
android:id="@+id/lwl"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"