1
0
mirror of https://github.com/fumiama/copymanga.git synced 2026-06-12 11:40:27 +08:00
修复
1. 最大只能阅读50页
优化
1. 卡顿
This commit is contained in:
源文雨
2025-06-21 00:49:24 +09:00
parent eeb3735103
commit dbb0b9d2b3
25 changed files with 488 additions and 319 deletions

2
.idea/.name generated
View File

@@ -1 +1 @@
拷贝漫画 拷贝漫画Lite

10
.idea/deploymentTargetSelector.xml generated Normal file
View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetSelector">
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
</selectionStates>
</component>
</project>

9
.idea/dictionaries/fumiama.xml generated Normal file
View File

@@ -0,0 +1,9 @@
<component name="ProjectDictionaryState">
<dictionary name="fumiama">
<words>
<w>copymanga</w>
<w>lowpan</w>
<w>volturn</w>
</words>
</dictionary>
</component>

1
.idea/misc.xml generated
View File

@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="DesignSurface"> <component name="DesignSurface">
<option name="filePathToZoomLevelMap"> <option name="filePathToZoomLevelMap">

2
.idea/vcs.xml generated
View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="VcsDirectoryMappings"> <component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" /> <mapping directory="" vcs="Git" />
</component> </component>
</project> </project>

View File

@@ -1,6 +1,5 @@
# copymanga 拷贝漫画 # copymanga Lite
拷贝漫画的第三方APP优化阅读/下载体验 拷贝漫画的第三方APP优化阅读/下载体验
近日官方取消了网页端,本项目已不再可用,因此被存档
# 说明 # 说明
本应用基于官方的`HLML5`手机版本网页端,作者不对其中呈现的任何内容负责 本应用基于官方的`HLML5`手机版本网页端,作者不对其中呈现的任何内容负责
# 功能 # 功能

View File

