diff --git a/app/build.gradle b/app/build.gradle index 667609b..43a1599 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ android { applicationId "top.fumiama.copymanga" minSdkVersion 23 targetSdkVersion 30 - versionCode 7 - versionName '1.2.1' + versionCode 8 + versionName '1.3' resConfigs "zh", "zh-rCN" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/app/src/main/java/top/fumiama/copymanga/activity/DlActivity.kt b/app/src/main/java/top/fumiama/copymanga/activity/DlActivity.kt index b7bab84..d6abdcd 100644 --- a/app/src/main/java/top/fumiama/copymanga/activity/DlActivity.kt +++ b/app/src/main/java/top/fumiama/copymanga/activity/DlActivity.kt @@ -4,6 +4,7 @@ import android.animation.ObjectAnimator import android.annotation.SuppressLint import android.app.Activity import android.os.Bundle +import android.os.Looper import android.view.View import android.view.ViewGroup import android.view.ViewTreeObserver @@ -40,7 +41,7 @@ class DlActivity : Activity() { private lateinit var ltbtn: View var tbtnlist: List = arrayListOf() var tbtnUrlList = arrayListOf() - private val handler = DlHandler(this) + private val handler = DlHandler(this, Looper.myLooper()!!) private var btnw = 0 private var cdwnWidth = 0 private var canDl = false @@ -87,7 +88,7 @@ class DlActivity : Activity() { } private fun dlThead(dlMethod: (i: ToggleButton) -> Unit) { - sleep(2333) + sleep(100000) for (i in tbtnlist.listIterator()) { if (i.isChecked) dlMethod(i) if (!canDl) { @@ -133,14 +134,14 @@ class DlActivity : Activity() { haveDlStarted = true canDl = true handler.sendEmptyMessage(9) //set dl card color to red - Toast.makeText(this, "准备下载...", Toast.LENGTH_SHORT).show() + Toast.makeText(this, "十秒后开始下载...", Toast.LENGTH_SHORT).show() fillChapters() Thread { dlThead { downloadChapterPages(it) } }.start() } } } cdwn.setOnLongClickListener { - Thread { handler.sendEmptyMessage(4) }.start() + handler.sendEmptyMessage(4) return@setOnLongClickListener true } isearch.setOnClickListener { showMultiSelectInfo() } @@ -250,9 +251,7 @@ class DlActivity : Activity() { it.tbtn.isChecked = true tdwn.text = "$dldChapter/${++checkedChapter}" } - Thread { - handler.sendEmptyMessage(7) - }.start() + handler.sendEmptyMessage(7) }) } true diff --git a/app/src/main/java/top/fumiama/copymanga/activity/DlListActivity.kt b/app/src/main/java/top/fumiama/copymanga/activity/DlListActivity.kt index 6d704d2..661a2ef 100644 --- a/app/src/main/java/top/fumiama/copymanga/activity/DlListActivity.kt +++ b/app/src/main/java/top/fumiama/copymanga/activity/DlListActivity.kt @@ -2,25 +2,41 @@ package top.fumiama.copymanga.activity import android.app.Activity import android.app.AlertDialog +import android.app.Dialog import android.content.Intent import android.os.Bundle +import android.os.Looper +import android.util.Log import android.widget.ArrayAdapter import android.widget.Toast import kotlinx.android.synthetic.main.activity_dlist.* import kotlinx.android.synthetic.main.widget_titlebar.* import top.fumiama.copymanga.R +import top.fumiama.copymanga.handler.DlLHandler import java.io.File +import java.util.regex.Pattern +import java.util.zip.ZipInputStream class DlListActivity:Activity() { + var nullZipDirStr = emptyArray() + var handler: DlLHandler? = null + var loadingDialog: Dialog? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_dlist) ttitle.text = intent.getStringExtra("title") - scanFile(currentDir) + loadingDialog = Dialog(this) + loadingDialog?.setContentView(R.layout.dialog_loading) + handler = DlLHandler(Looper.myLooper()!!, this) + handler?.obtainMessage(3, currentDir)?.sendToTarget() //call scanFile } - private fun scanFile(cd: File?){ - cd?.list()?.sortedArray()?.let { + fun scanFile(cd: File?){ + cd?.list()?.sortedArrayWith { o1, o2 -> + if(o1.endsWith(".zip") && o2.endsWith(".zip")) (10000*getFloat(o1) - 10000*getFloat(o2) + 0.5).toInt() + else o1[0] - o2[0] + }?.let { mylv.adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, it) mylv.setOnItemClickListener { _, _, position, _ -> val chosenFile = File(cd, it[position]) @@ -38,23 +54,28 @@ class DlListActivity:Activity() { Toast.makeText(this, "加载中...", Toast.LENGTH_SHORT).show() ViewMangaActivity.zipFile = chosenFile ViewMangaActivity.titleText = it[position] + ViewMangaActivity.zipPosition = position + ViewMangaActivity.zipList = it + ViewMangaActivity.cd = cd startActivity(Intent(this, ViewMangaActivity::class.java)) } } mylv.setOnItemLongClickListener { _, _, position, _ -> val chosenFile = File(cd, it[position]) AlertDialog.Builder(this) - .setIcon(R.drawable.ic_launcher_foreground).setMessage("是否删除?") - .setTitle("提示").setPositiveButton("确定"){ _, _ -> - if(chosenFile.exists()) rmrf(chosenFile) - scanFile(cd) - }.setNegativeButton("取消"){_, _ ->}.show() + .setIcon(R.drawable.ic_launcher_foreground).setMessage("是否在此执行删除/查错?") + .setTitle("提示").setPositiveButton(android.R.string.ok){ _, _ -> + if(chosenFile.exists()) handler?.obtainMessage(2, chosenFile)?.sendToTarget() //call rmrf + handler?.obtainMessage(3, cd)?.sendToTarget() //call scanFile + }.setNegativeButton(android.R.string.cancel){_, _ ->} + .setNeutralButton("查错"){_, _ -> handler?.obtainMessage(1, chosenFile)?.sendToTarget()} //call checkDir + .show() true } } } - private fun rmrf(f: File) { + fun rmrf(f: File) { if (f.isDirectory) f.listFiles()?.let { for (i in it) if (i.isDirectory) rmrf(i) @@ -63,6 +84,81 @@ class DlListActivity:Activity() { f.delete() } + fun checkDir(f: File){ + nullZipDirStr = emptyArray() + findNullWebpZipFileInDir(f) + if(nullZipDirStr.isNotEmpty()) showErrorZip(nullZipDirStr.joinToString("\n")) + else Toast.makeText(this, "未发现错误", Toast.LENGTH_SHORT).show() + } + + fun showLoading() = loadingDialog?.show() + + fun hideLoading() = loadingDialog?.hide() + + private fun findNullWebpZipFileInDir(f: File){ + if (f.isDirectory) f.listFiles()?.let { + for (i in it) + if (i.isDirectory) findNullWebpZipFileInDir(i) + else if(!checkZip(i)) nullZipDirStr += i.path.substringAfterLast(getExternalFilesDir("").toString()) + } + } + + private fun checkZip(f: File): Boolean{ + return try { + val exist = f.exists() + if (!exist) true + else { + var re = true + val zip = ZipInputStream(f.inputStream().buffered()) + var entry = zip.nextEntry + while (entry != null) { + if (!entry.isDirectory){ + if(zip.read() == -1 && entry.size == 0L){ + re = false + break + } + } + entry = zip.nextEntry + } + zip.closeEntry() + zip.close() + re + } + } catch (e: Exception) { + Toast.makeText(this, "读取${f.name}错误!", Toast.LENGTH_SHORT).show() + true + } + } + + private fun showErrorZip(msg: CharSequence) = AlertDialog.Builder(this) + .setIcon(R.drawable.ic_launcher_foreground) + .setTitle("找到以下错误文件,是否删除?") + .setMessage(msg) + .setPositiveButton(android.R.string.ok){_, _ -> deleteErrorZip()} + .setNegativeButton(android.R.string.cancel){_, _ ->} + .show() + + private fun deleteErrorZip(){ + val exf = getExternalFilesDir("") + for(i in nullZipDirStr){ + val f = File(exf, i) + if(f.exists()) f.delete() + } + } + + private fun getFloat(oldString: String): Float { + val newString = StringBuffer() + var matcher = Pattern.compile("\\d+.+\\d+").matcher(oldString) + while (matcher.find()) newString.append(matcher.group()) + //Log.d("MyDLL1", newString.toString()) + if(newString.isEmpty()){ + matcher = Pattern.compile("\\d").matcher(oldString) + while (matcher.find()) newString.append(matcher.group()) + } + //Log.d("MyDLL2", newString.toString().toFloat().toString()) + return newString.toString().toFloat() + } + companion object{ var currentDir: File? = null } diff --git a/app/src/main/java/top/fumiama/copymanga/activity/ViewMangaActivity.kt b/app/src/main/java/top/fumiama/copymanga/activity/ViewMangaActivity.kt index 9643f79..b7a8bdb 100644 --- a/app/src/main/java/top/fumiama/copymanga/activity/ViewMangaActivity.kt +++ b/app/src/main/java/top/fumiama/copymanga/activity/ViewMangaActivity.kt @@ -54,7 +54,7 @@ class ViewMangaActivity : Activity() { lateinit var toolsBox: ToolsBox private lateinit var p: PropertiesTools private var mangaZip = zipFile - private val dlZip2View = mangaZip != null + val dlZip2View = mangaZip != null var pageNum = 1 get() { field = getPageNumber() @@ -424,5 +424,8 @@ class ViewMangaActivity : Activity() { var titleText = "Null" var nextChapterUrl: String? = null var previousChapterUrl: String? = null + var zipPosition = 0 + var zipList: Array? = null + var cd: File? = null } } \ No newline at end of file diff --git a/app/src/main/java/top/fumiama/copymanga/handler/DlHandler.kt b/app/src/main/java/top/fumiama/copymanga/handler/DlHandler.kt index 09b0c3e..11dca93 100644 --- a/app/src/main/java/top/fumiama/copymanga/handler/DlHandler.kt +++ b/app/src/main/java/top/fumiama/copymanga/handler/DlHandler.kt @@ -2,6 +2,7 @@ package top.fumiama.copymanga.handler import android.annotation.SuppressLint import android.os.Handler +import android.os.Looper import android.os.Message import android.widget.Toast import android.widget.ToggleButton @@ -11,9 +12,10 @@ import top.fumiama.copymanga.activity.DlActivity import top.fumiama.copymanga.tool.MangaDlTools.Companion.wmdlt import java.lang.ref.WeakReference -class DlHandler(activity: DlActivity) : Handler() { +class DlHandler(activity: DlActivity, looper: Looper) : Handler(looper) { private val da = WeakReference(activity) - private val d = da.get() + private val d + get() = da.get() @ExperimentalStdlibApi @SuppressLint("SetTextI18n") @@ -26,31 +28,31 @@ class DlHandler(activity: DlActivity) : Handler() { d?.tbtnlist?.get(msg.arg1)?.isChecked = false d?.updateProgressBar() if (d?.haveDlStarted == false) { - d.dldChapter = 0 - d.checkedChapter = 0 + d?.dldChapter = 0 + d?.checkedChapter = 0 this.postDelayed({ - d.setProgress2(0, 233) - d.tdwn?.text = "0/0" + d?.setProgress2(0, 233) + d?.tdwn?.text = "0/0" }, 400) } } -1 -> { d?.tbtnlist?.get(msg.arg1)?.setBackgroundResource(R.drawable.rndbg_error) d!!.dldChapter-- - Toast.makeText(d, "下载${d.tbtnlist[msg.arg1].textOn}失败", Toast.LENGTH_SHORT).show() - d.updateProgressBar() + Toast.makeText(d, "下载${d?.tbtnlist?.get(msg.arg1)?.textOn}失败", Toast.LENGTH_SHORT).show() + d?.updateProgressBar() } 4 -> { d?.pdwn?.progress = 0 val selectDownloaded = d?.multiSelect?:false if (d?.haveSElectAll == true) { - for (i in d.tbtnlist.listIterator()) { + d?.tbtnlist?.listIterator()?.forEach { i -> if(i.freezesText) i.setBackgroundResource(R.drawable.rndbg_checked) else i.setBackgroundResource(R.drawable.toggle_button) i.isChecked = false } - d.haveSElectAll = false - d.checkedChapter = 0 - d.dldChapter = 0 + d?.haveSElectAll = false + d?.checkedChapter = 0 + d?.dldChapter = 0 } else { d?.let { val checkBtn = { i: ToggleButton, it: DlActivity -> @@ -79,8 +81,8 @@ class DlHandler(activity: DlActivity) : Handler() { } 6 -> d?.tdwn?.text = "${d?.dldChapter}/${d?.checkedChapter}" 7 -> d?.deleteChapters() - 8 -> d?.cdwn?.setCardBackgroundColor(d.resources.getColor(R.color.colorBlue)) - 9 -> d?.cdwn?.setCardBackgroundColor(d.resources.getColor(R.color.colorRed)) + 8 -> d?.resources?.getColor(R.color.colorBlue)?.let { d?.cdwn?.setCardBackgroundColor(it) } + 9 -> d?.resources?.getColor(R.color.colorRed)?.let { d?.cdwn?.setCardBackgroundColor(it) } 10 -> Toast.makeText(d, "下载${d?.tbtnlist?.get(msg.arg1)?.textOn}的第${msg.arg2}页失败,尝试重新下载...", Toast.LENGTH_SHORT).show() } } diff --git a/app/src/main/java/top/fumiama/copymanga/handler/DlLHandler.kt b/app/src/main/java/top/fumiama/copymanga/handler/DlLHandler.kt new file mode 100644 index 0000000..34f0ded --- /dev/null +++ b/app/src/main/java/top/fumiama/copymanga/handler/DlLHandler.kt @@ -0,0 +1,27 @@ +package top.fumiama.copymanga.handler + +import android.os.Handler +import android.os.Looper +import android.os.Message +import top.fumiama.copymanga.activity.DlListActivity +import java.io.File +import java.lang.ref.WeakReference + + +class DlLHandler(looper: Looper, activity: DlListActivity): Handler(looper) { + private val dll = WeakReference(activity) + override fun handleMessage(msg: Message) { + super.handleMessage(msg) + when(msg.what){ + 1 -> load { dll.get()?.checkDir(msg.obj as File) } + 2 -> load { dll.get()?.rmrf(msg.obj as File) } + 3 -> load { dll.get()?.scanFile(msg.obj as File) } + } + } + + private fun load(func:()->Unit){ + dll.get()?.showLoading() + func() + dll.get()?.hideLoading() + } +} \ No newline at end of file diff --git a/app/src/main/java/top/fumiama/copymanga/tool/PagesManager.kt b/app/src/main/java/top/fumiama/copymanga/tool/PagesManager.kt index 75b682c..bc591b7 100644 --- a/app/src/main/java/top/fumiama/copymanga/tool/PagesManager.kt +++ b/app/src/main/java/top/fumiama/copymanga/tool/PagesManager.kt @@ -1,9 +1,11 @@ package top.fumiama.copymanga.tool +import android.content.Intent import android.widget.Toast import kotlinx.android.synthetic.main.activity_main.* import top.fumiama.copymanga.activity.MainActivity.Companion.wm import top.fumiama.copymanga.activity.ViewMangaActivity +import java.io.File import java.lang.ref.WeakReference class PagesManager(w: WeakReference) { @@ -11,18 +13,15 @@ class PagesManager(w: WeakReference) { private var isEndL = false private var isEndR = false @ExperimentalStdlibApi - fun toPreviousPage(){ - toPage(v?.r2l==true) - } + fun toPreviousPage(){ toPage(v?.r2l==true) } @ExperimentalStdlibApi - fun toNextPage(){ - toPage(v?.r2l!=true) - } + fun toNextPage(){ toPage(v?.r2l!=true) } private fun judgePrevious() = v?.pageNum?:0 > 1 private fun judgeNext() = v?.pageNum?:0 < v?.count?:0 @ExperimentalStdlibApi private fun toPage(goNext:Boolean){ val chapterUrl = if(goNext) ViewMangaActivity.nextChapterUrl else ViewMangaActivity.previousChapterUrl + val newZipPosition = ViewMangaActivity.zipPosition + (if(goNext) 1 else -1) val hint = if(goNext) "下" else "上" if (v?.clicked == false) { if (if(goNext)judgeNext() else judgePrevious()) { @@ -38,16 +37,18 @@ class PagesManager(w: WeakReference) { wm?.get()?.w?.loadUrl("javascript:invoke.clickClass(\"comicControlBottomTopClick\",${if(goNext)1 else 0});") v.tt.canDo = false v.finish() - } else { - Toast.makeText( - v.applicationContext, - "再次按下加载${hint}一章", - Toast.LENGTH_SHORT - ).show() - if(goNext) isEndR = true - else isEndL = true - } - } else Toast.makeText( + } else doubleTapToast(hint, goNext) + } else if(v.dlZip2View && newZipPosition >= 0 && newZipPosition < ViewMangaActivity.zipList?.size?:0){ + if (if(goNext)isEndR else isEndL){ + ViewMangaActivity.zipPosition = newZipPosition + ViewMangaActivity.titleText = ViewMangaActivity.zipList?.get(newZipPosition) ?: "null" + ViewMangaActivity.zipFile = ViewMangaActivity.zipList?.let { File(ViewMangaActivity.cd, ViewMangaActivity.titleText) } + v.startActivity(Intent(v, ViewMangaActivity::class.java)) + v.tt.canDo = false + v.finish() + }else doubleTapToast(hint, goNext) + } + else Toast.makeText( v.applicationContext, "已经到头了~", Toast.LENGTH_SHORT @@ -57,4 +58,13 @@ class PagesManager(w: WeakReference) { fun manageInfo(){ if (v?.clicked == false) v.showObjs() else v?.hideObjs() } + private fun doubleTapToast(hint: String, goNext: Boolean){ + Toast.makeText( + v?.applicationContext, + "再次按下加载${hint}一章", + Toast.LENGTH_SHORT + ).show() + if(goNext) isEndR = true + else isEndL = true + } } \ No newline at end of file diff --git a/app/src/main/java/top/fumiama/copymanga/tool/ToolsBox.kt b/app/src/main/java/top/fumiama/copymanga/tool/ToolsBox.kt index d2aa189..928ba32 100644 --- a/app/src/main/java/top/fumiama/copymanga/tool/ToolsBox.kt +++ b/app/src/main/java/top/fumiama/copymanga/tool/ToolsBox.kt @@ -5,10 +5,12 @@ import android.app.AlertDialog import android.content.Context import android.net.ConnectivityManager import android.net.NetworkCapabilities +import android.util.Log import android.widget.Toast import top.fumiama.copymanga.R import java.lang.ref.WeakReference import java.util.* +import java.util.regex.Pattern import kotlin.math.sqrt class ToolsBox(w: WeakReference) { diff --git a/app/src/main/res/layout/dialog_loading.xml b/app/src/main/res/layout/dialog_loading.xml new file mode 100644 index 0000000..f6a9f41 --- /dev/null +++ b/app/src/main/res/layout/dialog_loading.xml @@ -0,0 +1,28 @@ + + + + + + + \ No newline at end of file