diff --git a/.idea/dictionaries/rumia.xml b/.idea/dictionaries/rumia.xml
index ddce754..8708a95 100644
--- a/.idea/dictionaries/rumia.xml
+++ b/.idea/dictionaries/rumia.xml
@@ -1,9 +1,8 @@
- cdwn
- manga
- rmrf
+ copymanga
+ fumiama
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
index a5f05cd..2370474 100644
--- a/.idea/jarRepositories.xml
+++ b/.idea/jarRepositories.xml
@@ -21,5 +21,10 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
new file mode 100644
index 0000000..7f68460
--- /dev/null
+++ b/.idea/runConfigurations.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 47247c8..dbfce5e 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,16 @@
# copymanga 拷贝漫画
拷贝漫画的第三方APP,优化阅读/下载体验
+
# 说明
-本应用基于官方的`HLML5`手机版本网页端,作者不对其中呈现的任何内容负责
+1. 本应用原基于官方的`HTML5`手机版本网页端,官方关闭`H5`后,从`2.0`版本开始使用官方`APP`的`API`,作者不对其中呈现的任何内容负责
+2. 下载文件为`webp`格式图片,按章节打包为`zip`,可使用本应用或其他漫画阅读应用打开
+3. 若想查看下载的漫画是否有错误,可以长按该漫画目录执行查错
+4. 下载文件位于`./Android/data/top.fumiama.copymanga/files`目录
+
# 功能
-1. 阅读漫画更改为横屏模式,适于墨水屏阅读
-2. 增加下载漫画功能,但是由于不可抗力,下载速度较慢且容易出错,这绝对不是优化的原因,绝对不是
-3. 增加阅读下载的漫画的功能,但是无法切换章节,需要手动点选
\ No newline at end of file
+1. 浏览主页、分类,查看漫画并阅读
+2. 下载漫画。但是由于不可抗力,下载速度较慢且容易出错,这绝对不是优化的原因,绝对不是
+3. 阅读下载的漫画
+
+# 未实现功能
+未在上表列出的官方`APP`的其他功能
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 3ffefd1..40f8079 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -4,20 +4,6 @@ apply plugin: 'kotlin-android-extensions'
apply plugin: 'AndResGuard'
android {
- compileSdkVersion 30
- buildToolsVersion "30.0.2"
-
- defaultConfig {
- applicationId "top.fumiama.copymanga"
- minSdkVersion 23
- targetSdkVersion 30
- versionCode 10
- versionName '1.3.2'
- resConfigs "zh", "zh-rCN"
-
- testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
- }
-
signingConfigs {
release {
storeFile file('../../../OneDrive/swc/developer/android_key/open_key')
@@ -27,6 +13,26 @@ android {
v1SigningEnabled true
v2SigningEnabled true
}
+ /*winrelease {
+ storeFile file('C:/Users/spayi/OneDrive/swc/developer/android_key/open_key')
+ storePassword 'fumiama'
+ keyAlias 'default'
+ keyPassword 'fumiama'
+ v1SigningEnabled true
+ v2SigningEnabled true
+ }*/
+ }
+ compileSdkVersion 30
+
+ defaultConfig {
+ applicationId 'top.fumiama.copymanga'
+ minSdkVersion 23
+ targetSdkVersion 30
+ versionCode 12
+ versionName '2.0.beta'
+ resConfigs "zh", "zh-rCN"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
@@ -36,30 +42,60 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
- /*debug{
+ /*winrelease {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ signingConfig signingConfigs.winrelease
+ }
+ debug{
+ minifyEnabled false
+ shrinkResources false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ signingConfig signingConfigs.winrelease
}*/
}
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+ bundle{
+ density{
+ enableSplit = true
+ }
+ language{
+ enableSplit = false
+ }
+ }
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
- //implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'androidx.legacy:legacy-support-v4:1.0.0'
+ implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
- implementation 'androidx.cardview:cardview:1.0.0'
- implementation 'androidx.viewpager2:viewpager2:1.0.0'
- //implementation 'com.google.android.material:material:1.2.1'
- testImplementation 'junit:junit:4.13.1'
+ implementation 'androidx.navigation:navigation-fragment-ktx:2.3.3'
+ implementation 'androidx.navigation:navigation-ui-ktx:2.3.3'
+ implementation 'androidx.navigation:navigation-fragment-ktx:2.3.3'
+ implementation 'androidx.navigation:navigation-ui-ktx:2.3.3'
+ testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
- implementation 'com.github.bumptech.glide:glide:4.11.0'
- annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
+ implementation 'com.afollestad.material-dialogs:input:3.3.0'
+ implementation 'com.github.yalantis:ucrop:2.2.6'
+ implementation 'com.to.aboomy:pager2banner:1.0.1'
+ implementation 'com.github.bumptech.glide:glide:4.12.0'
+ annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
implementation 'com.google.code.gson:gson:2.8.6'
- //implementation 'com.liaoinstan.springview:library:1.7.0'
+ implementation 'com.github.vovaksenov99:OverscrollableScrollView:1.0'
+ implementation 'com.liaoinstan.springview:library:1.7.0'
+ implementation 'com.github.zawadz88.materialpopupmenu:material-popup-menu:4.0.1'
}
andResGuard {
@@ -67,14 +103,15 @@ andResGuard {
mappingFile = null
use7zip = true
useSign = true
- // 打开这个开关,会keep住所有资源的原始路径,只混淆资源的名字
+ // It will keep the origin path of your resources when it's true
keepRoot = false
- // 设置这个值,会把arsc name列混淆成相同的名字,减少string常量池的大小
+ // If set, name column in arsc those need to proguard will be kept to this value
fixedResName = "arg"
- // 打开这个开关会合并所有哈希值相同的资源,但请不要过度依赖这个功能去除去冗余资源
+ // It will merge the duplicated resources, but don't rely on this feature too much.
+ // it's always better to remove duplicated resource from repo
mergeDuplicatedRes = true
whiteList = [
- // for your icon
+ // your icon
"R.drawable.icon",
// for fabric
"R.string.com.crashlytics.*",
@@ -92,20 +129,10 @@ andResGuard {
"*.jpg",
"*.jpeg",
"*.gif",
+ "resources.arsc"
]
sevenzip {
artifact = 'com.tencent.mm:SevenZip:1.2.20'
//path = "/usr/local/bin/7za"
}
-
- /**
- * 可选: 如果不设置则会默认覆盖assemble输出的apk
- **/
- // finalApkBackupPath = "${project.rootDir}/final.apk"
-
- /**
- * 可选: 指定v1签名时生成jar文件的摘要算法
- * 默认值为“SHA-1”
- **/
- // digestalg = "SHA-256"
}
\ No newline at end of file
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
index 44100e9..d2e97db 100644
--- a/app/proguard-rules.pro
+++ b/app/proguard-rules.pro
@@ -27,10 +27,27 @@
**[] $VALUES;
public *;
}
--keep class com.bumptech.glide.load.data.ParcelFileDescriptorRewinder$InternalRewinder {
+-keep class com.bumptech.glide.load.data.ParcelFileDescriptorRewinder.InternalRewinder$** {
*** rewind();
}
+-assumenosideeffects class android.util.Log {
+ public static *** d(...);
+ public static *** e(...);
+ public static *** i(...);
+ public static *** v(...);
+ public static *** println(...);
+ public static *** w(...);
+ public static *** wtf(...);
+}
+
+-keep class com.to.aboomy.pager2banner.* {*;}
+-keep class androidx.viewpager2.widget.* {*;}
+
+-dontwarn com.yalantis.ucrop**
+-keep class com.yalantis.ucrop** { *; }
+-keep interface com.yalantis.ucrop** { *; }
+
##---------------Begin: proguard configuration for Gson ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
@@ -44,7 +61,7 @@
#-keep class com.google.gson.stream.** { *; }
# Application classes that will be serialized/deserialized over Gson
--keep public class top.fumiama.copymanga.data.* { *; }
+-keep class top.fumiama.dmzjxs.json.*{ *; }
# Prevent proguard from stripping interface information from TypeAdapter, TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
@@ -59,13 +76,3 @@
}
##---------------End: proguard configuration for Gson ----------
-
--assumenosideeffects class android.util.Log {
- public static *** d(...);
- public static *** e(...);
- public static *** i(...);
- public static *** v(...);
- public static *** println(...);
- public static *** w(...);
- public static *** wtf(...);
-}
diff --git a/app/src/androidTest/java/top/fumiama/copymanga/ExampleInstrumentedTest.kt b/app/src/androidTest/java/top/fumiama/dmzj/dmzjxs/ExampleInstrumentedTest.kt
similarity index 84%
rename from app/src/androidTest/java/top/fumiama/copymanga/ExampleInstrumentedTest.kt
rename to app/src/androidTest/java/top/fumiama/dmzj/dmzjxs/ExampleInstrumentedTest.kt
index 5b6eb95..e52f095 100644
--- a/app/src/androidTest/java/top/fumiama/copymanga/ExampleInstrumentedTest.kt
+++ b/app/src/androidTest/java/top/fumiama/dmzj/dmzjxs/ExampleInstrumentedTest.kt
@@ -1,4 +1,4 @@
-package top.fumiama.copymanga
+package top.fumiama.dmzj.dmzjxs
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -19,6 +19,6 @@ class ExampleInstrumentedTest {
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
- assertEquals("top.fumiama.copymanga", appContext.packageName)
+ assertEquals("top.fumiama.dmzj.dmzjxs", appContext.packageName)
}
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2d18a56..994a910 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,23 +1,48 @@
+
+ package="top.fumiama.dmzj.copymanga">
-
+
+
-
+ android:theme="@style/AppTheme"
+ android:usesCleartextTraffic="true">
+
+
+
+
+
+
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/assets/h.js b/app/src/main/assets/h.js
deleted file mode 100644
index e748a43..0000000
--- a/app/src/main/assets/h.js
+++ /dev/null
@@ -1,45 +0,0 @@
-javascript:
-if (typeof (loaded) == "undefined"){
- var loaded = true;
- function scanChapters(chapter){
- var chapterList = chapter.getElementsByClassName("table-all")[0].getElementsByTagName("a");
- var chapterArr = Array();
- for(var i = 0; i < chapterList.length; i++){
- chapterArr.push(JSON.constructor());
- chapterArr[i]["name"] = chapterList[i].title;
- chapterArr[i]["url"] = chapterList[i].href;
- }
- return chapterArr;
- }
- function modify(){
- var url = location.href;
- if(url.indexOf("/chapter/")>0){
- 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);
- }else {
- var json = Array();
- var chapters = document.getElementsByClassName("upLoop")[0].children;
- var newObj = null;
- for(var i = 0; i < chapters.length; i++) {
- if(i % 2) {
- newObj["chapters"] = scanChapters(chapters[i]);
- json.push(newObj);
- newObj = null;
- }
- else {
- newObj = JSON.constructor();
- newObj["name"] = chapters[i].innerText;
- }
- }
- GM.setTitle(document.getElementsByTagName("h6")[0].title);
- GM.setFab(JSON.stringify(json));
- }
- }
- modify();
-}else modify();
\ No newline at end of file
diff --git a/app/src/main/assets/i.js b/app/src/main/assets/i.js
deleted file mode 100644
index 77ab9ef..0000000
--- a/app/src/main/assets/i.js
+++ /dev/null
@@ -1,47 +0,0 @@
-javascript:
-if (typeof (loaded) == "undefined") {
- var loaded = true;
- var invoke = {
- preUrl: "",
- pinTitle: function () {
- /*document.getElementsByClassName("van-button__content")[2].click();*/
- document.getElementsByClassName("indexTitle")[0].style.position = "fixed";
- document.getElementsByClassName("indexTitle")[0].style.zIndex = 999;
- document.getElementsByClassName("indexTitle")[0].style.width = document.body.clientWidth - 18 + "px";
- document.getElementsByClassName("copySwiper")[0].style.marginTop = "56px";
- document.getElementsByClassName("indexTitle")[0].style.marginTop = "-56px";
- },
- notCallGM: function (url) {
- if (this.preUrl == url) return false;
- else {
- this.preUrl = url;
- return true;
- }
- },
- clickClass: function (name, index) { document.getElementsByClassName(name)[index].click(); },
- clickClassCenter: function (name, index) {
- var ev = document.createEvent('HTMLEvents');
- ev.clientX = innerWidth / 2;
- ev.clientY = innerHeight / 2;
- ev.initEvent('click', false, true);
- document.getElementsByClassName(name)[index].dispatchEvent(ev);
- },
- resetPreUrl: function () { this.preUrl = ""; },
- loadChapter: function () { this.clickClassCenter("comicContentPopupImageItem", 0); GM.loadComic(location.href); },
- urlChangeListener: function (todo) {
- setInterval(function () { if (invoke.notCallGM(location.href)) { todo(); } }, 1000);
- }
- };
- function modify() {
- var url = location.href;
- GM.hideFab();
- if (url.endsWith("/index")) invoke.pinTitle();
- else if (url.indexOf("/comicContent/") > 0) setTimeout(function () { invoke.loadChapter() }, 1000);
- else if (url.indexOf("/details/comic/") > 0) GM.loadComic(url);
- else if (url.indexOf("/personal") > 0) GM.enterProfile();
- }
- modify();
- invoke.urlChangeListener(modify);
-} else {
- setTimeout(modify, 1280);
-}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/LoginActivity.kt b/app/src/main/java/top/fumiama/copymanga/LoginActivity.kt
new file mode 100644
index 0000000..e5acaf6
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/LoginActivity.kt
@@ -0,0 +1,12 @@
+package top.fumiama.copymanga
+
+import android.app.Activity
+import android.os.Bundle
+import top.fumiama.dmzj.copymanga.R
+
+class LoginActivity:Activity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_login)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/MainActivity.kt b/app/src/main/java/top/fumiama/copymanga/MainActivity.kt
new file mode 100644
index 0000000..de7fc9a
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/MainActivity.kt
@@ -0,0 +1,263 @@
+package top.fumiama.copymanga
+
+import android.Manifest
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.net.Uri
+import android.os.Build
+import android.os.Bundle
+import android.provider.MediaStore
+import android.util.Log
+import android.view.Menu
+import android.view.MenuItem
+import android.view.View
+import android.widget.TextView
+import android.widget.Toast
+import androidx.appcompat.app.AlertDialog
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.app.ActivityCompat
+import androidx.core.content.ContextCompat
+import androidx.core.net.toUri
+import androidx.drawerlayout.widget.DrawerLayout
+import androidx.navigation.findNavController
+import androidx.navigation.ui.AppBarConfiguration
+import androidx.navigation.ui.navigateUp
+import androidx.navigation.ui.setupActionBarWithNavController
+import androidx.navigation.ui.setupWithNavController
+import com.afollestad.materialdialogs.MaterialDialog
+import com.afollestad.materialdialogs.input.input
+import com.yalantis.ucrop.UCrop
+import kotlinx.android.synthetic.main.activity_main.*
+import kotlinx.android.synthetic.main.app_bar_main.*
+import kotlinx.android.synthetic.main.nav_header_main.*
+import top.fumiama.dmzj.copymanga.R
+import top.fumiama.copymanga.tools.PropertiesTools
+import top.fumiama.copymanga.ui.download.DownloadFragment
+import java.io.File
+import java.io.FileInputStream
+import java.lang.ref.WeakReference
+
+
+class MainActivity : AppCompatActivity() {
+ var isDrawerClosed = true
+ var menuMain: Menu? = null
+
+ private lateinit var appBarConfiguration: AppBarConfiguration
+ private lateinit var p: PropertiesTools
+ private lateinit var headPic: File
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+ setSupportActionBar(toolbar)
+ //translucentStatusBar()
+ coordiv.layoutParams.height = getStatusBarHeight()
+
+ val navController = findNavController(R.id.nav_host_fragment)
+ appBarConfiguration = AppBarConfiguration(
+ setOf(
+ R.id.nav_home,
+ R.id.nav_sort,
+ R.id.nav_rank,
+ R.id.nav_sub,
+ R.id.nav_history,
+ R.id.nav_download,
+ R.id.nav_settings
+ ), drawer_layout
+ )
+ setupActionBarWithNavController(navController, appBarConfiguration)
+ nav_view.setupWithNavController(navController)
+
+ p = PropertiesTools(File(filesDir, "database.prop"))
+ headPic = File(getExternalFilesDir(""), "headPic")
+ mainWeakReference = WeakReference(this)
+ drawer_layout.addDrawerListener(object : DrawerLayout.DrawerListener {
+ override fun onDrawerClosed(drawerView: View) {
+ Log.d("MyMain", "onDrawerClosed")
+ isDrawerClosed = true
+ }
+
+ override fun onDrawerOpened(drawerView: View) {
+ Log.d("MyMain", "onDrawerOpened")
+ isDrawerClosed = false
+ DownloadFragment.currentDir = getExternalFilesDir("")
+ }
+
+ override fun onDrawerSlide(drawerView: View, slideOffset: Float) {}
+ override fun onDrawerStateChanged(newState: Int) {}
+ })
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu): Boolean {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ menuInflater.inflate(R.menu.main, menu)
+ menuMain = menu
+ return true
+ }
+
+ override fun onSupportNavigateUp(): Boolean {
+ val navController = findNavController(R.id.nav_host_fragment)
+
+ checkHeadPicture()
+ if (headPic.exists()) navhbg.setOnLongClickListener {
+ if (headPic.exists()) {
+ val dl = AlertDialog.Builder(this)
+ dl.setMessage(R.string.clearHeadImgMsg)
+ dl.setPositiveButton(android.R.string.ok) { _, _ ->
+ if (headPic.exists()) headPic.delete()
+ navhbg.setImageResource(R.drawable.illust_57793944_20190427_134853)
+ }
+ dl.show()
+ }
+ true
+ }
+ p["navTextInfo"].let { if (it != "null") navtinfo.text = it }
+ return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ if (resultCode == RESULT_OK) when (requestCode) {
+ UCrop.REQUEST_CROP -> {
+ val fi = headPic.inputStream()
+ navhbg.setImageBitmap(BitmapFactory.decodeStream(fi))
+ fi.close()
+ }
+ 1 -> {
+ data?.data?.let {
+ saveFile(it)
+ cropImageUri()
+ }
+ }
+ }
+ }
+
+ override fun onRequestPermissionsResult(
+ requestCode: Int,
+ permissions: Array,
+ grantResults: IntArray
+ ) {
+ when (requestCode) {
+ 1 -> {
+ if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) pickPicture()
+ else Toast.makeText(this, R.string.permissionDenied, Toast.LENGTH_SHORT).show()
+ }
+ }
+ }
+
+ private fun checkReadPermission(): Boolean {
+ return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N && ContextCompat.checkSelfPermission(
+ this,
+ Manifest.permission.READ_EXTERNAL_STORAGE
+ ) != PackageManager.PERMISSION_GRANTED
+ ) {
+ ActivityCompat.requestPermissions(
+ this,
+ arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 1
+ )
+ false
+ } else true
+ }
+
+ private fun pickPicture() {
+ val i = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
+ i.type = "image/*"
+ startActivityForResult(i, 1)
+ }
+
+ private fun saveFile(uri: Uri) {
+ //val f = File(getExternalFilesDir(""), "headPic")
+ val fd = contentResolver.openFileDescriptor(uri, "r")
+ fd?.fileDescriptor?.let {
+ val fi = FileInputStream(it)
+ val fo = headPic.outputStream()
+ fi.copyTo(fo)
+ fi.close()
+ fo.close()
+ }
+ fd?.close()
+ }
+
+ private fun checkHeadPicture() {
+ //val hp = File(getExternalFilesDir(""), "headPic")
+ if (headPic.exists()) navhbg.setImageURI(headPic.toUri())
+ }
+
+ private fun cropImageUri() {
+ val op = UCrop.Options()
+ val r = navhbg.width.toFloat() / navhbg.height.toFloat()
+ Log.d("MyMain", "Img info: (${navhbg.width}, ${navhbg.height})")
+ Log.d("MyMain", "Result code: ${UCrop.REQUEST_CROP}")
+ op.setCompressionFormat(Bitmap.CompressFormat.WEBP)
+ op.setStatusBarColor(resources.getColor(R.color.colorPrimaryDark, theme))
+ op.setToolbarColor(resources.getColor(R.color.colorPrimary, theme))
+ op.setActiveControlsWidgetColor(resources.getColor(R.color.colorAccent, theme))
+ UCrop.of(headPic.toUri(), headPic.toUri())
+ .withAspectRatio(r, 1F)
+ .withMaxResultSize(navhbg.width, navhbg.height)
+ .withOptions(op)
+ .start(this)
+ }
+
+ /*private fun translucentStatusBar() {
+ //添加Flag把状态栏设为可绘制模式
+ window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
+ //如果为全透明模式,取消设置Window半透明的Flag
+ window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
+ //设置状态栏为透明
+ window.statusBarColor = Color.TRANSPARENT
+ //设置window的状态栏不可见
+ window.decorView.systemUiVisibility =
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ //view不根据系统窗口来调整自己的布局
+ val mContentView: ViewGroup = window.findViewById(Window.ID_ANDROID_CONTENT) as ViewGroup
+ val mChildView: View = mContentView.getChildAt(0)
+ ViewCompat.requestApplyInsets(mChildView)
+
+ coordiv.layoutParams.height = getStatusBarHeight()
+ }*/
+
+ private fun getStatusBarHeight() =
+ resources.getDimensionPixelOffset(
+ resources.getIdentifier(
+ "status_bar_height",
+ "dimen",
+ "android"
+ )
+ )
+
+
+ fun showAbout(item: MenuItem) {
+ val dl = android.app.AlertDialog.Builder(this)
+ dl.setMessage(R.string.app_description)
+ dl.setTitle(R.string.action_info)
+ dl.setIcon(R.mipmap.ic_launcher)
+ dl.setPositiveButton(android.R.string.ok) { _, _ -> }
+ dl.show()
+ }
+
+ fun onNavTInfoClicked(it: View) {
+ MaterialDialog(this).show {
+ input(prefill = (it as TextView).text) { _, charSequence ->
+ it.text = charSequence
+ p["navTextInfo"] = charSequence.toString()
+ }
+ positiveButton(android.R.string.ok)
+ title(R.string.navTextInfoInputHint)
+ }
+ }
+
+ fun onNavHBgClicked(v: View) {
+ if (checkReadPermission()) pickPicture()
+ }
+
+ fun startLoginActivity(v: View){
+ startActivity(Intent(this, LoginActivity::class.java))
+ }
+
+ companion object{
+ var mainWeakReference: WeakReference? = null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/activity/DlActivity.kt b/app/src/main/java/top/fumiama/copymanga/activity/DlActivity.kt
deleted file mode 100644
index 6e6302c..0000000
--- a/app/src/main/java/top/fumiama/copymanga/activity/DlActivity.kt
+++ /dev/null
@@ -1,332 +0,0 @@
-package top.fumiama.copymanga.activity
-
-import android.animation.ObjectAnimator
-import android.annotation.SuppressLint
-import android.app.Activity
-import android.content.Intent
-import android.os.Bundle
-import android.os.Looper
-import android.view.View
-import android.view.ViewGroup
-import android.view.ViewTreeObserver
-import android.widget.Toast
-import android.widget.ToggleButton
-import com.google.gson.Gson
-import kotlinx.android.synthetic.main.activity_dl.*
-import kotlinx.android.synthetic.main.button_tbutton.view.*
-import kotlinx.android.synthetic.main.line_caption.view.*
-import kotlinx.android.synthetic.main.line_horizonal.view.*
-import kotlinx.android.synthetic.main.widget_downloadbar.*
-import kotlinx.android.synthetic.main.widget_titlebar.*
-import top.fumiama.copymanga.R
-import top.fumiama.copymanga.activity.MainActivity.Companion.mh
-import top.fumiama.copymanga.data.ComicStructure
-import top.fumiama.copymanga.handler.DlHandler
-import top.fumiama.copymanga.tool.MangaDlTools
-import top.fumiama.copymanga.tool.MangaDlTools.Companion.wmdlt
-import top.fumiama.copymanga.tool.ToolsBox
-import top.fumiama.copymanga.view.ChapterToggleButton
-import top.fumiama.copymanga.view.LazyScrollView
-import java.io.File
-import java.lang.Thread.sleep
-import java.lang.ref.WeakReference
-import java.util.zip.ZipFile
-
-
-class DlActivity : Activity() {
- private var tbtncnt = 0
- private var isNewTitle = false
- var haveSElectAll = false
- var checkedChapter = 0
- var dldChapter = 0
- var haveDlStarted = false
- private var btnNumPerRow = 4
- private lateinit var ltbtn: View
- var tbtnlist: Array = arrayOf()
- private val handler = DlHandler(this, Looper.myLooper()!!)
- private var btnw = 0
- private var cdwnWidth = 0
- private var canDl = false
- private lateinit var toolsBox: ToolsBox
- private lateinit var mangaDlTools: MangaDlTools
- var multiSelect = false
-
- @ExperimentalStdlibApi
- @SuppressLint("SetTextI18n")
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_dl)
- mh?.saveUrlsOnly = true
- mangaDlTools = MangaDlTools(this)
- handler.sendEmptyMessage(-2) //setLayouts
- }
-
- override fun onDestroy() {
- mh?.saveUrlsOnly = false
- wmdlt?.get()?.exit = true
- super.onDestroy()
- }
-
- private fun showDlCard(){
- //ObjectAnimator.ofFloat(csdwn, "alpha", 0.3f, 0.9f).setDuration(233).start()
- ObjectAnimator.ofFloat(csdwn, "translationX", cdwnWidth.toFloat() * 0.9f, 0f).setDuration(
- 233
- ).start()
- }
-
- private fun hideDlCard(){
- //ObjectAnimator.ofFloat(csdwn, "alpha", 0.9f, 0.3f).setDuration(233).start()
- ObjectAnimator.ofFloat(csdwn, "translationX", 0f, cdwnWidth.toFloat() * 0.9f).setDuration(
- 233
- ).start()
- }
-
- private fun fillChapters() {
- mangaDlTools.allocateChapterUrls(checkedChapter)
- for (i in tbtnlist) {
- if (i.isChecked) mangaDlTools.dlChapterUrl(i.url.toString())
- }
- }
-
- private fun dlThread(dlMethod: (i: ChapterToggleButton) -> Unit) {
- sleep(10000)
- for (i in tbtnlist) {
- if (i.isChecked) dlMethod(i)
- if (!canDl) {
- checkedChapter -= dldChapter
- dldChapter = 0
- break
- }
- }
- if (canDl) {
- haveDlStarted = false
- canDl = false
- }
- handler.sendEmptyMessage(8) //set dl card color to blue
- }
-
- @ExperimentalStdlibApi
- @SuppressLint("SetTextI18n")
- fun setLayouts() {
- ttitle.text = comicName
- toolsBox = ToolsBox(WeakReference(this))
- val widthData = toolsBox.calcWidthFromDp(8, 64)
- btnNumPerRow = widthData[0]
- btnw = widthData[1]
- csdwn.viewTreeObserver.addOnGlobalLayoutListener(object :
- ViewTreeObserver.OnGlobalLayoutListener {
- override fun onGlobalLayout() {
- cdwnWidth = csdwn.width
- csdwn.viewTreeObserver.removeOnGlobalLayoutListener(this)
- }
- })
- dllazys.onScrollListener = object : LazyScrollView.OnScrollListener {
- override fun onBottom() {}
- override fun onScroll() { if (csdwn.translationX == 0f) hideDlCard() }
- override fun onTop() {}
- }
- cdwn.setOnClickListener {
- if (csdwn.translationX != 0f) showDlCard()
- else if (checkedChapter == 0) hideDlCard()
- else {
- pdwn.progress = 0
- if (canDl || checkedChapter == 0) canDl = false
- else {
- haveDlStarted = true
- canDl = true
- handler.sendEmptyMessage(9) //set dl card color to red
- Toast.makeText(this, "十秒后开始下载...", Toast.LENGTH_SHORT).show()
- fillChapters()
- Thread { dlThread { downloadChapterPages(it) } }.start()
- }
- }
- }
- cdwn.setOnLongClickListener {
- handler.sendEmptyMessage(4)
- return@setOnLongClickListener true
- }
- isearch.setOnClickListener { showMultiSelectInfo() }
- analyzeStructure()
- }
-
- private fun showMultiSelectInfo() {
- toolsBox.buildInfo("进入多选模式?", "确定后,长按下载条可选中全部漫画,而不仅限于未下载者;点击已下载漫画可进行选择。",
- "确定", null, "取消", { multiSelect = true })
- }
-
- private fun analyzeStructure() {
- ViewMangaActivity.zipList = arrayOf()
- Gson().fromJson(json?.reader(), Array::class.java)?.let {
- for (group in it) {
- val tc = layoutInflater.inflate(R.layout.line_caption, ldwn, false)
- tc.tcptn.text = group.name
- ldwn.addView(
- tc,
- ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT
- )
- )
- ldwn.addView(
- layoutInflater.inflate(R.layout.div_h, ldwn, false),
- ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT
- )
- )
- isNewTitle = true
- for (chapter in group.chapters) addTbtn(chapter.name, chapter.url, group.name)
- }
- }
- val mangaHome = File("${getExternalFilesDir("")}/$comicName")
- val jsonFile = File(mangaHome, "info.bin")
- if(!mangaHome.exists()) mangaHome.mkdirs()
- if(!(jsonFile.exists() && intent.getBooleanExtra("callFromDlList", false))) json?.let { jsonFile.writeText(it) }
- }
-
- @ExperimentalStdlibApi
- private fun downloadChapterPages(i: ChapterToggleButton) {
- mangaDlTools.onDownloadedListener =
- object : MangaDlTools.OnDownloadedListener {
- override fun handleMessage(succeed: Boolean) {
- handler.obtainMessage(if (succeed) 1 else -1, i.index, 0)
- .sendToTarget()
- }
- override fun handleMessage(succeed: Boolean, pageNow: Int) {
- handler.obtainMessage(
- 5,
- i.index,
- pageNow,
- succeed
- ).sendToTarget()
- }
- override fun handleMessage(pageNow: Int){
- handler.obtainMessage(
- 10,
- i.index,
- pageNow
- ).sendToTarget()
- }
- }
- i.hash?.let {
- mangaDlTools.dlChapterAndPackIntoZip(
- File("${getExternalFilesDir("")}/$comicName/${i.hint}/${i.textOn}.zip"),
- it
- )
- }
- }
-
- @SuppressLint("SetTextI18n")
- fun addTbtn(title: String, url: String, caption: String) {
- if ((tbtncnt % btnNumPerRow == 0) || isNewTitle) {
- ltbtn = layoutInflater.inflate(R.layout.line_horizonal, ldwn, false)
- ldwn.addView(ltbtn)
- tbtncnt = 0
- isNewTitle = false
- }
- val tbv = layoutInflater.inflate(R.layout.button_tbutton, ltbtn.ltbtn, false)
- tbv.tbtn.index = tbtnlist.size
- tbtnlist += tbv.tbtn
- tbv.tbtn.url = url
- tbtncnt++
- val zipPosition = ViewMangaActivity.zipList?.size
- ViewMangaActivity.zipList = ViewMangaActivity.zipList?.plus("$title.zip")
- tbv.tbtn.textOff = title
- tbv.tbtn.textOn = title
- tbv.tbtn.text = title
- tbv.tbtn.hint = caption
- tbv.tbtn.layoutParams.width = btnw
- val zipf = File("${getExternalFilesDir("")}/$comicName/$caption/$title.zip")
- if (zipf.exists()) {
- tbv.tbtn.setBackgroundResource(R.drawable.rndbg_checked)
- tbv.tbtn.isChecked = false
- tbv.tbtn.freezesText = true
- }
- ltbtn.ltbtn.addView(tbv)
- ltbtn.invalidate()
- tbv.tbtn.setOnClickListener {
- val normalAct = (multiSelect && zipf.exists()) || !zipf.exists()
- if (zipf.exists() && !it.tbtn.isChecked) it.tbtn.setBackgroundResource(R.drawable.rndbg_checked)
- else if(normalAct) it.tbtn.setBackgroundResource(R.drawable.toggle_button)
- if(normalAct){
- if (it.tbtn.isChecked) tdwn.text = "$dldChapter/${++checkedChapter}"
- else tdwn.text = "$dldChapter/${--checkedChapter}"
- }else if(it.tbtn.isChecked){
- it.tbtn.isChecked = false
- zipPosition?.let { callVM(title, zipf, it) }
- }
- }
- tbv.tbtn.setOnLongClickListener {
- if (zipf.exists()) {
- toolsBox.buildInfo("确认删除这些章节?",
- "该操作将不可撤销",
- "确定",
- null,
- "取消",
- {
- if (checkedChapter == 0) {
- it.tbtn.isChecked = true
- tdwn.text = "$dldChapter/${++checkedChapter}"
- }
- handler.sendEmptyMessage(7)
- })
- }
- true
- }
- }
-
- fun deleteChapters() {
- for (i in tbtnlist) {
- if (i.isChecked) {
- val f = File("${getExternalFilesDir("")}/$comicName/${i.hint}/${i.textOn}.zip")
- if (f.exists()) {
- deleteChapter(f, i)
- checkedChapter--
- }
- }
- }
- handler.sendEmptyMessage(6)
- }
-
- private fun callVM(titleText: String, zipFile: File, zipPosition:Int){
- ViewMangaActivity.titleText = titleText
- ViewMangaActivity.zipFile = zipFile
- //ViewMangaActivity.zipList = zipArrayList
- ViewMangaActivity.zipPosition = zipPosition
- ViewMangaActivity.cd = zipFile.parentFile
- startActivity(Intent(this, ViewMangaActivity::class.java))
- }
-
- private fun deleteChapter(f: File, v: ToggleButton) {
- f.delete()
- v.setBackgroundResource(R.drawable.toggle_button)
- v.isChecked = false
- }
-
- @SuppressLint("SetTextI18n")
- fun updateProgressBar() {
- tdwn.text = "${++dldChapter}/$checkedChapter"
- setProgress2(dldChapter * 100 / checkedChapter, 233)
- }
-
- fun updateProgressBar(pageNow: Int, size: Int) {
- val delta = 100 / checkedChapter
- val start = dldChapter * delta
- val now = pageNow * delta / size
- setProgress2(start + now, 64)
- }
-
- fun setProgress2(end: Int, duration: Long) {
- ObjectAnimator.ofInt(
- pdwn,
- "progress",
- pdwn.progress,
- end
- ).setDuration(duration).start()
- }
-
- companion object {
- var comicName = "Null"
- var json: String? = null
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/activity/DlListActivity.kt b/app/src/main/java/top/fumiama/copymanga/activity/DlListActivity.kt
deleted file mode 100644
index 99072d0..0000000
--- a/app/src/main/java/top/fumiama/copymanga/activity/DlListActivity.kt
+++ /dev/null
@@ -1,174 +0,0 @@
-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() {
- private var nullZipDirStr = emptyArray()
- private var handler: DlLHandler? = null
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_dlist)
- ttitle.text = intent.getStringExtra("title")
- handler = DlLHandler(Looper.myLooper()!!, this)
- handler?.obtainMessage(3, currentDir)?.sendToTarget() //call scanFile
- }
-
- fun scanFile(cd: File?){
- val isRoot = cd == getExternalFilesDir("")
- val jsonFile = File(cd, "info.bin")
- if(isRoot || !jsonFile.exists()) 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])
- val chosenJson = File(chosenFile, "info.bin")
- //Toast.makeText(this, "进入$chosenFile", Toast.LENGTH_SHORT).show()
- when {
- chosenJson.exists() -> callDownloadActivity(chosenJson)
- chosenFile.isDirectory -> {
- currentDir = chosenFile
- startActivity(
- Intent(
- this,
- DlListActivity::class.java
- ).putExtra("title", it[position])
- )
- }
- chosenFile.name.endsWith(".zip") -> {
- Toast.makeText(this, "加载中...", Toast.LENGTH_SHORT).show()
- ViewMangaActivity.zipFile = chosenFile
- ViewMangaActivity.titleText = it[position]
- ViewMangaActivity.zipPosition = position
- ViewMangaActivity.zipList = it as Array
- 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()) 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
- }
- }
- }
-
- fun rmrf(f: File) {
- if (f.isDirectory) f.listFiles()?.let {
- for (i in it)
- if (i.isDirectory) rmrf(i)
- else i.delete()
- }
- 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()
- }
-
- private fun callDownloadActivity(jsonFile: File){
- DlActivity.json = jsonFile.readText()
- DlActivity.comicName = jsonFile.parentFile?.name?:"Null"
- startActivity(
- Intent(this, DlActivity::class.java)
- .putExtra("callFromDlList", true)
- )
- }
-
- 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 if(newString.isEmpty()) 0f else newString.toString().toFloat()
- }
-
- companion object{
- var currentDir: File? = null
- }
-}
-
diff --git a/app/src/main/java/top/fumiama/copymanga/activity/MainActivity.kt b/app/src/main/java/top/fumiama/copymanga/activity/MainActivity.kt
deleted file mode 100644
index a8a7096..0000000
--- a/app/src/main/java/top/fumiama/copymanga/activity/MainActivity.kt
+++ /dev/null
@@ -1,65 +0,0 @@
-package top.fumiama.copymanga.activity
-
-import android.annotation.SuppressLint
-import android.app.Activity
-import android.content.Intent
-import android.os.Bundle
-import android.os.Looper
-import android.view.View
-import android.webkit.WebView
-import kotlinx.android.synthetic.main.activity_main.*
-import top.fumiama.copymanga.R
-import top.fumiama.copymanga.handler.MainHandler
-import top.fumiama.copymanga.tool.ToolsBox
-import top.fumiama.copymanga.view.JSWebView
-import top.fumiama.copymanga.web.JS
-import top.fumiama.copymanga.web.JSHidden
-import top.fumiama.copymanga.web.WebChromeClient
-import java.lang.ref.WeakReference
-
-class MainActivity: Activity() {
- var wh: JSWebView? = null
- var toolsBox: ToolsBox? = null
- @SuppressLint("JavascriptInterface")
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
-
- wm = WeakReference(this)
- mh = MainHandler(Looper.myLooper()!!)
- toolsBox = ToolsBox(wm as WeakReference)
- toolsBox?.netinfo?.let {
- if(it == "无网络" || it == "错误"){
- Thread{mh?.sendEmptyMessage(6)}.start()
- }else{
- WebView.setWebContentsDebuggingEnabled(true)
- w.setWebViewClient("i.js")
- w.webChromeClient = WebChromeClient()
- w.loadJSInterface(JS())
- w.loadUrl(getString(R.string.web_home))
-
- wh = JSWebView(this, getString(R.string.pc_ua))
- wh?.setWebViewClient("h.js")
- wh?.loadJSInterface(JSHidden())
- }
- }
- }
-
- override fun onBackPressed() {
- if(w.canGoBack()) w.goBack()
- else super.onBackPressed()
- }
-
- fun onFabClicked(v: View){
- DlListActivity.currentDir = getExternalFilesDir("")
- startActivity(
- Intent(this, (if(mh?.showDlList == true) DlListActivity::class else DlActivity::class).java)
- .putExtra("title", "我的下载")
- )
- }
-
- companion object{
- var wm: WeakReference? = null
- var mh: MainHandler? = null
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/activity/ViewMangaActivity.kt b/app/src/main/java/top/fumiama/copymanga/activity/ViewMangaActivity.kt
deleted file mode 100644
index 07b6e16..0000000
--- a/app/src/main/java/top/fumiama/copymanga/activity/ViewMangaActivity.kt
+++ /dev/null
@@ -1,444 +0,0 @@
-package top.fumiama.copymanga.activity
-
-import android.animation.ObjectAnimator
-import android.annotation.SuppressLint
-import android.app.Activity
-import android.graphics.Bitmap
-import android.graphics.BitmapFactory
-import android.os.*
-import android.util.Log
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.SeekBar
-import android.widget.Toast
-import androidx.recyclerview.widget.RecyclerView
-import androidx.viewpager2.widget.ViewPager2
-import com.bumptech.glide.Glide
-import kotlinx.android.synthetic.main.activity_main.*
-import kotlinx.android.synthetic.main.activity_viewmanga.*
-import kotlinx.android.synthetic.main.page_imgview.*
-import kotlinx.android.synthetic.main.page_imgview.view.*
-import kotlinx.android.synthetic.main.widget_infodrawer.*
-import kotlinx.android.synthetic.main.widget_infodrawer.view.*
-import kotlinx.android.synthetic.main.widget_titlebar.*
-import kotlinx.android.synthetic.main.widget_viewmangainfo.*
-import top.fumiama.copymanga.R
-import top.fumiama.copymanga.activity.MainActivity.Companion.wm
-import top.fumiama.copymanga.handler.TimeThread
-import top.fumiama.copymanga.tool.PropertiesTools
-import top.fumiama.copymanga.tool.ToolsBox
-import java.io.File
-import java.lang.ref.WeakReference
-import java.text.SimpleDateFormat
-import java.util.*
-import java.util.zip.ZipFile
-import java.util.zip.ZipInputStream
-
-
-class ViewMangaActivity : Activity() {
- var count = 0
- lateinit var handler: Handler
- lateinit var tt: TimeThread
- var clicked = false
- private var isInSeek = false
- private var useFullScreen = false
- var r2l = true
- private var currentItem = 0
- private var notUseVP = true
- //private var q = 90
- var infoDrawerDelta = 0f
- lateinit var toolsBox: ToolsBox
- private lateinit var p: PropertiesTools
- private var mangaZip = zipFile
- val dlZip2View = mangaZip != null
- var pageNum = 1
- get() {
- field = getPageNumber()
- return field
- }
- set(value) {
- setPageNumber(value)
- if (notUseVP) {
- //currentItem += delta
- try {
- loadOneImg()
- } catch (e: java.lang.Exception) {
- e.printStackTrace()
- toolsBox.toastError("页数${currentItem}不合法")
- }
- }// else vp.currentItem += delta
- field = getPageNumber()
- }
-
- @ExperimentalStdlibApi
- @SuppressLint("SetTextI18n")
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_viewmanga)
- toolsBox = ToolsBox(WeakReference(this))
- va = WeakReference(this)
- p = PropertiesTools(File("$filesDir/settings.properties"))
- useFullScreen = p["useFullScreen"] != "true"
- r2l = p["r2l"] == "true"
- //toolsBox = ToolsBox(WeakReference(this))
- notUseVP = p["noAnimation"] == "true"
- handler = MyHandler(infcard, toolsBox)
- //if (p["quality"] == "null") p["quality"] = "90"
- //else q = p["quality"].toInt()
- tt = TimeThread(handler, 22)
- tt.canDo = true
- tt.start()
- ttitle.text = titleText
- //isearch.visibility = View.VISIBLE
- Log.d("MyVM", "dlZip2View: $dlZip2View, mangaZip: $mangaZip")
- if(dlZip2View && mangaZip?.exists() != true) toolsBox.toastError("已经到头了~")
- else {
- try {
- count = if (dlZip2View) countZipItems() else imgUrls.size
- } catch (e: Exception) {
- e.printStackTrace()
- toolsBox.toastError("分析图片url错误")
- }
- try {
- prepareItems()
- if(pn > 0) {
- pageNum = pn
- pn = -1
- }else if(pn == -2){
- pageNum = count
- pn = -1
- }
- } catch (e: Exception) {
- e.printStackTrace()
- toolsBox.toastError("准备控件错误")
- }
- }
- }
-
- override fun onWindowFocusChanged(hasFocus: Boolean) {
- super.onWindowFocusChanged(hasFocus)
- if (useFullScreen) {
- window.decorView.systemUiVisibility =
- View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) window.setDecorFitsSystemWindows(false)
- }
- }
-
- private fun getPageNumber(): Int {
- return if (r2l && !notUseVP) count - vp.currentItem
- else (if (notUseVP) currentItem else vp.currentItem) + 1
- }
-
- private fun setPageNumber(num: Int) {
- if (r2l && !notUseVP) vp.currentItem = count - num
- else if (notUseVP) currentItem = num - 1 else vp.currentItem = num - 1
- }
-
- private fun getImgBitmap(position: Int): Bitmap? {
- if (position >= count || position < 0) return null
- else {
- val zip = ZipFile(mangaZip)
- //if (q == 100)
- return BitmapFactory.decodeStream(zip.getInputStream(zip.getEntry("${position}.webp")))
- /*else {
- val out = ByteArrayOutputStream()
- try {
- BitmapFactory.decodeStream(zip.getInputStream(zip.getEntry("${position}.jpg")))
- } catch (e: Exception) {
- e.printStackTrace()
- return null
- }?.compress(Bitmap.CompressFormat.JPEG, q, out)
- return BitmapFactory.decodeStream(ByteArrayInputStream(out.toByteArray()))
- }*/
- }
- }
-
- private fun loadOneImg() {
- if(dlZip2View) onei.setImageBitmap(getImgBitmap(currentItem))
- else Glide.with(this@ViewMangaActivity)
- .load(imgUrls[currentItem])
- .placeholder(R.drawable.ic_dl)
- .dontAnimate()
- .into(onei)
- updateSeekBar()
- }
-
- private fun setIdPosition(position: Int) {
- infoDrawerDelta = position.toFloat()
- infcard.translationY = infoDrawerDelta
- }
-
- @SuppressLint("SetTextI18n")
- private fun prepareItems() {
- prepareVP()
- prepareInfoBar(count)
- if (notUseVP) loadOneImg() else prepareIdBtVH()
- toolsBox.dp2px(67)?.let { setIdPosition(it) }
- prepareIdBtFullScreen()
- prepareIdBtVP()
- prepareIdBtLR()
- }
-
- private fun prepareIdBtLR() {
- idtblr.isChecked = r2l
- idtblr.setOnClickListener {
- if (idtblr.isChecked) p["r2l"] = "true"
- else p["r2l"] = "false"
- Toast.makeText(this, "下次浏览生效", Toast.LENGTH_SHORT).show()
- }
- }
-
- private fun prepareIdBtVP() {
- idtbvp.isChecked = notUseVP
- idtbvp.setOnClickListener {
- if (idtbvp.isChecked) p["noAnimation"] = "true"
- else p["noAnimation"] = "false"
- Toast.makeText(this, "下次浏览生效", Toast.LENGTH_SHORT).show()
- }
- }
-
- private fun prepareVP() {
- if (notUseVP) {
- vp.visibility = View.INVISIBLE
- vone.visibility = View.VISIBLE
- } else {
- vp.visibility = View.VISIBLE
- vone.visibility = View.INVISIBLE
- vp.adapter = ViewData(vp).RecyclerViewAdapter()
- vp.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
- override fun onPageSelected(position: Int) {
- updateSeekBar()
- super.onPageSelected(position)
- }
- })
- if (r2l) vp.currentItem = count - 1
- }
- }
-
- private fun updateSeekBar() {
- if (!isInSeek) hideObjs()
- updateSeekText()
- updateSeekProgress()
- sendProgress()
- }
-
- @SuppressLint("SetTextI18n")
- private fun prepareInfoBar(size: Int) {
- oneinfo.alpha = 0F
- infseek.visibility = View.INVISIBLE
- isearch.visibility = View.INVISIBLE
- inftxtprogress.text = "$pageNum/$size"
- infseek.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
- override fun onProgressChanged(p0: SeekBar?, p1: Int, isHuman: Boolean) {
- if (isHuman) {
- if (p1 >= (pageNum + 1) * 100 / size) scrollForward()
- else if (p1 < (pageNum - 1) * 100 / size) scrollBack()
- }
- }
-
- override fun onStartTrackingTouch(p0: SeekBar?) {
- isInSeek = true
- }
-
- override fun onStopTrackingTouch(p0: SeekBar?) {
- isInSeek = false
- }
- })
- isearch.setOnClickListener {
- handler.sendEmptyMessage(3)
- }
- }
-
- private fun prepareIdBtVH() {
- idtbvh.isChecked =
- p["vertical"] == "true"
- if (idtbvh.isChecked) vp.orientation = ViewPager2.ORIENTATION_VERTICAL
- idtbvh.setOnClickListener {
- if (idtbvh.isChecked) {
- vp.orientation = ViewPager2.ORIENTATION_VERTICAL
- p["vertical"] = "true"
- } else {
- vp.orientation = ViewPager2.ORIENTATION_HORIZONTAL
- p["vertical"] = "false"
- }
- }
- }
-
- private fun prepareIdBtFullScreen() {
- idtbfullscreen.isChecked = !useFullScreen
- idtbfullscreen.setOnClickListener {
- if (idtbfullscreen.isChecked) p["useFullScreen"] =
- "true"
- else p["useFullScreen"] = "false"
- Toast.makeText(this, "下次浏览生效", Toast.LENGTH_SHORT).show()
- }
- }
-
- private fun countZipItems(): Int {
- var c = 0
- try {
- val exist = mangaZip?.exists() == true
- if (!exist) return 0
- else {
- Log.d("Myvm", "zipf: $mangaZip")
- val zip = ZipInputStream(mangaZip?.inputStream()?.buffered())
- var entry = zip.nextEntry
- while (entry != null) {
- if (!entry.isDirectory) c++
- entry = zip.nextEntry
- }
- zip.closeEntry()
- zip.close()
- }
- } catch (e: Exception) {
- toolsBox.toastError("读取zip错误!")
- }
- return c
- }
-
- fun scrollBack() {
- pageNum--
- }
-
- fun scrollForward() {
- pageNum++
- }
-
- private fun sendProgress() {
-
- }
-
- @SuppressLint("SetTextI18n")
- private fun updateSeekText() {
- inftxtprogress.text = "$pageNum/$count"
- }
-
- private fun updateSeekProgress() {
- infseek.progress = pageNum * 100 / count
- }
-
- override fun onBackPressed() {
- tt.canDo = false
- wm?.get()?.w?.goBack()
- super.onBackPressed()
- }
-
- override fun onDestroy() {
- tt.canDo = false
- super.onDestroy()
- }
-
- inner class ViewData(itemView: View) : RecyclerView.ViewHolder(itemView) {
- inner class RecyclerViewAdapter :
- RecyclerView.Adapter() {
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewData {
- return ViewData(
- LayoutInflater.from(parent.context)
- .inflate(R.layout.page_imgview, parent, false)
- )
- }
-
- @SuppressLint("ClickableViewAccessibility", "SetTextI18n")
- override fun onBindViewHolder(holder: ViewData, position: Int) {
- val pos = if (r2l) count - position - 1 else position
- if(dlZip2View) getImgBitmap(pos)?.let {
- //Glide.with(this@ViewMangaActivity).load(it).placeholder(R.drawable.bg_comment).into(holder.itemView.onei)
- holder.itemView.onei.setImageBitmap(it)
- }
- else Glide.with(this@ViewMangaActivity).load(imgUrls[pos]).placeholder(R.drawable.ic_dl).dontAnimate().timeout(10000).into(holder.itemView.onei)
- }
-
- override fun getItemCount(): Int {
- return count
- }
- }
- }
-
- fun showObjs() {
- infseek.visibility = View.VISIBLE
- isearch.visibility = View.VISIBLE
- ObjectAnimator.ofFloat(
- oneinfo,
- "alpha",
- oneinfo.alpha,
- 1F
- ).setDuration(233).start()
- clicked = true
- }
-
- fun hideObjs() {
- ObjectAnimator.ofFloat(
- oneinfo,
- "alpha",
- oneinfo.alpha,
- 0F
- ).setDuration(233).start()
- clicked = false
- infseek.postDelayed({
- infseek.visibility = View.INVISIBLE
- isearch.visibility = View.INVISIBLE
- }, 300)
- handler.sendEmptyMessage(1)
- }
-
- class MyHandler(
- private val infcard: View,
- private val toolsBox: ToolsBox
- ) : Handler(Looper.myLooper()!!) {
- private var infcShowed = false
- private var delta = -1f
- get() {
- if (field < 0) field = va?.get()?.infoDrawerDelta ?: 0f
- return field
- }
-
- @SuppressLint("SimpleDateFormat", "SetTextI18n")
- override fun handleMessage(msg: Message) {
- super.handleMessage(msg)
- when (msg.what) {
- 1 -> if (infcShowed) {
- hideInfCard(); infcShowed = false
- }
- 2 -> if (!infcShowed) {
- showInfCard(); infcShowed = true
- }
- 3 -> infcShowed = if (infcShowed) {
- hideInfCard(); false
- } else {
- showInfCard(); true
- }
- 22 -> toolsBox.zis?.idtime?.text =
- SimpleDateFormat("HH:mm").format(Date()) + toolsBox.week + toolsBox.netinfo
- }
- }
-
- private fun showInfCard() {
- ObjectAnimator.ofFloat(infcard.idc, "alpha", 0.3F, 0.8F).setDuration(233).start()
- ObjectAnimator.ofFloat(infcard, "translationY", delta, 0F).setDuration(233).start()
- }
-
- private fun hideInfCard() {
- ObjectAnimator.ofFloat(infcard.idc, "alpha", 0.8F, 0.3F).setDuration(233).start()
- ObjectAnimator.ofFloat(infcard, "translationY", 0F, delta).setDuration(233).start()
- }
- }
-
- companion object {
- var va: WeakReference? = null
- var imgUrls = arrayOf()
- var zipFile: File? = null
- get() {
- val re = field
- if(field != null) field = null
- return re
- }
- var titleText = "Null"
- var nextChapterUrl: String? = null
- var previousChapterUrl: String? = null
- var zipPosition = 0
- var zipList: Array? = null
- var cd: File? = null
- var pn = -1
- }
-}
\ 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
deleted file mode 100644
index 635a755..0000000
--- a/app/src/main/java/top/fumiama/copymanga/handler/DlHandler.kt
+++ /dev/null
@@ -1,97 +0,0 @@
-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
-import kotlinx.android.synthetic.main.widget_downloadbar.*
-import top.fumiama.copymanga.R
-import top.fumiama.copymanga.activity.DlActivity
-import top.fumiama.copymanga.tool.MangaDlTools.Companion.wmdlt
-import java.lang.ref.WeakReference
-
-class DlHandler(activity: DlActivity, looper: Looper) : Handler(looper) {
- private val da = WeakReference(activity)
- private val d
- get() = da.get()
- private var size = 0
- private var refreshSize = true
-
- @ExperimentalStdlibApi
- @SuppressLint("SetTextI18n")
- override fun handleMessage(msg: Message) {
- super.handleMessage(msg)
- when (msg.what) {
- -2 -> d?.setLayouts()
- 1 -> {
- d?.tbtnlist?.get(msg.arg1)?.setBackgroundResource(R.drawable.rndbg_checked)
- d?.tbtnlist?.get(msg.arg1)?.isChecked = false
- d?.updateProgressBar()
- if (d?.haveDlStarted == false) {
- d?.dldChapter = 0
- d?.checkedChapter = 0
- this.postDelayed({
- 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?.get(msg.arg1)?.textOn}失败", Toast.LENGTH_SHORT).show()
- d?.updateProgressBar()
- }
- 4 -> {
- d?.pdwn?.progress = 0
- val selectDownloaded = d?.multiSelect?:false
- if (d?.haveSElectAll == true) {
- d?.tbtnlist?.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
- } else {
- d?.let {
- val checkBtn = { i: ToggleButton, it: DlActivity ->
- i.setBackgroundResource(R.drawable.toggle_button)
- i.isChecked = true
- it.checkedChapter++
- }
- for (i in it.tbtnlist) {
- if(selectDownloaded) checkBtn(i, it)
- else if(!i.freezesText) checkBtn(i, it)
- }
- }
- d?.haveSElectAll = true
- }
- d?.tdwn?.text = "${d?.dldChapter}/${d?.checkedChapter}"
- }
- 5 -> {
- setSize(msg.arg2, msg.arg1)
- d?.updateProgressBar(msg.arg2, size)
- if (!(msg.obj as Boolean)) {
- Toast.makeText(d, "下载${d?.tbtnlist?.get(msg.arg1)?.textOn}的第${msg.arg2}页失败", Toast.LENGTH_SHORT).show()
- }else{
- val progressTxt = d?.tdwn?.text.toString()
- d?.tdwn?.text = "${progressTxt.substringBefore(' ')} 的 ${msg.arg2}/${size} 页"
- }
- }
- 6 -> d?.tdwn?.text = "${d?.dldChapter}/${d?.checkedChapter}"
- 7 -> d?.deleteChapters()
- 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()
- }
- }
- private fun setSize(pageNow: Int, tbtnNo: Int){
- if(refreshSize || size == 0) {
- size = d?.tbtnlist?.get(tbtnNo)?.hash?.let { wmdlt?.get()?.getImgsCountByHash(it) }?:0
- refreshSize = false
- }else if(pageNow == size) refreshSize = true
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/handler/MainHandler.kt b/app/src/main/java/top/fumiama/copymanga/handler/MainHandler.kt
deleted file mode 100644
index e7f4ab9..0000000
--- a/app/src/main/java/top/fumiama/copymanga/handler/MainHandler.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-package top.fumiama.copymanga.handler
-
-import android.animation.ObjectAnimator
-import android.content.Intent
-import android.os.Handler
-import android.os.Looper
-import android.os.Message
-import android.view.View
-import kotlinx.android.synthetic.main.activity_main.*
-import top.fumiama.copymanga.activity.DlActivity.Companion.json
-import top.fumiama.copymanga.activity.MainActivity.Companion.wm
-import top.fumiama.copymanga.activity.ViewMangaActivity
-import top.fumiama.copymanga.tool.MangaDlTools.Companion.wmdlt
-
-class MainHandler(looper: Looper):Handler(looper) {
- var saveUrlsOnly = false
- var showDlList = false
- override fun handleMessage(msg: Message) {
- super.handleMessage(msg)
- when(msg.what){
- 1 -> loadUrlInHiddenWebView(msg.obj as String)
- 2 -> callViewManga(msg.obj as String)
- 3 -> updateLoadProgress(msg.arg1)
- 4 -> setFab(msg.obj as String)
- 5 -> hideFab()
- 6 -> setFab2DlList()
- }
- }
- private fun loadUrlInHiddenWebView(url: String){wm?.get()?.wh?.loadUrl(url)}
- private fun callViewManga(content: String){
- val listChapter = content.split('\n')
- if(!saveUrlsOnly) {
- ViewMangaActivity.titleText = listChapter[0].substringBeforeLast(' ')
- ViewMangaActivity.nextChapterUrl = listChapter[1].let { if(it == "null") null else it }
- ViewMangaActivity.previousChapterUrl = listChapter[2].let { if(it == "null") null else it }
- ViewMangaActivity.imgUrls = arrayOf()
- for(i in 3 until listChapter.size) ViewMangaActivity.imgUrls += listChapter[i]
- wm?.get()?.let { it.startActivity(Intent(it, ViewMangaActivity::class.java)) }
- } else{
- var imgs = arrayOf()
- for(i in 3 until listChapter.size) imgs += listChapter[i]
- wmdlt?.get()?.setChapterImgs(listChapter[0].substringAfterLast(' '), imgs)
- }
- }
- private fun updateLoadProgress(progress: Int){
- wm?.get()?.let{
- if(it.pw.progress == 100 && progress < 100) {
- it.pw.progress = 0
- it.pw.visibility = View.VISIBLE
- }
- ObjectAnimator.ofInt(it.pw, "progress", it.pw.progress, progress).setDuration(233).start()
- if(progress == 100) it.pw.postDelayed({it.pw.visibility = View.GONE}, 500)
- }
- }
- private fun showFab() {wm?.get()?.fab?.visibility = View.VISIBLE}
- private fun hideFab() {wm?.get()?.fab?.visibility = View.GONE}
- private fun setFab(content: String){
- //Log.d("MyMH", "Get chapter json: $content")
- showDlList = false
- json = content
- showFab()
- }
- private fun setFab2DlList(){
- showDlList = true
- showFab()
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/json/BookInfoStructure.java b/app/src/main/java/top/fumiama/copymanga/json/BookInfoStructure.java
new file mode 100644
index 0000000..343f5e9
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/json/BookInfoStructure.java
@@ -0,0 +1,11 @@
+package top.fumiama.copymanga.json;
+
+import java.util.HashMap;
+
+public class BookInfoStructure extends ReturnBase {
+ public Results results;
+ public static class Results extends ResultsBase{
+ public ComicStructure comic;
+ public HashMap groups;
+ }
+}
diff --git a/app/src/main/java/top/fumiama/copymanga/json/BookListStructure.java b/app/src/main/java/top/fumiama/copymanga/json/BookListStructure.java
new file mode 100644
index 0000000..515a2b7
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/json/BookListStructure.java
@@ -0,0 +1,11 @@
+package top.fumiama.copymanga.json;
+
+public class BookListStructure extends ReturnBase {
+ public Results results;
+ public static class Results {
+ public int total;
+ public ComicStructure[] list;
+ public int limit;
+ public int offset;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/json/Chapter2Return.java b/app/src/main/java/top/fumiama/copymanga/json/Chapter2Return.java
new file mode 100644
index 0000000..42314a9
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/json/Chapter2Return.java
@@ -0,0 +1,9 @@
+package top.fumiama.copymanga.json;
+
+public class Chapter2Return extends ReturnBase {
+ public Results results;
+ public static class Results extends ResultsBase{
+ public ComicStructure comic;
+ public ChapterWithContent chapter;
+ }
+}
diff --git a/app/src/main/java/top/fumiama/copymanga/json/ChapterStructure.java b/app/src/main/java/top/fumiama/copymanga/json/ChapterStructure.java
new file mode 100644
index 0000000..7302dc6
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/json/ChapterStructure.java
@@ -0,0 +1,18 @@
+package top.fumiama.copymanga.json;
+
+public class ChapterStructure {
+ public int index;
+ public String uuid;
+ public int count;
+ public int size;
+ public String name;
+ public String comic_id;
+ public String comic_path_word;
+ public String group_id;
+ public String group_path_word;
+ public int type;
+ public int img_type;
+ public String datetime_created;
+ public String prev;
+ public String next;
+}
diff --git a/app/src/main/java/top/fumiama/copymanga/json/ChapterWithContent.java b/app/src/main/java/top/fumiama/copymanga/json/ChapterWithContent.java
new file mode 100644
index 0000000..7de6f3b
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/json/ChapterWithContent.java
@@ -0,0 +1,7 @@
+package top.fumiama.copymanga.json;
+
+public class ChapterWithContent extends ChapterStructure {
+ public UUIDUrlPair[] contents;
+ public int[] words;
+ public Boolean is_long;
+}
diff --git a/app/src/main/java/top/fumiama/copymanga/json/ComicStructure.java b/app/src/main/java/top/fumiama/copymanga/json/ComicStructure.java
new file mode 100644
index 0000000..a0cd262
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/json/ComicStructure.java
@@ -0,0 +1,16 @@
+package top.fumiama.copymanga.json;
+
+public class ComicStructure {
+ public String uuid;
+ public String name;
+ public String alias;
+ public ValueDisplayPair status;
+ public ThemeStructure[] theme;
+ public String path_word;
+ public ThemeStructure[] author;
+ public int img_type;
+ public String brief;
+ public String datetime_updated;
+ public String cover;
+ public int popular;
+}
diff --git a/app/src/main/java/top/fumiama/copymanga/data/ComicStructure.java b/app/src/main/java/top/fumiama/copymanga/json/ComicStructureOld.java
similarity index 68%
rename from app/src/main/java/top/fumiama/copymanga/data/ComicStructure.java
rename to app/src/main/java/top/fumiama/copymanga/json/ComicStructureOld.java
index 42719f6..360ad47 100644
--- a/app/src/main/java/top/fumiama/copymanga/data/ComicStructure.java
+++ b/app/src/main/java/top/fumiama/copymanga/json/ComicStructureOld.java
@@ -1,6 +1,6 @@
-package top.fumiama.copymanga.data;
+package top.fumiama.copymanga.json;
-public class ComicStructure {
+public class ComicStructureOld {
public String name;
public Chapters[] chapters;
public static class Chapters{
diff --git a/app/src/main/java/top/fumiama/copymanga/json/FilterStructure.java b/app/src/main/java/top/fumiama/copymanga/json/FilterStructure.java
new file mode 100644
index 0000000..a08fe10
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/json/FilterStructure.java
@@ -0,0 +1,8 @@
+package top.fumiama.copymanga.json;
+
+public class FilterStructure extends ReturnBase {
+ public Results results;
+ public static class Results{
+ public ThemeStructure[] theme;
+ }
+}
diff --git a/app/src/main/java/top/fumiama/copymanga/json/IndexStructure.java b/app/src/main/java/top/fumiama/copymanga/json/IndexStructure.java
new file mode 100644
index 0000000..2d3efee
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/json/IndexStructure.java
@@ -0,0 +1,58 @@
+package top.fumiama.copymanga.json;
+
+public class IndexStructure extends ReturnBase {
+ public Results results;
+ public static class Results{
+ public Banners[] banners;
+ public Topics topics;
+ public RecComics recComics;
+ public RankComics rankDayComics;
+ public RankComics rankWeekComics;
+ public RankComics rankMonthComics;
+ public ComicWrap[] hotComics;
+ public ComicWrap[] newComics;
+ public FinishComics finishComics;
+
+ public static class Banners{
+ public String cover;
+ public String brief;
+ public String out_uuid;
+ public ComicStructure comic;
+ }
+ public static class Topics extends InfoBase{
+ public List[] list;
+
+ public static class List{
+ public String title;
+ public SeriesStructure series;
+ public String journal;
+ public String cover;
+ public String period;
+ public int type;
+ public String brief;
+ public String path_word;
+ public String datetime_created;
+ }
+ }
+ public static class RecComics extends InfoBase{
+ public List[] list;
+
+ public static class List{
+ public int type;
+ public ComicStructure comic;
+ }
+ }
+ public static class RankComics extends InfoBase{
+ public InfoStructure[] list;
+ }
+ public static class ComicWrap{
+ public ComicStructure comic;
+ }
+ public static class FinishComics extends InfoBase{
+ public ComicStructure[] list;
+ public String path_word;
+ public String name;
+ public String type;
+ }
+ }
+}
diff --git a/app/src/main/java/top/fumiama/copymanga/json/InfoBase.java b/app/src/main/java/top/fumiama/copymanga/json/InfoBase.java
new file mode 100644
index 0000000..9981601
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/json/InfoBase.java
@@ -0,0 +1,7 @@
+package top.fumiama.copymanga.json;
+
+public class InfoBase {
+ public int total;
+ public int limit;
+ public int offset;
+}
diff --git a/app/src/main/java/top/fumiama/copymanga/json/InfoStructure.java b/app/src/main/java/top/fumiama/copymanga/json/InfoStructure.java
new file mode 100644
index 0000000..8e7dfaa
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/json/InfoStructure.java
@@ -0,0 +1,11 @@
+package top.fumiama.copymanga.json;
+
+public class InfoStructure {
+ public int sort;
+ public int sort_last;
+ public int rise_sort;
+ public int rise_num;
+ public int date_type;
+ public int popular;
+ public ComicStructure comic;
+}
diff --git a/app/src/main/java/top/fumiama/copymanga/json/ResultsBase.java b/app/src/main/java/top/fumiama/copymanga/json/ResultsBase.java
new file mode 100644
index 0000000..81eba1d
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/json/ResultsBase.java
@@ -0,0 +1,8 @@
+package top.fumiama.copymanga.json;
+
+public class ResultsBase {
+ public Boolean is_lock;
+ public Boolean is_login;
+ public Boolean is_mobile_bind;
+ public Boolean is_vip;
+}
diff --git a/app/src/main/java/top/fumiama/copymanga/json/ReturnBase.java b/app/src/main/java/top/fumiama/copymanga/json/ReturnBase.java
new file mode 100644
index 0000000..4f603df
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/json/ReturnBase.java
@@ -0,0 +1,6 @@
+package top.fumiama.copymanga.json;
+
+public class ReturnBase {
+ public int code;
+ public String message;
+}
diff --git a/app/src/main/java/top/fumiama/copymanga/json/SeriesStructure.java b/app/src/main/java/top/fumiama/copymanga/json/SeriesStructure.java
new file mode 100644
index 0000000..5faf989
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/json/SeriesStructure.java
@@ -0,0 +1,5 @@
+package top.fumiama.copymanga.json;
+
+public class SeriesStructure extends ThemeStructure {
+ public String color;
+}
diff --git a/app/src/main/java/top/fumiama/copymanga/json/ThemeStructure.java b/app/src/main/java/top/fumiama/copymanga/json/ThemeStructure.java
new file mode 100644
index 0000000..b2ae915
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/json/ThemeStructure.java
@@ -0,0 +1,6 @@
+package top.fumiama.copymanga.json;
+
+public class ThemeStructure {
+ public String name;
+ public String path_word;
+}
diff --git a/app/src/main/java/top/fumiama/copymanga/json/UUIDUrlPair.java b/app/src/main/java/top/fumiama/copymanga/json/UUIDUrlPair.java
new file mode 100644
index 0000000..9af6abf
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/json/UUIDUrlPair.java
@@ -0,0 +1,6 @@
+package top.fumiama.copymanga.json;
+
+public class UUIDUrlPair {
+ public String uuid;
+ public String url;
+}
diff --git a/app/src/main/java/top/fumiama/copymanga/json/ValueDisplayPair.java b/app/src/main/java/top/fumiama/copymanga/json/ValueDisplayPair.java
new file mode 100644
index 0000000..4cb8815
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/json/ValueDisplayPair.java
@@ -0,0 +1,6 @@
+package top.fumiama.copymanga.json;
+
+public class ValueDisplayPair {
+ public int value;
+ public String display;
+}
diff --git a/app/src/main/java/top/fumiama/copymanga/json/VolumeStructure.java b/app/src/main/java/top/fumiama/copymanga/json/VolumeStructure.java
new file mode 100644
index 0000000..cb5787c
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/json/VolumeStructure.java
@@ -0,0 +1,8 @@
+package top.fumiama.copymanga.json;
+
+public class VolumeStructure extends ReturnBase {
+ public Results results;
+ public static class Results extends InfoBase{
+ public ChapterStructure[] list;
+ }
+}
diff --git a/app/src/main/java/top/fumiama/copymanga/template/ActivityTemplate.kt b/app/src/main/java/top/fumiama/copymanga/template/ActivityTemplate.kt
new file mode 100644
index 0000000..7f5adb4
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/template/ActivityTemplate.kt
@@ -0,0 +1,28 @@
+package top.fumiama.copymanga.template
+
+import android.app.Activity
+import android.os.Bundle
+import android.view.View
+import top.fumiama.copymanga.tools.PropertiesTools
+import top.fumiama.copymanga.tools.UITools
+import java.io.File
+import java.lang.ref.WeakReference
+
+open class ActivityTemplate:Activity() {
+ lateinit var p: PropertiesTools
+ lateinit var toolsBox: UITools
+ private val allFullScreen
+ get() = p["allFullScreen"] == "true"
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ p = PropertiesTools(File("$filesDir/settings.properties"))
+ toolsBox = UITools(WeakReference(this))
+ }
+
+ override fun onWindowFocusChanged(hasFocus: Boolean) {
+ super.onWindowFocusChanged(hasFocus)
+ if(allFullScreen) window.decorView.systemUiVisibility =
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/template/AutoDownloadHandler.kt b/app/src/main/java/top/fumiama/copymanga/template/AutoDownloadHandler.kt
new file mode 100644
index 0000000..ec21ea1
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/template/AutoDownloadHandler.kt
@@ -0,0 +1,60 @@
+package top.fumiama.copymanga.template
+
+import android.os.Handler
+import android.os.Looper
+import android.os.Message
+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.ReturnBase
+import top.fumiama.copymanga.tools.DownloadTools
+import top.fumiama.copymanga.tools.TimeThread
+
+open class AutoDownloadHandler(private val url: String, private val jsonClass: Class<*>, looper: Looper, private val callCheckMsg: Int = -1): Handler(looper) {
+ private var timeThread: TimeThread? = null
+ private var checkTimes = 0
+ override fun handleMessage(msg: Message) {
+ super.handleMessage(msg)
+ when(msg.what){
+ callCheckMsg -> check()
+ 0 -> setLayouts()
+ }
+ }
+ open fun setGsonItem(gsonObj: Any) {}
+ open fun getGsonItem(): ReturnBase? = null
+ open fun onError() {}
+ open fun doWhenFinishDownload() {}
+ fun startLoad() {
+ sendEmptyMessage(0)
+ }
+ private fun download(){
+ Thread{
+ DownloadTools.getHttpContent(url,
+ mainWeakReference?.get()?.getString(R.string.referUrl)!!,
+ mainWeakReference?.get()?.getString(R.string.pc_ua)!!
+ )?.let {
+ val fi = it.inputStream()
+ setGsonItem(Gson().fromJson(fi.reader(), jsonClass))
+ fi.close()
+ }
+ }.start()
+ checkTimes = 0
+ timeThread = TimeThread(this, callCheckMsg)
+ timeThread?.canDo = true
+ timeThread?.start()
+ }
+ private fun check(){
+ val g = getGsonItem()
+ if(g != null) {
+ timeThread?.canDo = false
+ if(g.code == 200) sendEmptyMessage(0)
+ else onError()
+ Log.d("MyADH", "[${g.code}]${g.message}")
+ } else if(checkTimes++ > 10) timeThread?.canDo = false
+ }
+ private fun setLayouts() {
+ if(getGsonItem() == null) download()
+ else doWhenFinishDownload()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/template/AutoDownloadThread.kt b/app/src/main/java/top/fumiama/copymanga/template/AutoDownloadThread.kt
new file mode 100644
index 0000000..b45aabe
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/template/AutoDownloadThread.kt
@@ -0,0 +1,20 @@
+package top.fumiama.copymanga.template
+
+import top.fumiama.dmzj.copymanga.R
+import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference
+import top.fumiama.copymanga.tools.DownloadTools
+
+class AutoDownloadThread(private val url: String, private val whenFinish: (result: ByteArray?)->Unit): Thread() {
+ override fun run() {
+ super.run()
+ var re: ByteArray? = null
+ var c = 0
+ while (re == null && c++ < 3){
+ re = DownloadTools.getHttpContent(url,
+ mainWeakReference?.get()?.getString(R.string.referUrl)!!,
+ mainWeakReference?.get()?.getString(R.string.pc_ua)!!
+ )
+ }
+ whenFinish(re)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/template/CardList.kt b/app/src/main/java/top/fumiama/copymanga/template/CardList.kt
new file mode 100644
index 0000000..4467cac
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/template/CardList.kt
@@ -0,0 +1,109 @@
+package top.fumiama.copymanga.template
+
+import android.annotation.SuppressLint
+import android.net.Uri
+import android.util.Log
+import android.view.View
+import androidx.fragment.app.Fragment
+import com.bumptech.glide.Glide
+import com.bumptech.glide.load.model.GlideUrl
+import kotlinx.android.synthetic.main.card_book.view.*
+import kotlinx.android.synthetic.main.line_horizonal_empty.view.*
+import kotlinx.android.synthetic.main.line_lazybooklines.*
+import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference
+import top.fumiama.copymanga.tools.CMApi
+import top.fumiama.dmzj.copymanga.R
+import java.io.File
+import java.lang.ref.WeakReference
+
+class CardList(
+ fragment: WeakReference,
+ private val cardWidth: Int,
+ private val cardHeight: Int,
+ private val cardPerRow: Int
+) {
+ private val that = fragment.get()
+ private var rows:Array = arrayOfNulls(20)
+ private var index = 0
+ private var count = 0
+ var initClickListeners: InitClickListeners? = null
+
+ fun reset(){
+ rows = arrayOfNulls(20)
+ index = 0
+ count = 0
+ }
+
+ private fun manageRow(){
+ if(count++ % cardPerRow == 0) inflateRow()
+ Log.d("MyCL", "index: $index, cardPR: $cardPerRow")
+ }
+
+ private fun inflateRow(){
+ that?.layoutInflater?.inflate(R.layout.line_horizonal_empty, that.mydll, false)?.let {
+ it.layoutParams.height = cardHeight + 16
+ mainWeakReference?.get()?.runOnUiThread {
+ that.mydll.addView(it)
+ }
+ recycleOneRow(it)
+ }
+ }
+
+ private fun recycleOneRow(v:View?){
+ if(index < 20) rows[index] = v
+ else{
+ mainWeakReference?.get()?.runOnUiThread {
+ that?.mydll?.removeView(rows[index % 20])
+ //zis.mys?.scrollY = zis.mys?.scrollY?.minus(cardHeight + 16)?:0
+ }
+ rows[index % 20] = v
+ }
+ index++
+ }
+
+ @ExperimentalStdlibApi
+ fun addCard(name: String, append: String? = null, head: String? = null, path: String? = null, chapterUUID: String? = null, pn: Int? = null, isFinish: Boolean = false){
+ manageRow()
+ that?.layoutInflater?.inflate(R.layout.card_book, that.mydll.ltbtn, false)?.let {
+ val card = it.cic
+ card.name = name
+ card.append = append
+ card.headImageUrl = head
+ card.path = path
+ card.index = index - 1
+ card.chapterUUID = chapterUUID
+ card.pageNumber = pn
+ card.isFinish = isFinish
+ mainWeakReference?.get()?.runOnUiThread{
+ addCard(it)
+ }
+ }
+ }
+ @SuppressLint("SetTextI18n")
+ @ExperimentalStdlibApi
+ fun addCard(cardFrame: View) {
+ val card = cardFrame.cic
+ val name = card.name + (card.append?:"")
+ val head = card.headImageUrl
+ val file = File(that?.context?.getExternalFilesDir(""), card.name)
+ cardFrame.let {
+ it.tic.text = name
+ if(!file.exists()){
+ that?.context?.let { context ->
+ Glide.with(context).load(GlideUrl(head, CMApi.myGlideHeaders)).into(it.imic)
+ }
+ }else {
+ val img = File(file, "head.jpg")
+ if(img.exists()) it.imic.setImageURI(Uri.fromFile(img))
+ }
+ if(card.isFinish) it.sgnic.visibility = View.VISIBLE
+ initClickListeners?.prepareListeners(card, card.name, card.path, card.chapterUUID, card.pageNumber)
+ rows[card.index % 20]?.ltbtn?.addView(it)
+ it.layoutParams.height = cardHeight
+ it.layoutParams.width = cardWidth
+ }
+ }
+ interface InitClickListeners{
+ fun prepareListeners(v: View, name: String, path: String?, chapterUUID: String?, pn: Int?)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/template/InfoCardLoader.kt b/app/src/main/java/top/fumiama/copymanga/template/InfoCardLoader.kt
new file mode 100644
index 0000000..d3322f6
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/template/InfoCardLoader.kt
@@ -0,0 +1,60 @@
+package top.fumiama.copymanga.template
+
+import android.os.Bundle
+import android.util.JsonReader
+import android.view.View
+import androidx.fragment.app.Fragment
+import androidx.navigation.Navigation
+import com.google.gson.Gson
+import top.fumiama.dmzj.copymanga.R
+import top.fumiama.copymanga.json.BookListStructure
+import top.fumiama.copymanga.tools.DownloadTools
+import java.io.File
+import java.lang.ref.WeakReference
+
+@ExperimentalStdlibApi
+open class InfoCardLoader(inflateRes:Int, private val navId:Int): MangaPagesFragmentTemplate(inflateRes) {
+ private val subUrl get() = getApiUrl()
+
+ init {
+ pageHandler = object : PageHandler {
+ override fun addPage(){
+ AutoDownloadThread(subUrl){
+ if(isRefresh){
+ page = 0
+ isRefresh = false
+ }
+ val bookList = Gson().fromJson(it?.decodeToString(), BookListStructure::class.java)
+ bookList?.let {
+ if(it.code == 200) it.results.list?.forEach{ book ->
+ cardList.addCard(book.name, null, book.cover, book.path_word, null, null, false)
+ }
+ }
+ page++
+ onLoadFinish()
+ }.start()
+ }
+ override fun initCardList(weakReference: WeakReference) {
+ cardList = CardList(weakReference, cardWidth, cardHeight, cardPerRow)
+ cardList.initClickListeners = object : CardList.InitClickListeners {
+ override fun prepareListeners(v: View, name: String, path: String?, chapterUUID: String?, pn: Int?) {
+ v.setOnClickListener {
+ val bundle = Bundle()
+ bundle.putString("path", path)
+ rootView?.let { Navigation.findNavController(it).navigate(navId, bundle) }
+ }
+ }
+ }
+ }
+ override fun setListeners() { this@InfoCardLoader.setListeners() }
+ }
+ }
+
+ open fun getApiUrl(): String{
+ return ""
+ }
+
+ open fun setListeners(){}
+
+ open fun onLoadFinish(){}
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/template/MangaPagesFragmentTemplate.kt b/app/src/main/java/top/fumiama/copymanga/template/MangaPagesFragmentTemplate.kt
new file mode 100644
index 0000000..0b6a47a
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/template/MangaPagesFragmentTemplate.kt
@@ -0,0 +1,67 @@
+package top.fumiama.copymanga.template
+
+import android.annotation.SuppressLint
+import android.os.Bundle
+import android.util.JsonReader
+import android.util.Log
+import android.view.View
+import androidx.fragment.app.Fragment
+import kotlinx.android.synthetic.main.line_header.view.*
+import kotlinx.android.synthetic.main.line_lazybooklines.*
+import top.fumiama.copymanga.template.handler.MPATHandler
+import top.fumiama.copymanga.tools.UITools
+import java.lang.Thread.sleep
+import java.lang.ref.WeakReference
+
+open class MangaPagesFragmentTemplate(inflateRes:Int, val isLazy: Boolean = true, val forceLoad: Boolean = false) : NoBackRefreshFragment(inflateRes) {
+ var cardPerRow = 3
+ var cardWidth = 0
+ var cardHeight = 0
+ lateinit var cardList: CardList
+ var mh: MPATHandler? = null
+ var row: View? = null
+ var isEnd = false
+ var jsonReaderNow: JsonReader? = null
+ var page = 0
+
+ var isRefresh = false
+
+ @SuppressLint("ClickableViewAccessibility")
+ @ExperimentalStdlibApi
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ if(isFirstInflate) {
+ mh = MPATHandler(WeakReference(this))
+ Thread {
+ sleep(600)
+ mh?.sendEmptyMessage(0)
+ }.start()
+ }
+ }
+
+ fun setLayouts() {
+ val toolsBox = this.context?.let { UITools(it) }
+ val widthData = toolsBox?.calcWidthFromDp(8, 135)
+ cardPerRow = widthData?.get(0) ?: 3
+ cardWidth = widthData?.get(2) ?: 128
+ cardHeight = (cardWidth / 0.75 + 0.5).toInt()
+ mysp.footerView.lht.text = "加载"
+ mysp.headerView.lht.text = "刷新"
+ Log.d("MyMPAT", "Card per row: $cardPerRow")
+ Log.d("MyMPAT", "Card width: $cardWidth")
+
+ pageHandler?.initCardList(WeakReference(this))
+ Thread { mh?.sendEmptyMessage(1) }.start()
+ pageHandler?.setListeners()
+ //mypl.visibility = View.GONE
+ }
+
+ var pageHandler: PageHandler? = null
+
+ interface PageHandler {
+ fun addPage()
+ fun initCardList(weakReference: WeakReference)
+ fun setListeners()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/template/NoBackRefreshFragment.kt b/app/src/main/java/top/fumiama/copymanga/template/NoBackRefreshFragment.kt
new file mode 100644
index 0000000..0b8075b
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/template/NoBackRefreshFragment.kt
@@ -0,0 +1,23 @@
+package top.fumiama.copymanga.template
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+
+open class NoBackRefreshFragment(private val layoutToLoad: Int):Fragment() {
+ var rootView: View? = null
+ var isFirstInflate = true
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ if(rootView == null){
+ isFirstInflate = true
+ rootView = inflater.inflate(layoutToLoad, container, false)
+ } else isFirstInflate = false
+ return rootView
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/template/TitleActivityTemplate.kt b/app/src/main/java/top/fumiama/copymanga/template/TitleActivityTemplate.kt
new file mode 100644
index 0000000..9188164
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/template/TitleActivityTemplate.kt
@@ -0,0 +1,13 @@
+package top.fumiama.copymanga.template
+
+import android.os.Bundle
+import kotlinx.android.synthetic.main.widget_titlebar.*
+
+open class TitleActivityTemplate:ActivityTemplate() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ ilogo.setOnClickListener {
+ onBackPressed()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/template/handler/MPATHandler.kt b/app/src/main/java/top/fumiama/copymanga/template/handler/MPATHandler.kt
new file mode 100644
index 0000000..961aabe
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/template/handler/MPATHandler.kt
@@ -0,0 +1,83 @@
+package top.fumiama.copymanga.template.handler
+
+import android.content.Context
+import android.net.ConnectivityManager
+import android.net.NetworkCapabilities
+import android.os.Handler
+import android.os.Message
+import android.view.View
+import android.widget.Toast
+import com.liaoinstan.springview.widget.SpringView
+import top.fumiama.dmzj.copymanga.R
+import kotlinx.android.synthetic.main.line_lazybooklines.*
+import top.fumiama.copymanga.template.MangaPagesFragmentTemplate
+import java.lang.ref.WeakReference
+
+
+class MPATHandler(private val w: WeakReference) : Handler() {
+ private val wa get() = w.get()
+ private val netinfo: String
+ get() {
+ val cm: ConnectivityManager =
+ wa?.context?.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+ return cm.getNetworkCapabilities(cm.activeNetwork)?.let {
+ when {
+ it.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> return@let wa?.context?.getString(
+ R.string.TRANSPORT_WIFI)
+ it.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> return@let wa?.context?.getString(
+ R.string.TRANSPORT_CELLULAR)
+ it.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH) -> return@let wa?.context?.getString(
+ R.string.TRANSPORT_BLUETOOTH)
+ it.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> return@let wa?.context?.getString(
+ R.string.TRANSPORT_ETHERNET)
+ it.hasTransport(NetworkCapabilities.TRANSPORT_LOWPAN) -> return@let wa?.context?.getString(
+ R.string.TRANSPORT_LOWPAN)
+ it.hasTransport(NetworkCapabilities.TRANSPORT_VPN) -> return@let "VPN"
+ else -> return@let wa?.context?.getString(R.string.TRANSPORT_NULL)
+ }
+ } ?: "错误"
+ }
+ override fun handleMessage(msg: Message) {
+ super.handleMessage(msg)
+ if (wa?.forceLoad == true || netinfo != "无网络" && netinfo != "错误") {
+ when (msg.what) {
+ 0 -> wa?.setLayouts()
+ 1 -> managePage()
+ 2 -> addPageHandler()
+ 3 -> {
+ wa?.pageHandler?.addPage()
+ //wa?.myp?.visibility = View.GONE
+ wa?.mysp?.onFinishFreshAndLoad()
+ //wa?.mys?.fullScroll(ScrollView.FOCUS_UP)
+ }
+ 4 ->{
+ wa?.mydll?.removeAllViews()
+ wa?.isEnd = false
+ wa?.jsonReaderNow = null
+ wa?.page = 0
+ wa?.cardList?.reset()
+ addPageHandler()
+ wa?.mysp?.onFinishFreshAndLoad()
+ wa?.mypl?.visibility = View.VISIBLE
+ }
+ }
+ } else Toast.makeText(wa?.context, "${netinfo}链接!", Toast.LENGTH_SHORT).show()
+ }
+
+ private fun managePage() {
+ addPageHandler()
+ if (wa?.isLazy == true) wa?.mysp?.setListener(object :SpringView.OnFreshListener{
+ override fun onLoadmore() {
+ Thread { this@MPATHandler.sendEmptyMessage(2) }.start()
+ }
+ override fun onRefresh() {
+ Thread { this@MPATHandler.sendEmptyMessage(4) }.start()
+ }
+ })
+ }
+
+ private fun addPageHandler() {
+ //wa?.myp?.visibility = View.VISIBLE
+ Thread { this.sendEmptyMessage(3) }.start()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/tool/DownloadTools.kt b/app/src/main/java/top/fumiama/copymanga/tool/DownloadTools.kt
deleted file mode 100644
index 5d4d3a2..0000000
--- a/app/src/main/java/top/fumiama/copymanga/tool/DownloadTools.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-package top.fumiama.copymanga.tool
-
-import android.util.Log
-import java.net.HttpURLConnection
-import java.net.URL
-import java.util.concurrent.Callable
-import java.util.concurrent.FutureTask
-
-class DownloadTools {
- fun getHttpContent(Url: String, refer: String? = null, ua: String? = null): ByteArray? {
- Log.d("Mydl", "getHttp: $Url")
- var ret: ByteArray? = null
- val task = FutureTask(Callable {
- try {
- val connection = URL(Url).openConnection() as HttpURLConnection
- connection.requestMethod = "GET"
- connection.connectTimeout = 10000
- connection.readTimeout = 10000
- refer?.let { connection.setRequestProperty("referer", it) }
- ua?.let { connection.setRequestProperty("User-agent", it) }
-
- ret = connection.inputStream.readBytes()
- connection.disconnect()
- } catch (ex: Exception) {
- ex.printStackTrace()
- }
- return@Callable ret
- })
- Thread(task).start()
- return try {
- task.get()
- } catch (ex: Exception) {
- ex.printStackTrace()
- null
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/tool/MangaDlTools.kt b/app/src/main/java/top/fumiama/copymanga/tool/MangaDlTools.kt
deleted file mode 100644
index 89993b6..0000000
--- a/app/src/main/java/top/fumiama/copymanga/tool/MangaDlTools.kt
+++ /dev/null
@@ -1,94 +0,0 @@
-package top.fumiama.copymanga.tool
-
-import top.fumiama.copymanga.R
-import top.fumiama.copymanga.activity.DlActivity
-import top.fumiama.copymanga.data.ComicStructure
-import top.fumiama.copymanga.view.JSWebView
-import top.fumiama.copymanga.web.JSHidden
-import java.io.File
-import java.lang.Thread.sleep
-import java.lang.ref.WeakReference
-import java.util.zip.CRC32
-import java.util.zip.CheckedOutputStream
-import java.util.zip.ZipEntry
-import java.util.zip.ZipOutputStream
-
-class MangaDlTools(activity: DlActivity) {
- var exit = false
- private val da = WeakReference(activity)
- private val d = da.get()
- private val p = PropertiesTools(File("${d?.filesDir}/chapters.hash"))
- private var imgUrlsList: Array?>? = null
- private var chaptersCount = 0
- private val newWebViewHidden: JSWebView?
- get() {
- val re = d?.let { JSWebView(it, it.getString(R.string.pc_ua)) }
- re?.setWebViewClient("h.js")
- re?.loadJSInterface(JSHidden())
- return re
- }
-
- init {
- wmdlt = WeakReference(this)
- }
-
- fun getImgsCountByHash(hash: String): Int?{
- return imgUrlsList?.get(p[hash].toInt())?.size
- }
-
- fun allocateChapterUrls(count: Int){
- imgUrlsList = arrayOfNulls(count)
- chaptersCount = 0
- }
-
- fun dlChapterUrl(url: String){
- p[url.substringAfterLast("/")] = (chaptersCount++).toString()
- newWebViewHidden?.loadUrl(url)
- }
-
- fun setChapterImgs(hash: String, imgUrls: Array){
- imgUrlsList?.set(p[hash].toInt(), imgUrls)
- }
-
- fun dlChapterAndPackIntoZip(zipf: File, hash: String){
- imgUrlsList?.get(p[hash].toInt())?.let {
- val dl = DownloadTools()
- 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 it.indices) {
- zip.putNextEntry(ZipEntry("$i.webp"))
- var tryTimes = 3
- var s = false
- while (!s && tryTimes-- > 0){
- s = dl.getHttpContent(it[i], d?.getString(R.string.web_home_www), d?.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()
- if (exit) break
- }
- zip.close()
- onDownloadedListener?.handleMessage(succeed)
- }
- }
-
- var onDownloadedListener: OnDownloadedListener? = null
-
- interface OnDownloadedListener {
- fun handleMessage(succeed: Boolean)
- fun handleMessage(succeed: Boolean, pageNow: Int)
- fun handleMessage(pageNow: Int)
- }
-
- companion object {
- var wmdlt: WeakReference? = null
- }
-}
\ 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
deleted file mode 100644
index 0c24196..0000000
--- a/app/src/main/java/top/fumiama/copymanga/tool/PagesManager.kt
+++ /dev/null
@@ -1,76 +0,0 @@
-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) {
- val v = w.get()
- private var isEndL = false
- private var isEndR = false
- @ExperimentalStdlibApi
- fun toPreviousPage(){ toPage(v?.r2l==true) }
- @ExperimentalStdlibApi
- 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){
- if (v?.clicked == false) {
- if (if(goNext)judgeNext() else judgePrevious()) {
- if(goNext) {
- v.scrollForward()
- isEndR = false
- } else {
- v.scrollBack()
- isEndL = false
- }
- } else {
- val chapterUrl = if(goNext) ViewMangaActivity.nextChapterUrl else ViewMangaActivity.previousChapterUrl
- if (chapterUrl != null) {
- if (if(goNext)isEndR else isEndL) {
- if(!goNext) ViewMangaActivity.pn = -2
- wm?.get()?.w?.loadUrl("javascript:invoke.clickClass(\"comicControlBottomTopClick\",${if(goNext)1 else 0});")
- v.tt.canDo = false
- v.finish()
- } else doubleTapToast(goNext)
- } else {
- val newZipPosition = ViewMangaActivity.zipPosition + (if(goNext) 1 else -1)
- if(v.dlZip2View && newZipPosition >= 0 && newZipPosition < ViewMangaActivity.zipList?.size?:0){
- if (if(goNext)isEndR else isEndL){
- if(!goNext) ViewMangaActivity.pn = -2
- ViewMangaActivity.zipPosition = newZipPosition
- ViewMangaActivity.titleText = ViewMangaActivity.zipList?.get(newZipPosition) ?: "null"
- ViewMangaActivity.zipFile = File(ViewMangaActivity.cd, ViewMangaActivity.titleText)
- v.startActivity(Intent(v, ViewMangaActivity::class.java))
- v.tt.canDo = false
- v.finish()
- }else doubleTapToast(goNext)
- }
- else Toast.makeText(
- v.applicationContext,
- "已经到头了~",
- Toast.LENGTH_SHORT
- ).show()
- }
- }
- } else v?.hideObjs()
- }
- fun manageInfo(){
- if (v?.clicked == false) v.showObjs() else v?.hideObjs()
- }
- private fun doubleTapToast(goNext: Boolean){
- val hint = if(goNext) "下" else "上"
- 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/tools/CMApi.kt b/app/src/main/java/top/fumiama/copymanga/tools/CMApi.kt
new file mode 100644
index 0000000..6e6fb99
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/tools/CMApi.kt
@@ -0,0 +1,18 @@
+package top.fumiama.copymanga.tools
+
+import com.bumptech.glide.load.model.LazyHeaders
+import top.fumiama.dmzj.copymanga.R
+import top.fumiama.copymanga.MainActivity
+import top.fumiama.copymanga.json.Chapter2Return
+import java.io.File
+
+object CMApi {
+ var myGlideHeaders: LazyHeaders? = null
+ get() {
+ if(field === null) field = LazyHeaders.Builder().addHeader("referer", MainActivity.mainWeakReference?.get()?.getString(R.string.referUrl)!!).addHeader("User-Agent", MainActivity.mainWeakReference?.get()?.getString(R.string.pc_ua)!!).build()
+ return field
+ }
+ fun getImgZipFileFromVM(exDir: File?, chapter2Return: Chapter2Return?) = File(exDir, "${chapter2Return?.results?.comic?.name}/${chapter2Return?.results?.chapter?.group_path_word}/${chapter2Return?.results?.chapter?.name}.zip")
+ fun getZipFile(exDir: File?, manga: String, caption: CharSequence, name: CharSequence) = File(exDir, "$manga/$caption/$name.zip")
+ fun getApiUrl(id: Int, arg1: String?, arg2: String?) = MainActivity.mainWeakReference?.get()?.getString(id)?.let { String.format(it, arg1, arg2) }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/tools/DownloadTools.kt b/app/src/main/java/top/fumiama/copymanga/tools/DownloadTools.kt
new file mode 100644
index 0000000..db05f84
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/tools/DownloadTools.kt
@@ -0,0 +1,119 @@
+package top.fumiama.copymanga.tools
+
+import android.util.Log
+import java.io.File
+import java.net.HttpURLConnection
+import java.net.URL
+import java.util.concurrent.Callable
+import java.util.concurrent.FutureTask
+
+object DownloadTools {
+ fun getHttpContent(Url: String, refer: String? = null, ua: String? = null): ByteArray? {
+ Log.d("Mydl", "getHttp: $Url")
+ var ret: ByteArray? = null
+ val task = FutureTask(Callable {
+ try {
+ val connection = URL(Url).openConnection() as HttpURLConnection
+ connection.requestMethod = "GET"
+ connection.connectTimeout = 10000
+ connection.readTimeout = 10000
+ refer?.let { connection.setRequestProperty("referer", it) }
+ ua?.let { connection.setRequestProperty("User-agent", it) }
+
+ ret = connection.inputStream.readBytes()
+ connection.disconnect()
+ } catch (ex: Exception) {
+ ex.printStackTrace()
+ }
+ return@Callable ret
+ })
+ Thread(task).start()
+ return try {
+ task.get()
+ } catch (ex: Exception) {
+ ex.printStackTrace()
+ null
+ }
+ }
+ fun downloadUsingUrlRet(Url: String?, f: File): Boolean {
+ Log.d("Mydl", "Ret Get Url: $Url, File: $f")
+ val task = FutureTask(Callable {
+ try {
+ val connection = URL(Url).openConnection() as HttpURLConnection
+ connection.requestMethod = "GET"
+ connection.connectTimeout = 10000
+ connection.readTimeout = 10000
+
+ if (f.exists()) f.delete()
+ else f.parentFile?.mkdirs()
+ f.parentFile?.let {
+ if (!it.canRead()) it.setReadable(true)
+ if (!it.canWrite()) it.setWritable(true)
+ }
+ connection.inputStream.buffered().copyTo(f.outputStream())
+ connection.disconnect()
+ return@Callable true
+ } catch (ex: Exception) {
+ ex.printStackTrace()
+ return@Callable false
+ }
+ })
+ Thread(task).start()
+ return try {
+ task.get()
+ } catch (ex: Exception) {
+ ex.printStackTrace()
+ false
+ }
+ }
+ fun downloadUsingUrl(Url: String?, f: File, refer: String? = null) {
+ Log.d("Mydl", "Get Url: $Url, File: $f")
+ Thread(Runnable {
+ try {
+ val connection = URL(Url).openConnection() as HttpURLConnection
+ connection.requestMethod = "GET"
+ connection.connectTimeout = 10000
+ connection.readTimeout = 10000
+ refer?.let { connection.setRequestProperty("referer", it) }
+
+ if (f.exists()) f.delete()
+ else f.parentFile?.mkdirs()
+ f.parentFile?.let {
+ if (!it.canRead()) it.setReadable(true)
+ if (!it.canWrite()) it.setWritable(true)
+ }
+ connection.inputStream.buffered().copyTo(f.outputStream())
+ connection.disconnect()
+ } catch (ex: Exception) {
+ ex.printStackTrace()
+ }
+ }).start()
+ }
+
+ fun getHttpContent(Url: String, refer: String? = null): ByteArray? {
+ Log.d("Mydl", "getHttp: $Url")
+ var ret: ByteArray? = null
+ val task = FutureTask(Callable {
+ try {
+ val connection = URL(Url).openConnection() as HttpURLConnection
+ connection.requestMethod = "GET"
+ connection.connectTimeout = 10000
+ connection.readTimeout = 10000
+ refer?.let { connection.setRequestProperty("referer", it) }
+
+ ret = connection.inputStream.readBytes()
+ connection.disconnect()
+ } catch (ex: Exception) {
+ ex.printStackTrace()
+ }
+ return@Callable ret
+ })
+ Thread(task).start()
+ return try {
+ task.get()
+ } catch (ex: Exception) {
+ ex.printStackTrace()
+ null
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/tools/GlideBlurTransformation.kt b/app/src/main/java/top/fumiama/copymanga/tools/GlideBlurTransformation.kt
new file mode 100644
index 0000000..8b325c4
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/tools/GlideBlurTransformation.kt
@@ -0,0 +1,52 @@
+package top.fumiama.copymanga.tools
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.renderscript.Allocation
+import android.renderscript.Element
+import android.renderscript.RenderScript
+import android.renderscript.ScriptIntrinsicBlur
+import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
+import com.bumptech.glide.load.resource.bitmap.CenterCrop
+
+class GlideBlurTransformation(private val context: Context) : CenterCrop() {
+ override fun transform(
+ pool: BitmapPool,
+ toTransform: Bitmap,
+ outWidth: Int,
+ outHeight: Int
+ ): Bitmap {
+ val bitmap = super.transform(pool, toTransform, outWidth, outHeight)
+ return blurBitmap(context, bitmap, 25f, outWidth / 2, outHeight / 2)
+ }
+
+ private fun blurBitmap(
+ context: Context?,
+ image: Bitmap?,
+ blurRadius: Float,
+ outWidth: Int,
+ outHeight: Int
+ ): Bitmap {
+ // 将缩小后的图片做为预渲染的图片
+ val inputBitmap = Bitmap.createScaledBitmap(image!!, outWidth, outHeight, false)
+ // 创建一张渲染后的输出图片
+ val outputBitmap = Bitmap.createBitmap(inputBitmap)
+ // 创建RenderScript内核对象
+ val rs = RenderScript.create(context)
+ // 创建一个模糊效果的RenderScript的工具对象
+ val blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs))
+ // 由于RenderScript并没有使用VM来分配内存,所以需要使用Allocation类来创建和分配内存空间
+ // 创建Allocation对象的时候其实内存是空的,需要使用copyTo()将数据填充进去
+ val tmpIn = Allocation.createFromBitmap(rs, inputBitmap)
+ val tmpOut = Allocation.createFromBitmap(rs, outputBitmap)
+ // 设置渲染的模糊程度, 25f是最大模糊度
+ blurScript.setRadius(blurRadius)
+ // 设置blurScript对象的输入内存
+ blurScript.setInput(tmpIn)
+ // 将输出数据保存到输出内存中
+ blurScript.forEach(tmpOut)
+ // 将数据填充到Allocation中
+ tmpOut.copyTo(outputBitmap)
+ return outputBitmap
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/tools/MangaDlTools.kt b/app/src/main/java/top/fumiama/copymanga/tools/MangaDlTools.kt
new file mode 100644
index 0000000..c3e6cf3
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/tools/MangaDlTools.kt
@@ -0,0 +1,106 @@
+package top.fumiama.copymanga.tools
+
+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.AutoDownloadThread
+import top.fumiama.copymanga.tools.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
+
+ 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{
+ var re: Array = arrayOf()
+ val hm: HashMap = 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) {
+ 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) {
+ 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()
+ if (exit) break
+ }
+ 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)
+ }
+}
diff --git a/app/src/main/java/top/fumiama/copymanga/tool/PropertiesTools.kt b/app/src/main/java/top/fumiama/copymanga/tools/PropertiesTools.kt
similarity index 60%
rename from app/src/main/java/top/fumiama/copymanga/tool/PropertiesTools.kt
rename to app/src/main/java/top/fumiama/copymanga/tools/PropertiesTools.kt
index 0be5aab..be5dcf1 100644
--- a/app/src/main/java/top/fumiama/copymanga/tool/PropertiesTools.kt
+++ b/app/src/main/java/top/fumiama/copymanga/tools/PropertiesTools.kt
@@ -1,32 +1,31 @@
-package top.fumiama.copymanga.tool
+package top.fumiama.copymanga.tools
//PropertiesTools.kt
//created by fumiama 20200724
-import android.util.Log
import java.io.File
import java.io.InputStream
import java.util.*
class PropertiesTools(private val f: File):Properties() {
private val propfile:File
- get() {
- if(!f.exists()) {
- if(f.parentFile?.exists() != true) f.parentFile?.mkdirs()
+ get() {
+ if(!f.exists()) {
+ if(f.parentFile?.exists() != true) f.parentFile?.mkdirs()
+ if(f.parentFile?.canWrite() != true) f.parentFile?.setWritable(true)
+ createNew(f)
+ }else if(f.isDirectory) {
+ if(f.parentFile?.canWrite() != true) f.parentFile?.setWritable(true)
+ f.delete()
+ createNew(f)
+ }
if(f.parentFile?.canWrite() != true) f.parentFile?.setWritable(true)
- createNew(f)
- }else if(f.isDirectory) {
- if(f.parentFile?.canWrite() != true) f.parentFile?.setWritable(true)
- f.delete()
- createNew(f)
+ if(f.parentFile?.canRead() != true) f.parentFile?.setReadable(true)
+ return f
}
- if(f.parentFile?.canWrite() != true) f.parentFile?.setWritable(true)
- if(f.parentFile?.canRead() != true) f.parentFile?.setReadable(true)
- return f
- }
private fun createNew(f: File){
f.createNewFile()
val o = f.outputStream()
this.storeToXML(o, "store")
- Log.d("MyPT", "Generate new prop.")
+ //Log.d("MyPT", "Generate new prop.")
o.close()
}
private fun loadFromXml(`in`: InputStream?): PropertiesTools {
@@ -40,14 +39,14 @@ class PropertiesTools(private val f: File):Properties() {
operator fun get(key: String): String{
val i = propfile.inputStream()
val re = this.loadFromXml(i).getProperty(key)?:"null"
- Log.d("MyPT", "Get $key = $re")
+ //Log.d("MyPT", "Get prop: $re")
i.close()
return re
}
operator fun set(key: String, value: String){
val o = propfile.outputStream()
this.setProp(key, value).storeToXML(o, "store")
- Log.d("MyPT", "Set $key = $value")
+ //Log.d("MyPT", "Set $key = $value")
o.close()
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/top/fumiama/copymanga/handler/TimeThread.kt b/app/src/main/java/top/fumiama/copymanga/tools/TimeThread.kt
similarity index 91%
rename from app/src/main/java/top/fumiama/copymanga/handler/TimeThread.kt
rename to app/src/main/java/top/fumiama/copymanga/tools/TimeThread.kt
index 270785e..f5c76cc 100644
--- a/app/src/main/java/top/fumiama/copymanga/handler/TimeThread.kt
+++ b/app/src/main/java/top/fumiama/copymanga/tools/TimeThread.kt
@@ -1,4 +1,4 @@
-package top.fumiama.copymanga.handler
+package top.fumiama.copymanga.tools
import android.os.Handler
diff --git a/app/src/main/java/top/fumiama/copymanga/tool/ToolsBox.kt b/app/src/main/java/top/fumiama/copymanga/tools/UITools.kt
similarity index 74%
rename from app/src/main/java/top/fumiama/copymanga/tool/ToolsBox.kt
rename to app/src/main/java/top/fumiama/copymanga/tools/UITools.kt
index 928ba32..3ffb301 100644
--- a/app/src/main/java/top/fumiama/copymanga/tool/ToolsBox.kt
+++ b/app/src/main/java/top/fumiama/copymanga/tools/UITools.kt
@@ -1,34 +1,19 @@
-package top.fumiama.copymanga.tool
+package top.fumiama.copymanga.tools
import android.app.Activity
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 top.fumiama.dmzj.copymanga.R
import java.lang.ref.WeakReference
-import java.util.*
-import java.util.regex.Pattern
import kotlin.math.sqrt
-class ToolsBox(w: WeakReference) {
- val zis = (w as WeakReference).get()
- val week: String
- get() {
- val cal = Calendar.getInstance()
- return when (cal[Calendar.DAY_OF_WEEK]) {
- 1 -> "周日"
- 2 -> "周一"
- 3 -> "周二"
- 4 -> "周三"
- 5 -> "周四"
- 6 -> "周五"
- 7 -> "周六"
- else -> ""
- }
- }
+class UITools(that: Context?, w: WeakReference? = null) {
+ private val zis = that
+ private val weak = w
+ constructor(w: WeakReference): this(w.get()?.applicationContext, w)
val netinfo: String
get() {
val cm: ConnectivityManager =
@@ -37,6 +22,7 @@ class ToolsBox(w: WeakReference) {
when {
it.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> return@let "WIFI"
it.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> return@let "移动数据"
+ it.hasTransport(NetworkCapabilities.TRANSPORT_WIFI_AWARE) -> return@let "WIFI_AWARE"
it.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH) -> return@let "蓝牙"
it.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> return@let "以太网"
it.hasTransport(NetworkCapabilities.TRANSPORT_LOWPAN) -> return@let "LOWPAN"
@@ -45,8 +31,8 @@ class ToolsBox(w: WeakReference) {
} ?: "错误"
}
fun toastError(s: String, willFinish: Boolean = true) {
- Toast.makeText(zis?.applicationContext, s, Toast.LENGTH_SHORT).show()
- if (willFinish) zis?.finish()
+ Toast.makeText(zis, s, Toast.LENGTH_SHORT).show()
+ if (willFinish) weak?.get()?.finish()
}
fun buildInfo(
title: String,
@@ -70,9 +56,18 @@ class ToolsBox(w: WeakReference) {
fun dp2px(dp:Int):Int?{
return zis?.resources?.displayMetrics?.density?.let { (dp * it + 0.5).toInt()}
}
- private fun px2dp(px:Int):Int?{
+ fun px2dp(px:Int):Int?{
return zis?.resources?.displayMetrics?.density?.let { (px.toDouble() / it + 0.5).toInt()}
}
+ fun calcWidthFromDp(marginLeftDp:Int, widthDp:Int):List{
+ val margin = marginLeftDp.toDouble()
+ val marginPx = dp2px(marginLeftDp)?:16
+ val screenWidth = zis?.resources?.displayMetrics?.widthPixels?:1080
+ val numPerRow = ((px2dp(screenWidth)?:400).toDouble() / (widthDp + 2 * margin) + 0.5).toInt()
+ val w = (screenWidth - marginPx*numPerRow*2)/numPerRow
+ val totalWidth = screenWidth/numPerRow
+ return listOf(numPerRow, w, totalWidth)
+ }
private fun root(a:Double, b:Double, c:Double):List?{
val d = b*b - 4.0 * a * c
if(d < 0) return null
@@ -81,7 +76,7 @@ class ToolsBox(w: WeakReference) {
val x2 = (-b - sd)/(2.0 * a)
return listOf(x1, x2)
}
- fun calcWidthFromDp(marginLeftDp:Int, widthDp:Int):List{
+ fun calcWidthFromDpRoot(marginLeftDp:Int, widthDp:Int):List{
val margin = marginLeftDp.toDouble()
val marginPx = dp2px(marginLeftDp)?:16
val root = root(margin, widthDp.toDouble(), -((px2dp(zis?.resources?.displayMetrics?.widthPixels?:1080))?:400).toDouble())
@@ -90,4 +85,4 @@ class ToolsBox(w: WeakReference) {
val totalWidth = ((zis?.resources?.displayMetrics?.widthPixels?:1080)-marginPx)/numPerRow
return listOf(numPerRow, w, totalWidth)
}
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/ui/book/BookFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/book/BookFragment.kt
new file mode 100644
index 0000000..44313a3
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/ui/book/BookFragment.kt
@@ -0,0 +1,72 @@
+package top.fumiama.copymanga.ui.book
+
+import android.os.Bundle
+import android.util.Log
+import android.view.Menu
+import android.view.View
+import androidx.navigation.Navigation
+import top.fumiama.dmzj.copymanga.R
+import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference
+import top.fumiama.copymanga.template.NoBackRefreshFragment
+import java.lang.Thread.sleep
+import java.lang.ref.WeakReference
+
+class BookFragment:NoBackRefreshFragment(R.layout.fragment_book) {
+ private lateinit var bookHandler: BookHandler
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ if(isFirstInflate) {
+ bookHandler = BookHandler(WeakReference(this), arguments?.getString("path")?:"null")
+ Thread{
+ sleep(600)
+ bookHandler.startLoad()
+ }.start()
+ }
+ else bookHandler.fbibinfo?.layoutParams?.height = (bookHandler.fbibinfo?.width?:0 * 4.0 / 9.0 + 0.5).toInt()
+ }
+
+ override fun onResume() {
+ super.onResume()
+ mainWeakReference?.get()?.menuMain?.let { setMenuVisible(it) }
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ mainWeakReference?.get()?.menuMain?.let { setMenuInvisible(it) }
+ }
+
+ private fun setMenuInvisible(menu: Menu){
+ menu.findItem(R.id.action_download)?.isVisible = false
+ }
+
+ private fun setMenuVisible(menu: Menu) {
+ Log.d("MyBF", "显示下载按钮")
+ val dl = menu.findItem(R.id.action_download)
+ dl?.isVisible = true
+ dl?.setIcon(R.drawable.ic_menu_download)
+ dl?.setOnMenuItemClickListener {
+ if(bookHandler.complete && it.itemId == R.id.action_download){
+ navigate2dl()
+ true
+ }
+ else it.itemId == R.id.action_download
+ }
+ }
+
+ private fun navigate2dl(){
+ val bundle = Bundle()
+ bundle.putString("path", arguments?.getString("path")?:"null")
+ bundle.putString("name", bookHandler.book?.results?.comic?.name)
+ val groups = bookHandler.book?.results?.groups
+ var keys = arrayOf()
+ var gpws = arrayOf()
+ groups?.values?.forEach {
+ keys += it.name
+ gpws += it.path_word
+ }
+ bundle.putStringArray("group", gpws)
+ bundle.putStringArray("groupNames", keys)
+ rootView?.let { Navigation.findNavController(it).navigate(R.id.action_nav_book_to_nav_group, bundle) }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/ui/book/BookHandler.kt b/app/src/main/java/top/fumiama/copymanga/ui/book/BookHandler.kt
new file mode 100644
index 0000000..16cae6b
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/ui/book/BookHandler.kt
@@ -0,0 +1,192 @@
+package top.fumiama.copymanga.ui.book
+
+import android.os.Bundle
+import android.os.Looper
+import android.os.Message
+import android.util.Log
+import android.view.Menu
+import android.view.View
+import android.view.ViewTreeObserver
+import android.widget.TextView
+import android.widget.Toast
+import androidx.navigation.Navigation
+import com.bumptech.glide.Glide
+import com.bumptech.glide.load.model.GlideUrl
+import com.bumptech.glide.load.model.LazyHeaders
+import com.bumptech.glide.request.RequestOptions
+import kotlinx.android.synthetic.main.app_bar_main.*
+import kotlinx.android.synthetic.main.card_book.*
+import kotlinx.android.synthetic.main.fragment_book.*
+import kotlinx.android.synthetic.main.line_2chapters.view.*
+import kotlinx.android.synthetic.main.line_bookinfo.*
+import kotlinx.android.synthetic.main.line_bookinfo_text.*
+import kotlinx.android.synthetic.main.line_chapter.view.*
+import top.fumiama.dmzj.copymanga.R
+import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference
+import top.fumiama.copymanga.json.BookInfoStructure
+import top.fumiama.copymanga.json.ReturnBase
+import top.fumiama.copymanga.json.ThemeStructure
+import top.fumiama.copymanga.template.AutoDownloadHandler
+import top.fumiama.copymanga.tools.CMApi
+import top.fumiama.copymanga.tools.GlideBlurTransformation
+import java.lang.ref.WeakReference
+
+class BookHandler(that: WeakReference, path: String)
+ :AutoDownloadHandler(
+ that.get()?.getString(R.string.bookInfoApiUrl)?.let { String.format(it, path) } ?: "",
+ BookInfoStructure::class.java,
+ Looper.myLooper()!!){
+ private val that = that.get()
+ private var hasToastedError = false
+ get(){
+ val re = field
+ field = true
+ return re
+ }
+ var book: BookInfoStructure? = null
+ var fbibinfo:View? = null
+ var complete = false
+ private val divider get() = that?.layoutInflater?.inflate(R.layout.div_h, that.fbl, false)
+ private var fbtinfo: View? = null
+
+ override fun handleMessage(msg: Message) {
+ super.handleMessage(msg)
+ when(msg.what){
+ //0 -> setLayouts()
+ 1 -> setCover()
+ 2 -> setTexts()
+ 3 -> fbibinfo?.let { setInfoHeight(it) }
+ //4 -> setThemes()
+ 5 -> setOverScale()
+ 6 -> endSetLayouts()
+ }
+ }
+
+ override fun onError() {
+ super.onError()
+ if(!hasToastedError) {
+ Toast.makeText(that?.context, R.string.null_book, Toast.LENGTH_SHORT).show()
+ that?.rootView?.let { it1 ->
+ Navigation.findNavController(it1).navigateUp()
+ }
+ }
+ }
+
+ override fun setGsonItem(gsonObj: Any) {
+ super.setGsonItem(gsonObj)
+ book = gsonObj as BookInfoStructure
+ }
+
+ override fun getGsonItem() = book
+ override fun doWhenFinishDownload() {
+ super.doWhenFinishDownload()
+ inflateComponents()
+ Thread{ for (i in 1..6) sendEmptyMessage(i) }.start()
+ }
+
+ private fun endSetLayouts(){
+ that?.fbloading?.visibility = View.GONE
+ complete = true
+ Log.d("MyBH", "Set complete: true")
+ }
+
+ private fun inflateComponents(){
+ fbibinfo = that?.layoutInflater?.inflate(R.layout.line_bookinfo, that.fbl, false)
+ fbtinfo = that?.layoutInflater?.inflate(R.layout.line_text_info, that.fbl, false)
+ }
+
+ private fun setOverScale(){
+ that?.fbov?.setScaleView(that.lbibg)
+ }
+
+ private fun setCover(){
+ that?.let {
+ it.fbl.addView(fbibinfo)
+ val load = Glide.with(it).load(
+ GlideUrl(book?.results?.comic?.cover, CMApi.myGlideHeaders)
+ ).timeout(10000)
+ load.into(it.imic)
+ it.context?.let { it1 -> GlideBlurTransformation(it1) }
+ ?.let { it2 -> RequestOptions.bitmapTransform(it2) }
+ ?.let { it3 -> load.apply(it3).into(it.lbibg) }
+ it.imf.visibility = View.GONE
+ }
+ that?.fbl?.addView(divider)
+ }
+
+ private fun getThemeSeq(authors: Array): CharSequence{
+ var re = ""
+ for(author in authors) re += author.name + ' '
+ return re
+ }
+
+ private fun setTexts(){
+ //that?.tic?.text = book?.name
+ that?.tic?.visibility = View.GONE
+ mainWeakReference?.get()?.toolbar?.title = book?.results?.comic?.name
+ that?.btauth?.text = book?.results?.comic?.author?.let { getThemeSeq(it) }
+ that?.bttag?.text = book?.results?.comic?.theme?.let { getThemeSeq(it) }
+ that?.bthit?.text = that?.getString(R.string.text_format_hit)?.let { String.format(
+ it,
+ book?.results?.comic?.popular
+ ) }?:""
+ that?.btsub?.text = that?.getString(R.string.text_format_stat)?.let { String.format(
+ it,
+ book?.results?.comic?.status?.display
+ ) }?:""
+ that?.bttime?.text = book?.results?.comic?.datetime_updated
+ (fbtinfo as TextView).text = book?.results?.comic?.brief
+ that?.fbl?.addView(fbtinfo)
+ that?.fbl?.addView(divider)
+ }
+
+ private fun setInfoHeight(v: View){
+ v.viewTreeObserver.addOnGlobalLayoutListener {
+ Log.d("MyMy", "Width: ${v.width}")
+ val newH = (v.width * 4.0 / 9.0 + 0.5).toInt()
+ v.layoutParams.height = newH
+ v.invalidate()
+ }
+ }
+
+ private fun setThemes(){
+ book?.results?.groups?.let {
+ val keyIterator = it.keys.iterator()
+ for(i in 0 until it.size){
+ if(i % 2 == 0){
+ that?.fbl?.addView(if(i < it.size - 1){
+ val line = that.layoutInflater.inflate(R.layout.line_2chapters, that.fbl, false)
+ val leftKey = keyIterator.next()
+ line?.l2cl?.lct?.text = it[leftKey]?.name
+ line?.l2cl?.setOnClickListener { _->
+ loadVolume(it[leftKey]?.path_word?:"null")
+ }
+ val rightKey = keyIterator.next()
+ line?.l2cr?.lct?.text = it[rightKey]?.name
+ line?.l2cr?.setOnClickListener { _->
+ loadVolume(it[rightKey]?.path_word?:"null")
+ }
+ line
+ }else{
+ //Log.d("MyBH", "Add chapter: ${vol[i].volume_name}")
+ val line = that.layoutInflater.inflate(R.layout.line_chapter, that.fbl, false)
+ val key = keyIterator.next()
+ line?.lct?.text = it[key]?.name
+ line?.lcc?.setOnClickListener { _->
+ loadVolume(it[key]?.path_word?:"null")
+ }
+ line
+ })
+ }
+ }
+ }
+ }
+
+ private fun loadVolume(gpw: String){
+ Log.d("MyBH", "start to load chapter")
+ val bundle = Bundle()
+ bundle.putString("group", gpw)
+ book?.results?.comic?.path_word?.let { bundle.putString("path", it) }
+ that?.rootView?.let { Navigation.findNavController(it).navigate(R.id.action_nav_book_to_nav_chapter, bundle) }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/ui/chapter/ChapterFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/chapter/ChapterFragment.kt
new file mode 100644
index 0000000..7a952f8
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/ui/chapter/ChapterFragment.kt
@@ -0,0 +1,22 @@
+package top.fumiama.copymanga.ui.chapter
+
+import android.os.Bundle
+import android.view.View
+import top.fumiama.dmzj.copymanga.R
+import top.fumiama.copymanga.template.NoBackRefreshFragment
+import java.lang.Thread.sleep
+import java.lang.ref.WeakReference
+
+class ChapterFragment:NoBackRefreshFragment(R.layout.fragment_chapters) {
+ var handler: ChapterHandler? = null
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ if(isFirstInflate){
+ handler = arguments?.let { ChapterHandler(WeakReference(this), it.getString("path")?:"", it.getString("group")?:"") }
+ Thread{
+ sleep(600)
+ handler?.startLoad()
+ }.start()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/ui/chapter/ChapterHandler.kt b/app/src/main/java/top/fumiama/copymanga/ui/chapter/ChapterHandler.kt
new file mode 100644
index 0000000..f7c9d62
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/ui/chapter/ChapterHandler.kt
@@ -0,0 +1,81 @@
+package top.fumiama.copymanga.ui.chapter
+
+import android.os.Looper
+import android.os.Message
+import android.view.View
+import android.widget.Toast
+import androidx.navigation.Navigation
+import kotlinx.android.synthetic.main.fragment_book.*
+import kotlinx.android.synthetic.main.fragment_chapters.*
+import kotlinx.android.synthetic.main.line_2chapters.view.*
+import kotlinx.android.synthetic.main.line_chapter.view.*
+import top.fumiama.dmzj.copymanga.R
+import top.fumiama.copymanga.json.ChapterStructure
+import top.fumiama.copymanga.json.VolumeStructure
+import top.fumiama.copymanga.template.AutoDownloadHandler
+import java.lang.ref.WeakReference
+
+class ChapterHandler(that: WeakReference, pw: String, gpw: String):AutoDownloadHandler(
+ that.get()?.getString(R.string.groupInfoApiUrl)?.let { String.format(it, pw, gpw) } ?: "",
+ VolumeStructure::class.java,
+ Looper.myLooper()!!
+) {
+ private val that = that.get()
+ var hasToastedError = false
+ get(){
+ val re = field
+ field = true
+ return re
+ }
+ private var chapters: VolumeStructure? = null
+
+ override fun handleMessage(msg: Message) {
+ super.handleMessage(msg)
+ when(msg.what){
+ //0 -> setLayouts()
+ 1 -> inflateChapters()
+ }
+
+ }
+
+ override fun getGsonItem() = chapters
+ override fun setGsonItem(gsonObj: Any) {
+ super.setGsonItem(gsonObj)
+ chapters = gsonObj as VolumeStructure
+ }
+
+ override fun onError() {
+ super.onError()
+ if(!hasToastedError) {
+ Toast.makeText(that?.context, R.string.null_book, Toast.LENGTH_SHORT).show()
+ that?.rootView?.let { it1 ->
+ Navigation.findNavController(it1).navigateUp()
+ }
+ }
+ }
+ override fun doWhenFinishDownload() {
+ super.doWhenFinishDownload()
+ Thread{ sendEmptyMessage(1) }.start()
+ }
+ private fun inflateChapters(){
+
+ that?.fcloading?.visibility = View.GONE
+ }
+ private fun addLine(size: Int, name:String, onClick:(()->Unit)? = null){
+ val line =
+ that?.let { it.layoutInflater.inflate(R.layout.line_chapter, it.fbl, false) }
+ line?.lct?.text = name
+ onClick?.let {action->
+ line?.lcc?.setOnClickListener {action()}
+ }
+ that?.fcl?.addView(line)
+ }
+ private fun loadChapter(chapter: ChapterStructure){
+ /*val bundle = Bundle()
+
+ bundle.putInt("id", id)
+ bundle.putInt("volume", volId)
+ bundle.putInt("chapter", cid)
+ that?.rootView?.let { Navigation.findNavController(it).navigate(R.id.action_nav_chapter_to_nav_reader, bundle) }
+ */}
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/ui/comicdl/ComicDlFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/comicdl/ComicDlFragment.kt
new file mode 100644
index 0000000..5881d1e
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/ui/comicdl/ComicDlFragment.kt
@@ -0,0 +1,137 @@
+package top.fumiama.copymanga.ui.comicdl
+
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import android.os.Message
+import android.util.Log
+import android.view.Menu
+import android.view.View
+import com.google.gson.Gson
+import top.fumiama.dmzj.copymanga.R
+import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference
+import top.fumiama.copymanga.json.VolumeStructure
+import top.fumiama.copymanga.template.AutoDownloadThread
+import top.fumiama.copymanga.template.NoBackRefreshFragment
+import top.fumiama.copymanga.tools.CMApi
+import java.io.File
+import java.lang.Thread.sleep
+import java.lang.ref.WeakReference
+
+class ComicDlFragment:NoBackRefreshFragment(R.layout.fragment_dlcomic) {
+ var handler: ComicDlHandler? = null
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ if(isFirstInflate){
+ when {
+ arguments?.getBoolean("callFromOldDL", false) == true -> initOldComicData()
+ arguments?.getBoolean("loadJson", false) == true -> context?.getExternalFilesDir("")?.let { home ->
+ arguments?.getString("name")?.let {
+ start2load(loadFromJson(), true, loadGroupsFromFile(File(home, "$it/grps.json")))
+ }
+ }
+ else -> initComicData(
+ arguments?.getString("path"),
+ arguments?.getStringArray("group")
+ )
+ }
+ }
+ mainWeakReference?.get()?.menuMain?.let { setMenuVisible(it) }
+ }
+
+ /*override fun onDestroy() {
+ super.onDestroy()
+ mainWeakReference?.get()?.menuMain?.let { setMenuInvisible(it) }
+ }*/
+
+ fun start2load(volumes: Array, isFromFile: Boolean = false, groupArray: Array? =null){
+ handler = ComicDlHandler(Looper.myLooper()!!,
+ WeakReference(this),
+ volumes,
+ arguments?.getString("name")?:"null",
+ if(isFromFile) groupArray else arguments?.getStringArray("groupNames"))
+ if(!isFromFile) Thread{
+ context?.getExternalFilesDir("")?.let { home ->
+ arguments?.getString("name")?.let { name ->
+ val mangaFolder = File(home, name)
+ if(!mangaFolder.exists()) mangaFolder.mkdirs()
+ File(mangaFolder, "info.json").writeText(Gson().toJson(volumes))
+ arguments?.getStringArray("groupNames")?.let {
+ File(mangaFolder, "grps.json").writeText(Gson().toJson(it))
+ }
+ }
+ }
+ }.start()
+ handler?.startLoad()
+ }
+
+ private fun loadFromJson() = Gson().fromJson(json, Array::class.java)
+ private fun loadGroupsFromFile(file: File) = Gson().fromJson(file.reader(), Array::class.java)
+
+ private fun setMenuVisible(menu: Menu) {
+ val dl = menu.findItem(R.id.action_download)
+ dl?.isVisible = true
+ dl?.setIcon(R.drawable.ic_menu_sort)
+ dl?.setOnMenuItemClickListener {
+ if(handler?.complete == true && it.itemId == R.id.action_download){
+ handler?.showMultiSelectInfo()
+ true
+ }
+ else it.itemId == R.id.action_download
+ }
+ }
+
+ /*private fun setMenuInvisible(menu: Menu){
+ menu.findItem(R.id.action_download)?.isVisible = false
+ }*/
+
+ private fun initComicData(pw: String?, gpws: Array?) {
+ var volumes = arrayOf()
+ val waitHandler = WaitHandler(WeakReference(this))
+ if (gpws != null) {
+ gpws.forEach { gpw ->
+ Log.d("MyCDF", "下载:$gpw")
+ CMApi.getApiUrl(R.string.groupInfoApiUrl, pw, gpw)?.let {
+ AutoDownloadThread(it) { result ->
+ //Log.d("MyCDF", "返回:${result?.decodeToString()}")
+ volumes += Gson().fromJson(
+ result?.decodeToString(),
+ VolumeStructure::class.java
+ )
+ }.start()
+ }
+ }
+ Thread {
+ var c = 0
+ while (c < 80 && volumes.size != gpws.size) {
+ sleep(100)
+ Log.d("MyCDF", "已有:${volumes.size} 共:${gpws.size}")
+ c++
+ }
+ if (volumes.size == gpws.size) {
+ waitHandler.obtainMessage(0, volumes).sendToTarget()
+ }
+ }.start()
+ }
+ }
+
+ private fun initOldComicData() {
+ handler = ComicDlHandler(Looper.myLooper()!!,
+ WeakReference(this),
+ arguments?.getString("name")?:"null")
+ handler?.startLoad()
+ }
+
+ class WaitHandler(private val that: WeakReference): Handler(Looper.myLooper()!!){
+ override fun handleMessage(msg: Message) {
+ super.handleMessage(msg)
+ when(msg.what){
+ 0 -> that.get()?.start2load(msg.obj as Array)
+ }
+ }
+ }
+
+ companion object {
+ var json: String? = null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/ui/comicdl/ComicDlHandler.kt b/app/src/main/java/top/fumiama/copymanga/ui/comicdl/ComicDlHandler.kt
new file mode 100644
index 0000000..d42058f
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/ui/comicdl/ComicDlHandler.kt
@@ -0,0 +1,451 @@
+package top.fumiama.copymanga.ui.comicdl
+
+import android.animation.ObjectAnimator
+import android.annotation.SuppressLint
+import android.app.Dialog
+import android.content.Intent
+import android.os.Handler
+import android.os.Looper
+import android.os.Message
+import android.util.Log
+import android.view.View
+import android.view.ViewGroup
+import android.view.ViewTreeObserver
+import android.widget.Toast
+import com.google.gson.Gson
+import kotlinx.android.synthetic.main.fragment_book.*
+import kotlinx.android.synthetic.main.fragment_chapters.*
+import kotlinx.android.synthetic.main.line_chapter.view.*
+import kotlinx.android.synthetic.main.widget_downloadbar.*
+import kotlinx.android.synthetic.main.fragment_dlcomic.*
+import kotlinx.android.synthetic.main.line_horizonal_empty.view.*
+import kotlinx.android.synthetic.main.button_tbutton.*
+import kotlinx.android.synthetic.main.button_tbutton.view.*
+import kotlinx.android.synthetic.main.line_caption.view.*
+import top.fumiama.dmzj.copymanga.R
+import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference
+import top.fumiama.copymanga.json.ComicStructureOld
+import top.fumiama.copymanga.json.VolumeStructure
+import top.fumiama.copymanga.tools.CMApi
+import top.fumiama.copymanga.tools.MangaDlTools
+import top.fumiama.copymanga.tools.PropertiesTools
+import top.fumiama.copymanga.tools.UITools
+import top.fumiama.copymanga.ui.comicdl.ComicDlFragment.Companion.json
+import top.fumiama.copymanga.ui.vm.ViewMangaActivity
+import top.fumiama.copymanga.views.ChapterToggleButton
+import top.fumiama.copymanga.views.LazyScrollView
+import java.io.File
+import java.lang.ref.WeakReference
+
+class ComicDlHandler(looper: Looper, that: WeakReference, private val vols: Array, private val comicName: String, private val groupNames: Array?):Handler(looper) {
+ constructor(looper: Looper, that: WeakReference, comicName: String) : this(looper, that, arrayOf(), comicName, null) {
+ isOld = true
+ }
+ private var isOld = false
+ var complete = false
+ private val that = that.get()
+ private val toolsBox = UITools(that.get()?.context)
+ private val p = PropertiesTools(File("${that.get()?.context?.filesDir}/settings.properties"))
+ private var btnNumPerRow = 4
+ 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 var canDl = false
+ private var tbtnlist: Array = arrayOf()
+ private var tbtncnt = 0
+ private var isNewTitle = false
+ private val mangaDlTools = MangaDlTools()
+ private var multiSelect = false
+ private var size = 0
+ private var refreshSize = true
+ private var ltbtn: View? = null
+
+
+ @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 -> {
+ that?.pdwn?.progress = 0
+ if (haveSElectAll) {
+ for (i in tbtnlist) {
+ if (!isChapterExists(i.chapterName, i.caption ?: "null")) {
+ i.setBackgroundResource(R.drawable.toggle_button)
+ i.isChecked = false
+ } else if(multiSelect) {
+ i.setBackgroundResource(R.drawable.rndbg_checked)
+ i.isChecked = false
+ }
+ }
+ haveSElectAll = false
+ checkedChapter = 0
+ dldChapter = 0
+ } else {
+ for (i in tbtnlist) {
+ if (multiSelect || !i.isChecked && !isChapterExists(i.chapterName, i.caption ?: "null")) {
+ i.setBackgroundResource(R.drawable.toggle_button)
+ i.isChecked = true
+ checkedChapter++
+ }
+ }
+ haveSElectAll = true
+ }
+ 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)
+ 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() }
+ }
+ }
+
+ fun startLoad(){
+ setComponents()
+ if(isOld) analyzeOldStructure()
+ else Thread{
+ ViewMangaActivity.urlArray = arrayOf()
+ ViewMangaActivity.fileArray = arrayOf()
+ vols.forEachIndexed { i, vol ->
+ val caption = groupNames?.get(i)?:vol.results.list[0].group_path_word
+ Log.d("MyCDH", "caption: $caption, group name: ${groupNames?.get(i)}")
+ obtainMessage(11, caption).sendToTarget() //addCaption
+ vol.results.list.forEach { chapter ->
+ var data = arrayOf()
+ data += chapter.name
+ data += chapter.uuid
+ data += caption
+ data += CMApi.getApiUrl(R.string.chapterInfoApiUrl, chapter.comic_path_word, chapter.uuid)?:""
+ obtainMessage(10, data).sendToTarget()
+ }
+ sendEmptyMessage(12) //addDiv
+ }
+ complete = true
+ }.start()
+
+ }
+ private fun addDiv(){
+ that?.ldwn?.addView(
+ that.layoutInflater.inflate(R.layout.div_h, that.ldwn, false),
+ ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ )
+ }
+ private fun addCaption(title: String){
+ val tc = that?.layoutInflater?.inflate(R.layout.line_caption, that.ldwn, false)
+ tc?.tcptn?.text = title
+ that?.ldwn?.addView(
+ tc,
+ ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ )
+ addDiv()
+ isNewTitle = true
+ }
+ private fun deleteChapter(f: File, v: ChapterToggleButton) {
+ f.delete()
+ v.setBackgroundResource(R.drawable.toggle_button)
+ v.isChecked = false
+ }
+ private fun deleteChapters(zipf: File, index: Int) {
+ if (multiSelect) {
+ for (i in tbtnlist) {
+ if (i.isChecked) {
+ val f = CMApi.getZipFile(that?.context?.getExternalFilesDir(""), comicName, i.caption?:"null", i.chapterName)
+ if (f.exists()) {
+ deleteChapter(f, i)
+ checkedChapter--
+ }
+ }
+ }
+ multiSelect = false
+ sendEmptyMessage(6)
+ } else deleteChapter(zipf, tbtnlist[index])
+ }
+ private fun isChapterExists(chapter: CharSequence, caption: CharSequence) =
+ 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) {
+ val delta = 100 / checkedChapter
+ val start = dldChapter * delta
+ val now = pageNow * delta / size
+ setProgress2(start + now, 64)
+ }
+ private fun setProgress2(end: Int, duration: Long) {
+ ObjectAnimator.ofInt(
+ that?.pdwn,
+ "progress",
+ that?.pdwn?.progress?:0,
+ 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]
+ btnw = widthData[1]
+ dl = mainWeakReference?.get()?.let { Dialog(it) }
+ dl?.setContentView(R.layout.dialog_unzipping)
+ that?.dlsdwn?.viewTreeObserver?.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener{
+ override fun onGlobalLayout() {
+ cdwnWidth = that.dlsdwn.width
+ Log.d("MyDl", "Get dlsdwn height: $cdwnWidth")
+ that.dlsdwn.viewTreeObserver.removeOnGlobalLayoutListener(this)
+ }
+ })
+ that?.dllazys?.onScrollListener = object : LazyScrollView.OnScrollListener{
+ override fun onBottom() { //if(dlsdwn.translationX > 0f) showDlCard()
+ }
+ override fun onScroll() { if(that?.dlsdwn?.translationX == 0f) hideDlCard() }
+ override fun onTop() { //if(dlsdwn.translationX > 0f) showDlCard()
+ }
+ }
+ that?.cdwn?.setOnClickListener {
+ if(that.dlsdwn.translationX != 0f) showDlCard()
+ else if(checkedChapter == 0) hideDlCard()
+ else{
+ that.pdwn.progress = 0
+ if (canDl || checkedChapter == 0) canDl = false
+ else {
+ haveDlStarted = true
+ canDl = true
+ 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()
+ }
+ }
+ }
+ that?.cdwn?.setOnLongClickListener {
+ Thread { sendEmptyMessage(4) }.start()
+ return@setOnLongClickListener true
+ }
+ }
+ fun showMultiSelectInfo() {
+ toolsBox.buildInfo("进入多选模式?", "之后可以对已下载漫画进行批量删除/重新下载",
+ "确定", null, "取消", { multiSelect = true })
+ }
+ private fun downloadMangas(){
+ for (i in tbtnlist) {
+ if (i.isChecked) downloadChapterPages(i)
+ if (!canDl) {
+ checkedChapter -= dldChapter
+ dldChapter = 0
+ break
+ }
+ }
+ if (canDl) {
+ haveDlStarted = false
+ canDl = 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()
+ }
+ }
+ i.url?.let {
+ mangaDlTools.downloadChapterInVol(
+ it,
+ i.chapterName,
+ i.caption?:"null",
+ i.index
+ )
+ }
+ }
+ 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()
+ }
+
+ private fun hideDlCard(){
+ //ObjectAnimator.ofFloat(dlsdwn, "alpha", 0.9f, 0.3f).setDuration(233).start()
+ ObjectAnimator.ofFloat(that?.dlsdwn, "translationX", 0f, cdwnWidth.toFloat() * 0.9f).setDuration(233).start()
+ }
+ private fun addTbtn(data: Array){
+ addTbtn(data[0], data[1], data[2], data[3])
+ ViewMangaActivity.urlArray += data[3]
+ }
+ @SuppressLint("SetTextI18n")
+ private fun addTbtn(title: String, uuid: String, caption: String, url: String) {
+ if ((tbtncnt % btnNumPerRow == 0) || isNewTitle) {
+ ltbtn = that?.layoutInflater?.inflate(R.layout.line_horizonal_empty, that.ldwn, false)
+ that?.ldwn?.addView(ltbtn)
+ tbtncnt = 0
+ isNewTitle = false
+ }
+ that?.layoutInflater?.inflate(R.layout.button_tbutton, ltbtn?.ltbtn, false)?.let { tbv ->
+ tbv.tbtn.index = tbtnlist.size
+ tbtnlist += tbv.tbtn
+ tbtncnt++
+
+ tbv.tbtn.uuid = uuid
+ tbv.tbtn.chapterName = title
+ tbv.tbtn.url = url
+ //tbv.tbtn.hint = caption
+ tbv.tbtn.caption = caption
+ tbv.tbtn.layoutParams.width = btnw
+ val zipf = CMApi.getZipFile(that.context?.getExternalFilesDir(""), comicName, caption, title)
+ Log.d("MyCD", "Get zipf: $zipf")
+ ViewMangaActivity.fileArray += zipf
+ if (zipf.exists()) {
+ tbv.tbtn.setBackgroundResource(R.drawable.rndbg_checked)
+ tbv.tbtn.isChecked = false
+ }
+ ltbtn?.ltbtn?.addView(tbv)
+ ltbtn?.invalidate()
+ tbv.tbtn.setOnClickListener {
+ if (zipf.exists() && !multiSelect) {
+ it.tbtn.setBackgroundResource(R.drawable.rndbg_checked)
+ it.tbtn.isChecked = false
+ ViewMangaActivity.zipFile = zipf
+ ViewMangaActivity.dlhandler = this
+ ViewMangaActivity.position = it.tbtn.index
+ dl?.show()
+
+ that.startActivity(Intent(that.context, ViewMangaActivity::class.java)
+ .putExtra("callFrom", "zipFirst")
+ )
+ } else {
+ it.tbtn.setBackgroundResource(R.drawable.toggle_button)
+ if (it.tbtn.isChecked) that.tdwn?.text = "$dldChapter/${++checkedChapter}"
+ else that.tdwn.text = "$dldChapter/${--checkedChapter}"
+ }
+ }
+ tbv.tbtn.setOnLongClickListener {
+ if (zipf.exists()) {
+ toolsBox.buildInfo("确认删除${if (multiSelect) "这些" else "本"}章节?",
+ "该操作将不可撤销",
+ "确定",
+ null,
+ "取消",
+ {
+ Thread {
+ obtainMessage(7, it.tbtn.index, 0, zipf).sendToTarget()
+ }.start()
+ })
+ }else{
+ toolsBox.buildInfo("直接观看", "不下载而进行观看", "确定",
+ null, "取消", {
+ ViewMangaActivity.zipFile = null
+ ViewMangaActivity.dlhandler = this
+ ViewMangaActivity.position = it.tbtn.index
+ dl?.show()
+
+ that.startActivity(Intent(that.context, ViewMangaActivity::class.java))
+ }, null, null
+ )
+ }
+ true
+ }
+ }
+ }
+
+ private fun analyzeOldStructure() = Thread{
+ Gson().fromJson(json?.reader(), Array::class.java)?.let {
+ for (group in it) {
+ that?.layoutInflater?.inflate(R.layout.line_caption, that.ldwn, false)?.let { tc ->
+ tc.tcptn.text = group.name
+ that.ldwn.addView(
+ tc,
+ ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ )
+ that.ldwn.addView(
+ that.layoutInflater.inflate(R.layout.div_h, that.ldwn, false),
+ ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+ )
+ isNewTitle = true
+ for (chapter in group.chapters) {
+ val newUrl = CMApi.getApiUrl(R.string.chapterInfoApiUrl, chapter.url.substringAfter("/comic/").substringBefore('/'), chapter.url.substringAfterLast('/'))?:""
+ Log.d("MyCD", "Generate new url: $newUrl")
+ obtainMessage(10, arrayOf(chapter.name, "", group.name, newUrl)).sendToTarget()
+ }
+ }
+ }
+ }
+ }.start()
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/handler/DlLHandler.kt b/app/src/main/java/top/fumiama/copymanga/ui/download/DlLHandler.kt
similarity index 65%
rename from app/src/main/java/top/fumiama/copymanga/handler/DlLHandler.kt
rename to app/src/main/java/top/fumiama/copymanga/ui/download/DlLHandler.kt
index d5d02c0..6fa4c57 100644
--- a/app/src/main/java/top/fumiama/copymanga/handler/DlLHandler.kt
+++ b/app/src/main/java/top/fumiama/copymanga/ui/download/DlLHandler.kt
@@ -1,15 +1,13 @@
-package top.fumiama.copymanga.handler
+package top.fumiama.copymanga.ui.download
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)
+class DlLHandler(looper: Looper, dl: DownloadFragment): Handler(looper) {
+ private val dll = WeakReference(dl)
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
when(msg.what){
diff --git a/app/src/main/java/top/fumiama/copymanga/ui/download/DownloadFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/download/DownloadFragment.kt
new file mode 100644
index 0000000..781e0de
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/ui/download/DownloadFragment.kt
@@ -0,0 +1,201 @@
+package top.fumiama.copymanga.ui.download
+
+import android.app.AlertDialog
+import android.content.Intent
+import android.os.Bundle
+import android.os.Looper
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ArrayAdapter
+import android.widget.Toast
+import androidx.navigation.Navigation
+import kotlinx.android.synthetic.main.app_bar_main.*
+import kotlinx.android.synthetic.main.fragment_download.*
+import top.fumiama.dmzj.copymanga.R
+import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference
+import top.fumiama.copymanga.template.NoBackRefreshFragment
+import top.fumiama.copymanga.ui.comicdl.ComicDlFragment
+import top.fumiama.copymanga.ui.vm.ViewMangaActivity
+import java.io.File
+import java.util.regex.Pattern
+import java.util.zip.ZipInputStream
+
+class DownloadFragment: NoBackRefreshFragment(R.layout.fragment_download) {
+ private var nullZipDirStr = emptyArray()
+ 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
+ }
+ }
+
+ fun scanFile(cd: File?){
+ val isRoot = cd == context?.getExternalFilesDir("")
+ val jsonFile = File(cd, "info.bin")
+ if(isRoot || !jsonFile.exists()) 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.apply {
+ context.let { c ->
+ adapter = ArrayAdapter(c, android.R.layout.simple_list_item_1, it)
+ setOnItemClickListener { _, _, position, _ ->
+ val chosenFile = File(cd, it[position])
+ val chosenJson = File(chosenFile, "info.bin")
+ val newJson = File(chosenFile, "info.json")
+ //Toast.makeText(this, "进入$chosenFile", Toast.LENGTH_SHORT).show()
+ when {
+ chosenJson.exists() -> callDownloadFragment(chosenJson)
+ newJson.exists() -> callDownloadFragment(newJson, true)
+ chosenFile.isDirectory -> {
+ currentDir = chosenFile
+ callSelf(it[position])
+ }
+ chosenFile.name.endsWith(".zip") -> {
+ Toast.makeText(context, "加载中...", Toast.LENGTH_SHORT).show()
+ ViewMangaActivity.zipFile = chosenFile
+ ViewMangaActivity.comicName = it[position]
+ ViewMangaActivity.position = position
+ ViewMangaActivity.fileArray = it.map { File(cd, it) }.toTypedArray()
+ ViewMangaActivity.urlArray = Array(it.size) {return@Array ""}
+ startActivity(Intent(context, ViewMangaActivity::class.java))
+ }
+ }
+ }
+ 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
+ }.setNegativeButton(android.R.string.cancel) { _, _ -> }
+ .setNeutralButton("查错") { _, _ ->
+ handler?.obtainMessage(1, chosenFile)?.sendToTarget()
+ } //call checkDir
+ .show()
+ true
+ }
+ }
+ }
+ }
+ }
+
+
+ fun rmrf(f: File) {
+ if (f.isDirectory) f.listFiles()?.let {
+ for (i in it)
+ if (i.isDirectory) rmrf(i)
+ else i.delete()
+ }
+ 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")
+ bundle.putBoolean(if(isNew) "loadJson" else "callFromOldDL", true)
+ bundle.putString("name", jsonFile.parentFile?.name?:"Null")
+ ComicDlFragment.json = jsonFile.readText()
+ Log.d("MyDF", "root view: $rootView")
+ rootView?.let {
+ Log.d("MyDF", "action_nav_download_to_nav_group")
+ Navigation.findNavController(it).navigate(R.id.action_nav_download_to_nav_group, bundle)
+ }
+ }
+
+ private fun callSelf(title: String){
+ val bundle = Bundle()
+ bundle.putString("title", title)
+ Log.d("MyDF", "Call self to $title")
+ Log.d("MyDF", "root view: $rootView")
+ rootView?.let {
+ Log.d("MyDF", "action_nav_download_self")
+ Navigation.findNavController(it).navigate(R.id.action_nav_download_self, bundle)
+ }
+ }
+
+ 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(context?.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(context, "读取${f.name}错误!", Toast.LENGTH_SHORT).show()
+ true
+ }
+ }
+
+ private fun showErrorZip(msg: CharSequence) = AlertDialog.Builder(context)
+ .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 = context?.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 if(newString.isEmpty()) 0f else newString.toString().toFloat()
+ }
+
+ companion object{
+ var currentDir: File? = null
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/ui/history/HistoryFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/history/HistoryFragment.kt
new file mode 100644
index 0000000..4cf5317
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/ui/history/HistoryFragment.kt
@@ -0,0 +1,19 @@
+package top.fumiama.copymanga.ui.history
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import kotlinx.android.synthetic.main.fragment_history.*
+import top.fumiama.dmzj.copymanga.R
+
+class HistoryFragment : Fragment() {
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ return inflater.inflate(R.layout.fragment_history, container, false)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/ui/home/HomeFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/home/HomeFragment.kt
new file mode 100644
index 0000000..50d814b
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/ui/home/HomeFragment.kt
@@ -0,0 +1,74 @@
+package top.fumiama.copymanga.ui.home
+
+import android.os.Bundle
+import android.view.View
+import android.view.ViewGroup
+import androidx.navigation.Navigation
+import androidx.recyclerview.widget.RecyclerView
+import com.bumptech.glide.Glide
+import com.bumptech.glide.load.model.GlideUrl
+import com.bumptech.glide.load.model.LazyHeaders
+import kotlinx.android.synthetic.main.fragment_home.*
+import kotlinx.android.synthetic.main.viewpage_horizonal.view.*
+import top.fumiama.dmzj.copymanga.R
+import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference
+import top.fumiama.copymanga.template.NoBackRefreshFragment
+import top.fumiama.copymanga.tools.CMApi
+import java.lang.Thread.sleep
+import java.lang.ref.WeakReference
+
+class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) {
+ lateinit var homeHandler: HomeHandler
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ if(isFirstInflate){
+ val theme = resources.newTheme()
+ swiperefresh.setColorSchemeColors(
+ resources.getColor(R.color.colorAccent, theme),
+ resources.getColor(R.color.colorBlue2, theme),
+ resources.getColor(R.color.colorGreen, theme))
+
+ Thread{
+ homeHandler.obtainMessage(-1, true).sendToTarget()
+ while(mainWeakReference?.get()?.isDrawerClosed != true) sleep(233)
+ //homeHandler.sendEmptyMessage(6) //removeAllViews
+ homeHandler.fhib = null
+ sleep(600)
+ homeHandler.startLoad()
+ }.start()
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ homeHandler = HomeHandler(WeakReference(this))
+ }
+
+ inner class ViewData(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ inner class RecyclerViewAdapter :
+ RecyclerView.Adapter() {
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewData {
+ return ViewData(layoutInflater.inflate(R.layout.viewpage_horizonal, parent, false))
+ }
+
+ override fun onBindViewHolder(holder: ViewData, position: Int) {
+ val thisBanner = homeHandler.index?.results?.banners?.get(position)
+ thisBanner?.cover?.let {
+ //Log.d("MyHomeFVP", "Load img: $it")
+ Glide.with(this@HomeFragment).load(
+ GlideUrl(it, CMApi.myGlideHeaders)
+ ).timeout(10000).into(holder.itemView.vpi)
+ }
+ holder.itemView.vpt.text = thisBanner?.brief
+ holder.itemView.vpc.setOnClickListener {
+ val bundle = Bundle()
+ homeHandler.index?.results?.banners?.get(position)?.comic?.path_word?.let { it1 -> bundle.putString("path", it1) }
+ rootView?.let { it1 -> Navigation.findNavController(it1).navigate(R.id.action_nav_home_to_nav_book, bundle) }
+ }
+ }
+
+ override fun getItemCount(): Int = homeHandler.index?.results?.banners?.size?:0
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/ui/home/HomeHandler.kt b/app/src/main/java/top/fumiama/copymanga/ui/home/HomeHandler.kt
new file mode 100644
index 0000000..788f460
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/ui/home/HomeHandler.kt
@@ -0,0 +1,326 @@
+package top.fumiama.copymanga.ui.home
+
+import android.animation.ObjectAnimator
+import android.graphics.Color
+import android.os.Bundle
+import android.os.Looper
+import android.os.Message
+import android.util.Log
+import android.view.View
+import android.view.ViewTreeObserver
+import android.widget.Toast
+import androidx.cardview.widget.CardView
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.navigation.Navigation
+import com.bumptech.glide.Glide
+import com.bumptech.glide.load.model.GlideUrl
+import com.to.aboomy.pager2banner.Banner
+import com.to.aboomy.pager2banner.IndicatorView
+import com.to.aboomy.pager2banner.ScaleInTransformer
+import kotlinx.android.synthetic.main.card_book.view.*
+import kotlinx.android.synthetic.main.fragment_home.*
+import kotlinx.android.synthetic.main.line_1bookline.view.*
+import top.fumiama.dmzj.copymanga.R
+import top.fumiama.copymanga.json.ComicStructure
+import top.fumiama.copymanga.json.IndexStructure
+import top.fumiama.copymanga.template.AutoDownloadHandler
+import top.fumiama.copymanga.tools.CMApi
+import top.fumiama.copymanga.tools.UITools
+import java.lang.Thread.sleep
+import java.lang.ref.WeakReference
+
+class HomeHandler(that: WeakReference) :AutoDownloadHandler(
+ that.get()?.getString(R.string.mainPageApiUrl) ?: "",
+ IndexStructure::class.java,
+ Looper.myLooper()!!,
+ 9
+) {
+ private val homeF = that.get()
+ var index: IndexStructure? = null
+ var fhib: View? = null
+ get() {
+ Log.d("MyHH", "Get fhib.")
+ if(field == null){
+ field = homeF?.layoutInflater?.inflate(R.layout.viewpage_banner, homeF.fhl, false)
+ Thread{homeF?.homeHandler?.sendEmptyMessage(3)}.start()
+ }
+ return field
+ }
+ var indexLines = arrayOf()
+
+ override fun handleMessage(msg: Message) {
+ super.handleMessage(msg)
+ when (msg.what) {
+ -1 -> {
+ homeF?.swiperefresh?.isEnabled = msg.obj as Boolean
+ homeF?.swiperefresh?.isRefreshing = msg.obj as Boolean
+ }
+ //0 -> setLayouts()
+ 1 -> inflateCardLines()
+
+ 3 -> setBanner(fhib as Banner)
+
+ 5 -> setBannerInfo(msg.obj as Banner)
+ 6 -> {
+ homeF?.fhl?.let {
+ ObjectAnimator.ofFloat(it, "alpha", 1f, 0f).setDuration(233).start()
+ it.postDelayed({
+ it.removeAllViews()
+ ObjectAnimator.ofFloat(it, "alpha", 0f, 1f).setDuration(233).start()
+ }, 233)
+ }
+ }
+ 7 -> inflateBanner()
+ 8 -> homeF?.fhl?.addView(indexLines[msg.arg1])
+ //9 -> checkIndex()
+ }
+ }
+
+ override fun getGsonItem() = index
+ override fun setGsonItem(gsonObj: Any) {
+ super.setGsonItem(gsonObj)
+ index = gsonObj as IndexStructure
+ }
+ override fun onError() {
+ super.onError()
+ Toast.makeText(homeF?.context, R.string.web_error, Toast.LENGTH_SHORT).show()
+ }
+ override fun doWhenFinishDownload() {
+ super.doWhenFinishDownload()
+ try {
+ Thread {
+ sendEmptyMessage(7) //inflateBanner
+ sendEmptyMessage(1) //inflateCardLines
+ }.start()
+ } catch (e: Exception) {
+ Toast.makeText(homeF?.context, R.string.load_home_error, Toast.LENGTH_SHORT).show()
+ }
+ }
+
+ private fun inflateBanner() = homeF?.fhl?.addView(fhib)
+
+ private fun inflateTopics(){
+ index?.results?.topics?.list?.let {
+ var comics = arrayOf()
+ for((i, topic) in it.withIndex()){
+ if(i > 2) break
+ val newComic = ComicStructure()
+ newComic.name = topic.title
+ newComic.cover = topic.cover
+ newComic.path_word = topic.path_word
+ comics += newComic
+ }
+ if(comics.size == 3) allocateLine(homeF?.getString(R.string.topics_series)?:"", R.drawable.img_hot_serial, comics)
+ }
+ }
+
+ private fun inflateRec(){
+ index?.results?.recComics?.list?.let {
+ var comics = arrayOf()
+ for((i, rec) in it.withIndex()){
+ if(i > 2) break
+ comics += rec.comic
+ }
+ if(comics.size == 3) allocateLine(homeF?.getString(R.string.manga_rec)?:"", R.drawable.img_master_work, comics)
+ }
+ }
+
+ private fun inflateRank(){
+ var comics = arrayOf()
+ index?.results?.rankDayComics?.list?.let {
+ for((i, book) in it.withIndex()){
+ if(i > 2) break
+ comics += book.comic
+ }
+ }
+ index?.results?.rankWeekComics?.list?.let {
+ for((i, book) in it.withIndex()){
+ if(i > 2) break
+ comics += book.comic
+ }
+ }
+ index?.results?.rankMonthComics?.list?.let {
+ for((i, book) in it.withIndex()){
+ if(i > 2) break
+ comics += book.comic
+ }
+ }
+ if(comics.size == 9) allocateLine(homeF?.getString(R.string.rank_list)?:"", R.drawable.img_novel_bill, comics)
+ }
+
+ private fun inflateHot(){
+ index?.results?.hotComics?.let {
+ var comics = arrayOf()
+ for((i, rec) in it.withIndex()){
+ if(i > 8) break
+ comics += rec.comic
+ }
+ if(comics.size == 9) allocateLine(homeF?.getString(R.string.hot_list)?:"", R.drawable.img_hot, comics)
+ }
+ }
+
+ private fun inflateNew(){
+ index?.results?.newComics?.let {
+ var comics = arrayOf()
+ for((i, rec) in it.withIndex()){
+ if(i > 8) break
+ comics += rec.comic
+ }
+ if(comics.size == 9) allocateLine(homeF?.getString(R.string.new_list)?:"", R.drawable.img_latest_pub, comics)
+ }
+ }
+
+ private fun inflateFinish(){
+ index?.results?.finishComics?.list?.let {
+ var comics = arrayOf()
+ for((i, rec) in it.withIndex()){
+ if(i > 5) break
+ comics += rec
+ }
+ if(comics.size == 6) allocateLine(homeF?.getString(R.string.complete)?:"", R.drawable.img_novel_eye, comics, true)
+ }
+ }
+
+ private fun inflateCardLines() {
+ inflateRec()
+ inflateTopics()
+ inflateHot()
+ inflateNew()
+ inflateFinish()
+ inflateRank()
+ Thread{
+ for(i in indexLines.indices) obtainMessage(8, i, 0).sendToTarget()
+ obtainMessage(-1, false).sendToTarget() //closeLoad
+ }.start()
+ }
+
+ private fun setBanner(v: Banner): Banner {
+ v.viewTreeObserver.addOnGlobalLayoutListener(object :
+ ViewTreeObserver.OnGlobalLayoutListener {
+ override fun onGlobalLayout() {
+ //Log.d("MyMy", "Width: ${v.width}")
+ v.layoutParams.height = (v.width / 1.875 + 0.5).toInt()
+ v.invalidate()
+ v.viewTreeObserver.removeOnGlobalLayoutListener(this)
+ }
+ })
+ Thread{this.obtainMessage(5, v).sendToTarget()}.start() //setBannerInfo
+ return v
+ }
+
+ private fun setBannerInfo(v: Banner){
+ homeF?.context?.let { UITools(it) }?.let {
+ v
+ .addPageTransformer(ScaleInTransformer())
+ .setPageMargin(it.dp2px(20) ?: 0, it.dp2px(10) ?: 0)
+ .setIndicator(
+ IndicatorView(homeF.context)
+ .setIndicatorColor(Color.DKGRAY)
+ .setIndicatorSelectorColor(Color.WHITE)
+ .setIndicatorStyle(IndicatorView.IndicatorStyle.INDICATOR_BEZIER)
+ ).adapter = homeF.ViewData(v).RecyclerViewAdapter()
+ }
+ v.invalidate()
+ homeF?.fhov?.swipeRefreshLayout = homeF?.swiperefresh
+ homeF?.swiperefresh?.setOnRefreshListener {
+ Log.d("MyHFH", "Refresh items.")
+ //index = null
+ //Thread{this@HomeHandler.obtainMessage(-1, true).sendToTarget()}.start() //startLoad
+ Thread{
+ index = null
+ //fhib = null
+ indexLines = arrayOf()
+ this@HomeHandler.sendEmptyMessage(6) //removeAllViews
+ sleep(300)
+ this@HomeHandler.sendEmptyMessage(0) //setLayouts
+ }.start()
+ }
+ }
+
+ private fun allocateLine(title: String, iconResId: Int, comics: Array, finish: Boolean = false): Int{
+ val p = indexLines.size
+ val c = comics.size / 3
+ homeF?.layoutInflater?.inflate(
+ when(c){
+ 1 -> R.layout.line_1bookline
+ 2 -> R.layout.line_2bookline
+ 3 -> R.layout.line_3bookline
+ else -> return -1
+ }, homeF.fhl, false)?.let {
+ scanCards(it, comics, finish)
+ it.rttitle.text = title
+ it.ir.setImageResource(iconResId)
+ setLineHeight(it, c)
+ indexLines += it
+ }
+ return p
+ }
+
+ /*private fun setLines(v: View, position: Int) {
+ lines?.let {
+ v.rttitle.text = it[position].title
+ v.ir.setImageResource(
+ when (position) {
+ 1 -> R.drawable.img_novel_refresh
+ 2 -> R.drawable.img_novel_more
+ 3 -> R.drawable.img_novel_play
+ 4 -> R.drawable.img_novel_eye
+ else -> R.drawable.img_novel_refresh
+ }
+ )
+ Thread{this.obtainMessage(4, position, 0, v).sendToTarget()}.start() //scanCards
+ setLineHeight(v, if (position == 4) 2 else 1)
+ if(position == 4) {
+ Thread{ this.obtainMessage(-1, false).sendToTarget() }.start() //closeLoad
+ }
+ if(position == 1) v.setOnClickListener {
+ Navigation.findNavController(it).navigate(R.id.action_nav_home_to_nav_latest)
+ }else v.rimore.visibility = View.GONE
+ }
+ }*/
+
+ private fun scanCards(v: View, comics: Array, finish: Boolean = false){
+ var id = v.rc1.id
+ var card = v.findViewById(id)
+ for (data in comics){
+ setCards(
+ card.cic,
+ data.path_word,
+ data.name,
+ data.cover,
+ finish
+ )
+ card = v.findViewById(++id)
+ }
+ }
+
+ private fun setCards(cv: CardView, pw: String, name: String, img: String, isFinal: Boolean = false) {
+ cv.tic.text = name
+ homeF?.let {
+ Glide.with(it).load(GlideUrl(img, CMApi.myGlideHeaders)).timeout(10000).into(cv.imic)
+ }
+ if (isFinal) cv.sgnic.visibility = View.VISIBLE
+ cv.setOnClickListener {
+ val bundle = Bundle()
+ bundle.putString("path", pw)
+ homeF?.rootView?.let { Navigation.findNavController(it).navigate(R.id.action_nav_home_to_nav_book, bundle) }
+ }
+ }
+
+ private fun setLineHeight(v: View, cardCount: Int) {
+ v.viewTreeObserver.addOnGlobalLayoutListener(object :
+ ViewTreeObserver.OnGlobalLayoutListener {
+ override fun onGlobalLayout() {
+ homeF?.context?.let { UITools(it) }?.let {
+ val spaceTitle = it.dp2px(49)!!
+ val cardSpace = it.dp2px(16)!!
+ v.layoutParams.height =
+ ((v.width - cardSpace * 3) * cardCount * 4.0 / 9.0 + spaceTitle + cardSpace * cardCount + 0.5).toInt()
+ v.invalidate()
+ v.viewTreeObserver.removeOnGlobalLayoutListener(this)
+ }
+ //Log.d("MyVTOL", "Set card line: (${v.width}, ${v.height})")
+ }
+ })
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/ui/latest/LatestFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/latest/LatestFragment.kt
new file mode 100644
index 0000000..78a511a
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/ui/latest/LatestFragment.kt
@@ -0,0 +1,10 @@
+package top.fumiama.copymanga.ui.latest
+
+import androidx.fragment.app.Fragment
+import top.fumiama.dmzj.copymanga.R
+import top.fumiama.copymanga.template.InfoCardLoader
+
+@ExperimentalStdlibApi
+class LatestFragment: Fragment()/*InfoCardLoader(R.layout.line_lazybooklines, R.id.action_nav_latest_to_nav_book, "name", "cover", "id") {
+ override fun getApiUrl() = getString(R.string.recentUpdateApiUrl).let { String.format(it, page) }
+}*/
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/ui/rank/RankFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/rank/RankFragment.kt
new file mode 100644
index 0000000..916c271
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/ui/rank/RankFragment.kt
@@ -0,0 +1,94 @@
+package top.fumiama.copymanga.ui.rank
+
+import androidx.core.content.ContextCompat
+import androidx.fragment.app.Fragment
+import com.github.zawadz88.materialpopupmenu.popupMenu
+import com.google.gson.Gson
+import kotlinx.android.synthetic.main.anchor_popular.view.*
+import kotlinx.android.synthetic.main.line_rank.*
+import top.fumiama.dmzj.copymanga.R
+import top.fumiama.copymanga.json.FilterStructure
+import top.fumiama.copymanga.template.InfoCardLoader
+import java.lang.Thread.sleep
+
+@ExperimentalStdlibApi
+class RankFragment: Fragment()/*: InfoCardLoader(R.layout.fragment_rank, R.id.action_nav_rank_to_nav_book, "name", "cover", "id") {
+ private var type = 0
+ private var pop_sub = 0
+ private var filter: Array? = null
+ get() {
+ if (field == null) {
+ context?.assets?.open(getString(R.string.assets_filter))?.let {
+ field = Gson().fromJson(it.reader(), Array::class.java)
+ it.close()
+ }
+ }
+ return field
+ }
+
+ override fun getApiUrl() =
+ getString(R.string.rankApiUrl).let { String.format(it, pop_sub, type, page) }
+
+ override fun setListeners() {
+ super.setListeners()
+ setPop()
+ setClasses()
+ }
+
+ private fun setPop(){
+ line_rank_pop.apt.setText(if(pop_sub == 1) R.string.menu_pop_sub else R.string.menu_pop_pop)
+ line_rank_pop.setOnClickListener {
+ val popupMenu = popupMenu {
+ style = R.style.Widget_MPM_Menu_Dark_CustomBackground
+ section {
+ item {
+ labelRes = if(pop_sub == 0) R.string.menu_pop_sub else R.string.menu_pop_pop
+ labelColor = it.apt.currentTextColor
+ iconDrawable =
+ this@RankFragment.context?.let { it1 -> ContextCompat.getDrawable(it1, R.drawable.ic_refresh) } //optional
+ iconColor = it.apt.currentTextColor
+ callback = { //optional
+ if(pop_sub == 0){
+ pop_sub = 1
+ it.apt.setText(R.string.menu_pop_sub)
+ }else{
+ pop_sub = 0
+ it.apt.setText(R.string.menu_pop_pop)
+ }
+ Thread{
+ sleep(400)
+ mh?.sendEmptyMessage(4)
+ }.start()
+ }
+ }
+ }
+ }
+ this.context?.let { it1 -> popupMenu.show(it1, it) }
+ }
+ }
+
+ private fun setClasses(){
+ val items = filter?.get(0)?.items
+ line_rank_class.apt.text = items?.get(0)?.tag_name?:getString(R.string.text_null)
+ line_rank_class.setOnClickListener {
+ val popupMenu = popupMenu {
+ style = R.style.Widget_MPM_Menu_Dark_CustomBackground
+ if(items != null) section {
+ for(i in items.indices) item {
+ label = items[i]?.tag_name
+ labelColor = it.apt.currentTextColor
+ callback = { //optional
+ it.apt.text = label
+ type = items[i]?.tag_id?:0
+ Thread{
+ sleep(400)
+ mh?.sendEmptyMessage(4)
+ }.start()
+ }
+ }
+ }
+ }
+ this.context?.let { it1 -> popupMenu.show(it1, it) }
+ }
+ }
+}*/
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/ui/settings/SettingsFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/settings/SettingsFragment.kt
new file mode 100644
index 0000000..b868b03
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/ui/settings/SettingsFragment.kt
@@ -0,0 +1,12 @@
+package top.fumiama.copymanga.ui.settings
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import top.fumiama.dmzj.copymanga.R
+import top.fumiama.copymanga.template.NoBackRefreshFragment
+
+class SettingsFragment:NoBackRefreshFragment(R.layout.fragment_settings) {
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/ui/sort/SortFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/sort/SortFragment.kt
new file mode 100644
index 0000000..ad3550c
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/ui/sort/SortFragment.kt
@@ -0,0 +1,126 @@
+package top.fumiama.copymanga.ui.sort
+
+import android.animation.ObjectAnimator
+import android.view.View
+import com.github.zawadz88.materialpopupmenu.popupMenu
+import com.google.gson.Gson
+import kotlinx.android.synthetic.main.anchor_popular.view.*
+import kotlinx.android.synthetic.main.line_lazybooklines.*
+import kotlinx.android.synthetic.main.line_sort.*
+import top.fumiama.dmzj.copymanga.R
+import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference
+import top.fumiama.copymanga.json.FilterStructure
+import top.fumiama.copymanga.template.AutoDownloadThread
+import top.fumiama.copymanga.template.InfoCardLoader
+import java.lang.Thread.sleep
+
+@ExperimentalStdlibApi
+class SortFragment : InfoCardLoader(R.layout.fragment_sort, R.id.action_nav_sort_to_nav_book) {
+ private val sortWay = listOf("datetime_updated", "-datetime_updated", "popular", "-popular")
+ private var theme = -1
+ private var sortValue = 0
+ private var filter: FilterStructure? = null
+
+ override fun getApiUrl() =
+ getString(R.string.sortApiUrl).let {
+ String.format(
+ it,
+ page * 21,
+ sortWay[sortValue],
+ if(theme >= 0) (filter?.results?.theme?.get(theme)?.path_word ?: "") else ""
+ )
+ }
+
+ override fun setListeners() {
+ super.setListeners()
+ setUpdate()
+ setHot()
+ AutoDownloadThread(getString(R.string.filterApiUrl)) {
+ it?.let {
+ filter = Gson().fromJson(it.inputStream().reader(), FilterStructure::class.java)
+ mainWeakReference?.get()?.runOnUiThread{
+ setClasses()
+ }
+ }
+ }.start()
+ }
+
+ override fun onLoadFinish() {
+ super.onLoadFinish()
+ mainWeakReference?.get()?.runOnUiThread {
+ mypl.visibility = View.GONE
+ }
+ }
+
+ private fun setUpdate(){
+ line_sort_time.apt.setText(R.string.menu_update_time)
+ line_sort_time.setOnClickListener {
+ sortValue = if(it.apim.rotation == 0f) {
+ ObjectAnimator.ofFloat(it.apim, "rotation", 0f, 180f).setDuration(233).start()
+ 1
+ }else{
+ ObjectAnimator.ofFloat(it.apim, "rotation", 180f, 0f).setDuration(233).start()
+ 0
+ }
+ Thread{
+ sleep(400)
+ mh?.sendEmptyMessage(4)
+ }.start()
+ }
+ }
+
+ private fun setClasses(){
+ filter?.results?.theme?.let { items ->
+ line_sort_class.apt.text = "全部"
+ line_sort_class.setOnClickListener {
+ val popupMenu = popupMenu {
+ style = R.style.Widget_MPM_Menu_Dark_CustomBackground
+ section {
+ item {
+ label = "全部"
+ labelColor = it.apt.currentTextColor
+ callback = {
+ theme = -1
+ it.apt.text = "全部"
+ Thread{
+ sleep(400)
+ mh?.sendEmptyMessage(4)
+ }.start()
+ }
+ }
+ for(i in items.indices) item {
+ label = items[i].name
+ labelColor = it.apt.currentTextColor
+ callback = { //optional
+ it.apt.text = label
+ theme = i
+ Thread{
+ sleep(400)
+ mh?.sendEmptyMessage(4)
+ }.start()
+ }
+ }
+ }
+ }
+ this.context?.let { it1 -> popupMenu.show(it1, it) }
+ }
+ }
+ }
+
+ private fun setHot() {
+ line_sort_hot.apt.setText(R.string.menu_hot)
+ line_sort_hot.setOnClickListener {
+ sortValue = if (it.apim.rotation == 0f) {
+ ObjectAnimator.ofFloat(it.apim, "rotation", 0f, 180f).setDuration(233).start()
+ 1
+ } else {
+ ObjectAnimator.ofFloat(it.apim, "rotation", 180f, 0f).setDuration(233).start()
+ 0
+ }
+ Thread {
+ sleep(400)
+ mh?.sendEmptyMessage(4)
+ }.start()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/ui/sub/SubFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/sub/SubFragment.kt
new file mode 100644
index 0000000..1fccdfc
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/ui/sub/SubFragment.kt
@@ -0,0 +1,19 @@
+package top.fumiama.copymanga.ui.sub
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import kotlinx.android.synthetic.main.fragment_sub.*
+import top.fumiama.dmzj.copymanga.R
+
+class SubFragment : Fragment() {
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ return inflater.inflate(R.layout.fragment_sub, container, false)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/ui/vm/PagesManager.kt b/app/src/main/java/top/fumiama/copymanga/ui/vm/PagesManager.kt
new file mode 100644
index 0000000..02c3a63
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/ui/vm/PagesManager.kt
@@ -0,0 +1,76 @@
+package top.fumiama.copymanga.ui.vm
+
+import android.content.Intent
+import android.widget.Toast
+import top.fumiama.copymanga.ui.vm.ViewMangaActivity.Companion.fileArray
+import top.fumiama.copymanga.ui.vm.ViewMangaActivity.Companion.position
+import top.fumiama.copymanga.ui.vm.ViewMangaActivity.Companion.urlArray
+import top.fumiama.copymanga.ui.vm.ViewMangaActivity.Companion.zipFile
+import java.lang.ref.WeakReference
+
+class PagesManager(w: WeakReference) {
+ val v = w.get()
+ private var isEndL = false
+ private var isEndR = false
+ @ExperimentalStdlibApi
+ fun toPreviousPage(){
+ toPage(v?.r2l==true)
+ }
+ @ExperimentalStdlibApi
+ fun toNextPage(){
+ toPage(v?.r2l!=true)
+ }
+ private fun judgePrevious() = v?.pageNum?:0 > 1
+ private fun judgeNext() = v?.pageNum?:0 < v?.count?:0
+ @ExperimentalStdlibApi
+ fun toPage(goNext:Boolean){
+ if (v?.clicked == false) {
+ if (if(goNext)judgeNext() else judgePrevious()) {
+ if(goNext) {
+ v.scrollForward()
+ isEndR = false
+ } else {
+ v.scrollBack()
+ isEndL = false
+ }
+ } else {
+ val chapterPosition = position + if(goNext) 1 else -1
+ urlArray.let {
+ if(chapterPosition >= 0 && chapterPosition < it.size) it[chapterPosition].let {
+ if (if(goNext)isEndR else isEndL) {
+ val f = fileArray[chapterPosition]
+ val intent = Intent(v, ViewMangaActivity::class.java)
+ //if(v.zipFirst) intent.putExtra("callFrom", "zipFirst")
+ if(!goNext){
+ ViewMangaActivity.pn = -2
+ intent.putExtra("function", "log")
+ }
+ zipFile = if (f.exists()) f else null
+ position = chapterPosition
+ v.tt.canDo = false
+ //ViewMangaActivity.dlhandler = null
+ v.startActivity(intent)
+ v.finish()
+ } else {
+ val hint = if(goNext) '下' else '上'
+ Toast.makeText(
+ v.applicationContext,
+ "再次按下加载${hint}一章",
+ Toast.LENGTH_SHORT
+ ).show()
+ if(goNext) isEndR = true
+ else isEndL = true
+ }
+ } else Toast.makeText(
+ v.applicationContext,
+ "已经到头了~",
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+ }
+ } else v?.hideObjs()
+ }
+ fun manageInfo(){
+ if (v?.clicked == false) v.showObjs() else v?.hideObjs()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/ui/vm/VMHandler.kt b/app/src/main/java/top/fumiama/copymanga/ui/vm/VMHandler.kt
new file mode 100644
index 0000000..37d9045
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/ui/vm/VMHandler.kt
@@ -0,0 +1,209 @@
+package top.fumiama.copymanga.ui.vm
+
+import android.animation.ObjectAnimator
+import android.annotation.SuppressLint
+import android.app.Dialog
+import android.os.Looper
+import android.os.Message
+import android.util.Log
+import android.view.View
+import com.google.gson.Gson
+import kotlinx.android.synthetic.main.activity_viewmanga.*
+import kotlinx.android.synthetic.main.widget_infodrawer.*
+import kotlinx.android.synthetic.main.widget_infodrawer.view.*
+import top.fumiama.dmzj.copymanga.R
+import top.fumiama.copymanga.json.Chapter2Return
+import top.fumiama.copymanga.json.ChapterWithContent
+import top.fumiama.copymanga.json.ComicStructure
+import top.fumiama.copymanga.template.AutoDownloadHandler
+import top.fumiama.copymanga.tools.PropertiesTools
+import top.fumiama.copymanga.ui.vm.ViewMangaActivity.Companion.comicName
+import top.fumiama.copymanga.ui.vm.ViewMangaActivity.Companion.pn
+import top.fumiama.copymanga.views.ScaleImageView
+import java.io.File
+import java.lang.Exception
+import java.lang.Thread.sleep
+import java.lang.ref.WeakReference
+import java.text.SimpleDateFormat
+import java.util.*
+import java.util.zip.ZipInputStream
+
+class VMHandler(activity: ViewMangaActivity, url: String) : AutoDownloadHandler(
+ url, Chapter2Return::class.java, Looper.myLooper()!!
+) {
+ var manga: Chapter2Return? = null
+ private val wv = WeakReference(activity)
+ private val infcard = wv.get()?.infcard
+ private var infcShowed = false
+ val dl = wv.get()?.let {
+ val re = Dialog(it)
+ re.setContentView(R.layout.dialog_unzipping)
+ re
+ }
+ private var delta = -1f
+ get() {
+ if (field < 0) field = wv.get()?.infoDrawerDelta ?: 0f
+ return field
+ }
+ private val week: String
+ get() {
+ val cal = Calendar.getInstance()
+ return when (cal[Calendar.DAY_OF_WEEK]) {
+ 1 -> "周日"
+ 2 -> "周一"
+ 3 -> "周二"
+ 4 -> "周三"
+ 5 -> "周四"
+ 6 -> "周五"
+ 7 -> "周六"
+ else -> ""
+ }
+ }
+ var progressLog: PropertiesTools? = null
+
+ @SuppressLint("SimpleDateFormat", "SetTextI18n")
+ override fun handleMessage(msg: Message) {
+ super.handleMessage(msg)
+ when (msg.what) {
+ 1 -> if (infcShowed) {
+ hideInfCard(); infcShowed = false
+ }
+ 2 -> if (!infcShowed) {
+ showInfCard(); infcShowed = true
+ }
+ 3 -> infcShowed = if (infcShowed) {
+ hideInfCard(); false
+ } else {
+ showInfCard(); true
+ }
+ 4 -> {
+ val simg = msg.obj as ScaleImageView
+ wv.get()?.loadImgOn(simg, msg.arg1)
+ simg.setHeight2FitImgWidth()
+ if(msg.arg2 == 1) sendEmptyMessage(8)
+ }
+ 5 -> wv.get()?.clearImgOn(msg.obj as ScaleImageView)
+ 6 -> wv.get()?.prepareLastPage(msg.arg1, msg.arg2)
+ 7 -> dl?.show()
+ 8 -> Thread{
+ sleep(233)
+ sendEmptyMessage(13)
+ }.start()
+ 9 -> loadThread(msg.arg1)
+ 10 -> loadThread()
+ 11 -> loadImgsIntoLine(msg.arg1)
+ 12 -> loadImgsIntoLine()
+ 13 -> {
+ dl?.hide()
+ wv.get()?.restorePN()
+ }
+ 14 -> {
+ val item = (pn - 1) / (wv.get()?.verticalLoadMaxCount?:40) * (wv.get()?.verticalLoadMaxCount?:40)
+ loadThread(item)
+ Log.d("MyVMH", "Load page from $item")
+ }
+ 22 -> wv.get()?.idtime?.text = SimpleDateFormat("HH:mm").format(Date()) + week + wv.get()?.toolsBox?.netinfo
+ }
+ }
+
+ override fun getGsonItem() = manga
+ override fun setGsonItem(gsonObj: Any) {
+ super.setGsonItem(gsonObj)
+ manga = gsonObj as Chapter2Return
+ }
+ override fun onError() {
+ super.onError()
+ wv.get()?.toolsBox?.toastError("下载章节信息失败")
+ }
+
+ @ExperimentalStdlibApi
+ override fun doWhenFinishDownload() {
+ super.doWhenFinishDownload()
+ prepareManga()
+ }
+
+ @ExperimentalStdlibApi
+ fun loadFromFile(file: File): Boolean {
+ return try {
+ val jsonFile = File(file.parentFile, "${file.nameWithoutExtension}.json")
+ if(jsonFile.exists()) manga = Gson().fromJson(jsonFile.reader(), Chapter2Return::class.java)
+ else{
+ manga = Chapter2Return()
+ manga?.let {
+ it.results = Chapter2Return.Results()
+ it.results.comic = ComicStructure()
+ it.results.comic.name = file.parentFile?.name
+ it.results.chapter = ChapterWithContent()
+ it.results.chapter.name = file.nameWithoutExtension
+ it.results.chapter.size = countZipEntries(file)
+ }
+ }
+ prepareManga()
+ true
+ }catch (e: Exception){
+ e.printStackTrace()
+ //wv.get()?.toolsBox?.toastError("读取本地章节信息失败")
+ false
+ }
+ }
+
+ private fun countZipEntries(file: File): Int{
+ var count = 0
+ try {
+ val zip = ZipInputStream(file.inputStream().buffered())
+ var entry = zip.nextEntry
+ while (entry != null) {
+ if (!entry.isDirectory) count++
+ entry = zip.nextEntry
+ }
+ zip.closeEntry()
+ zip.close()
+ } catch (e: Exception) {
+ wv.get()?.toolsBox?.toastError("统计zip图片数错误!")
+ }
+ return count
+ }
+
+ @ExperimentalStdlibApi
+ private fun prepareManga(){
+ comicName = manga?.results?.comic?.name
+ progressLog = PropertiesTools(File("${wv.get()?.filesDir}/progress/${manga?.results?.comic?.name}"))
+ wv.get()?.count = manga?.results?.chapter?.size?:0
+ wv.get()?.initManga()
+ wv.get()?.vprog?.visibility = View.GONE
+ }
+ private fun loadImgsIntoLine(item: Int = (wv.get()?.currentItem?:0), maxCount: Int = (wv.get()?.verticalLoadMaxCount?:40)){
+ Log.d("MyVMH", "Fun: loadImgsIntoLine($item)")
+ val count = wv.get()?.count?.minus(1)?:0
+ val notFull = item + maxCount > count
+ val loadCount = (if(notFull) count - item else maxCount) - 1
+ Log.d("MyVMH", "loadCount: $loadCount")
+ if(loadCount >= 0) for(i in 0..loadCount) obtainMessage(4,item + i, if(i == loadCount - 1)1 else 0, wv.get()?.scrollImages?.get(i)).sendToTarget()
+ else sendEmptyMessage(8)
+ if(notFull) obtainMessage(6, loadCount + 1, maxCount).sendToTarget()
+ }
+
+ private fun loadThread() = Thread{
+ sendEmptyMessage(7)
+ //sleep(233)
+ sendEmptyMessage(12)
+ }.start()
+
+ private fun loadThread(item: Int) = Thread{
+ sendEmptyMessage(7)
+ //sleep(233)
+ Log.d("MyVMH", "loadImgsIntoLine($item)")
+ obtainMessage(11, item, 0).sendToTarget()
+ }.start()
+
+ private fun showInfCard() {
+ Log.d("MyVMH", "Read info drawer delta: $delta")
+ ObjectAnimator.ofFloat(infcard?.idc, "alpha", 0.3F, 0.8F).setDuration(233).start()
+ ObjectAnimator.ofFloat(infcard, "translationY", delta, 0F).setDuration(233).start()
+ }
+
+ private fun hideInfCard() {
+ ObjectAnimator.ofFloat(infcard?.idc, "alpha", 0.8F, 0.3F).setDuration(233).start()
+ ObjectAnimator.ofFloat(infcard, "translationY", 0F, delta).setDuration(233).start()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/ui/vm/ViewMangaActivity.kt b/app/src/main/java/top/fumiama/copymanga/ui/vm/ViewMangaActivity.kt
new file mode 100644
index 0000000..6549f49
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/ui/vm/ViewMangaActivity.kt
@@ -0,0 +1,474 @@
+package top.fumiama.copymanga.ui.vm
+
+import android.animation.ObjectAnimator
+import android.annotation.SuppressLint
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.os.Bundle
+import android.os.Handler
+import android.util.Log
+import android.view.*
+import android.widget.SeekBar
+import android.widget.Toast
+import androidx.recyclerview.widget.RecyclerView
+import androidx.viewpager2.widget.ViewPager2
+import com.bumptech.glide.Glide
+import com.bumptech.glide.load.model.GlideUrl
+import com.liaoinstan.springview.widget.SpringView
+import kotlinx.android.synthetic.main.activity_viewmanga.*
+import kotlinx.android.synthetic.main.line_header.view.*
+import kotlinx.android.synthetic.main.page_imgview.*
+import kotlinx.android.synthetic.main.page_imgview.view.*
+import kotlinx.android.synthetic.main.page_scrollimgview.*
+import kotlinx.android.synthetic.main.page_scrollimgview.view.*
+import kotlinx.android.synthetic.main.widget_infodrawer.*
+import kotlinx.android.synthetic.main.widget_infodrawer.view.*
+import kotlinx.android.synthetic.main.widget_titlebar.*
+import kotlinx.android.synthetic.main.widget_titlebar.view.*
+import kotlinx.android.synthetic.main.widget_viewmangainfo.*
+import top.fumiama.dmzj.copymanga.R
+import top.fumiama.copymanga.template.TitleActivityTemplate
+import top.fumiama.copymanga.tools.CMApi
+import top.fumiama.copymanga.tools.DownloadTools
+import top.fumiama.copymanga.tools.TimeThread
+import top.fumiama.copymanga.views.ScaleImageView
+import java.io.ByteArrayInputStream
+import java.io.ByteArrayOutputStream
+import java.io.File
+import java.lang.ref.WeakReference
+import java.util.*
+import java.util.zip.ZipFile
+
+class ViewMangaActivity : TitleActivityTemplate() {
+ var count = 0
+ private lateinit var handler: VMHandler
+ lateinit var tt: TimeThread
+ var clicked = false
+ private var isInSeek = false
+ private var isInScroll = true
+ //private var progressLog: PropertiesTools? = null
+ var scrollImages = arrayOf()
+ //var zipFirst = false
+ private var useFullScreen = false
+ var r2l = true
+ var currentItem = 0
+ var verticalLoadMaxCount = 40
+ private var notUseVP = true
+ private var isVertical = false
+ private var q = 90
+ private val size get() = if(count / verticalLoadMaxCount > currentItem / verticalLoadMaxCount) verticalLoadMaxCount else count % verticalLoadMaxCount
+ var infoDrawerDelta = 0f
+ var pageNum: Int
+ get() = getPageNumber()
+ set(value) = setPageNumber(value)
+ //var pn = 0
+ private val isPnValid: Boolean get(){
+ if(pn == -2) pn = count
+ return intent.getStringExtra("function") == "log" && pn > 0
+ }
+
+ @ExperimentalStdlibApi
+ @SuppressLint("SetTextI18n")
+ override fun onCreate(savedInstanceState: Bundle?) {
+ setContentView(R.layout.activity_viewmanga)
+ super.onCreate(savedInstanceState)
+ va = WeakReference(this)
+ //progressLog = PropertiesTools(File("$filesDir/progress/${chapter2Return?.results?.chapter?.comic_id}"))
+ //dlZip2View = intent.getStringExtra("callFrom") == "Dl" || p["dlZip2View"] == "true"
+ //zipFirst = intent.getStringExtra("callFrom") == "zipFirst"
+ useFullScreen = p["useFullScreen"] != "true"
+ r2l = p["r2l"] == "true"
+ isVertical = p["vertical"] == "true"
+ notUseVP = p["noVP"] == "true" || isVertical
+ //url = intent.getStringExtra("url")
+ handler = VMHandler(this, if(urlArray.isNotEmpty()) urlArray[position] else "")
+ if (p["quality"] != "null") q = p["quality"].toInt()
+ if (p["verticalMax"] != "null") verticalLoadMaxCount = p["verticalMax"].toInt()
+ tt = TimeThread(handler, 22)
+ tt.canDo = true
+ tt.start()
+
+ Log.d("MyVM", "Now ZipFile is $zipFile")
+ try {
+ if (zipFile != null && zipFile?.exists() == true) {
+ if (!handler.loadFromFile(zipFile!!)) prepareImgFromWeb()
+ } else prepareImgFromWeb()
+ } catch (e: Exception) {
+ e.printStackTrace()
+ toolsBox.toastError("加载漫画错误")
+ }
+ }
+
+ override fun onWindowFocusChanged(hasFocus: Boolean) {
+ super.onWindowFocusChanged(hasFocus)
+ if(useFullScreen) {
+ if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.R)
+ window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+ else {
+ window.setDecorFitsSystemWindows(false)
+ window.insetsController?.hide(WindowInsets.Type.statusBars())
+ //window.insetsController?.hide(WindowInsets.Type.navigationBars())
+ }
+ }
+ }
+
+ fun restorePN(){
+ if (isPnValid) {
+ isInScroll = false
+ pageNum = pn
+ pn = -1
+ }
+ sendProgress()
+ }
+
+ @ExperimentalStdlibApi
+ fun initManga(){
+ prepareItems(count)
+ if (!isVertical) restorePN()
+ }
+
+ @ExperimentalStdlibApi
+ private fun prepareImgFromWeb() {
+ handler.startLoad()
+ }
+
+ private fun getPageNumber(): Int {
+ return if (r2l && !notUseVP) count - vp.currentItem
+ else (if (notUseVP) currentItem else vp.currentItem) + 1
+ }
+
+ private fun setPageNumber(num: Int) {
+ if (r2l && !notUseVP) vp.currentItem = count - num
+ else if (notUseVP) {
+ if(isVertical){
+ currentItem = num - 1
+ val delta = currentItem % verticalLoadMaxCount
+ Log.d("MyVM", "Height: ${psivl.height}, scrollY: ${psivs.scrollY}")
+ if (!isInScroll || isInSeek) psivs.scrollY = psivl.height / size * delta
+ updateSeekBar()
+ }
+ else {
+ currentItem = num - 1
+ try {
+ loadOneImg()
+ } catch (e: Exception) {
+ e.printStackTrace()
+ toolsBox.toastError("页数${currentItem}不合法")
+ }
+ }
+ } else vp.currentItem = num - 1
+ }
+
+ fun clearImgOn(imgView: ScaleImageView){
+ imgView.visibility = View.GONE
+ }
+
+ private fun getTempFile(position: Int) = File(cacheDir, "$position")
+
+ private fun getImgUrl(position: Int) = handler.manga?.results?.chapter?.let {
+ it.contents[it.words.indexOf(position)].url
+ }
+
+ fun loadImgOn(imgView: ScaleImageView, position: Int){
+ if (zipFile?.exists() == true) imgView.setImageBitmap(getImgBitmap(position))
+ else if(isVertical) {
+ val f = getTempFile(position)
+ if(DownloadTools.downloadUsingUrlRet(getImgUrl(position), f))
+ imgView.setImageBitmap(BitmapFactory.decodeFile(f.path))
+ else Toast.makeText(this, "下载第${position}页失败", Toast.LENGTH_SHORT).show()
+ }
+ else Glide.with(this)
+ .load(GlideUrl(getImgUrl(position), CMApi.myGlideHeaders))
+ .timeout(10000)
+ .into(imgView)
+ imgView.visibility = View.VISIBLE
+ }
+
+ private fun loadOneImg() {
+ loadImgOn(onei, currentItem)
+ updateSeekBar()
+ }
+
+ private fun initImgList(){
+ for (i in 0..39) {
+ val newImg = ScaleImageView(this)
+ scrollImages += newImg
+ psivl.addView(newImg)
+ }
+ }
+
+ fun prepareLastPage(loadCount: Int, maxCount: Int){
+ for (i in loadCount until maxCount) handler.obtainMessage(5, scrollImages[i]).sendToTarget()
+ handler.dl?.hide()
+ }
+
+ private fun getImgBitmap(position: Int): Bitmap? {
+ Log.d("MyVM", "Get bitmap @$position, count is $count")
+ if (position >= count || position < 0) return null
+ else {
+ val zip = ZipFile(zipFile)
+ if (q == 100) return BitmapFactory.decodeStream(zip.getInputStream(zip.getEntry("${position}.jpg")))
+ else {
+ val out = ByteArrayOutputStream()
+ try {
+ BitmapFactory.decodeStream(zip.getInputStream(zip.getEntry("${position}.webp")))
+ } catch (e: Exception) {
+ e.printStackTrace()
+ return null
+ }?.compress(Bitmap.CompressFormat.JPEG, q, out)
+ return BitmapFactory.decodeStream(ByteArrayInputStream(out.toByteArray()))
+ }
+ }
+ }
+
+ private fun setIdPosition(position: Int) {
+ infoDrawerDelta = position.toFloat()
+ infcard.translationY = infoDrawerDelta
+ Log.d("MyVM", "Set info drawer delta to $infoDrawerDelta")
+ }
+
+ @ExperimentalStdlibApi
+ @SuppressLint("SetTextI18n")
+ private fun prepareItems(size: Int) {
+ ttitle.text = handler.manga?.results?.chapter?.name
+ prepareVP()
+ prepareInfoBar(size)
+ if (notUseVP && !isVertical) loadOneImg()
+ prepareIdBtVH()
+ toolsBox.dp2px(67)?.let { setIdPosition(it) }
+ prepareIdBtFullScreen()
+ prepareIdBtVP()
+ prepareIdBtLR()
+ handler.progressLog?.let {
+ //it["uuid"] = handler.manga?.results?.comic?.uuid
+ it["name"] = inftitle.ttitle.text
+ }
+ }
+
+ private fun sendProgress() {
+ handler.progressLog?.let {
+ //it["chapterId"] = hm.chapterId.toString()
+ it["page"] = pageNum.toString()
+ //it["name"] = inftitle.ttitle.text
+ }
+ }
+
+ private fun prepareIdBtLR() {
+ idtblr.isChecked = r2l
+ idtblr.setOnClickListener {
+ if (idtblr.isChecked) p["r2l"] = "true"
+ else p["r2l"] = "false"
+ Toast.makeText(this, "下次浏览生效", Toast.LENGTH_SHORT).show()
+ }
+ }
+
+ private fun prepareIdBtVP() {
+ idtbvp.isChecked = notUseVP
+ idtbvp.setOnClickListener {
+ if (idtbvp.isChecked) p["noVP"] = "true"
+ else p["noVP"] = "false"
+ Toast.makeText(this, "下次浏览生效", Toast.LENGTH_SHORT).show()
+ }
+ }
+
+ private fun prepareVP() {
+ if (notUseVP) {
+ vp.visibility = View.GONE
+ if(!isVertical) vone.visibility = View.VISIBLE
+ } else {
+ vp.visibility = View.VISIBLE
+ vone.visibility = View.GONE
+ vp.adapter = ViewData(vp).RecyclerViewAdapter()
+ vp.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
+ override fun onPageSelected(position: Int) {
+ updateSeekBar()
+ super.onPageSelected(position)
+ }
+ })
+ if (r2l) vp.currentItem = count - 1
+ }
+ }
+
+ private fun updateSeekBar() {
+ if (!isInSeek) hideObjs()
+ updateSeekText()
+ updateSeekProgress()
+ sendProgress()
+ }
+
+ @SuppressLint("SetTextI18n")
+ private fun prepareInfoBar(size: Int) {
+ oneinfo.alpha = 0F
+ infseek.visibility = View.GONE
+ isearch.visibility = View.GONE
+ inftitle.ttitle.text = handler.manga?.results?.chapter?.name
+ inftxtprogress.text = "$pageNum/$size"
+ infseek.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
+ override fun onProgressChanged(p0: SeekBar?, p1: Int, isHuman: Boolean) {
+ if (isHuman) {
+ if (p1 >= (pageNum + 1) * 100 / size) scrollForward()
+ else if (p1 < (pageNum - 1) * 100 / size) scrollBack()
+ }
+ }
+ override fun onStartTrackingTouch(p0: SeekBar?) {
+ isInSeek = true
+ }
+
+ override fun onStopTrackingTouch(p0: SeekBar?) {
+ isInSeek = false
+ }
+ })
+ isearch.setOnClickListener {
+ handler.sendEmptyMessage(3)
+ }
+ }
+
+ @ExperimentalStdlibApi
+ private fun prepareIdBtVH() {
+ idtbvh.isChecked = isVertical
+ if (isVertical) {
+ val vsps = vsp as SpringView
+ vsps.footerView.lht.text = "更多"
+ vsps.headerView.lht.text = "更多"
+ val pm = PagesManager(WeakReference(this))
+ vsps.setListener(object :SpringView.OnFreshListener{
+ override fun onLoadmore() {
+ //scrollForward()
+ pm.toPage(true)
+ vsps.onFinishFreshAndLoad()
+ }
+ override fun onRefresh() {
+ //scrollBack()
+ pm.toPage(false)
+ vsps.onFinishFreshAndLoad()
+ }
+ })
+ vp.visibility = View.GONE
+ vsp.visibility = View.VISIBLE
+ initImgList()
+ handler.sendEmptyMessage(if(isPnValid)14 else 10)
+ psivs.setOnScrollChangeListener { _, _, scrollY, _, _ ->
+ isInScroll = true
+ if(!isInSeek){
+ val newCurrent = (scrollY.toFloat() * size.toFloat() / psivl.height.toFloat() + 0.5).toInt()
+ pageNum += newCurrent - currentItem % verticalLoadMaxCount
+ }
+ }
+ }
+ idtbvh.setOnClickListener {
+ p["vertical"] = if (idtbvh.isChecked) "true" else "false"
+ Toast.makeText(this, "下次浏览生效", Toast.LENGTH_SHORT).show()
+ }
+ }
+
+ private fun prepareIdBtFullScreen() {
+ idtbfullscreen.isChecked = !useFullScreen
+ idtbfullscreen.setOnClickListener {
+ p["useFullScreen"] = if (idtbfullscreen.isChecked) "true" else "false"
+ Toast.makeText(this, "下次浏览生效", Toast.LENGTH_SHORT).show()
+ }
+ }
+
+ fun scrollBack() {
+ isInScroll = false
+ if(isVertical && (pageNum-1) % verticalLoadMaxCount == 0){
+ Log.d("MyVM", "Do scroll back, isVertical: $isVertical, pageNum: $pageNum")
+ handler.obtainMessage(9, currentItem - verticalLoadMaxCount, 0).sendToTarget() //loadImgsIntoLine(currentItem - verticalLoadMaxCount)
+ psivl.postDelayed({ pageNum-- }, 233)
+ }else pageNum--
+ }
+
+ fun scrollForward() {
+ isInScroll = false
+ pageNum++
+ if(isVertical && (pageNum-1) % verticalLoadMaxCount == 0) handler.sendEmptyMessage(10)
+ }
+
+
+
+ @SuppressLint("SetTextI18n")
+ private fun updateSeekText() {
+ inftxtprogress.text = "$pageNum/$count"
+ }
+
+ private fun updateSeekProgress() {
+ infseek.progress = pageNum * 100 / count
+ }
+
+ override fun onDestroy() {
+ dlhandler?.sendEmptyMessage(0)
+ tt.canDo = false
+ dlhandler = null
+ super.onDestroy()
+ }
+
+ inner class ViewData(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ inner class RecyclerViewAdapter :
+ RecyclerView.Adapter() {
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewData {
+ return ViewData(
+ LayoutInflater.from(parent.context)
+ .inflate(R.layout.page_imgview, parent, false)
+ )
+ }
+
+ @SuppressLint("ClickableViewAccessibility", "SetTextI18n")
+ override fun onBindViewHolder(holder: ViewData, position: Int) {
+ val pos = if (r2l) count - position - 1 else position
+ if (zipFile?.exists() == true) getImgBitmap(pos)?.let {
+ Glide.with(this@ViewMangaActivity).load(it)
+ //.thumbnail(Glide.with(this@ViewMangaActivity).load(R.drawable.load))
+ .into(holder.itemView.onei)
+ //holder.itemView.onei.setImageBitmap(it)
+ }
+ else Glide.with(this@ViewMangaActivity).load(
+ GlideUrl(getImgUrl(pos), CMApi.myGlideHeaders))
+ .timeout(10000)
+ //.thumbnail(Glide.with(this@ViewMangaActivity).load(R.drawable.load))
+ .into(holder.itemView.onei)
+ }
+
+ override fun getItemCount(): Int {
+ return count
+ }
+ }
+ }
+
+ fun showObjs() {
+ infseek.visibility = View.VISIBLE
+ isearch.visibility = View.VISIBLE
+ ObjectAnimator.ofFloat(
+ oneinfo,
+ "alpha",
+ oneinfo.alpha,
+ 1F
+ ).setDuration(233).start()
+ clicked = true
+ }
+
+ fun hideObjs() {
+ ObjectAnimator.ofFloat(
+ oneinfo,
+ "alpha",
+ oneinfo.alpha,
+ 0F
+ ).setDuration(233).start()
+ clicked = false
+ infseek.postDelayed({
+ infseek.visibility = View.GONE
+ isearch.visibility = View.GONE
+ }, 300)
+ handler.sendEmptyMessage(1)
+ }
+
+ companion object {
+ var comicName: String? = null
+ var urlArray = arrayOf()
+ var fileArray = arrayOf()
+ var position = 0
+ var zipFile: File? = null
+ var dlhandler: Handler? = null
+ var va: WeakReference? = null
+ var pn = 0
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/view/JSWebView.kt b/app/src/main/java/top/fumiama/copymanga/view/JSWebView.kt
deleted file mode 100644
index b65ebff..0000000
--- a/app/src/main/java/top/fumiama/copymanga/view/JSWebView.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package top.fumiama.copymanga.view
-
-import android.annotation.SuppressLint
-import android.content.Context
-import android.util.AttributeSet
-import android.util.Log
-import android.webkit.WebView
-import top.fumiama.copymanga.web.WebViewClient
-import kotlin.reflect.KClass
-
-@SuppressLint("JavascriptInterface")
-class JSWebView : WebView {
- constructor(context: Context): super(context)
- constructor(context: Context, attributeSet: AttributeSet): super(context, attributeSet)
- constructor(context: Context, attributeSet: AttributeSet, defSA: Int): super(context, attributeSet, defSA)
- constructor(context: Context, UA: String) : super(context) { settings.userAgentString = UA }
- init {
- settings.javaScriptEnabled = true
- settings.domStorageEnabled = true
- Log.d("MyJSW", "UA is: ${settings.userAgentString}")
- }
- fun setWebViewClient(jsFileName: String){webViewClient = WebViewClient(context, jsFileName)}
- fun loadJSInterface(obj: Any){addJavascriptInterface(obj, "GM")}
-}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/view/ChapterToggleButton.kt b/app/src/main/java/top/fumiama/copymanga/views/ChapterToggleButton.kt
similarity index 87%
rename from app/src/main/java/top/fumiama/copymanga/view/ChapterToggleButton.kt
rename to app/src/main/java/top/fumiama/copymanga/views/ChapterToggleButton.kt
index 8e221e3..7e8d6b9 100644
--- a/app/src/main/java/top/fumiama/copymanga/view/ChapterToggleButton.kt
+++ b/app/src/main/java/top/fumiama/copymanga/views/ChapterToggleButton.kt
@@ -1,4 +1,4 @@
-package top.fumiama.copymanga.view
+package top.fumiama.copymanga.views
import android.content.Context
import android.util.AttributeSet
@@ -10,9 +10,9 @@ class ChapterToggleButton: ToggleButton {
constructor(context: Context?): super(context, null)
var url: CharSequence? = null
- val hash get() = url?.toString()?.substringAfterLast('/')
var caption: CharSequence? = null
var index: Int = 0
+ var uuid: CharSequence? = null
var chapterName: CharSequence = "null"
set(value) {
textOn = value
diff --git a/app/src/main/java/top/fumiama/copymanga/view/LazyScrollView.kt b/app/src/main/java/top/fumiama/copymanga/views/LazyScrollView.kt
similarity index 78%
rename from app/src/main/java/top/fumiama/copymanga/view/LazyScrollView.kt
rename to app/src/main/java/top/fumiama/copymanga/views/LazyScrollView.kt
index d585bad..550ce83 100644
--- a/app/src/main/java/top/fumiama/copymanga/view/LazyScrollView.kt
+++ b/app/src/main/java/top/fumiama/copymanga/views/LazyScrollView.kt
@@ -1,20 +1,20 @@
-package top.fumiama.copymanga.view
+package top.fumiama.copymanga.views
import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
-import android.widget.ScrollView
+import androidx.core.widget.NestedScrollView
@SuppressLint("ClickableViewAccessibility")
-class LazyScrollView : ScrollView {
+class LazyScrollView : NestedScrollView {
private val view: View?
get() = getChildAt(0)
- constructor(context: Context?) : super(context)
- constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
- constructor(context: Context?, attrs: AttributeSet?, defStyle: Int) : super(context, attrs, defStyle)
+ constructor(context: Context) : super(context)
+ constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
+ constructor(context: Context, attrs: AttributeSet?, defStyle: Int) : super(context, attrs, defStyle)
init {
setOnTouchListener { _, event ->
diff --git a/app/src/main/java/top/fumiama/copymanga/views/MangaCardView.kt b/app/src/main/java/top/fumiama/copymanga/views/MangaCardView.kt
new file mode 100644
index 0000000..dbb19d5
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/views/MangaCardView.kt
@@ -0,0 +1,22 @@
+package top.fumiama.copymanga.views
+
+import android.content.Context
+import android.util.AttributeSet
+import androidx.cardview.widget.CardView
+import java.io.File
+
+class MangaCardView:CardView {
+ constructor(context: Context): super(context)
+ constructor(context: Context, attrs: AttributeSet?): super (context, attrs)
+ constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int): super(context, attrs, defStyleAttr)
+
+ var name = ""
+ var append: String? = null
+ var headImageUrl: String? = null
+ //var uuid: String? = null
+ var path: String? = null
+ var isFinish = false
+ var index = 0
+ var chapterUUID: String? = null
+ var pageNumber: Int? = null
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/views/OverScrollView.kt b/app/src/main/java/top/fumiama/copymanga/views/OverScrollView.kt
new file mode 100644
index 0000000..710520a
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/views/OverScrollView.kt
@@ -0,0 +1,21 @@
+package top.fumiama.copymanga.views
+
+import android.content.Context
+import android.util.AttributeSet
+import com.akscorp.overscrollablescrollview.OverscrollableNestedScrollView
+import kotlinx.android.synthetic.main.app_bar_main.*
+import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference
+
+open class OverScrollView :OverscrollableNestedScrollView{
+ constructor(context: Context) : super(context)
+
+ constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
+
+ constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle)
+
+ override fun isAchieveTop(): Boolean {
+ val re = super.isAchieveTop()
+ if(re) mainWeakReference?.get()?.appbar?.setExpanded(true)
+ return re
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/view/ScaleImageView.kt b/app/src/main/java/top/fumiama/copymanga/views/ScaleImageView.kt
similarity index 89%
rename from app/src/main/java/top/fumiama/copymanga/view/ScaleImageView.kt
rename to app/src/main/java/top/fumiama/copymanga/views/ScaleImageView.kt
index 56d1e62..d6f293e 100644
--- a/app/src/main/java/top/fumiama/copymanga/view/ScaleImageView.kt
+++ b/app/src/main/java/top/fumiama/copymanga/views/ScaleImageView.kt
@@ -1,4 +1,4 @@
-package top.fumiama.copymanga.view
+package top.fumiama.copymanga.views
import android.animation.ValueAnimator
import android.animation.ValueAnimator.AnimatorUpdateListener
@@ -14,8 +14,8 @@ import android.view.GestureDetector
import android.view.GestureDetector.SimpleOnGestureListener
import android.view.MotionEvent
import android.widget.ImageView
-import top.fumiama.copymanga.activity.ViewMangaActivity
-import top.fumiama.copymanga.tool.PagesManager
+import top.fumiama.copymanga.ui.vm.PagesManager
+import top.fumiama.copymanga.ui.vm.ViewMangaActivity
import java.lang.ref.WeakReference
import java.util.*
import kotlin.math.sqrt
@@ -94,17 +94,17 @@ class ScaleImageView : ImageView {
* 外部变换矩阵记录了图片手势操作的最终结果,是相对于图片fit center状态的变换.
* 默认值为单位矩阵,此时图片为fit center状态.
*
- @param matrix 用于填充结果的对象
- @return 如果传了matrix参数则将matrix填充后返回,否则new一个填充返回
+ @param matrix 用于填充结果的对象
+ @return 如果传了matrix参数则将matrix填充后返回,否则new一个填充返回
fun getOuterMatrix(matrix: Matrix?): Matrix {
- var matrix = matrix
- if (matrix == null) {
- matrix = Matrix(mOuterMatrix)
- } else {
- matrix.set(mOuterMatrix)
- }
- return matrix
+ var matrix = matrix
+ if (matrix == null) {
+ matrix = Matrix(mOuterMatrix)
+ } else {
+ matrix.set(mOuterMatrix)
+ }
+ return matrix
}*/
/**
@@ -140,21 +140,23 @@ class ScaleImageView : ImageView {
}
fun setHeight2FitImgWidth(){
- matrix.reset()
- val imgX = drawable.intrinsicWidth.toFloat()
- val imgY = drawable.intrinsicHeight.toFloat()
- //Log.d("MySIV", "ix: $imgX, iy: $imgY, w: $width, h: $height")
- //原图大小
- val tempSrc = rectFTake(0f, 0f, imgX, imgY)
- layoutParams.height = (imgY / imgX * width + 0.5).toInt()
- invalidate()
- //控件大小
- val tempDst = rectFTake(0f, 0f, width.toFloat(), height.toFloat())
- //计算fit center矩阵
- matrix.setRectToRect(tempSrc, tempDst, Matrix.ScaleToFit.CENTER)
- //释放临时对象
- rectFGiven(tempDst)
- rectFGiven(tempSrc)
+ if(matrix != null && drawable != null && layoutParams != null){
+ matrix.reset()
+ val imgX = drawable.intrinsicWidth.toFloat()
+ val imgY = drawable.intrinsicHeight.toFloat()
+ //Log.d("MySIV", "ix: $imgX, iy: $imgY, w: $width, h: $height")
+ //原图大小
+ val tempSrc = rectFTake(0f, 0f, imgX, imgY)
+ layoutParams.height = (imgY / imgX * width + 0.5).toInt()
+ invalidate()
+ //控件大小
+ val tempDst = rectFTake(0f, 0f, width.toFloat(), height.toFloat())
+ //计算fit center矩阵
+ matrix.setRectToRect(tempSrc, tempDst, Matrix.ScaleToFit.CENTER)
+ //释放临时对象
+ rectFGiven(tempDst)
+ rectFGiven(tempSrc)
+ }
}
/**
@@ -210,11 +212,11 @@ class ScaleImageView : ImageView {
* @return 返回当前的mask对象副本,如果当前没有设置mask则返回null
val mask: RectF?
- get() = if (mMask != null) {
- RectF(mMask)
- } else {
- null
- }*/
+ get() = if (mMask != null) {
+ RectF(mMask)
+ } else {
+ null
+ }*/
/**
* 与ViewPager结合的时候使用
@@ -262,29 +264,29 @@ class ScaleImageView : ImageView {
* 调用此方法会停止正在进行中的手势以及手势动画.
* 当duration为0时,outerMatrix值会被立即设置而不会启动动画.
*
- @param endMatrix 动画目标矩阵
- @param duration 动画持续时间
+ @param endMatrix 动画目标矩阵
+ @param duration 动画持续时间
*
- @see .getOuterMatrix
+ @see .getOuterMatrix
fun outerMatrixTo(endMatrix: Matrix?, duration: Long) {
- if (endMatrix == null) {
- return
- }
- //将手势设置为PINCH_MODE_FREE将停止后续手势的触发
- pinchMode = PINCH_MODE_FREE
- //停止所有正在进行的动画
- cancelAllAnimator()
- //如果时间不合法立即执行结果
- if (duration <= 0) {
- mOuterMatrix.set(endMatrix)
- dispatchOuterMatrixChanged()
- invalidate()
- } else {
- //创建矩阵变化动画
- mScaleAnimator = ScaleAnimator(mOuterMatrix, endMatrix, duration)
- mScaleAnimator!!.start()
- }
+ if (endMatrix == null) {
+ return
+ }
+ //将手势设置为PINCH_MODE_FREE将停止后续手势的触发
+ pinchMode = PINCH_MODE_FREE
+ //停止所有正在进行的动画
+ cancelAllAnimator()
+ //如果时间不合法立即执行结果
+ if (duration <= 0) {
+ mOuterMatrix.set(endMatrix)
+ dispatchOuterMatrixChanged()
+ invalidate()
+ } else {
+ //创建矩阵变化动画
+ mScaleAnimator = ScaleAnimator(mOuterMatrix, endMatrix, duration)
+ mScaleAnimator!!.start()
+ }
}*/
/**
@@ -294,32 +296,32 @@ class ScaleImageView : ImageView {
* 当前mask为null时,则不执行动画立即设置为目标mask.
* 当duration为0时,立即将当前mask设置为目标mask,不会执行动画.
*
- @param mask 动画目标mask
- @param duration 动画持续时间
+ @param mask 动画目标mask
+ @param duration 动画持续时间
*
- @see .getMask
+ @see .getMask
fun zoomMaskTo(mask: RectF?, duration: Long) {
- if (mask == null) {
- return
- }
- //停止mask动画
- if (mMaskAnimator != null) {
- mMaskAnimator!!.cancel()
- mMaskAnimator = null
- }
- //如果duration为0或者之前没有设置过mask,不执行动画,立即设置
- if (duration <= 0 || mMask == null) {
- if (mMask == null) {
- mMask = RectF()
- }
- mMask!!.set(mask)
- invalidate()
- } else {
- //执行mask动画
- mMaskAnimator = MaskAnimator(mMask!!, mask, duration)
- mMaskAnimator!!.start()
- }
+ if (mask == null) {
+ return
+ }
+ //停止mask动画
+ if (mMaskAnimator != null) {
+ mMaskAnimator!!.cancel()
+ mMaskAnimator = null
+ }
+ //如果duration为0或者之前没有设置过mask,不执行动画,立即设置
+ if (duration <= 0 || mMask == null) {
+ if (mMask == null) {
+ mMask = RectF()
+ }
+ mMask!!.set(mask)
+ invalidate()
+ } else {
+ //执行mask动画
+ mMaskAnimator = MaskAnimator(mMask!!, mask, duration)
+ mMaskAnimator!!.start()
+ }
}*/
/**
@@ -329,24 +331,24 @@ class ScaleImageView : ImageView {
* 但不清空drawable,以及事件绑定相关数据.
fun reset() {
- //重置位置到fit
- mOuterMatrix.reset()
- dispatchOuterMatrixChanged()
- //清空mask
- mMask = null
- //停止所有手势
- pinchMode = PINCH_MODE_FREE
- mLastMovePoint[0f] = 0f
- mScaleCenter[0f] = 0f
- mScaleBase = 0f
- //停止所有动画
- if (mMaskAnimator != null) {
- mMaskAnimator!!.cancel()
- mMaskAnimator = null
- }
- cancelAllAnimator()
- //重绘
- invalidate()
+ //重置位置到fit
+ mOuterMatrix.reset()
+ dispatchOuterMatrixChanged()
+ //清空mask
+ mMask = null
+ //停止所有手势
+ pinchMode = PINCH_MODE_FREE
+ mLastMovePoint[0f] = 0f
+ mScaleCenter[0f] = 0f
+ mScaleBase = 0f
+ //停止所有动画
+ if (mMaskAnimator != null) {
+ mMaskAnimator!!.cancel()
+ mMaskAnimator = null
+ }
+ cancelAllAnimator()
+ //重绘
+ invalidate()
}*/
////////////////////////////////对外广播事件////////////////////////////////
/**
@@ -399,64 +401,64 @@ class ScaleImageView : ImageView {
/**
* 添加外部矩阵变化监听
*
- @param listener
+ @param listener
fun addOuterMatrixChangedListener(listener: OuterMatrixChangedListener?) {
- if (listener == null) {
- return
- }
- //如果监听列表没有被修改锁定直接将监听添加到监听列表
- if (mDispatchOuterMatrixChangedLock == 0) {
- if (mOuterMatrixChangedListeners == null) {
- mOuterMatrixChangedListeners =
- ArrayList()
- }
- mOuterMatrixChangedListeners!!.add(listener)
- } else {
- //如果监听列表修改被锁定,那么尝试在监听列表副本上添加
- //监听列表副本将会在锁定被解除时替换到监听列表里
- if (mOuterMatrixChangedListenersCopy == null) {
- mOuterMatrixChangedListenersCopy = if (mOuterMatrixChangedListeners != null) {
- ArrayList(
- mOuterMatrixChangedListeners!!
- )
- } else {
- ArrayList()
- }
- }
- mOuterMatrixChangedListenersCopy!!.add(listener)
- }
+ if (listener == null) {
+ return
+ }
+ //如果监听列表没有被修改锁定直接将监听添加到监听列表
+ if (mDispatchOuterMatrixChangedLock == 0) {
+ if (mOuterMatrixChangedListeners == null) {
+ mOuterMatrixChangedListeners =
+ ArrayList()
+ }
+ mOuterMatrixChangedListeners!!.add(listener)
+ } else {
+ //如果监听列表修改被锁定,那么尝试在监听列表副本上添加
+ //监听列表副本将会在锁定被解除时替换到监听列表里
+ if (mOuterMatrixChangedListenersCopy == null) {
+ mOuterMatrixChangedListenersCopy = if (mOuterMatrixChangedListeners != null) {
+ ArrayList(
+ mOuterMatrixChangedListeners!!
+ )
+ } else {
+ ArrayList()
+ }
+ }
+ mOuterMatrixChangedListenersCopy!!.add(listener)
+ }
}*/
/**
* 删除外部矩阵变化监听
*
- @param listener
+ @param listener
fun removeOuterMatrixChangedListener(listener: OuterMatrixChangedListener?) {
- if (listener == null) {
- return
- }
- //如果监听列表没有被修改锁定直接在监听列表数据结构上修改
- if (mDispatchOuterMatrixChangedLock == 0) {
- if (mOuterMatrixChangedListeners != null) {
- mOuterMatrixChangedListeners!!.remove(listener)
- }
- } else {
- //如果监听列表被修改锁定,那么就在其副本上修改
- //其副本将会在锁定解除时替换回监听列表
- if (mOuterMatrixChangedListenersCopy == null) {
- if (mOuterMatrixChangedListeners != null) {
- mOuterMatrixChangedListenersCopy =
- ArrayList(
- mOuterMatrixChangedListeners!!
- )
- }
- }
- if (mOuterMatrixChangedListenersCopy != null) {
- mOuterMatrixChangedListenersCopy!!.remove(listener)
- }
- }
+ if (listener == null) {
+ return
+ }
+ //如果监听列表没有被修改锁定直接在监听列表数据结构上修改
+ if (mDispatchOuterMatrixChangedLock == 0) {
+ if (mOuterMatrixChangedListeners != null) {
+ mOuterMatrixChangedListeners!!.remove(listener)
+ }
+ } else {
+ //如果监听列表被修改锁定,那么就在其副本上修改
+ //其副本将会在锁定解除时替换回监听列表
+ if (mOuterMatrixChangedListenersCopy == null) {
+ if (mOuterMatrixChangedListeners != null) {
+ mOuterMatrixChangedListenersCopy =
+ ArrayList(
+ mOuterMatrixChangedListeners!!
+ )
+ }
+ }
+ if (mOuterMatrixChangedListenersCopy != null) {
+ mOuterMatrixChangedListenersCopy!!.remove(listener)
+ }
+ }
}*/
/**
@@ -583,10 +585,10 @@ class ScaleImageView : ImageView {
* 记录两个手指的中点,作为和mScaleCenter绑定的点.
* 这个绑定可以保证mScaleCenter无论如何都会跟随这个中点.
*
- @see .mScaleCenter
+ @see .mScaleCenter
*
- @see .scale
- @see .scaleEnd
+ @see .scale
+ @see .scaleEnd
*/
private val mLastMovePoint = PointF()
@@ -674,7 +676,6 @@ class ScaleImageView : ImageView {
}
var v :WeakReference? = null
- var pm:PagesManager? = null
override fun onSingleTapConfirmed(event: MotionEvent): Boolean {
if(v == null) {
v = ViewMangaActivity.va
@@ -1234,8 +1235,8 @@ class ScaleImageView : ImageView {
*
* 参数单位为 像素/帧
*
- @param vectorX 速度向量
- @param vectorY 速度向量
+ @param vectorX 速度向量
+ @param vectorY 速度向量
*/
init {
setFloatValues(0f, 1f)
@@ -1296,8 +1297,8 @@ class ScaleImageView : ImageView {
*
* 从一个矩阵变换到另外一个矩阵
*
- @param start 开始矩阵
- @param end 结束矩阵
+ @param start 开始矩阵
+ @param end 结束矩阵
*/
init {
setFloatValues(0f, 1f)
@@ -1387,7 +1388,7 @@ class ScaleImageView : ImageView {
/**
* 创建一个对象池
*
- @param size 对象池最大容量
+ @param size 对象池最大容量
*/
init {
mQueue = LinkedList()
@@ -1485,11 +1486,11 @@ class ScaleImageView : ImageView {
* 获取某个矩形的副本
fun rectFTake(rectF: RectF?): RectF {
- val result = mRectFPool.take()!!
- if (rectF != null) {
- result.set(rectF)
- }
- return result
+ val result = mRectFPool.take()!!
+ if (rectF != null) {
+ result.set(rectF)
+ }
+ return result
}*/
/**
@@ -1630,5 +1631,7 @@ class ScaleImageView : ImageView {
* @see .getPinchMode
*/
const val PINCH_MODE_SCALE = 2
+
+ var pm:PagesManager? = null
}
}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/views/ScrollRefreshView.kt b/app/src/main/java/top/fumiama/copymanga/views/ScrollRefreshView.kt
new file mode 100644
index 0000000..bfa3f06
--- /dev/null
+++ b/app/src/main/java/top/fumiama/copymanga/views/ScrollRefreshView.kt
@@ -0,0 +1,26 @@
+package top.fumiama.copymanga.views
+
+import android.content.Context
+import android.util.AttributeSet
+import androidx.core.widget.NestedScrollView
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
+
+class ScrollRefreshView : NestedScrollView {
+ constructor(context: Context) : super(context)
+
+ constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
+
+ constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(
+ context,
+ attrs,
+ defStyle
+ )
+
+ var swipeRefreshLayout: SwipeRefreshLayout? = null
+
+ override fun onScrollChanged(l: Int, t: Int, oldl: Int, oldt: Int) {
+ super.onScrollChanged(l, t, oldl, oldt)
+ //Log.d("MyOSV", "$l, $t, $oldl, $oldt")
+ swipeRefreshLayout?.isEnabled = t == 0
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/web/JS.kt b/app/src/main/java/top/fumiama/copymanga/web/JS.kt
deleted file mode 100644
index e43508f..0000000
--- a/app/src/main/java/top/fumiama/copymanga/web/JS.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-package top.fumiama.copymanga.web
-
-import android.util.Log
-import android.webkit.JavascriptInterface
-import top.fumiama.copymanga.R
-import top.fumiama.copymanga.activity.MainActivity.Companion.mh
-import top.fumiama.copymanga.activity.MainActivity.Companion.wm
-import top.fumiama.copymanga.activity.ViewMangaActivity
-
-class JS {
- @JavascriptInterface
- fun loadComic(url: String){
- val u = when {
- 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("/")}"
- else -> ""
- }
- Log.d("MyJS", "Load comic: $u")
- Thread{mh?.obtainMessage(1, u)?.sendToTarget()}.start()
- }
- @JavascriptInterface
- fun hideFab(){
- Thread{mh?.sendEmptyMessage(5)}.start()
- }
- @JavascriptInterface
- fun enterProfile(){
- Thread{mh?.sendEmptyMessage(6)}.start()
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/web/JSHidden.kt b/app/src/main/java/top/fumiama/copymanga/web/JSHidden.kt
deleted file mode 100644
index af7bf13..0000000
--- a/app/src/main/java/top/fumiama/copymanga/web/JSHidden.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package top.fumiama.copymanga.web
-
-import android.util.Log
-import android.webkit.JavascriptInterface
-import top.fumiama.copymanga.activity.DlActivity
-import top.fumiama.copymanga.activity.MainActivity.Companion.mh
-
-class JSHidden {
- @JavascriptInterface
- fun loadChapter(listString: String){
- Thread{mh?.obtainMessage(2, listString)?.sendToTarget()}.start()
- }
- @JavascriptInterface
- fun setTitle(title:String){
- Log.d("MyJSH", "Set title: $title")
- DlActivity.comicName = title
- }
- @JavascriptInterface
- fun setFab(content: String){
- Thread{mh?.obtainMessage(4, content)?.sendToTarget()}.start()
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/web/WebChromeClient.kt b/app/src/main/java/top/fumiama/copymanga/web/WebChromeClient.kt
deleted file mode 100644
index f9b792f..0000000
--- a/app/src/main/java/top/fumiama/copymanga/web/WebChromeClient.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-package top.fumiama.copymanga.web
-
-import android.webkit.JsPromptResult
-import android.webkit.JsResult
-import android.webkit.WebChromeClient
-import android.webkit.WebView
-import top.fumiama.copymanga.activity.MainActivity.Companion.mh
-
-class WebChromeClient:WebChromeClient() {
- override fun onProgressChanged(view: WebView?, newProgress: Int) {
- super.onProgressChanged(view, newProgress)
- //Log.d("MyWCC", "W progress: $newProgress")
- Thread{mh?.obtainMessage(3, newProgress, 0)?.sendToTarget()}.start()
- }
-
- override fun onJsAlert(
- view: WebView?,
- url: String?,
- message: String?,
- result: JsResult?
- ): Boolean {
- result?.confirm()
- return true
- }
-
- override fun onJsPrompt(
- view: WebView?,
- url: String?,
- message: String?,
- defaultValue: String?,
- result: JsPromptResult?
- ): Boolean {
- result?.confirm()
- return true
- }
-
- override fun onJsConfirm(
- view: WebView?,
- url: String?,
- message: String?,
- result: JsResult?
- ): Boolean {
- result?.confirm()
- return true
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/top/fumiama/copymanga/web/WebViewClient.kt b/app/src/main/java/top/fumiama/copymanga/web/WebViewClient.kt
deleted file mode 100644
index 6605af8..0000000
--- a/app/src/main/java/top/fumiama/copymanga/web/WebViewClient.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-package top.fumiama.copymanga.web
-
-import android.content.Context
-import android.graphics.Bitmap
-import android.util.Log
-import android.webkit.WebView
-import android.webkit.WebViewClient
-import android.widget.Toast
-import top.fumiama.copymanga.R
-
-class WebViewClient(private val context: Context, jsFileName: String):WebViewClient() {
- private val js = context.assets.open(jsFileName).readBytes().decodeToString()
- override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
- super.onPageStarted(view, url, favicon)
- Log.d("MyWC", "Load URL: $url")
- url?.let {
- if(!it.startsWith(context.getString(R.string.web_home)) && !it.startsWith(context.getString(R.string.web_home_www))){
- view?.goBack()
- Toast.makeText(context, R.string.blocked_ad, Toast.LENGTH_SHORT).show()
- }
- }
- }
-
- override fun onPageFinished(view: WebView?, url: String?) {
- super.onPageFinished(view, url)
- url?.let {
- view?.loadUrl(js)
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/res/anim/slide_in_right.xml b/app/src/main/res/anim/slide_in_right.xml
new file mode 100644
index 0000000..4466b8e
--- /dev/null
+++ b/app/src/main/res/anim/slide_in_right.xml
@@ -0,0 +1,8 @@
+
+
+
+
diff --git a/app/src/main/res/anim/slide_in_right_exit.xml b/app/src/main/res/anim/slide_in_right_exit.xml
new file mode 100644
index 0000000..61153db
--- /dev/null
+++ b/app/src/main/res/anim/slide_in_right_exit.xml
@@ -0,0 +1,8 @@
+
+
+
+
diff --git a/app/src/main/res/anim/slide_out_left.xml b/app/src/main/res/anim/slide_out_left.xml
new file mode 100644
index 0000000..f3d4368
--- /dev/null
+++ b/app/src/main/res/anim/slide_out_left.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/anim/slide_out_left_exit.xml b/app/src/main/res/anim/slide_out_left_exit.xml
new file mode 100644
index 0000000..2970ce4
--- /dev/null
+++ b/app/src/main/res/anim/slide_out_left_exit.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable-anydpi/bg_rnd_green.xml b/app/src/main/res/drawable-anydpi/bg_rnd_green.xml
new file mode 100644
index 0000000..9fd42dc
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/bg_rnd_green.xml
@@ -0,0 +1,33 @@
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable-anydpi/buttonshapewhitebg.xml b/app/src/main/res/drawable-anydpi/buttonshapewhitebg.xml
new file mode 100644
index 0000000..75276c1
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/buttonshapewhitebg.xml
@@ -0,0 +1,11 @@
+
+
+ -
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable-anydpi/ic_anchor_down.xml b/app/src/main/res/drawable-anydpi/ic_anchor_down.xml
new file mode 100644
index 0000000..f23db4f
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_anchor_down.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable-anydpi/ic_edit.xml b/app/src/main/res/drawable-anydpi/ic_author.xml
similarity index 92%
rename from app/src/main/res/drawable-anydpi/ic_edit.xml
rename to app/src/main/res/drawable-anydpi/ic_author.xml
index 2cc2fb6..466034d 100644
--- a/app/src/main/res/drawable-anydpi/ic_edit.xml
+++ b/app/src/main/res/drawable-anydpi/ic_author.xml
@@ -5,6 +5,6 @@
android:viewportWidth="1024"
android:viewportHeight="1024">
\ No newline at end of file
diff --git a/app/src/main/res/drawable-anydpi/ic_dere.xml b/app/src/main/res/drawable-anydpi/ic_dere.xml
new file mode 100644
index 0000000..b73d2f6
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_dere.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable-anydpi/ic_email_white_24dp.xml b/app/src/main/res/drawable-anydpi/ic_email_white_24dp.xml
new file mode 100644
index 0000000..e13e10f
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_email_white_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable-anydpi/ic_launcher_background.xml b/app/src/main/res/drawable-anydpi/ic_launcher_background.xml
index 9486190..31cf32b 100644
--- a/app/src/main/res/drawable-anydpi/ic_launcher_background.xml
+++ b/app/src/main/res/drawable-anydpi/ic_launcher_background.xml
@@ -5,7 +5,7 @@
android:viewportWidth="108"
android:viewportHeight="108">
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable-anydpi/ic_list.xml b/app/src/main/res/drawable-anydpi/ic_list.xml
new file mode 100644
index 0000000..8ff5e5e
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_list.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable-anydpi/ic_locate.xml b/app/src/main/res/drawable-anydpi/ic_locate.xml
new file mode 100644
index 0000000..0ff4239
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_locate.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable-anydpi/ic_lock_white_24dp.xml b/app/src/main/res/drawable-anydpi/ic_lock_white_24dp.xml
new file mode 100644
index 0000000..3f1ce3d
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_lock_white_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable-anydpi/ic_dl.xml b/app/src/main/res/drawable-anydpi/ic_menu_download.xml
similarity index 82%
rename from app/src/main/res/drawable-anydpi/ic_dl.xml
rename to app/src/main/res/drawable-anydpi/ic_menu_download.xml
index 3663c9c..d4e677e 100644
--- a/app/src/main/res/drawable-anydpi/ic_dl.xml
+++ b/app/src/main/res/drawable-anydpi/ic_menu_download.xml
@@ -1,10 +1,9 @@
-
-
\ No newline at end of file
+ android:fillColor="?attr/colorOnSurface"
+ android:pathData="M565 780l51-55a32 32 0 0 1 45-1 33 33 0 0 1 1 46l-97 104a37 37 0 0 1-53 1l-108-104a33 33 0 0 1-1-46 32 32 0 0 1 45-1L501 774V512c0-18 14-32 32-32s32 15 32 32v268zM512 139c123 0 228 87 259 207C864 347 939 426 939 523c0 98-76 177-170 177-18 0-32-14-32-32 0-18 14-32 32-32 58 0 106-50 106-112 0-62-48-112-106-112-6 0-12 1-17 1-18 3-34-9-37-27C698 281 613 203 512 203c-74 0-141 42-177 108a32 32 0 0 1-30 17 140 140 0 0 0-10-0c-80 0-146 69-146 154 0 85 65 154 146 154 18 0 32 14 32 32 0 18-14 32-32 32C179 700 85 602 85 481c0-118 90-215 203-218C338 186 421 139 512 139z" />
+
diff --git a/app/src/main/res/drawable-anydpi/ic_menu_history.xml b/app/src/main/res/drawable-anydpi/ic_menu_history.xml
new file mode 100644
index 0000000..1456506
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_menu_history.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable-anydpi/ic_menu_home.xml b/app/src/main/res/drawable-anydpi/ic_menu_home.xml
new file mode 100644
index 0000000..8c7f4b8
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_menu_home.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable-anydpi/ic_menu_rank.xml b/app/src/main/res/drawable-anydpi/ic_menu_rank.xml
new file mode 100644
index 0000000..db70de8
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_menu_rank.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable-anydpi/ic_menu_sort.xml b/app/src/main/res/drawable-anydpi/ic_menu_sort.xml
new file mode 100644
index 0000000..c88392f
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_menu_sort.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable-anydpi/ic_menu_sub.xml b/app/src/main/res/drawable-anydpi/ic_menu_sub.xml
new file mode 100644
index 0000000..d82f62f
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_menu_sub.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable-anydpi/ic_refresh.xml b/app/src/main/res/drawable-anydpi/ic_refresh.xml
new file mode 100644
index 0000000..7ac81f8
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_refresh.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable-anydpi/ic_settings.xml b/app/src/main/res/drawable-anydpi/ic_settings.xml
new file mode 100644
index 0000000..4bc9b40
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_settings.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable-anydpi/ic_time.xml b/app/src/main/res/drawable-anydpi/ic_time.xml
new file mode 100644
index 0000000..3936ba9
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_time.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable-anydpi/mask_blackbottom.xml b/app/src/main/res/drawable-anydpi/mask_blackbottom.xml
new file mode 100644
index 0000000..50becf6
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/mask_blackbottom.xml
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable-anydpi/mask_blacktop.xml b/app/src/main/res/drawable-anydpi/mask_blacktop.xml
new file mode 100644
index 0000000..4d8ce78
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/mask_blacktop.xml
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable-anydpi/rndbg_error.xml b/app/src/main/res/drawable-anydpi/rndbg_error.xml
index e3e24c0..e0225a4 100644
--- a/app/src/main/res/drawable-anydpi/rndbg_error.xml
+++ b/app/src/main/res/drawable-anydpi/rndbg_error.xml
@@ -16,7 +16,7 @@
-
-
+
diff --git a/app/src/main/res/drawable-anydpi/rndbg_round.xml b/app/src/main/res/drawable-anydpi/rndbg_round.xml
deleted file mode 100644
index db76800..0000000
--- a/app/src/main/res/drawable-anydpi/rndbg_round.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/drawable-anydpi/rndbg_white.xml b/app/src/main/res/drawable-anydpi/rndbg_white.xml
index 4c7dcbe..6931909 100644
--- a/app/src/main/res/drawable-anydpi/rndbg_white.xml
+++ b/app/src/main/res/drawable-anydpi/rndbg_white.xml
@@ -16,7 +16,7 @@
-
-
+
diff --git a/app/src/main/res/drawable-anydpi/toggle_button.xml b/app/src/main/res/drawable-anydpi/toggle_button.xml
index 193cd6f..d0726a2 100644
--- a/app/src/main/res/drawable-anydpi/toggle_button.xml
+++ b/app/src/main/res/drawable-anydpi/toggle_button.xml
@@ -1,12 +1,12 @@
-
+
-
+
-
+
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable-nodpi/illust_57793944_20190427_134853.webp b/app/src/main/res/drawable-nodpi/illust_57793944_20190427_134853.webp
new file mode 100644
index 0000000..aec4e45
Binary files /dev/null and b/app/src/main/res/drawable-nodpi/illust_57793944_20190427_134853.webp differ
diff --git a/app/src/main/res/drawable-nodpi/img_hot.webp b/app/src/main/res/drawable-nodpi/img_hot.webp
new file mode 100644
index 0000000..99f58c2
Binary files /dev/null and b/app/src/main/res/drawable-nodpi/img_hot.webp differ
diff --git a/app/src/main/res/drawable-nodpi/img_hot_serial.png b/app/src/main/res/drawable-nodpi/img_hot_serial.png
new file mode 100644
index 0000000..14382a3
Binary files /dev/null and b/app/src/main/res/drawable-nodpi/img_hot_serial.png differ
diff --git a/app/src/main/res/drawable-nodpi/img_latest_pub.png b/app/src/main/res/drawable-nodpi/img_latest_pub.png
new file mode 100644
index 0000000..02b30f2
Binary files /dev/null and b/app/src/main/res/drawable-nodpi/img_latest_pub.png differ
diff --git a/app/src/main/res/drawable-nodpi/img_master_work.webp b/app/src/main/res/drawable-nodpi/img_master_work.webp
new file mode 100644
index 0000000..c66e953
Binary files /dev/null and b/app/src/main/res/drawable-nodpi/img_master_work.webp differ
diff --git a/app/src/main/res/drawable-nodpi/img_novel_bill.png b/app/src/main/res/drawable-nodpi/img_novel_bill.png
new file mode 100644
index 0000000..9264161
Binary files /dev/null and b/app/src/main/res/drawable-nodpi/img_novel_bill.png differ
diff --git a/app/src/main/res/drawable-nodpi/img_novel_eye.webp b/app/src/main/res/drawable-nodpi/img_novel_eye.webp
new file mode 100644
index 0000000..6a80f61
Binary files /dev/null and b/app/src/main/res/drawable-nodpi/img_novel_eye.webp differ
diff --git a/app/src/main/res/font/calibri.ttf b/app/src/main/res/font/calibri.ttf
new file mode 100644
index 0000000..2fede68
Binary files /dev/null and b/app/src/main/res/font/calibri.ttf differ
diff --git a/app/src/main/res/font/gotham.ttf b/app/src/main/res/font/gotham.ttf
new file mode 100644
index 0000000..58018ad
Binary files /dev/null and b/app/src/main/res/font/gotham.ttf differ
diff --git a/app/src/main/res/layout/activity_dl.xml b/app/src/main/res/layout/activity_dl.xml
deleted file mode 100644
index 77af730..0000000
--- a/app/src/main/res/layout/activity_dl.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml
new file mode 100644
index 0000000..06dd6f3
--- /dev/null
+++ b/app/src/main/res/layout/activity_login.xml
@@ -0,0 +1,156 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index d8ee88f..97d9d41 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,39 +1,25 @@
-
+ android:layout_height="match_parent"
+ android:fitsSystemWindows="false"
+ tools:openDrawer="start">
-
-
-
-
-
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_viewmanga.xml b/app/src/main/res/layout/activity_viewmanga.xml
index f095c0e..8ad3038 100644
--- a/app/src/main/res/layout/activity_viewmanga.xml
+++ b/app/src/main/res/layout/activity_viewmanga.xml
@@ -1,7 +1,6 @@
@@ -11,31 +10,34 @@
layout="@layout/page_imgview"
android:layout_width="0dp"
android:layout_height="0dp"
- android:visibility="invisible"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
+
+
+ app:layout_constraintTop_toTopOf="parent" >
-
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/anchor_popular.xml b/app/src/main/res/layout/anchor_popular.xml
new file mode 100644
index 0000000..6b090cc
--- /dev/null
+++ b/app/src/main/res/layout/anchor_popular.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/app_bar_main.xml b/app/src/main/res/layout/app_bar_main.xml
new file mode 100644
index 0000000..a84e742
--- /dev/null
+++ b/app/src/main/res/layout/app_bar_main.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/button_tbutton.xml b/app/src/main/res/layout/button_tbutton.xml
index ebaae01..f7639ad 100644
--- a/app/src/main/res/layout/button_tbutton.xml
+++ b/app/src/main/res/layout/button_tbutton.xml
@@ -1,5 +1,5 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml
new file mode 100644
index 0000000..04b67fd
--- /dev/null
+++ b/app/src/main/res/layout/content_main.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_unzipping.xml b/app/src/main/res/layout/dialog_unzipping.xml
new file mode 100644
index 0000000..61ae892
--- /dev/null
+++ b/app/src/main/res/layout/dialog_unzipping.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_book.xml b/app/src/main/res/layout/fragment_book.xml
new file mode 100644
index 0000000..a664a2b
--- /dev/null
+++ b/app/src/main/res/layout/fragment_book.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_chapters.xml b/app/src/main/res/layout/fragment_chapters.xml
new file mode 100644
index 0000000..e66d7ac
--- /dev/null
+++ b/app/src/main/res/layout/fragment_chapters.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_dlcomic.xml b/app/src/main/res/layout/fragment_dlcomic.xml
new file mode 100644
index 0000000..92baca2
--- /dev/null
+++ b/app/src/main/res/layout/fragment_dlcomic.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_download.xml b/app/src/main/res/layout/fragment_download.xml
new file mode 100644
index 0000000..451afad
--- /dev/null
+++ b/app/src/main/res/layout/fragment_download.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_history.xml b/app/src/main/res/layout/fragment_history.xml
new file mode 100644
index 0000000..f375cd7
--- /dev/null
+++ b/app/src/main/res/layout/fragment_history.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml
new file mode 100644
index 0000000..54341a2
--- /dev/null
+++ b/app/src/main/res/layout/fragment_home.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_dlist.xml b/app/src/main/res/layout/fragment_rank.xml
similarity index 73%
rename from app/src/main/res/layout/activity_dlist.xml
rename to app/src/main/res/layout/fragment_rank.xml
index 95b2348..dc2c723 100644
--- a/app/src/main/res/layout/activity_dlist.xml
+++ b/app/src/main/res/layout/fragment_rank.xml
@@ -1,26 +1,27 @@
+ tools:context="top.fumiama.copymanga.ui.rank.RankFragment">
-
+ app:layout_constraintTop_toBottomOf="@+id/frlai" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_reader.xml b/app/src/main/res/layout/fragment_reader.xml
new file mode 100644
index 0000000..3de05ba
--- /dev/null
+++ b/app/src/main/res/layout/fragment_reader.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml
new file mode 100644
index 0000000..61a4490
--- /dev/null
+++ b/app/src/main/res/layout/fragment_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_sort.xml b/app/src/main/res/layout/fragment_sort.xml
new file mode 100644
index 0000000..f75504c
--- /dev/null
+++ b/app/src/main/res/layout/fragment_sort.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_sub.xml b/app/src/main/res/layout/fragment_sub.xml
new file mode 100644
index 0000000..09c304b
--- /dev/null
+++ b/app/src/main/res/layout/fragment_sub.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/line_1bookline.xml b/app/src/main/res/layout/line_1bookline.xml
new file mode 100644
index 0000000..a4e151a
--- /dev/null
+++ b/app/src/main/res/layout/line_1bookline.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/line_2bookline.xml b/app/src/main/res/layout/line_2bookline.xml
new file mode 100644
index 0000000..a110c0b
--- /dev/null
+++ b/app/src/main/res/layout/line_2bookline.xml
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/line_2chapters.xml b/app/src/main/res/layout/line_2chapters.xml
new file mode 100644
index 0000000..cf481c2
--- /dev/null
+++ b/app/src/main/res/layout/line_2chapters.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/line_3bookline.xml b/app/src/main/res/layout/line_3bookline.xml
new file mode 100644
index 0000000..a663466
--- /dev/null
+++ b/app/src/main/res/layout/line_3bookline.xml
@@ -0,0 +1,148 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/line_bookinfo.xml b/app/src/main/res/layout/line_bookinfo.xml
new file mode 100644
index 0000000..893505e
--- /dev/null
+++ b/app/src/main/res/layout/line_bookinfo.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/line_bookinfo_text.xml b/app/src/main/res/layout/line_bookinfo_text.xml
new file mode 100644
index 0000000..b6d0869
--- /dev/null
+++ b/app/src/main/res/layout/line_bookinfo_text.xml
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/line_booktandb.xml b/app/src/main/res/layout/line_booktandb.xml
new file mode 100644
index 0000000..4ee7399
--- /dev/null
+++ b/app/src/main/res/layout/line_booktandb.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/line_caption.xml b/app/src/main/res/layout/line_caption.xml
index 94a6aa7..85949f5 100644
--- a/app/src/main/res/layout/line_caption.xml
+++ b/app/src/main/res/layout/line_caption.xml
@@ -1,5 +1,6 @@
-
diff --git a/app/src/main/res/layout/line_chapter.xml b/app/src/main/res/layout/line_chapter.xml
new file mode 100644
index 0000000..b020a48
--- /dev/null
+++ b/app/src/main/res/layout/line_chapter.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/line_header.xml b/app/src/main/res/layout/line_header.xml
new file mode 100644
index 0000000..a150079
--- /dev/null
+++ b/app/src/main/res/layout/line_header.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/line_horizonal.xml b/app/src/main/res/layout/line_horizonal_empty.xml
similarity index 100%
rename from app/src/main/res/layout/line_horizonal.xml
rename to app/src/main/res/layout/line_horizonal_empty.xml
diff --git a/app/src/main/res/layout/line_lazybooklines.xml b/app/src/main/res/layout/line_lazybooklines.xml
new file mode 100644
index 0000000..d360a96
--- /dev/null
+++ b/app/src/main/res/layout/line_lazybooklines.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/line_rank.xml b/app/src/main/res/layout/line_rank.xml
new file mode 100644
index 0000000..d292514
--- /dev/null
+++ b/app/src/main/res/layout/line_rank.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/line_sort.xml b/app/src/main/res/layout/line_sort.xml
new file mode 100644
index 0000000..8680dff
--- /dev/null
+++ b/app/src/main/res/layout/line_sort.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/line_text_info.xml b/app/src/main/res/layout/line_text_info.xml
new file mode 100644
index 0000000..93f3390
--- /dev/null
+++ b/app/src/main/res/layout/line_text_info.xml
@@ -0,0 +1,6 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/nav_header_main.xml b/app/src/main/res/layout/nav_header_main.xml
new file mode 100644
index 0000000..e0cbe60
--- /dev/null
+++ b/app/src/main/res/layout/nav_header_main.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/page_imgview.xml b/app/src/main/res/layout/page_imgview.xml
index eb4762a..0b83e00 100644
--- a/app/src/main/res/layout/page_imgview.xml
+++ b/app/src/main/res/layout/page_imgview.xml
@@ -4,7 +4,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
-
diff --git a/app/src/main/res/layout/page_scrollimgview.xml b/app/src/main/res/layout/page_scrollimgview.xml
new file mode 100644
index 0000000..8d4c781
--- /dev/null
+++ b/app/src/main/res/layout/page_scrollimgview.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/viewpage_banner.xml b/app/src/main/res/layout/viewpage_banner.xml
new file mode 100644
index 0000000..5301808
--- /dev/null
+++ b/app/src/main/res/layout/viewpage_banner.xml
@@ -0,0 +1,5 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/viewpage_horizonal.xml b/app/src/main/res/layout/viewpage_horizonal.xml
new file mode 100644
index 0000000..a773855
--- /dev/null
+++ b/app/src/main/res/layout/viewpage_horizonal.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/widget_downloadbar.xml b/app/src/main/res/layout/widget_downloadbar.xml
index 947eb22..4c26e08 100644
--- a/app/src/main/res/layout/widget_downloadbar.xml
+++ b/app/src/main/res/layout/widget_downloadbar.xml
@@ -46,6 +46,7 @@
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="0/0"
+ android:textColor="@android:color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@@ -57,6 +58,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="单击此处下载/暂停 长按此处全选/清空 长按某话删除"
+ android:textColor="@android:color/black"
app:layout_constraintBottom_toTopOf="@+id/pdwn"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
diff --git a/app/src/main/res/layout/widget_finalmark.xml b/app/src/main/res/layout/widget_finalmark.xml
new file mode 100644
index 0000000..c2ee9be
--- /dev/null
+++ b/app/src/main/res/layout/widget_finalmark.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/widget_infodrawer.xml b/app/src/main/res/layout/widget_infodrawer.xml
index 68b1c55..1cb0dcd 100644
--- a/app/src/main/res/layout/widget_infodrawer.xml
+++ b/app/src/main/res/layout/widget_infodrawer.xml
@@ -31,7 +31,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="加载中..."
- android:textColor="#000000"
+ android:textColor="?attr/colorOnSurface"
app:layout_constraintBottom_toTopOf="@+id/idtbvh"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
diff --git a/app/src/main/res/layout/widget_titlebar.xml b/app/src/main/res/layout/widget_titlebar.xml
index d29959c..4b5a280 100644
--- a/app/src/main/res/layout/widget_titlebar.xml
+++ b/app/src/main/res/layout/widget_titlebar.xml
@@ -1,7 +1,6 @@
@@ -9,7 +8,7 @@
android:layout_width="match_parent"
android:layout_height="48dp"
android:foreground="?android:attr/selectableItemBackground"
- app:cardBackgroundColor="#FFFFFF"
+ app:cardBackgroundColor="?attr/colorSurface"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@@ -38,7 +37,7 @@
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_marginEnd="8dp"
- android:src="@drawable/ic_edit"
+ android:src="@drawable/ic_line_more"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
diff --git a/app/src/main/res/menu/activity_main_drawer.xml b/app/src/main/res/menu/activity_main_drawer.xml
new file mode 100644
index 0000000..aefd57a
--- /dev/null
+++ b/app/src/main/res/menu/activity_main_drawer.xml
@@ -0,0 +1,50 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/main.xml b/app/src/main/res/menu/main.xml
new file mode 100644
index 0000000..a807181
--- /dev/null
+++ b/app/src/main/res/menu/main.xml
@@ -0,0 +1,18 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml
new file mode 100644
index 0000000..599d2a6
--- /dev/null
+++ b/app/src/main/res/navigation/mobile_navigation.xml
@@ -0,0 +1,152 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index e5c1ad6..86d88d0 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -1,12 +1,14 @@
- #FFCC7F
- #8F8F8F
- #F6837A
- #FFCFCB
- #C9E6A4
+ #2ca9e1
+ #007bbb
+ #00a3af
+ #c1e4e9
#f2faff
#00beff
#81caf8
#c7eaff
+ #BFEA88
+ #ffffff
+ #F6837A
\ No newline at end of file
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..7ba630a
--- /dev/null
+++ b/app/src/main/res/values/dimens.xml
@@ -0,0 +1,14 @@
+
+
+ 16dp
+ 16dp
+ 8dp
+ 176dp
+ 32dp
+ 24dp
+ 16dp
+
+ 0.8
+ 16dp
+ 4dp
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index b769034..edca884 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,10 +1,66 @@
拷贝漫画
- https://copymanga.net
- https://www.copymanga.net
- https://www.copymanga.net/comic
+ 设定
+ 关于
+ 下载
+
+ 主页
+ 分类
+ 排行
+ ©2021源文雨@CoolApk\n本应用为拷贝漫画的第三方客户端,数据均来源于网络,作者不对其中所呈现的任何内容负责。
+ 浏览历史
+ 我的订阅
+ 我的下载
+ 最近更新
+ 图书详情
+ 章节内容
+ 漫画下载
+
+ illust: Hiten(490219)
+ 请设定提示文字内容
+ 清除设定的图片?
+
+ 权限被拒绝
+ 未登录
+ "加载主页控件出错"
+ N/A
+ 获取图书信息失败
+ 网络错误
+
+ https://api.copymanga.com/api/v3/h5/homeIndex
+ "https://api.copymanga.com"
+ https://nnv3api.dmzj1.com/novel/recentUpdate/%1$d.json
+ https://nnv3api.dmzj1.com/novel/rank/%1$d/%2$d/%3$d.json
+ https://api.copymanga.com/api/v3/h5/filterIndex/comic/tags
+ https://api.copymanga.com/api/v3/comics?limit=21&offset=%1$d&ordering=%2$s&theme=%3$s
+ https://api.copymanga.com/api/v3/comic2/%1$s
+ https://api.copymanga.com/api/v3/comic/%1$s/group/%2$s/chapters
+ https://api.copymanga.com/api/v3/comic/%1$s/chapter2/%2$s
+ https://nnv3api.dmzj1.com/novel/download/%1$d_%2$d_%3$d.txt
+
+ 已完结
+
+ WIFI
+ 移动网络
+ 蓝牙
+ 以太网
+ LOWPAN
+ 无网络
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36 Edg/86.0.622.38
- 已屏蔽其他网站页面
+ 更新时间
+ 热度
+
+ 加入书架
+ 开始阅读
+
+ 热度 %1$d
+ 状态 %1$s
+
+ 专题系列
+ 漫画推荐
+ 排行榜 ☟日周月 ☛冠亚季
+ 热门更新
+ 全新上架
\ No newline at end of file
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 5192fef..68fa182 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -1,10 +1,24 @@
-
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/provider_paths.xml b/app/src/main/res/xml/provider_paths.xml
new file mode 100644
index 0000000..c3e47b3
--- /dev/null
+++ b/app/src/main/res/xml/provider_paths.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/test/java/top/fumiama/copymanga/ExampleUnitTest.kt b/app/src/test/java/top/fumiama/dmzj/dmzjxs/ExampleUnitTest.kt
similarity index 90%
rename from app/src/test/java/top/fumiama/copymanga/ExampleUnitTest.kt
rename to app/src/test/java/top/fumiama/dmzj/dmzjxs/ExampleUnitTest.kt
index 36c022e..0cb541b 100644
--- a/app/src/test/java/top/fumiama/copymanga/ExampleUnitTest.kt
+++ b/app/src/test/java/top/fumiama/dmzj/dmzjxs/ExampleUnitTest.kt
@@ -1,4 +1,4 @@
-package top.fumiama.copymanga
+package top.fumiama.dmzj.dmzjxs
import org.junit.Test
diff --git a/build.gradle b/build.gradle
index c9fcacf..b7e45fb 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,12 +1,14 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
- ext.kotlin_version = '1.4.21'
+ ext.kotlin_version = '1.4.31'
repositories {
google()
jcenter()
+ mavenCentral()
+ maven { url 'https://maven.google.com' }
}
dependencies {
- classpath 'com.android.tools.build:gradle:4.1.1'
+ classpath 'com.android.tools.build:gradle:4.1.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.20'
@@ -19,6 +21,7 @@ allprojects {
repositories {
google()
jcenter()
+ maven { url "https://jitpack.io" }
}
}
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index c0bf759..14fc473 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Wed Oct 14 16:47:38 CST 2020
+#Fri Sep 04 18:15:43 CST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-all.zip