@@ -12,8 +12,8 @@ android {
minSdkVersion 23 minSdkVersion 23
//noinspection OldTargetApi //noinspection OldTargetApi
targetSdkVersion 34 targetSdkVersion 34
versionCode 13 versionCode 14
versionName '1.5.0' versionName '1.5.1'
resConfigs "zh", "zh-rCN" resConfigs "zh", "zh-rCN"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -96,7 +96,7 @@ if (propFile.canRead()){
dependencies { dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"]) implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.8.0' implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.constraintlayout:constraintlayout:2.2.1' implementation 'androidx.constraintlayout:constraintlayout:2.2.1'
implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.viewpager2:viewpager2:1.1.0' implementation 'androidx.viewpager2:viewpager2:1.1.0'

View File

@@ -1,40 +1,62 @@
javascript: javascript:
if (typeof (loaded) == "undefined"){ if (typeof (loaded) == "undefined") {
var loaded = true; var loaded = true;
function scanChapters(chapter) { function scanChapters(chapter) {
var chapterList = chapter.getElementsByClassName("tab-pane fade show active")[0].getElementsByTagName("ul")[0].getElementsByTagName("a"); var chapterList = chapter.getElementsByClassName("tab-pane fade show active")[0].getElementsByTagName("ul")[0].getElementsByTagName("a");
var chapterArr = Array(); var chapterArr = Array();
for(var i = 0; i < chapterList.length; i++){ for (var i = 0; i < chapterList.length; i++) {
chapterArr.push(JSON.constructor()); chapterArr.push(JSON.constructor());
chapterArr[i]["name"] = chapterList[i].title; chapterArr[i]["name"] = chapterList[i].title;
chapterArr[i]["url"] = chapterList[i].href; chapterArr[i]["url"] = chapterList[i].href;
} }
return chapterArr; return chapterArr;
} }
function smoothLoadChapter(speed, interval) {
let prevHeight = document.body.scrollHeight;
let lastTime = 0;
let ticking = false;
function requestTick() {
if (!ticking) {
ticking = true;
requestAnimationFrame(step);
}
}
function step(timestamp) {
if (!lastTime) lastTime = timestamp;
const elapsed = timestamp - lastTime;
if (elapsed >= interval) {
const index = document.getElementsByClassName("comicIndex")[0].innerText;
const count = document.getElementsByClassName("comicCount")[0].innerText;
GM.setLoadingDialogProgress(index, count);
window.scrollBy(0, speed);
lastTime = timestamp;
const currentHeight = document.body.scrollHeight;
if (Math.round(window.innerHeight+window.scrollY+0.5) >= currentHeight) { /*避免小数不符无法触发*/
if (currentHeight === prevHeight) {
var images = document.getElementsByClassName("container-fluid comicContent")[0].getElementsByTagName("li");
var nextChapter = document.getElementsByClassName("comicContent-next")[0].getElementsByTagName("a")[0].href;
var prevChapter = document.getElementsByClassName("comicContent-prev")[1].getElementsByTagName("a")[0].href;
if(nextChapter == location.href) nextChapter = "null";
if(prevChapter == location.href) prevChapter = "null";
var result = document.title.split(" - ")[1] + " " + location.href.substring(location.href.lastIndexOf("/")+1) + "\n" + nextChapter + "\n" + prevChapter;
for(var i = 0; i < images.length; i++) result += "\n" + images[i].getElementsByTagName("img")[0].dataset.src;
GM.setLoadingDialog(false);
GM.loadChapter(result);
return;
}
prevHeight = currentHeight;
}
}
ticking = false;
requestTick();
}
requestTick();
}
function modify() { function modify() {
var url = location.href; var url = location.href;
if(url.indexOf("/chapter/")>0){ if(url.indexOf("/chapter/") > 0){
window.scroll({ top: document.body.scrollHeight, left: 0, behavior: 'smooth' }); GM.setLoadingDialog(true);
setTimeout(() => { smoothLoadChapter(320, 16);
window.scroll({ top: document.body.scrollHeight, left: 0, behavior: 'smooth' });
setTimeout(() => {
window.scroll({ top: document.body.scrollHeight, left: 0, behavior: 'smooth' });
setTimeout(() => {
window.scroll({ top: document.body.scrollHeight, left: 0, behavior: 'smooth' });
setTimeout(() => {
window.scroll({ top: document.body.scrollHeight, left: 0, behavior: 'smooth' });
var imglist = document.getElementsByClassName("container-fluid comicContent")[0].getElementsByTagName("li");
var nextChapter = document.getElementsByClassName("comicContent-next")[0].getElementsByTagName("a")[0].href;
var prevChapter = document.getElementsByClassName("comicContent-prev")[1].getElementsByTagName("a")[0].href;
if(nextChapter == location.href) nextChapter = "null";
if(prevChapter == location.href) prevChapter = "null";
var liststr = document.title.split(" - ")[1] + " " + location.href.substring(location.href.lastIndexOf("/")+1) + "\n" + nextChapter + "\n" + prevChapter;
for(var i = 0; i < imglist.length; i++) liststr += "\n" + imglist[i].getElementsByTagName("img")[0].dataset.src;
GM.loadChapter(liststr);
}, 500);
}, 500);
}, 500);
}, 500);
} else { } else {
var json = Array(); var json = Array();
var chapters = document.getElementsByClassName("upLoop")[0].children; var chapters = document.getElementsByClassName("upLoop")[0].children;
@@ -55,4 +77,4 @@ if (typeof (loaded) == "undefined"){
} }
} }
modify(); modify();
}else modify(); } else modify();

View File

@@ -2,7 +2,6 @@ package top.fumiama.copymangaweb.activity
import android.animation.ObjectAnimator import android.animation.ObjectAnimator
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.os.Looper import android.os.Looper
@@ -20,21 +19,20 @@ import kotlinx.android.synthetic.main.widget_downloadbar.*
import kotlinx.android.synthetic.main.widget_titlebar.* import kotlinx.android.synthetic.main.widget_titlebar.*
import top.fumiama.copymangaweb.R import top.fumiama.copymangaweb.R
import top.fumiama.copymangaweb.activity.MainActivity.Companion.mh import top.fumiama.copymangaweb.activity.MainActivity.Companion.mh
import top.fumiama.copymangaweb.activity.template.ToolsBoxActivity
import top.fumiama.copymangaweb.data.ComicStructure import top.fumiama.copymangaweb.data.ComicStructure
import top.fumiama.copymangaweb.databinding.ActivityDlBinding import top.fumiama.copymangaweb.databinding.ActivityDlBinding
import top.fumiama.copymangaweb.handler.DlHandler import top.fumiama.copymangaweb.handler.DlHandler
import top.fumiama.copymangaweb.tool.MangaDlTools import top.fumiama.copymangaweb.tool.MangaDlTools
import top.fumiama.copymangaweb.tool.MangaDlTools.Companion.wmdlt import top.fumiama.copymangaweb.tool.MangaDlTools.Companion.wmdlt
import top.fumiama.copymangaweb.tool.ToolsBox
import top.fumiama.copymangaweb.view.ChapterToggleButton import top.fumiama.copymangaweb.view.ChapterToggleButton
import top.fumiama.copymangaweb.view.LazyScrollView import top.fumiama.copymangaweb.view.LazyScrollView
import top.fumiama.copymangaweb.web.JSHidden import top.fumiama.copymangaweb.web.JSHidden
import top.fumiama.copymangaweb.web.WebChromeClient import top.fumiama.copymangaweb.web.WebChromeClient
import java.io.File import java.io.File
import java.lang.Thread.sleep import java.lang.Thread.sleep
import java.lang.ref.WeakReference
class DlActivity : Activity() { class DlActivity : ToolsBoxActivity() {
private var tbtncnt = 0 private var tbtncnt = 0
private var isNewTitle = false private var isNewTitle = false
var haveSElectAll = false var haveSElectAll = false
@@ -42,13 +40,12 @@ class DlActivity : Activity() {
var dldChapter = 0 var dldChapter = 0
var haveDlStarted = false var haveDlStarted = false
private var btnNumPerRow = 4 private var btnNumPerRow = 4
private lateinit var ltbtn: View private lateinit var toggleButtonLine: View
var tbtnlist: Array<ChapterToggleButton> = arrayOf() var tbtnlist: Array<ChapterToggleButton> = arrayOf()
private val handler = DlHandler(this, Looper.myLooper()!!) private val handler = DlHandler(this, Looper.myLooper()!!)
private var btnw = 0 private var btnw = 0
private var cdwnWidth = 0 private var cdwnWidth = 0
private var canDl = false private var canDl = false
private lateinit var toolsBox: ToolsBox
private lateinit var mangaDlTools: MangaDlTools private lateinit var mangaDlTools: MangaDlTools
var multiSelect = false var multiSelect = false
@@ -59,16 +56,19 @@ class DlActivity : Activity() {
setContentView(binding.root) setContentView(binding.root)
mh?.saveUrlsOnly = true mh?.saveUrlsOnly = true
mangaDlTools = MangaDlTools(this) mangaDlTools = MangaDlTools(this)
dwh.settings.userAgentString = getString(R.string.pc_ua) dwh.apply { post {
dwh.webChromeClient = WebChromeClient() settings.userAgentString = getString(R.string.pc_ua)
dwh.setWebViewClient("h.js") webChromeClient = WebChromeClient()
dwh.loadJSInterface(JSHidden()) setWebViewClient("h.js")
loadJSInterface(JSHidden())
} }
handler.sendEmptyMessage(-2) //setLayouts handler.sendEmptyMessage(-2) //setLayouts
} }
override fun onDestroy() { override fun onDestroy() {
mh?.saveUrlsOnly = false mh?.saveUrlsOnly = false
wmdlt?.get()?.exit = true wmdlt?.get()?.exit = true
handler.removeCallbacksAndMessages(null)
super.onDestroy() super.onDestroy()
} }
@@ -112,47 +112,48 @@ class DlActivity : Activity() {
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
fun setLayouts() { fun setLayouts() {
ttitle.text = comicName ttitle.apply { post { text = comicName } }
toolsBox = ToolsBox(WeakReference(this))
val widthData = toolsBox.calcWidthFromDp(8, 64) val widthData = toolsBox.calcWidthFromDp(8, 64)
btnNumPerRow = widthData[0] btnNumPerRow = widthData[0]
btnw = widthData[1] btnw = widthData[1]
csdwn.viewTreeObserver.addOnGlobalLayoutListener(object : csdwn.apply { post { viewTreeObserver.addOnGlobalLayoutListener(object :
ViewTreeObserver.OnGlobalLayoutListener { ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() { override fun onGlobalLayout() {
cdwnWidth = csdwn.width cdwnWidth = csdwn.width
csdwn.viewTreeObserver.removeOnGlobalLayoutListener(this) viewTreeObserver.removeOnGlobalLayoutListener(this)
} }
}) }) } }
dllazys.onScrollListener = object : LazyScrollView.OnScrollListener { dllazys.onScrollListener = object : LazyScrollView.OnScrollListener {
override fun onBottom() {} override fun onBottom() {}
override fun onScroll() { if (csdwn.translationX == 0f) hideDlCard() } override fun onScroll() { if (csdwn.translationX == 0f) hideDlCard() }
override fun onTop() {} override fun onTop() {}
} }
cdwn.setOnClickListener { cdwn.let { it.post {
if (csdwn.translationX != 0f) showDlCard() it.setOnClickListener {
else if (checkedChapter == 0) hideDlCard() if (csdwn.translationX != 0f) showDlCard()
else { else if (checkedChapter == 0) hideDlCard()
pdwn.progress = 0
if (canDl || checkedChapter == 0) canDl = false
else { else {
haveDlStarted = true pdwn.progress = 0
canDl = true if (canDl || checkedChapter == 0) canDl = false
handler.sendEmptyMessage(9) //set dl card color to red else {
Toast.makeText(this, "请耐心等待加载...", Toast.LENGTH_SHORT).show() haveDlStarted = true
Thread { canDl = true
fillChapters() handler.sendEmptyMessage(9) //set dl card color to red
dlThread { downloadChapterPages(it) } Toast.makeText(this@DlActivity, "请耐心等待加载...", Toast.LENGTH_SHORT).show()
}.start() Thread {
fillChapters()
dlThread { downloadChapterPages(it) }
}.start()
}
} }
} }
} it.setOnLongClickListener {
cdwn.setOnLongClickListener { handler.sendEmptyMessage(4)
handler.sendEmptyMessage(4) return@setOnLongClickListener true
return@setOnLongClickListener true }
} } }
isearch.setOnClickListener { showMultiSelectInfo() } isearch.apply { post { setOnClickListener { showMultiSelectInfo() } } }
analyzeStructure() Thread{ analyzeStructure() }.start()
} }
private fun showMultiSelectInfo() { private fun showMultiSelectInfo() {
@@ -166,22 +167,24 @@ class DlActivity : Activity() {
for (group in it) { for (group in it) {
val tc = layoutInflater.inflate(R.layout.line_caption, ldwn, false) val tc = layoutInflater.inflate(R.layout.line_caption, ldwn, false)
tc.tcptn.text = group.name tc.tcptn.text = group.name
ldwn.addView( ldwn.apply { post {
tc, addView(
ViewGroup.LayoutParams( tc,
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
) )
) addView(
ldwn.addView( layoutInflater.inflate(R.layout.div_h, ldwn, false),
layoutInflater.inflate(R.layout.div_h, ldwn, false), ViewGroup.LayoutParams(
ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT
ViewGroup.LayoutParams.WRAP_CONTENT )
) )
) } }
isNewTitle = true isNewTitle = true
for (chapter in group.chapters) addTbtn(chapter.name, chapter.url, group.name) for (chapter in group.chapters) addToggleButton(chapter.name, chapter.url, group.name)
} }
} }
val mangaHome = File("${getExternalFilesDir("")}/$comicName") val mangaHome = File("${getExternalFilesDir("")}/$comicName")
@@ -222,14 +225,17 @@ class DlActivity : Activity() {
} }
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
fun addTbtn(title: String, url: String, caption: String) { fun addToggleButton(title: String, url: String, caption: String) {
if ((tbtncnt % btnNumPerRow == 0) || isNewTitle) { if ((tbtncnt % btnNumPerRow == 0) || isNewTitle) {
ltbtn = layoutInflater.inflate(R.layout.line_horizonal, ldwn, false) toggleButtonLine = layoutInflater.inflate(R.layout.line_horizonal, ldwn, false)
ldwn.addView(ltbtn) ldwn.apply {
val t = toggleButtonLine
post { addView(t) }
}
tbtncnt = 0 tbtncnt = 0
isNewTitle = false isNewTitle = false
} }
val tbv = layoutInflater.inflate(R.layout.button_tbutton, ltbtn.ltbtn, false) val tbv = layoutInflater.inflate(R.layout.button_tbutton, toggleButtonLine.ltbtn, false)
tbv.tbtn.index = tbtnlist.size tbv.tbtn.index = tbtnlist.size
tbtnlist += tbv.tbtn tbtnlist += tbv.tbtn
tbv.tbtn.url = url tbv.tbtn.url = url
@@ -241,28 +247,34 @@ class DlActivity : Activity() {
tbv.tbtn.text = title tbv.tbtn.text = title
tbv.tbtn.hint = caption tbv.tbtn.hint = caption
tbv.tbtn.layoutParams.width = btnw tbv.tbtn.layoutParams.width = btnw
val zipf = File("${getExternalFilesDir("")}/$comicName/$caption/$title.zip") val zipFile = File("${getExternalFilesDir("")}/$comicName/$caption/$title.zip")
if (zipf.exists()) { if (zipFile.exists()) {
tbv.tbtn.setBackgroundResource(R.drawable.rndbg_checked) tbv.tbtn.setBackgroundResource(R.drawable.rndbg_checked)
tbv.tbtn.isChecked = false tbv.tbtn.isChecked = false
tbv.tbtn.freezesText = true tbv.tbtn.freezesText = true
} }
ltbtn.ltbtn.addView(tbv) toggleButtonLine.apply { post {
ltbtn.invalidate() ltbtn.addView(tbv)
tbv.tbtn.setOnClickListener { invalidate()
val normalAct = (multiSelect && zipf.exists()) || !zipf.exists() } }
if (zipf.exists() && !it.tbtn.isChecked) it.tbtn.setBackgroundResource(R.drawable.rndbg_checked) tbv.tbtn.setOnClickListener { v ->
else if(normalAct) it.tbtn.setBackgroundResource(R.drawable.toggle_button) val normalAct = (multiSelect && zipFile.exists()) || !zipFile.exists()
if(normalAct){ if (zipFile.exists() && !v.tbtn.isChecked) v.tbtn.apply { post { setBackgroundResource(R.drawable.rndbg_checked) } }
if (it.tbtn.isChecked) tdwn.text = "$dldChapter/${++checkedChapter}" else if(normalAct) v.tbtn.apply { post { setBackgroundResource(R.drawable.toggle_button) } }
else tdwn.text = "$dldChapter/${--checkedChapter}" if (normalAct) {
}else if(it.tbtn.isChecked){ if (v.tbtn.isChecked) tdwn.apply { post { text = "$dldChapter/${++checkedChapter}" } }
it.tbtn.isChecked = false else tdwn.apply { post { text = "$dldChapter/${--checkedChapter}" } }
zipPosition?.let { callVM(title, zipf, it) } } else if(v.tbtn.isChecked) {
v.tbtn.apply { post {
isChecked = false
zipPosition?.let { Thread {
callVM(title, zipFile, it)
}.start() }
} }
} }
} }
tbv.tbtn.setOnLongClickListener { tbv.tbtn.setOnLongClickListener {
if (zipf.exists()) { if (zipFile.exists()) {
toolsBox.buildInfo("确认删除这些章节?", toolsBox.buildInfo("确认删除这些章节?",
"该操作将不可撤销", "该操作将不可撤销",
"确定", "确定",
@@ -270,8 +282,8 @@ class DlActivity : Activity() {
"取消", "取消",
{ {
if (checkedChapter == 0) { if (checkedChapter == 0) {
it.tbtn.isChecked = true it.tbtn.apply { post { isChecked = true } }
tdwn.text = "$dldChapter/${++checkedChapter}" tdwn.apply { post { text = "$dldChapter/${++checkedChapter}" } }
} }
handler.sendEmptyMessage(7) handler.sendEmptyMessage(7)
}) })
@@ -293,24 +305,26 @@ class DlActivity : Activity() {
handler.sendEmptyMessage(6) handler.sendEmptyMessage(6)
} }
private fun callVM(titleText: String, zipFile: File, zipPosition:Int){ private fun callVM(titleText: String, zipFile: File, zipPosition:Int) {
ViewMangaActivity.titleText = titleText ViewMangaActivity.titleText = titleText
ViewMangaActivity.zipFile = zipFile ViewMangaActivity.zipFile = zipFile
//ViewMangaActivity.zipList = zipArrayList //ViewMangaActivity.zipList = zipArrayList
ViewMangaActivity.zipPosition = zipPosition ViewMangaActivity.zipPosition = zipPosition
ViewMangaActivity.cd = zipFile.parentFile ViewMangaActivity.cd = zipFile.parentFile
startActivity(Intent(this, ViewMangaActivity::class.java)) startActivity(Intent(this@DlActivity, ViewMangaActivity::class.java))
} }
private fun deleteChapter(f: File, v: ToggleButton) { private fun deleteChapter(f: File, v: ToggleButton) {
f.delete() f.delete()
v.setBackgroundResource(R.drawable.toggle_button) v.apply { post{
v.isChecked = false setBackgroundResource(R.drawable.toggle_button)
isChecked = false
} }
} }
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
fun updateProgressBar() { fun updateProgressBar() {
tdwn.text = "${++dldChapter}/$checkedChapter" tdwn.apply { post { text = "${++dldChapter}/$checkedChapter" } }
setProgress2(dldChapter * 100 / checkedChapter, 233) setProgress2(dldChapter * 100 / checkedChapter, 233)
} }

View File

@@ -16,7 +16,7 @@ import java.io.File
import java.util.regex.Pattern import java.util.regex.Pattern
import java.util.zip.ZipInputStream import java.util.zip.ZipInputStream
class DlListActivity:Activity() { class DlListActivity: Activity() {
private var nullZipDirStr = emptyArray<String>() private var nullZipDirStr = emptyArray<String>()
private var handler: DlLHandler? = null private var handler: DlLHandler? = null
@@ -29,6 +29,12 @@ class DlListActivity:Activity() {
handler?.obtainMessage(3, currentDir)?.sendToTarget() //call scanFile handler?.obtainMessage(3, currentDir)?.sendToTarget() //call scanFile
} }
override fun onDestroy() {
super.onDestroy()
handler?.removeCallbacksAndMessages(null)
handler = null
}
fun scanFile(cd: File?){ fun scanFile(cd: File?){
val isRoot = cd == getExternalFilesDir("") val isRoot = cd == getExternalFilesDir("")
val jsonFile = File(cd, "info.bin") val jsonFile = File(cd, "info.bin")

View File

@@ -1,7 +1,7 @@
package top.fumiama.copymangaweb.activity package top.fumiama.copymangaweb.activity
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity import android.app.Dialog
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
@@ -9,48 +9,59 @@ import android.os.Looper
import android.view.View import android.view.View
import android.webkit.ValueCallback import android.webkit.ValueCallback
import android.webkit.WebView import android.webkit.WebView
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.fab
import kotlinx.android.synthetic.main.activity_main.w
import kotlinx.android.synthetic.main.activity_main.wh
import top.fumiama.copymangaweb.R import top.fumiama.copymangaweb.R
import top.fumiama.copymangaweb.activity.template.ToolsBoxActivity
import top.fumiama.copymangaweb.databinding.ActivityMainBinding import top.fumiama.copymangaweb.databinding.ActivityMainBinding
import top.fumiama.copymangaweb.handler.MainHandler import top.fumiama.copymangaweb.handler.MainHandler
import top.fumiama.copymangaweb.tool.SetDraggable import top.fumiama.copymangaweb.tool.SetDraggable
import top.fumiama.copymangaweb.tool.ToolsBox
import top.fumiama.copymangaweb.web.JS import top.fumiama.copymangaweb.web.JS
import top.fumiama.copymangaweb.web.JSHidden import top.fumiama.copymangaweb.web.JSHidden
import top.fumiama.copymangaweb.web.WebChromeClient import top.fumiama.copymangaweb.web.WebChromeClient
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
class MainActivity: Activity() { class MainActivity: ToolsBoxActivity() {
var uploadMessageAboveL: ValueCallback<Array<Uri>>? = null var uploadMessageAboveL: ValueCallback<Array<Uri>>? = null
private var toolsBox: ToolsBox? = null var dialog: Dialog? = null
@SuppressLint("JavascriptInterface") @SuppressLint("JavascriptInterface")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
val binding = ActivityMainBinding.inflate(layoutInflater) val binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
dialog = Dialog(this)
dialog?.setContentView(R.layout.dialog_unzipping)
wm = WeakReference(this) wm = WeakReference(this)
mh = MainHandler(Looper.myLooper()!!) mh = MainHandler(Looper.myLooper()!!)
toolsBox = ToolsBox(wm as WeakReference<Any>) toolsBox.netInfo.let {
toolsBox?.netinfo?.let {
if(it == "无网络" || it == "错误") { if(it == "无网络" || it == "错误") {
Thread{mh?.sendEmptyMessage(6)}.start() mh?.sendEmptyMessage(MainHandler.SET_FAB_TO_DOWNLOAD_LIST)
}else{ return@let
WebView.setWebContentsDebuggingEnabled(true)
w.setWebViewClient("i.js")
w.webChromeClient = WebChromeClient()
w.loadJSInterface(JS())
w.loadUrl(getString(R.string.web_home))
wh.settings.userAgentString = getString(R.string.pc_ua)
wh.webChromeClient = WebChromeClient()
wh.setWebViewClient("h.js")
wh.loadJSInterface(JSHidden())
} }
WebView.setWebContentsDebuggingEnabled(true)
w.apply { post {
setWebViewClient("i.js")
webChromeClient = WebChromeClient()
loadJSInterface(JS())
loadUrl(getString(R.string.web_home))
} }
wh.apply { post {
settings.userAgentString = getString(R.string.pc_ua)
webChromeClient = WebChromeClient()
setWebViewClient("h.js")
loadJSInterface(JSHidden())
} }
} }
SetDraggable().with(this).onto(fab) SetDraggable().with(this).onto(fab)
} }
@Deprecated("Deprecated in Java")
override fun onBackPressed() { override fun onBackPressed() {
if(w.canGoBack()) w.goBack() if(w.canGoBack()) w.goBack()
else super.onBackPressed() else super.onBackPressed()
@@ -59,34 +70,27 @@ class MainActivity: Activity() {
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data) super.onActivityResult(requestCode, resultCode, data)
if (requestCode == FILE_CHOOSER_RESULT_CODE) { //处理返回的图片,并进行上传 if (requestCode == FILE_CHOOSER_RESULT_CODE) { //处理返回的图片,并进行上传
if (uploadMessageAboveL == null) return if (uploadMessageAboveL == null || resultCode != RESULT_OK) return
else { data?.let {
if(resultCode == RESULT_OK) { onActivityResultAboveL(requestCode, resultCode, it)
data?.apply {
if(uploadMessageAboveL != null) {
onActivityResultAboveL(requestCode, resultCode, this)
}
}
}
} }
} }
} }
private fun onActivityResultAboveL(requestCode: Int, resultCode: Int, intent: Intent) { private fun onActivityResultAboveL(requestCode: Int, resultCode: Int, intent: Intent) {
if (requestCode != FILE_CHOOSER_RESULT_CODE || uploadMessageAboveL == null) return if (requestCode != FILE_CHOOSER_RESULT_CODE ||
else { uploadMessageAboveL == null ||
if (resultCode == RESULT_OK) { resultCode != RESULT_OK
intent.clipData?.apply { ) return
var results = arrayOf<Uri>() intent.clipData?.let { clipData ->
for(i in 0..itemCount) { var results = arrayOf<Uri>()
val item = getItemAt(i) for (i in 0..clipData.itemCount) {
results += item.uri val item = clipData.getItemAt(i)
} results += item.uri
intent.dataString?.apply { }
uploadMessageAboveL?.onReceiveValue(results) if (intent.dataString != null) {
uploadMessageAboveL = null uploadMessageAboveL?.onReceiveValue(results)
} uploadMessageAboveL = null
}
} }
} }
} }
@@ -100,14 +104,17 @@ class MainActivity: Activity() {
} }
fun openImageChooserActivity() { fun openImageChooserActivity() {
//调用自己的图库 // 调用自己的图库
val i = Intent(Intent.ACTION_GET_CONTENT) startActivityForResult(
i.addCategory(Intent.CATEGORY_OPENABLE) Intent.createChooser(
i.type = "image/*" Intent(Intent.ACTION_GET_CONTENT)
startActivityForResult(Intent.createChooser(i, "Image Chooser"), FILE_CHOOSER_RESULT_CODE) .addCategory(Intent.CATEGORY_OPENABLE)
.setType("image/*"), "Image Chooser"
), FILE_CHOOSER_RESULT_CODE
)
} }
companion object{ companion object {
const val FILE_CHOOSER_RESULT_CODE = 1 const val FILE_CHOOSER_RESULT_CODE = 1
var wm: WeakReference<MainActivity>? = null var wm: WeakReference<MainActivity>? = null
var mh: MainHandler? = null var mh: MainHandler? = null

View File

@@ -2,10 +2,14 @@ package top.fumiama.copymangaweb.activity
import android.animation.ObjectAnimator import android.animation.ObjectAnimator
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity import android.app.Dialog
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.os.* import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.Log import android.util.Log
import android.view.KeyEvent import android.view.KeyEvent
import android.view.LayoutInflater import android.view.LayoutInflater
@@ -16,16 +20,26 @@ import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2 import androidx.viewpager2.widget.ViewPager2
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.w
import kotlinx.android.synthetic.main.activity_viewmanga.* import kotlinx.android.synthetic.main.activity_viewmanga.infcard
import kotlinx.android.synthetic.main.page_imgview.* import kotlinx.android.synthetic.main.activity_viewmanga.oneinfo
import kotlinx.android.synthetic.main.page_imgview.view.* import kotlinx.android.synthetic.main.activity_viewmanga.vone
import kotlinx.android.synthetic.main.widget_infodrawer.* import kotlinx.android.synthetic.main.activity_viewmanga.vp
import kotlinx.android.synthetic.main.widget_infodrawer.view.* import kotlinx.android.synthetic.main.page_imgview.onei
import kotlinx.android.synthetic.main.widget_titlebar.* import kotlinx.android.synthetic.main.page_imgview.view.onei
import kotlinx.android.synthetic.main.widget_viewmangainfo.* import kotlinx.android.synthetic.main.widget_infodrawer.idtblr
import kotlinx.android.synthetic.main.widget_infodrawer.idtbvh
import kotlinx.android.synthetic.main.widget_infodrawer.idtbvolturn
import kotlinx.android.synthetic.main.widget_infodrawer.idtbvp
import kotlinx.android.synthetic.main.widget_infodrawer.idtime
import kotlinx.android.synthetic.main.widget_infodrawer.view.idc
import kotlinx.android.synthetic.main.widget_titlebar.isearch
import kotlinx.android.synthetic.main.widget_titlebar.ttitle
import kotlinx.android.synthetic.main.widget_viewmangainfo.infseek
import kotlinx.android.synthetic.main.widget_viewmangainfo.inftxtprogress
import top.fumiama.copymangaweb.R import top.fumiama.copymangaweb.R
import top.fumiama.copymangaweb.activity.MainActivity.Companion.wm import top.fumiama.copymangaweb.activity.MainActivity.Companion.wm
import top.fumiama.copymangaweb.activity.template.ToolsBoxActivity
import top.fumiama.copymangaweb.databinding.ActivityViewmangaBinding import top.fumiama.copymangaweb.databinding.ActivityViewmangaBinding
import top.fumiama.copymangaweb.handler.TimeThread import top.fumiama.copymangaweb.handler.TimeThread
import top.fumiama.copymangaweb.tool.PropertiesTools import top.fumiama.copymangaweb.tool.PropertiesTools
@@ -33,20 +47,20 @@ import top.fumiama.copymangaweb.tool.ToolsBox
import java.io.File import java.io.File
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.Date
import java.util.zip.ZipFile import java.util.zip.ZipFile
import java.util.zip.ZipInputStream import java.util.zip.ZipInputStream
class ViewMangaActivity : Activity() { class ViewMangaActivity : ToolsBoxActivity() {
lateinit var handler: Handler lateinit var handler: Handler
lateinit var tt: TimeThread lateinit var tt: TimeThread
lateinit var toolsBox: ToolsBox
var count = 0 var count = 0
var clicked = false var clicked = false
var r2l = true var r2l = true
var infoDrawerDelta = 0f var infoDrawerDelta = 0f
private var dialog: Dialog? = null
private lateinit var p: PropertiesTools private lateinit var p: PropertiesTools
private var isInSeek = false private var isInSeek = false
private var currentItem = 0 private var currentItem = 0
@@ -78,7 +92,6 @@ class ViewMangaActivity : Activity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
val binding = ActivityViewmangaBinding.inflate(layoutInflater) val binding = ActivityViewmangaBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
toolsBox = ToolsBox(WeakReference(this))
va = WeakReference(this) va = WeakReference(this)
p = PropertiesTools(File("$filesDir/settings.properties")) p = PropertiesTools(File("$filesDir/settings.properties"))
r2l = p["r2l"] == "true" r2l = p["r2l"] == "true"
@@ -87,30 +100,39 @@ class ViewMangaActivity : Activity() {
tt = TimeThread(handler, 22) tt = TimeThread(handler, 22)
tt.canDo = true tt.canDo = true
tt.start() tt.start()
ttitle.text = titleText dialog = Dialog(this)
dialog?.apply {
setContentView(R.layout.dialog_unzipping)
show()
}
ttitle.apply { post { text = titleText } }
Log.d("MyVM", "dlZip2View: $dlZip2View, mangaZip: $mangaZip") Log.d("MyVM", "dlZip2View: $dlZip2View, mangaZip: $mangaZip")
if(dlZip2View && mangaZip?.exists() != true) toolsBox.toastError("已经到头了~") if(dlZip2View && mangaZip?.exists() != true) toolsBox.toastError("已经到头了~")
else { else Thread {
try { try {
count = if (dlZip2View) countZipItems() else imgUrls.size count = if (dlZip2View) countZipItems() else imgUrls.size
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
toolsBox.toastError("分析图片url错误") runOnUiThread { toolsBox.toastError("分析图片url错误") }
} }
try { runOnUiThread {
prepareItems() try {
if(pn > 0) { prepareItems()
pageNum = pn if(pn > 0) {
pn = -1 pageNum = pn
}else if(pn == -2){ pn = -1
pageNum = count }else if(pn == -2){
pn = -1 pageNum = count
pn = -1
}
} catch (e: Exception) {
e.printStackTrace()
toolsBox.toastError("准备控件错误")
} finally {
dialog?.hide()
} }
} catch (e: Exception) {
e.printStackTrace()
toolsBox.toastError("准备控件错误")
} }
} }.start()
} }
override fun onWindowFocusChanged(hasFocus: Boolean) { override fun onWindowFocusChanged(hasFocus: Boolean) {
@@ -141,7 +163,7 @@ class ViewMangaActivity : Activity() {
} }
private fun setPageNumber(num: Int) { private fun setPageNumber(num: Int) {
if (r2l && !notUseVP) vp.currentItem = count - num if (r2l && !notUseVP) vp.apply { post { currentItem = count - num } }
else if (notUseVP) currentItem = num - 1 else vp.currentItem = num - 1 else if (notUseVP) currentItem = num - 1 else vp.currentItem = num - 1
} }
@@ -154,7 +176,7 @@ class ViewMangaActivity : Activity() {
} }
private fun loadOneImg() { private fun loadOneImg() {
if(dlZip2View) onei.setImageBitmap(getImgBitmap(currentItem)) if(dlZip2View) onei.apply { post { setImageBitmap(getImgBitmap(currentItem)) } }
else Glide.with(this@ViewMangaActivity) else Glide.with(this@ViewMangaActivity)
.load(imgUrls[currentItem]) .load(imgUrls[currentItem])
.placeholder(R.drawable.ic_dl) .placeholder(R.drawable.ic_dl)
@@ -165,7 +187,7 @@ class ViewMangaActivity : Activity() {
private fun setIdPosition(position: Int) { private fun setIdPosition(position: Int) {
infoDrawerDelta = position.toFloat() infoDrawerDelta = position.toFloat()
infcard.translationY = infoDrawerDelta infcard.apply { post { translationY = infoDrawerDelta } }
} }
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
@@ -180,95 +202,108 @@ class ViewMangaActivity : Activity() {
} }
private fun prepareIdBtLR() { private fun prepareIdBtLR() {
idtblr.isChecked = r2l idtblr.apply { post {
idtblr.setOnClickListener { isChecked = r2l
if (idtblr.isChecked) p["r2l"] = "true" setOnClickListener {
else p["r2l"] = "false" if (idtblr.isChecked) p["r2l"] = "true"
Toast.makeText(this, "下次浏览生效", Toast.LENGTH_SHORT).show() else p["r2l"] = "false"
} Toast.makeText(this@ViewMangaActivity, "下次浏览生效", Toast.LENGTH_SHORT).show()
}
} }
} }
private fun prepareIdBtVP() { private fun prepareIdBtVP() {
idtbvp.isChecked = notUseVP idtbvp.apply { post {
idtbvp.setOnClickListener { isChecked = notUseVP
if (idtbvp.isChecked) p["noAnimation"] = "true" setOnClickListener {
else p["noAnimation"] = "false" if (idtbvp.isChecked) p["noAnimation"] = "true"
Toast.makeText(this, "下次浏览生效", Toast.LENGTH_SHORT).show() else p["noAnimation"] = "false"
} Toast.makeText(this@ViewMangaActivity, "下次浏览生效", Toast.LENGTH_SHORT).show()
}
} }
} }
private fun prepareVP() { private fun prepareVP() {
if (notUseVP) { if (notUseVP) {
vp.visibility = View.INVISIBLE vp.apply { post { visibility = View.INVISIBLE } }
vone.visibility = View.VISIBLE vone.apply { post { visibility = View.VISIBLE } }
} else { } else {
vp.visibility = View.VISIBLE vp.apply { post {
vone.visibility = View.INVISIBLE visibility = View.VISIBLE
vp.adapter = ViewData(vp).RecyclerViewAdapter() adapter = ViewData(this).RecyclerViewAdapter()
vp.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) { override fun onPageSelected(position: Int) {
updateSeekBar() updateSeekBar()
super.onPageSelected(position) super.onPageSelected(position)
} }
}) })
if (r2l) vp.currentItem = count - 1 if (r2l) currentItem = count - 1
} }
vone.apply { post { visibility = View.INVISIBLE } }
} }
} }
private fun updateSeekBar() { private fun updateSeekBar() {
if (!isInSeek) hideObjs() if (!isInSeek) hideSettings()
updateSeekText() updateSeekText()
updateSeekProgress() updateSeekProgress()
} }
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
private fun prepareInfoBar(size: Int) { private fun prepareInfoBar(size: Int) {
oneinfo.alpha = 0F oneinfo.apply { post { alpha = 0F } }
infseek.visibility = View.INVISIBLE infseek.apply { post {
isearch.visibility = View.INVISIBLE visibility = View.INVISIBLE
inftxtprogress.text = "$pageNum/$size" setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
infseek.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { override fun onProgressChanged(p0: SeekBar?, p1: Int, isHuman: Boolean) {
override fun onProgressChanged(p0: SeekBar?, p1: Int, isHuman: Boolean) { if (isHuman) {
if (isHuman) { if (p1 >= (pageNum + 1) * 100 / size) scrollForward()
if (p1 >= (pageNum + 1) * 100 / size) scrollForward() else if (p1 < (pageNum - 1) * 100 / size) scrollBack()
else if (p1 < (pageNum - 1) * 100 / size) scrollBack() }
} }
}
override fun onStartTrackingTouch(p0: SeekBar?) { override fun onStartTrackingTouch(p0: SeekBar?) {
isInSeek = true isInSeek = true
} }
override fun onStopTrackingTouch(p0: SeekBar?) { override fun onStopTrackingTouch(p0: SeekBar?) {
isInSeek = false isInSeek = false
}
})
} }
isearch.apply { post {
visibility = View.INVISIBLE
setOnClickListener {
handler.sendEmptyMessage(3)
} }
}) } }
isearch.setOnClickListener { inftxtprogress.apply { post { text = "$pageNum/$size" } }
handler.sendEmptyMessage(3)
}
} }
private fun prepareIdBtVH() { private fun prepareIdBtVH() {
idtbvh.isChecked = idtbvh.apply { post {
p["vertical"] == "true" isChecked = p["vertical"] == "true"
if (idtbvh.isChecked) vp.orientation = ViewPager2.ORIENTATION_VERTICAL setOnClickListener {
idtbvh.setOnClickListener { if (idtbvh.isChecked) {
if (idtbvh.isChecked) { vp.apply { post { orientation = ViewPager2.ORIENTATION_VERTICAL } }
vp.orientation = ViewPager2.ORIENTATION_VERTICAL p["vertical"] = "true"
p["vertical"] = "true" } else {
} else { vp.apply { post { orientation = ViewPager2.ORIENTATION_HORIZONTAL } }
vp.orientation = ViewPager2.ORIENTATION_HORIZONTAL p["vertical"] = "false"
p["vertical"] = "false" }
} }
} } }
if (idtbvh.isChecked) vp.apply { post { orientation = ViewPager2.ORIENTATION_VERTICAL } }
} }
private fun prepareIdBtVolTurn() { private fun prepareIdBtVolTurn() {
idtbvolturn.isChecked = volTurnPage idtbvolturn.apply { post {
idtbvolturn.setOnClickListener { isChecked = volTurnPage
if (idtbvolturn.isChecked) p["volturn"] = "true" setOnClickListener {
else p["volturn"] = "false" if (idtbvolturn.isChecked) p["volturn"] = "true"
} else p["volturn"] = "false"
}
} }
} }
private fun countZipItems(): Int { private fun countZipItems(): Int {
@@ -278,17 +313,12 @@ class ViewMangaActivity : Activity() {
if (!exist) return 0 if (!exist) return 0
else { else {
Log.d("Myvm", "zipf: $mangaZip") Log.d("Myvm", "zipf: $mangaZip")
val zip = ZipInputStream(mangaZip?.inputStream()?.buffered()) ZipFile(mangaZip).use { zip ->
var entry = zip.nextEntry c = zip.size()
while (entry != null) {
if (!entry.isDirectory) c++
entry = zip.nextEntry
} }
zip.closeEntry()
zip.close()
} }
} catch (e: Exception) { } catch (e: Exception) {
toolsBox.toastError("读取zip错误!") runOnUiThread { toolsBox.toastError("读取zip错误!") }
} }
return c return c
} }
@@ -303,13 +333,14 @@ class ViewMangaActivity : Activity() {
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
private fun updateSeekText() { private fun updateSeekText() {
inftxtprogress.text = "$pageNum/$count" inftxtprogress.apply { post { text = "$pageNum/$count" } }
} }
private fun updateSeekProgress() { private fun updateSeekProgress() {
infseek.progress = pageNum * 100 / count infseek.apply { post { progress = pageNum * 100 / count } }
} }
@Deprecated("Deprecated in Java")
override fun onBackPressed() { override fun onBackPressed() {
tt.canDo = false tt.canDo = false
wm?.get()?.w?.goBack() wm?.get()?.w?.goBack()
@@ -318,6 +349,7 @@ class ViewMangaActivity : Activity() {
override fun onDestroy() { override fun onDestroy() {
tt.canDo = false tt.canDo = false
handler.removeCallbacksAndMessages(null)
super.onDestroy() super.onDestroy()
} }
@@ -347,7 +379,7 @@ class ViewMangaActivity : Activity() {
} }
} }
fun showObjs() { fun showSettings() {
infseek.visibility = View.VISIBLE infseek.visibility = View.VISIBLE
isearch.visibility = View.VISIBLE isearch.visibility = View.VISIBLE
ObjectAnimator.ofFloat( ObjectAnimator.ofFloat(
@@ -359,7 +391,7 @@ class ViewMangaActivity : Activity() {
clicked = true clicked = true
} }
fun hideObjs() { fun hideSettings() {
ObjectAnimator.ofFloat( ObjectAnimator.ofFloat(
oneinfo, oneinfo,
"alpha", "alpha",
@@ -375,10 +407,10 @@ class ViewMangaActivity : Activity() {
} }
class MyHandler( class MyHandler(
private val infcard: View, private val infoCard: View,
private val toolsBox: ToolsBox private val toolsBox: ToolsBox
) : Handler(Looper.myLooper()!!) { ) : Handler(Looper.myLooper()!!) {
private var infcShowed = false private var infoShown = false
private var delta = -1f private var delta = -1f
get() { get() {
if (field < 0) field = va?.get()?.infoDrawerDelta ?: 0f if (field < 0) field = va?.get()?.infoDrawerDelta ?: 0f
@@ -389,30 +421,30 @@ class ViewMangaActivity : Activity() {
override fun handleMessage(msg: Message) { override fun handleMessage(msg: Message) {
super.handleMessage(msg) super.handleMessage(msg)
when (msg.what) { when (msg.what) {
1 -> if (infcShowed) { 1 -> if (infoShown) {
hideInfCard(); infcShowed = false hideInfCard(); infoShown = false
} }
2 -> if (!infcShowed) { 2 -> if (!infoShown) {
showInfCard(); infcShowed = true showInfCard(); infoShown = true
} }
3 -> infcShowed = if (infcShowed) { 3 -> infoShown = if (infoShown) {
hideInfCard(); false hideInfCard(); false
} else { } else {
showInfCard(); true showInfCard(); true
} }
22 -> toolsBox.zis?.idtime?.text = 22 -> toolsBox.zis?.idtime?.text =
SimpleDateFormat("HH:mm").format(Date()) + toolsBox.week + toolsBox.netinfo SimpleDateFormat("HH:mm").format(Date()) + toolsBox.week + toolsBox.netInfo
} }
} }
private fun showInfCard() { private fun showInfCard() {
ObjectAnimator.ofFloat(infcard.idc, "alpha", 0.3F, 0.8F).setDuration(233).start() ObjectAnimator.ofFloat(infoCard.idc, "alpha", 0.3F, 0.8F).setDuration(233).start()
ObjectAnimator.ofFloat(infcard, "translationY", delta, 0F).setDuration(233).start() ObjectAnimator.ofFloat(infoCard, "translationY", delta, 0F).setDuration(233).start()
} }
private fun hideInfCard() { private fun hideInfCard() {
ObjectAnimator.ofFloat(infcard.idc, "alpha", 0.8F, 0.3F).setDuration(233).start() ObjectAnimator.ofFloat(infoCard.idc, "alpha", 0.8F, 0.3F).setDuration(233).start()
ObjectAnimator.ofFloat(infcard, "translationY", 0F, delta).setDuration(233).start() ObjectAnimator.ofFloat(infoCard, "translationY", 0F, delta).setDuration(233).start()
} }
} }

View File

@@ -0,0 +1,15 @@
package top.fumiama.copymangaweb.activity.template
import android.app.Activity
import android.os.Bundle
import top.fumiama.copymangaweb.tool.ToolsBox
import java.lang.ref.WeakReference
open class ToolsBoxActivity: Activity() {
lateinit var toolsBox: ToolsBox
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
toolsBox = ToolsBox(WeakReference(this))
}
}

View File

@@ -14,8 +14,7 @@ import java.lang.ref.WeakReference
class DlHandler(activity: DlActivity, looper: Looper) : Handler(looper) { class DlHandler(activity: DlActivity, looper: Looper) : Handler(looper) {
private val da = WeakReference(activity) private val da = WeakReference(activity)
private val d private val d get() = da.get()
get() = da.get()
private var size = 0 private var size = 0
private var refreshSize = true private var refreshSize = true

View File

@@ -7,6 +7,7 @@ import android.os.Looper
import android.os.Message import android.os.Message
import android.view.View import android.view.View
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.dialog_unzipping.*
import top.fumiama.copymangaweb.activity.DlActivity.Companion.json import top.fumiama.copymangaweb.activity.DlActivity.Companion.json
import top.fumiama.copymangaweb.activity.MainActivity.Companion.wm import top.fumiama.copymangaweb.activity.MainActivity.Companion.wm
import top.fumiama.copymangaweb.activity.ViewMangaActivity import top.fumiama.copymangaweb.activity.ViewMangaActivity
@@ -15,19 +16,23 @@ import top.fumiama.copymangaweb.tool.MangaDlTools.Companion.wmdlt
class MainHandler(looper: Looper):Handler(looper) { class MainHandler(looper: Looper):Handler(looper) {
var saveUrlsOnly = false var saveUrlsOnly = false
var showDlList = false var showDlList = false
override fun handleMessage(msg: Message) { override fun handleMessage(msg: Message) {
super.handleMessage(msg) super.handleMessage(msg)
when(msg.what){ when(msg.what) {
1 -> loadUrlInHiddenWebView(msg.obj as String) LOAD_URL_IN_HIDDEN_WEB_VIEW -> loadUrlInHiddenWebView(msg.obj as String)
2 -> callViewManga(msg.obj as String) CALL_VIEW_MANGA -> callViewManga(msg.obj as String)
3 -> updateLoadProgress(msg.arg1) UPDATE_LOAD_PROGRESS -> updateLoadProgress(msg.arg1)
4 -> setFab(msg.obj as String) SET_FAB -> setFab(msg.obj as String)
5 -> hideFab() HIDE_FAB -> hideFab()
6 -> setFab2DlList() SET_FAB_TO_DOWNLOAD_LIST -> setFab2DlList()
SHOW_LOADING_DIALOG -> wm?.get()?.dialog?.show()
HIDE_LOADING_DIALOG -> wm?.get()?.dialog?.hide()
SET_LOADING_DIALOG_TEXT -> wm?.get()?.dialog?.tunz?.text = msg.obj as String
} }
} }
private fun loadUrlInHiddenWebView(url: String){wm?.get()?.wh?.loadUrl(url)} private fun loadUrlInHiddenWebView(url: String) { wm?.get()?.wh?.apply { post { loadUrl(url) } } }
private fun callViewManga(content: String){ private fun callViewManga(content: String) = Thread{
val listChapter = content.split('\n') val listChapter = content.split('\n')
if(!saveUrlsOnly) { if(!saveUrlsOnly) {
ViewMangaActivity.titleText = listChapter[0].substringBeforeLast(' ') ViewMangaActivity.titleText = listChapter[0].substringBeforeLast(' ')
@@ -35,26 +40,26 @@ class MainHandler(looper: Looper):Handler(looper) {
ViewMangaActivity.previousChapterUrl = listChapter[2].let { if(it == "null") null else it } ViewMangaActivity.previousChapterUrl = listChapter[2].let { if(it == "null") null else it }
ViewMangaActivity.imgUrls = arrayOf() ViewMangaActivity.imgUrls = arrayOf()
for(i in 3 until listChapter.size) ViewMangaActivity.imgUrls += listChapter[i] for(i in 3 until listChapter.size) ViewMangaActivity.imgUrls += listChapter[i]
wm?.get()?.let { it.startActivity(Intent(it, ViewMangaActivity::class.java)) } wm?.get()?.apply { runOnUiThread { startActivity(Intent(this, ViewMangaActivity::class.java)) } }
} else{ } else {
var imgs = arrayOf<String>() var imgs = arrayOf<String>()
for(i in 3 until listChapter.size) imgs += listChapter[i] for(i in 3 until listChapter.size) imgs += listChapter[i]
wmdlt?.get()?.setChapterImgs(listChapter[0].substringAfterLast(' '), imgs) wmdlt?.get()?.setChapterImgs(listChapter[0].substringAfterLast(' '), imgs)
} }
} }.start()
private fun updateLoadProgress(progress: Int){ private fun updateLoadProgress(p: Int) {
wm?.get()?.let{ wm?.get()?.pw?.apply { post {
if(it.pw.progress == 100 && progress < 100) { if(progress == 100 && p < 100) {
it.pw.progress = 0 progress = 0
it.pw.visibility = View.VISIBLE visibility = View.VISIBLE
} }
ObjectAnimator.ofInt(it.pw, "progress", it.pw.progress, progress).setDuration(233).start() ObjectAnimator.ofInt(this, "progress", progress, p).setDuration(233).start()
if(progress == 100) it.pw.postDelayed({it.pw.visibility = View.GONE}, 500) if(p == 100) postDelayed({ visibility = View.GONE }, 500)
} } }
} }
private fun showFab() {wm?.get()?.fab?.visibility = View.VISIBLE} private fun showFab() { wm?.get()?.fab?.apply { post { visibility = View.VISIBLE } } }
private fun hideFab() {wm?.get()?.fab?.visibility = View.GONE} private fun hideFab() { wm?.get()?.fab?.apply { post { visibility = View.GONE } } }
private fun setFab(content: String){ private fun setFab(content: String) {
//Log.d("MyMH", "Get chapter json: $content") //Log.d("MyMH", "Get chapter json: $content")
showDlList = false showDlList = false
json = content json = content
@@ -64,4 +69,16 @@ class MainHandler(looper: Looper):Handler(looper) {
showDlList = true showDlList = true
showFab() showFab()
} }
companion object {
const val LOAD_URL_IN_HIDDEN_WEB_VIEW = 1
const val CALL_VIEW_MANGA = 2
const val UPDATE_LOAD_PROGRESS = 3
const val SET_FAB = 4
const val HIDE_FAB = 5
const val SET_FAB_TO_DOWNLOAD_LIST = 6
const val SHOW_LOADING_DIALOG = 7
const val HIDE_LOADING_DIALOG = 8
const val SET_LOADING_DIALOG_TEXT = 9
}
} }

View File

@@ -55,10 +55,10 @@ class PagesManager(w: WeakReference<ViewMangaActivity>) {
).show() ).show()
} }
} }
} else v?.hideObjs() } else v?.hideSettings()
} }
fun manageInfo(){ fun manageInfo(){
if (v?.clicked == false) v.showObjs() else v?.hideObjs() if (v?.clicked == false) v.showSettings() else v?.hideSettings()
} }
private fun doubleTapToast(goNext: Boolean){ private fun doubleTapToast(goNext: Boolean){
val hint = if(goNext) "" else "" val hint = if(goNext) "" else ""

View File

@@ -1,5 +1,6 @@
package top.fumiama.copymangaweb.tool package top.fumiama.copymangaweb.tool
import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
@@ -15,12 +16,13 @@ class SetDraggable {
return this return this
} }
@SuppressLint("ClickableViewAccessibility")
fun onto(target: View) { fun onto(target: View) {
var lastX = 0 var lastX = 0
var lastY = 0 var lastY = 0
var firstX = 0 var firstX = 0
var firstY = 0 var firstY = 0
target.setOnTouchListener { v: View, event: MotionEvent -> target.post { target.setOnTouchListener { v: View, event: MotionEvent ->
when (event.action) { when (event.action) {
MotionEvent.ACTION_DOWN -> { MotionEvent.ACTION_DOWN -> {
lastX = event.rawX.toInt() lastX = event.rawX.toInt()
@@ -56,7 +58,7 @@ class SetDraggable {
lastY = event.rawY.toInt() lastY = event.rawY.toInt()
} }
} }
abs(firstX - lastX) > 3 || abs(firstY - lastY) > 3 //移动微小则判断为点击 abs(firstX - lastX) > 3 || abs(firstY - lastY) > 3 // 移动微小则判断为点击
} } }
} }
} }

View File

@@ -8,11 +8,11 @@ import android.net.NetworkCapabilities
import android.widget.Toast import android.widget.Toast
import top.fumiama.copymangaweb.R import top.fumiama.copymangaweb.R
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import java.util.* import java.util.Calendar
import kotlin.math.sqrt import kotlin.math.sqrt
class ToolsBox(w: WeakReference<Any>) { class ToolsBox(w: WeakReference<Activity>) {
val zis = (w as WeakReference<Activity>).get() val zis = w.get()
val week: String val week: String
get() { get() {
val cal = Calendar.getInstance() val cal = Calendar.getInstance()
@@ -27,7 +27,7 @@ class ToolsBox(w: WeakReference<Any>) {
else -> "" else -> ""
} }
} }
val netinfo: String val netInfo: String
get() { get() {
val cm: ConnectivityManager = val cm: ConnectivityManager =
zis?.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager zis?.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

View File

@@ -5,24 +5,25 @@ import android.webkit.JavascriptInterface
import top.fumiama.copymangaweb.R import top.fumiama.copymangaweb.R
import top.fumiama.copymangaweb.activity.MainActivity.Companion.mh import top.fumiama.copymangaweb.activity.MainActivity.Companion.mh
import top.fumiama.copymangaweb.activity.MainActivity.Companion.wm import top.fumiama.copymangaweb.activity.MainActivity.Companion.wm
import top.fumiama.copymangaweb.handler.MainHandler
class JS { class JS {
@JavascriptInterface @JavascriptInterface
fun loadComic(url: String){ fun loadComic(url: String) {
val u = when { val u = when {
url.contains("/details/comic/") -> "${wm?.get()?.getString(R.string.web_comic_detail_pc)}${url.substringAfter("comic")}" url.contains("/details/comic/") -> "${wm?.get()?.getString(R.string.web_comic_detail_pc)}${url.substringAfter("comic")}"
url.contains("/comicContent/") -> "${wm?.get()?.getString(R.string.web_comic_detail_pc)}/${url.substringAfter("comicContent/").substringBefore("/")}/chapter/${url.substringAfterLast("/")}" url.contains("/comicContent/") -> "${wm?.get()?.getString(R.string.web_comic_detail_pc)}/${url.substringAfter("comicContent/").substringBefore("/")}/chapter/${url.substringAfterLast("/")}"
else -> "" else -> ""
} }
Log.d("MyJS", "Load comic: $u") Log.d("MyJS", "Load comic: $u")
Thread{mh?.obtainMessage(1, u)?.sendToTarget()}.start() mh?.obtainMessage(MainHandler.LOAD_URL_IN_HIDDEN_WEB_VIEW, u)?.sendToTarget()
} }
@JavascriptInterface @JavascriptInterface
fun hideFab(){ fun hideFab() {
Thread{mh?.sendEmptyMessage(5)}.start() mh?.sendEmptyMessage(MainHandler.HIDE_FAB)
} }
@JavascriptInterface @JavascriptInterface
fun enterProfile(){ fun enterProfile(){
Thread{mh?.sendEmptyMessage(6)}.start() mh?.sendEmptyMessage(MainHandler.SET_FAB_TO_DOWNLOAD_LIST)
} }
} }

View File

@@ -4,11 +4,12 @@ import android.util.Log
import android.webkit.JavascriptInterface import android.webkit.JavascriptInterface
import top.fumiama.copymangaweb.activity.DlActivity import top.fumiama.copymangaweb.activity.DlActivity
import top.fumiama.copymangaweb.activity.MainActivity.Companion.mh import top.fumiama.copymangaweb.activity.MainActivity.Companion.mh
import top.fumiama.copymangaweb.handler.MainHandler
class JSHidden { class JSHidden {
@JavascriptInterface @JavascriptInterface
fun loadChapter(listString: String){ fun loadChapter(listString: String){
Thread{mh?.obtainMessage(2, listString)?.sendToTarget()}.start() mh?.obtainMessage(MainHandler.CALL_VIEW_MANGA, listString)?.sendToTarget()
} }
@JavascriptInterface @JavascriptInterface
fun setTitle(title:String){ fun setTitle(title:String){
@@ -17,6 +18,14 @@ class JSHidden {
} }
@JavascriptInterface @JavascriptInterface
fun setFab(content: String){ fun setFab(content: String){
Thread{mh?.obtainMessage(4, content)?.sendToTarget()}.start() mh?.obtainMessage(MainHandler.SET_FAB, content)?.sendToTarget()
}
@JavascriptInterface
fun setLoadingDialog(display: Boolean) {
mh?.sendEmptyMessage(if (display) MainHandler.SHOW_LOADING_DIALOG else MainHandler.HIDE_LOADING_DIALOG)
}
@JavascriptInterface
fun setLoadingDialogProgress(index: String, count: String) {
mh?.obtainMessage(MainHandler.SET_LOADING_DIALOG_TEXT, "$index/$count")?.sendToTarget()
} }
} }

View File

@@ -5,12 +5,13 @@ import android.webkit.*
import android.webkit.WebChromeClient import android.webkit.WebChromeClient
import top.fumiama.copymangaweb.activity.MainActivity.Companion.mh import top.fumiama.copymangaweb.activity.MainActivity.Companion.mh
import top.fumiama.copymangaweb.activity.MainActivity.Companion.wm import top.fumiama.copymangaweb.activity.MainActivity.Companion.wm
import top.fumiama.copymangaweb.handler.MainHandler
class WebChromeClient:WebChromeClient() { class WebChromeClient:WebChromeClient() {
override fun onProgressChanged(view: WebView?, newProgress: Int) { override fun onProgressChanged(view: WebView?, newProgress: Int) {
super.onProgressChanged(view, newProgress) super.onProgressChanged(view, newProgress)
//Log.d("MyWCC", "W progress: $newProgress") //Log.d("MyWCC", "W progress: $newProgress")
Thread{mh?.obtainMessage(3, newProgress, 0)?.sendToTarget()}.start() mh?.obtainMessage(MainHandler.UPDATE_LOAD_PROGRESS, newProgress, 0)?.sendToTarget()
} }
override fun onJsAlert( override fun onJsAlert(

View File

@@ -34,9 +34,9 @@ class WebViewClient(private val context: Context, jsFileName: String):WebViewCli
}.start() }.start()
} }
override fun onReceivedSslError(view: WebView?, handler: SslErrorHandler?, error: SslError?) { /*override fun onReceivedSslError(view: WebView?, handler: SslErrorHandler?, error: SslError?) {
handler?.proceed() // ignore ssl errors handler?.proceed() // ignore ssl errors
} }*/
override fun shouldInterceptRequest( override fun shouldInterceptRequest(
view: WebView?, view: WebView?,

View File

@@ -0,0 +1,27 @@
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<ProgressBar
android:id="@+id/punz"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/tunz"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tunz"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="准备中..."
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/punz" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -1,5 +1,5 @@
<resources> <resources>
<string name="app_name">拷贝漫画</string> <string name="app_name">拷贝Lite</string>
<string name="web_home">https://www.copy20.com</string> <string name="web_home">https://www.copy20.com</string>
<string name="web_home_www">https://www.copy20.com</string> <string name="web_home_www">https://www.copy20.com</string>
<string name="web_comic_detail_pc">https://www.copy20.com/comic</string> <string name="web_comic_detail_pc">https://www.copy20.com/comic</string>

View File

@@ -5,4 +5,4 @@ pluginManagement {
} }
include ':app' include ':app'
rootProject.name = "拷贝漫画" rootProject.name = "拷贝Lite"