v1.0
4
.idea/codeStyles/Project.xml
generated
@@ -17,6 +17,7 @@
|
||||
<package name="" alias="true" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</JetCodeStyleSettings>
|
||||
<codeStyleSettings language="XML">
|
||||
<indentOptions>
|
||||
@@ -130,5 +131,8 @@
|
||||
</rules>
|
||||
</arrangement>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="kotlin">
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
||||
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
||||
7
.idea/gradle.xml
generated
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
@@ -7,6 +8,12 @@
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="1.8" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
|
||||
25
.idea/jarRepositories.xml
generated
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RemoteRepositoriesConfiguration">
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Maven Central repository" />
|
||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="jboss.community" />
|
||||
<option name="name" value="JBoss Community repository" />
|
||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="BintrayJCenter" />
|
||||
<option name="name" value="BintrayJCenter" />
|
||||
<option name="url" value="https://jcenter.bintray.com/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="Google" />
|
||||
<option name="name" value="Google" />
|
||||
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
||||
2
.idea/vcs.xml
generated
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/dmzj" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,6 +1,7 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'AndResGuard'
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
@@ -12,13 +13,32 @@ android {
|
||||
targetSdkVersion 30
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
resConfigs "zh", "zh-rCN"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
release {
|
||||
storeFile file('../../../OneDrive/swc/developer/android_key/open_key')
|
||||
storePassword 'fumiama'
|
||||
keyAlias 'default'
|
||||
keyPassword 'fumiama'
|
||||
v1SigningEnabled true
|
||||
v2SigningEnabled true
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
minifyEnabled true
|
||||
shrinkResources true
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
debug{
|
||||
minifyEnabled true
|
||||
shrinkResources true
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
@@ -27,10 +47,64 @@ android {
|
||||
dependencies {
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation 'androidx.core:core-ktx:1.1.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
implementation 'androidx.core:core-ktx:1.3.2'
|
||||
//implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
|
||||
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'
|
||||
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.google.code.gson:gson:2.8.6'
|
||||
}
|
||||
|
||||
andResGuard {
|
||||
// mappingFile = file("./resource_mapping.txt")
|
||||
mappingFile = null
|
||||
use7zip = true
|
||||
useSign = true
|
||||
// 打开这个开关,会keep住所有资源的原始路径,只混淆资源的名字
|
||||
keepRoot = false
|
||||
// 设置这个值,会把arsc name列混淆成相同的名字,减少string常量池的大小
|
||||
fixedResName = "arg"
|
||||
// 打开这个开关会合并所有哈希值相同的资源,但请不要过度依赖这个功能去除去冗余资源
|
||||
mergeDuplicatedRes = true
|
||||
whiteList = [
|
||||
// for your icon
|
||||
"R.drawable.icon",
|
||||
// for fabric
|
||||
"R.string.com.crashlytics.*",
|
||||
// for google-services
|
||||
"R.string.google_app_id",
|
||||
"R.string.gcm_defaultSenderId",
|
||||
"R.string.default_web_client_id",
|
||||
"R.string.ga_trackingId",
|
||||
"R.string.firebase_database_url",
|
||||
"R.string.google_api_key",
|
||||
"R.string.google_crash_reporting_api_key"
|
||||
]
|
||||
compressFilePattern = [
|
||||
"*.png",
|
||||
"*.jpg",
|
||||
"*.jpeg",
|
||||
"*.gif",
|
||||
]
|
||||
sevenzip {
|
||||
artifact = 'com.tencent.mm:SevenZip:1.2.19'
|
||||
//path = "/usr/local/bin/7za"
|
||||
}
|
||||
|
||||
/**
|
||||
* 可选: 如果不设置则会默认覆盖assemble输出的apk
|
||||
**/
|
||||
// finalApkBackupPath = "${project.rootDir}/final.apk"
|
||||
|
||||
/**
|
||||
* 可选: 指定v1签名时生成jar文件的摘要算法
|
||||
* 默认值为“SHA-1”
|
||||
**/
|
||||
// digestalg = "SHA-256"
|
||||
}
|
||||
42
app/proguard-rules.pro
vendored
@@ -18,4 +18,44 @@
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
#-renamesourcefileattribute SourceFile
|
||||
-keep public class * implements com.bumptech.glide.module.GlideModule
|
||||
-keep class * extends com.bumptech.glide.module.AppGlideModule {
|
||||
<init>(...);
|
||||
}
|
||||
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
|
||||
**[] $VALUES;
|
||||
public *;
|
||||
}
|
||||
-keep class com.bumptech.glide.load.data.ParcelFileDescriptorRewinder$InternalRewinder {
|
||||
*** rewind();
|
||||
}
|
||||
|
||||
##---------------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.
|
||||
-keepattributes Signature
|
||||
|
||||
# For using GSON @Expose annotation
|
||||
-keepattributes *Annotation*
|
||||
|
||||
# Gson specific classes
|
||||
-dontwarn sun.misc.**
|
||||
#-keep class com.google.gson.stream.** { *; }
|
||||
|
||||
# Application classes that will be serialized/deserialized over Gson
|
||||
-keep public class top.fumiama.copymanga.data.* { *; }
|
||||
|
||||
# Prevent proguard from stripping interface information from TypeAdapter, TypeAdapterFactory,
|
||||
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
|
||||
-keep class * extends com.google.gson.TypeAdapter
|
||||
-keep class * implements com.google.gson.TypeAdapterFactory
|
||||
-keep class * implements com.google.gson.JsonSerializer
|
||||
-keep class * implements com.google.gson.JsonDeserializer
|
||||
|
||||
# Prevent R8 from leaving Data object members always null
|
||||
-keepclassmembers,allowobfuscation class * {
|
||||
@com.google.gson.annotations.SerializedName <fields>;
|
||||
}
|
||||
|
||||
##---------------End: proguard configuration for Gson ----------
|
||||
@@ -1,12 +1,22 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="top.fumiama.copymanga">
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:roundIcon="@mipmap/ic_launcher"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme" />
|
||||
|
||||
android:theme="@style/AppTheme" >
|
||||
<activity android:name=".activity.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".activity.ViewMangaActivity"/>
|
||||
<activity android:name=".activity.DlActivity"/>
|
||||
</application>
|
||||
</manifest>
|
||||
45
app/src/main/assets/h.js
Normal file
@@ -0,0 +1,45 @@
|
||||
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();
|
||||
46
app/src/main/assets/i.js
Normal file
@@ -0,0 +1,46 @@
|
||||
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);
|
||||
}
|
||||
modify();
|
||||
invoke.urlChangeListener(modify);
|
||||
} else {
|
||||
setTimeout(modify, 1280);
|
||||
}
|
||||
292
app/src/main/java/top/fumiama/copymanga/activity/DlActivity.kt
Normal file
@@ -0,0 +1,292 @@
|
||||
package top.fumiama.copymanga.activity
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewTreeObserver
|
||||
import android.widget.Toast
|
||||
import android.widget.ToggleButton
|
||||
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.handler.DlHandler
|
||||
import top.fumiama.copymanga.tool.MangaDlTools
|
||||
import top.fumiama.copymanga.tool.MangaDlTools.Companion.comicStructure
|
||||
import top.fumiama.copymanga.tool.MangaDlTools.Companion.wmdlt
|
||||
import top.fumiama.copymanga.tool.ToolsBox
|
||||
import top.fumiama.copymanga.view.LazyScrollView
|
||||
import java.io.File
|
||||
import java.lang.Thread.sleep
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
|
||||
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: List<ToggleButton> = arrayListOf()
|
||||
var tbtnUrlList = arrayListOf<String>()
|
||||
private val handler = DlHandler(this)
|
||||
private var btnw = 0
|
||||
private var cdwnHeight = 0
|
||||
private var canDl = false
|
||||
private lateinit var toolsBox: ToolsBox
|
||||
val mangaDlTools = MangaDlTools()
|
||||
|
||||
|
||||
@ExperimentalStdlibApi
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_dl)
|
||||
mh?.saveUrlsOnly = true
|
||||
handler.sendEmptyMessage(-2)
|
||||
}
|
||||
|
||||
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, "translationY", cdwnHeight.toFloat(), 0f).setDuration(233)
|
||||
.start()
|
||||
}
|
||||
|
||||
private fun hideDlCard() {
|
||||
//ObjectAnimator.ofFloat(csdwn, "alpha", 0.9f, 0.3f).setDuration(233).start()
|
||||
ObjectAnimator.ofFloat(csdwn, "translationY", 0f, cdwnHeight.toFloat()).setDuration(233)
|
||||
.start()
|
||||
}
|
||||
|
||||
private fun fillChapters() {
|
||||
mangaDlTools.allocateChapterUrls(checkedChapter)
|
||||
for (i in tbtnlist.indices) {
|
||||
if (tbtnlist[i].isChecked) mangaDlTools.dlChapterUrl(tbtnUrlList[i])
|
||||
}
|
||||
}
|
||||
|
||||
private fun dlThead(dlMethod: (i: ToggleButton) -> Unit) {
|
||||
sleep(2333)
|
||||
for (i in tbtnlist.listIterator()) {
|
||||
if (i.isChecked) dlMethod(i)
|
||||
if (!canDl) break
|
||||
}
|
||||
if (canDl) {
|
||||
haveDlStarted = false
|
||||
canDl = false
|
||||
}
|
||||
handler.sendEmptyMessage(8)
|
||||
}
|
||||
|
||||
@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() {
|
||||
cdwnHeight = csdwn.height
|
||||
Log.d("MyDl", "Get csdwn height: $cdwnHeight")
|
||||
csdwn.viewTreeObserver.removeOnGlobalLayoutListener(this)
|
||||
}
|
||||
})
|
||||
dllazys.onScrollListener = object : LazyScrollView.OnScrollListener {
|
||||
override fun onBottom() {
|
||||
if (csdwn.translationY > 0f) showDlCard()
|
||||
}
|
||||
|
||||
override fun onScroll() {
|
||||
if (csdwn.translationY == 0f) hideDlCard()
|
||||
}
|
||||
|
||||
override fun onTop() {
|
||||
if (csdwn.translationY > 0f) showDlCard()
|
||||
}
|
||||
}
|
||||
cdwn.setOnClickListener {
|
||||
pdwn.progress = 0
|
||||
if (canDl || checkedChapter == 0) canDl = false
|
||||
else {
|
||||
haveDlStarted = true
|
||||
canDl = true
|
||||
handler.sendEmptyMessage(9)
|
||||
Toast.makeText(this, "准备下载...", Toast.LENGTH_SHORT).show()
|
||||
fillChapters()
|
||||
Thread { dlThead { downloadChapterPages(it) } }.start()
|
||||
}
|
||||
}
|
||||
cdwn.setOnLongClickListener {
|
||||
Thread { handler.sendEmptyMessage(4) }.start()
|
||||
return@setOnLongClickListener true
|
||||
}
|
||||
analyzeStructure()
|
||||
}
|
||||
|
||||
private fun analyzeStructure() {
|
||||
comicStructure?.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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ExperimentalStdlibApi
|
||||
private fun downloadChapterPages(i: ToggleButton) {
|
||||
mangaDlTools.onDownloadedListener =
|
||||
object : MangaDlTools.OnDownloadedListener {
|
||||
override fun handleMessage(succeed: Boolean) {
|
||||
handler.obtainMessage(if (succeed) 1 else -1, tbtnlist.indexOf(i), 0)
|
||||
.sendToTarget()
|
||||
}
|
||||
|
||||
override fun handleMessage(succeed: Boolean, pageNow: Int) {
|
||||
handler.obtainMessage(
|
||||
5,
|
||||
tbtnlist.indexOf(i),
|
||||
pageNow,
|
||||
succeed
|
||||
).sendToTarget()
|
||||
}
|
||||
}
|
||||
mangaDlTools.dlChapterAndPackIntoZip(
|
||||
File("${getExternalFilesDir("")}/$comicName/${i.hint}/${i.textOn}.zip"),
|
||||
tbtnUrlList[tbtnlist.indexOf(i)].substringAfterLast("/")
|
||||
)
|
||||
}
|
||||
|
||||
@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)
|
||||
tbtnlist += tbv.tbtn
|
||||
tbtncnt++
|
||||
tbtnUrlList.add(url)
|
||||
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
|
||||
}
|
||||
ltbtn.ltbtn.addView(tbv)
|
||||
ltbtn.invalidate()
|
||||
tbv.tbtn.setOnClickListener {
|
||||
if (zipf.exists() && !it.tbtn.isChecked) it.tbtn.setBackgroundResource(R.drawable.rndbg_checked)
|
||||
else it.tbtn.setBackgroundResource(R.drawable.toggle_button)
|
||||
if (it.tbtn.isChecked) tdwn.text = "$dldChapter/${++checkedChapter}"
|
||||
else tdwn.text = "$dldChapter/${--checkedChapter}"
|
||||
}
|
||||
tbv.tbtn.setOnLongClickListener {
|
||||
if (zipf.exists()) {
|
||||
toolsBox.buildInfo("确认删除这些章节?",
|
||||
"该操作将不可撤销",
|
||||
"确定",
|
||||
null,
|
||||
"取消",
|
||||
{
|
||||
Thread {
|
||||
handler.obtainMessage(
|
||||
7,
|
||||
tbtnlist.indexOf(it.tbtn),
|
||||
0,
|
||||
zipf
|
||||
).sendToTarget()
|
||||
}.start()
|
||||
})
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteChapters(zipf: File, index: Int) {
|
||||
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 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"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
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.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
|
||||
@SuppressLint("JavascriptInterface")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
|
||||
wm = WeakReference(this)
|
||||
mh = Looper.myLooper()?.let { MainHandler(it) }
|
||||
|
||||
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){
|
||||
startActivity(Intent(this, DlActivity::class.java))
|
||||
}
|
||||
|
||||
companion object{
|
||||
var wm: WeakReference<MainActivity>? = null
|
||||
var mh: MainHandler? = null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,372 @@
|
||||
package top.fumiama.copymanga.activity
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Message
|
||||
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.*
|
||||
|
||||
|
||||
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
|
||||
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
|
||||
try {
|
||||
count = imgUrls.size
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
toolsBox.toastError("分析图片url错误")
|
||||
}
|
||||
try {
|
||||
prepareItems(count)
|
||||
} 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
|
||||
}
|
||||
|
||||
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 loadOneImg() {
|
||||
Glide.with(this@ViewMangaActivity.applicationContext).load(
|
||||
imgUrls[currentItem]
|
||||
).thumbnail(
|
||||
Glide.with(this@ViewMangaActivity.applicationContext).load(R.drawable.bg_comment)
|
||||
).into(onei)
|
||||
updateSeekBar()
|
||||
}
|
||||
|
||||
private fun setIdPosition(position: Int) {
|
||||
infoDrawerDelta = position.toFloat()
|
||||
infcard.translationY = infoDrawerDelta
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
private fun prepareItems(size: Int) {
|
||||
prepareVP()
|
||||
prepareInfoBar(size)
|
||||
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.applicationContext, "下次浏览生效", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun prepareIdBtVP() {
|
||||
idtbvp.setOnClickListener {
|
||||
if (idtbvp.isChecked) p["noAnimation"] = "true"
|
||||
else p["noAnimation"] = "false"
|
||||
Toast.makeText(this.applicationContext, "下次浏览生效", 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.applicationContext, "下次浏览生效", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
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<ViewData>() {
|
||||
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
|
||||
Glide.with(this@ViewMangaActivity.applicationContext).load(
|
||||
imgUrls[pos]
|
||||
).thumbnail(
|
||||
Glide.with(this@ViewMangaActivity.applicationContext)
|
||||
.load(R.drawable.bg_comment)
|
||||
).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() {
|
||||
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<ViewMangaActivity>? = null
|
||||
var imgUrls = arrayOf<String>()
|
||||
var titleText = "Null"
|
||||
var nextChapterUrl: String? = null
|
||||
var previousChapterUrl: String? = null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package top.fumiama.copymanga.data;
|
||||
|
||||
public class ComicStructure {
|
||||
public String name;
|
||||
public Chapters[] chapters;
|
||||
public static class Chapters{
|
||||
public String name;
|
||||
public String url;
|
||||
}
|
||||
}
|
||||
90
app/src/main/java/top/fumiama/copymanga/handler/DlHandler.kt
Normal file
@@ -0,0 +1,90 @@
|
||||
package top.fumiama.copymanga.handler
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Handler
|
||||
import android.os.Message
|
||||
import android.widget.Toast
|
||||
import kotlinx.android.synthetic.main.widget_downloadbar.*
|
||||
import top.fumiama.copymanga.R
|
||||
import top.fumiama.copymanga.activity.DlActivity
|
||||
import top.fumiama.copymanga.activity.ViewMangaActivity.Companion.imgUrls
|
||||
import top.fumiama.copymanga.tool.MangaDlTools.Companion.wmdlt
|
||||
import java.io.File
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
class DlHandler(activity: DlActivity) : Handler() {
|
||||
private val da = WeakReference(activity)
|
||||
private val d = da.get()
|
||||
|
||||
@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[msg.arg1].textOn}失败",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
d.updateProgressBar()
|
||||
}
|
||||
4 -> {
|
||||
d?.pdwn?.progress = 0
|
||||
if (d?.haveSElectAll == true) {
|
||||
for (i in d.tbtnlist.listIterator()) {
|
||||
i.setBackgroundResource(R.drawable.toggle_button)
|
||||
i.isChecked = false
|
||||
}
|
||||
d.haveSElectAll = false
|
||||
d.checkedChapter = 0
|
||||
d.dldChapter = 0
|
||||
} else {
|
||||
d?.let {
|
||||
for (i in it.tbtnlist.listIterator()) {
|
||||
i.setBackgroundResource(R.drawable.toggle_button)
|
||||
i.isChecked = true
|
||||
it.checkedChapter++
|
||||
}
|
||||
}
|
||||
d?.haveSElectAll = true
|
||||
}
|
||||
d?.tdwn?.text = "${d?.dldChapter}/${d?.checkedChapter}"
|
||||
}
|
||||
5 -> {
|
||||
d?.updateProgressBar(
|
||||
msg.arg2,
|
||||
wmdlt?.get()
|
||||
?.getImgsCountByHash(d.tbtnUrlList[msg.arg1].substringAfterLast("/")) ?: 0
|
||||
)
|
||||
if (!(msg.obj as Boolean)) {
|
||||
Toast.makeText(
|
||||
d,
|
||||
"下载${d?.tbtnlist?.get(msg.arg1)?.textOn}的第${msg.arg2}页失败",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
6 -> d?.tdwn?.text = "${d?.dldChapter}/${d?.checkedChapter}"
|
||||
7 -> d?.deleteChapters(msg.obj as File, msg.arg1)
|
||||
8 -> d?.cdwn?.setCardBackgroundColor(d.resources.getColor(R.color.colorBlue))
|
||||
9 -> d?.cdwn?.setCardBackgroundColor(d.resources.getColor(R.color.colorRed))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
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.util.Log
|
||||
import android.view.View
|
||||
import com.google.gson.Gson
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import top.fumiama.copymanga.activity.DlActivity
|
||||
import top.fumiama.copymanga.activity.MainActivity.Companion.wm
|
||||
import top.fumiama.copymanga.activity.ViewMangaActivity
|
||||
import top.fumiama.copymanga.data.ComicStructure
|
||||
import top.fumiama.copymanga.tool.MangaDlTools
|
||||
import top.fumiama.copymanga.tool.MangaDlTools.Companion.comicStructure
|
||||
import top.fumiama.copymanga.tool.MangaDlTools.Companion.wmdlt
|
||||
|
||||
class MainHandler(looper: Looper):Handler(looper) {
|
||||
var saveUrlsOnly = 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()
|
||||
}
|
||||
}
|
||||
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<String>()
|
||||
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 setFab(content: String){
|
||||
//Log.d("MyMH", "Get chapter json: $content")
|
||||
comicStructure = Gson().fromJson(content.reader(), Array<ComicStructure>::class.java)
|
||||
wm?.get()?.fab?.visibility = View.VISIBLE
|
||||
}
|
||||
private fun hideFab() {wm?.get()?.fab?.visibility = View.GONE}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package top.fumiama.copymanga.handler
|
||||
|
||||
import android.os.Handler
|
||||
|
||||
class TimeThread(private val handler: Handler, private val msg: Int) : Thread() {
|
||||
var canDo = false
|
||||
override fun run() {
|
||||
while (canDo) {
|
||||
try {
|
||||
handler.sendEmptyMessage(msg)
|
||||
sleep(3000)
|
||||
} catch (e: InterruptedException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package top.fumiama.copymanga.tool
|
||||
|
||||
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
|
||||
|
||||
class DownloadTools {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
83
app/src/main/java/top/fumiama/copymanga/tool/MangaDlTools.kt
Normal file
@@ -0,0 +1,83 @@
|
||||
package top.fumiama.copymanga.tool
|
||||
|
||||
import top.fumiama.copymanga.R
|
||||
import top.fumiama.copymanga.activity.MainActivity.Companion.wm
|
||||
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.ref.WeakReference
|
||||
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 val p = PropertiesTools(File("${wm?.get()?.filesDir}/chapters.hash"))
|
||||
private var imgUrlsList: Array<Array<String>?>? = null
|
||||
private var chaptersCount = 0
|
||||
private val newWebViewHidden: JSWebView?
|
||||
get() {
|
||||
val re = wm?.get()?.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<String>){
|
||||
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"))
|
||||
val s = dl.getHttpContent(it[i])?.let { zip.write(it); true } ?: false
|
||||
if (!s) succeed = s
|
||||
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)
|
||||
}
|
||||
|
||||
companion object {
|
||||
var wmdlt: WeakReference<MangaDlTools>? = null
|
||||
var comicStructure: Array<ComicStructure>? = null
|
||||
}
|
||||
}
|
||||
60
app/src/main/java/top/fumiama/copymanga/tool/PagesManager.kt
Normal file
@@ -0,0 +1,60 @@
|
||||
package top.fumiama.copymanga.tool
|
||||
|
||||
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.lang.ref.WeakReference
|
||||
|
||||
class PagesManager(w: WeakReference<ViewMangaActivity>) {
|
||||
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){
|
||||
val chapterUrl = if(goNext) ViewMangaActivity.nextChapterUrl else ViewMangaActivity.previousChapterUrl
|
||||
val hint = if(goNext) "下" else "上"
|
||||
if (v?.clicked == false) {
|
||||
if (if(goNext)judgeNext() else judgePrevious()) {
|
||||
if(goNext) {
|
||||
v.scrollForward()
|
||||
isEndR = false
|
||||
} else {
|
||||
v.scrollBack()
|
||||
isEndL = false
|
||||
}
|
||||
} else if (chapterUrl != null) {
|
||||
if (if(goNext)isEndR else isEndL) {
|
||||
wm?.get()?.w?.loadUrl("javascript:invoke.clickClass(\"comicControlBottomTopClick\",${if(goNext)1 else 0});")
|
||||
v.tt.canDo = false
|
||||
v.finish()
|
||||
} else {
|
||||
Toast.makeText(
|
||||
v.applicationContext,
|
||||
"再次按下加载${hint}一章",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
if(goNext) isEndR = true
|
||||
else isEndL = true
|
||||
}
|
||||
} else Toast.makeText(
|
||||
v.applicationContext,
|
||||
"已经到头了~",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
} else v?.hideObjs()
|
||||
}
|
||||
fun manageInfo(){
|
||||
if (v?.clicked == false) v.showObjs() else v?.hideObjs()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package top.fumiama.copymanga.tool
|
||||
//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()
|
||||
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)
|
||||
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.")
|
||||
o.close()
|
||||
}
|
||||
private fun loadFromXml(`in`: InputStream?): PropertiesTools {
|
||||
this.loadFromXML(`in`)
|
||||
return this
|
||||
}
|
||||
private fun setProp(key: String?, value: String?): PropertiesTools {
|
||||
this.setProperty(key, value)
|
||||
return this
|
||||
}
|
||||
operator fun get(key: String): String{
|
||||
val i = propfile.inputStream()
|
||||
val re = this.loadFromXml(i).getProperty(key)?:"null"
|
||||
Log.d("MyPT", "Get $key = $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")
|
||||
o.close()
|
||||
}
|
||||
}
|
||||
91
app/src/main/java/top/fumiama/copymanga/tool/ToolsBox.kt
Normal file
@@ -0,0 +1,91 @@
|
||||
package top.fumiama.copymanga.tool
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.NetworkCapabilities
|
||||
import android.widget.Toast
|
||||
import top.fumiama.copymanga.R
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.*
|
||||
import kotlin.math.sqrt
|
||||
|
||||
class ToolsBox(w: WeakReference<Any>) {
|
||||
val zis = (w as WeakReference<Activity>).get()
|
||||
val week: String
|
||||
get() {
|
||||
val cal = Calendar.getInstance()
|
||||
return when (cal[Calendar.DAY_OF_WEEK]) {
|
||||
1 -> "周日"
|
||||
2 -> "周一"
|
||||
3 -> "周二"
|
||||
4 -> "周三"
|
||||
5 -> "周四"
|
||||
6 -> "周五"
|
||||
7 -> "周六"
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
val netinfo: String
|
||||
get() {
|
||||
val cm: ConnectivityManager =
|
||||
zis?.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
return cm.getNetworkCapabilities(cm.activeNetwork)?.let {
|
||||
when {
|
||||
it.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> return@let "WIFI"
|
||||
it.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> return@let "移动数据"
|
||||
it.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH) -> return@let "蓝牙"
|
||||
it.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> return@let "以太网"
|
||||
it.hasTransport(NetworkCapabilities.TRANSPORT_LOWPAN) -> return@let "LOWPAN"
|
||||
else -> return@let "无网络"
|
||||
}
|
||||
} ?: "错误"
|
||||
}
|
||||
fun toastError(s: String, willFinish: Boolean = true) {
|
||||
Toast.makeText(zis?.applicationContext, s, Toast.LENGTH_SHORT).show()
|
||||
if (willFinish) zis?.finish()
|
||||
}
|
||||
fun buildInfo(
|
||||
title: String,
|
||||
msg: String,
|
||||
txtOk: String? = null,
|
||||
txtN: String? = null,
|
||||
txtCancel: String? = null,
|
||||
ok: (() -> Unit)? = null,
|
||||
neutral: (() -> Unit)? = null,
|
||||
cancel: (() -> Unit)? = null
|
||||
) {
|
||||
val info = AlertDialog.Builder(zis)
|
||||
info.setIcon(R.drawable.ic_launcher_foreground)
|
||||
info.setTitle(title)
|
||||
info.setMessage(msg)
|
||||
txtOk?.let { info.setPositiveButton(it) { _, _ -> ok?.let { it() } } }
|
||||
txtCancel?.let { info.setNegativeButton(it) { _, _ -> cancel?.let { it() } } }
|
||||
txtN?.let { info.setNeutralButton(it) { _, _ -> neutral?.let { it() } } }
|
||||
info.show()
|
||||
}
|
||||
fun dp2px(dp:Int):Int?{
|
||||
return zis?.resources?.displayMetrics?.density?.let { (dp * it + 0.5).toInt()}
|
||||
}
|
||||
private fun px2dp(px:Int):Int?{
|
||||
return zis?.resources?.displayMetrics?.density?.let { (px.toDouble() / it + 0.5).toInt()}
|
||||
}
|
||||
private fun root(a:Double, b:Double, c:Double):List<Double>?{
|
||||
val d = b*b - 4.0 * a * c
|
||||
if(d < 0) return null
|
||||
val sd = sqrt(d)
|
||||
val x1 = (-b + sd)/(2.0 * a)
|
||||
val x2 = (-b - sd)/(2.0 * a)
|
||||
return listOf(x1, x2)
|
||||
}
|
||||
fun calcWidthFromDp(marginLeftDp:Int, widthDp:Int):List<Int>{
|
||||
val margin = marginLeftDp.toDouble()
|
||||
val marginPx = dp2px(marginLeftDp)?:16
|
||||
val root = root(margin, widthDp.toDouble(), -((px2dp(zis?.resources?.displayMetrics?.widthPixels?:1080))?:400).toDouble())
|
||||
val numPerRow = root?.let { (it[0]+0.5).toInt()}?:3
|
||||
val w = ((zis?.resources?.displayMetrics?.widthPixels?:1080)-marginPx*(numPerRow+1))/numPerRow
|
||||
val totalWidth = ((zis?.resources?.displayMetrics?.widthPixels?:1080)-marginPx)/numPerRow
|
||||
return listOf(numPerRow, w, totalWidth)
|
||||
}
|
||||
}
|
||||
24
app/src/main/java/top/fumiama/copymanga/view/JSWebView.kt
Normal file
@@ -0,0 +1,24 @@
|
||||
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")}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package top.fumiama.copymanga.view
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.widget.ScrollView
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
class LazyScrollView : ScrollView {
|
||||
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)
|
||||
|
||||
init {
|
||||
setOnTouchListener { _, event ->
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_UP -> this.postDelayed({
|
||||
if (view != null && onScrollListener != null) {
|
||||
if (onScrollListener != null) {
|
||||
//Log.d("MyS", "view?.measuredHeight: ${view?.measuredHeight}, scrollY: $scrollY, height: $height")
|
||||
when {
|
||||
view?.measuredHeight?:0 <= scrollY + height -> onScrollListener?.onBottom()
|
||||
scrollY == 0 -> onScrollListener?.onTop()
|
||||
else -> onScrollListener?.onScroll()
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 233)
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 定义接口
|
||||
* @author admin
|
||||
*/
|
||||
interface OnScrollListener {
|
||||
fun onBottom()
|
||||
fun onTop()
|
||||
fun onScroll()
|
||||
}
|
||||
var onScrollListener: OnScrollListener? = null
|
||||
}
|
||||
1892
app/src/main/java/top/fumiama/copymanga/view/ScaleImageView.kt
Normal file
25
app/src/main/java/top/fumiama/copymanga/web/JS.kt
Normal file
@@ -0,0 +1,25 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
22
app/src/main/java/top/fumiama/copymanga/web/JSHidden.kt
Normal file
@@ -0,0 +1,22 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
30
app/src/main/java/top/fumiama/copymanga/web/WebViewClient.kt
Normal file
@@ -0,0 +1,30 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
11
app/src/main/res/drawable-anydpi/bg_comment.xml
Normal file
10
app/src/main/res/drawable-anydpi/ic_dl.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
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"/>
|
||||
</vector>
|
||||
10
app/src/main/res/drawable-anydpi/ic_edit.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M896 864a32 32 0 0 1 0 64H128a32 32 0 0 1 0-64z m-60-734l15 15c46 46 46 120 0 166L419 743a160 160 0 0 1-78 43l-152 34c-24 5-45-17-38-40l43-147a160 160 0 0 1 40-68l435-435c46-46 120-46 166 0zM636 254L280 611a96 96 0 0 0-24 41l-28 95 99-22a96 96 0 0 0 47-26L727 345l-91-91z m79-79l-33 33 91 91 33-33a53 53 0 0 0 0-75l-15-15a53 53 0 0 0-75 0z"/>
|
||||
</vector>
|
||||
@@ -5,7 +5,7 @@
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:fillColor="@color/colorPrimary"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="64dp"
|
||||
android:height="64dp"
|
||||
android:viewportWidth="916"
|
||||
android:viewportHeight="916">
|
||||
<path
|
||||
android:fillColor="@color/colorBlue2"
|
||||
android:pathData="M477 229c89 3 160 74 181 148 10 34 11 92-6 121-4-1-4-2-6-4 1-13 2-25 3-38-11-67-32-111-77-142-11-6-23-13-34-19-13-5-29-6-39-14-9-17-17-34-26-51 1 0 3-1 4-1zm-21 7h4c6 13 19 21 21 39-12 2-31 4-41 0 5-13 11-26 16-39zm-63 52c2 0 3 1 5 1v4c-13 7-27 13-40 20-34 23-62 61-75 105-7 24-8 57-3 84 2 10 3 20 5 30-3 11-24 34-33 39-1 0-3-1-4-1-5-20-12-41-16-64-15-90 45-161 91-192 21-14 45-15 70-26zm67 0c9 0 18 1 27 1 10 7 27 68 22 86-16 1-27 7-36 14-19 0-40-8-58-14 0-16 13-80 21-85 8-1 16-1 24-2zm-137 85c27-1 54 3 74 11 0 53 0 52-35 71-11-8-58-57-51-75l5-5c2-1 5-1 7-2zm258 0c10 0 20 1 30 1 2 2 3 4 5 6 0 18-35 64-47 70-3 0-7 1-10 1-11-8-21-16-32-24-4-8-7-36-2-44 19-3 37-7 56-10zm-166 14c13 0 25 6 36 11 0 1-1 3-1 4-15 7-29 15-44 22 1-9 3-31 9-37zm91 1c2 0 3 1 5 1v23c-1 0-1 1-2 1-6-2-17-7-20-12-2-4 0-6 2-9 5-1 10-3 15-4zm-45 26c67 0 69 97 5 104-30 3-68-31-53-70 8-21 27-25 48-34zm1 29c-9 6-13 9-20 17-1 18 7 23 19 28 14-1 23-10 24-24-7-11-10-16-23-21zm63 1c3 0 5 1 8 1 7 5 15 11 22 16v4c-7 7-16 19-27 22-1 0-1-1-2-1 0-14-1-28-1-42zm-137 8c2 0 4 1 6 1 1 1 2 1 3 2 0 9 1 18 1 27h-4c-8-5-15-10-23-15 1-2 1-5 2-7 5-3 10-5 15-8zm175 19c13 2 66 52 68 64-6 10-19 36-29 41-15 4-71-16-81-23 0-60 19-51 42-82zm-209 2c13 1 37 16 44 25 6 8 11 44 7 54-3 3-71 28-79 25-4-2-28-41-26-49 3-17 42-42 54-55zm155 42l3 3c-2 9-5 17-7 26-10 0-24-4-29-10 0-1 1-3 1-4 13-2 23-9 32-15zm-93 1c11 1 20 10 25 18-1 2-1 3-2 5-6 2-12 3-18 5-1-1-1-2-2-3-1-8-2-17-3-25zm40 25c14 1 37 11 48 18-1 28-22 67-38 82-15-1-48-67-43-82 7-9 25-10 33-18zm183 3c10 3 21 23 26 31-1 3 0 1-2 3h-45v-1l21-33zm-352 2h6c5 8 18 24 16 35-12 1-35 7-45 0 5-15 15-23 23-35zm323 43c20 0 37 1 50 4v6l-46 46c-42 29-114 56-181 33-17-6-32-15-46-24-16-11-45-26-50-47l1-1c4 1 3 0 5 2 9 7 19 14 28 21 14 6 29 11 43 17 82 25 153-22 196-57z" />
|
||||
</vector>
|
||||
33
app/src/main/res/drawable-anydpi/rndbg.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:state_pressed="true">
|
||||
<shape android:shape="rectangle" >
|
||||
<!-- 填充的颜色 -->
|
||||
<solid android:color="@color/colorPrimaryDark" />
|
||||
<!-- 设置按钮的四个角为弧形 -->
|
||||
<!-- android:radius 弧形的半径 -->
|
||||
<corners android:radius="16dip" />
|
||||
<!-- padding:Button里面的文字与Button边界的间隔 -->
|
||||
<padding android:bottom="1dp" android:left="1dp" android:right="1dp" android:top="1dp" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:state_pressed="false">
|
||||
<shape android:shape="rectangle" >
|
||||
<!-- 填充的颜色 -->
|
||||
<solid android:color="@color/colorPrimary" />
|
||||
<!-- 设置按钮的四个角为弧形 -->
|
||||
<!-- android:radius 弧形的半径 -->
|
||||
<corners android:radius="16dip" />
|
||||
<!-- stroke 设置边框显示 -->
|
||||
<stroke
|
||||
android:dashGap="0dp"
|
||||
android:width="1dp"
|
||||
android:color="@color/colorAccent" />
|
||||
<!-- padding:Button里面的文字与Button边界的间隔 -->
|
||||
<padding android:bottom="1dp" android:left="1dp" android:right="1dp" android:top="1dp" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</selector>
|
||||
33
app/src/main/res/drawable-anydpi/rndbg_checked.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:state_pressed="true">
|
||||
<shape android:shape="rectangle" >
|
||||
<!-- 填充的颜色 -->
|
||||
<solid android:color="@color/colorPrimaryDark" />
|
||||
<!-- 设置按钮的四个角为弧形 -->
|
||||
<!-- android:radius 弧形的半径 -->
|
||||
<corners android:radius="16dip" />
|
||||
<!-- padding:Button里面的文字与Button边界的间隔 -->
|
||||
<padding android:bottom="1dp" android:left="1dp" android:right="1dp" android:top="1dp" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:state_pressed="false">
|
||||
<shape android:shape="rectangle" >
|
||||
<!-- 填充的颜色 -->
|
||||
<solid android:color="@color/colorGreen" />
|
||||
<!-- 设置按钮的四个角为弧形 -->
|
||||
<!-- android:radius 弧形的半径 -->
|
||||
<corners android:radius="16dip" />
|
||||
<!-- stroke 设置边框显示 -->
|
||||
<stroke
|
||||
android:dashGap="0dp"
|
||||
android:width="1dp"
|
||||
android:color="@color/colorAccent" />
|
||||
<!-- padding:Button里面的文字与Button边界的间隔 -->
|
||||
<padding android:bottom="1dp" android:left="1dp" android:right="1dp" android:top="1dp" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</selector>
|
||||
33
app/src/main/res/drawable-anydpi/rndbg_error.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:state_pressed="true">
|
||||
<shape android:shape="rectangle" >
|
||||
<!-- 填充的颜色 -->
|
||||
<solid android:color="@color/colorPrimaryDark" />
|
||||
<!-- 设置按钮的四个角为弧形 -->
|
||||
<!-- android:radius 弧形的半径 -->
|
||||
<corners android:radius="16dip" />
|
||||
<!-- padding:Button里面的文字与Button边界的间隔 -->
|
||||
<padding android:bottom="1dp" android:left="1dp" android:right="1dp" android:top="1dp" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:state_pressed="false">
|
||||
<shape android:shape="rectangle" >
|
||||
<!-- 填充的颜色 -->
|
||||
<solid android:color="@color/colorAccent" />
|
||||
<!-- 设置按钮的四个角为弧形 -->
|
||||
<!-- android:radius 弧形的半径 -->
|
||||
<corners android:radius="16dip" />
|
||||
<!-- stroke 设置边框显示 -->
|
||||
<stroke
|
||||
android:dashGap="0dp"
|
||||
android:width="1dp"
|
||||
android:color="@color/colorAccent" />
|
||||
<!-- padding:Button里面的文字与Button边界的间隔 -->
|
||||
<padding android:bottom="1dp" android:left="1dp" android:right="1dp" android:top="1dp" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</selector>
|
||||
13
app/src/main/res/drawable-anydpi/rndbg_round.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval"
|
||||
android:useLevel="false">
|
||||
<solid android:color="@color/colorAccent" />
|
||||
<size
|
||||
android:width="15dp"
|
||||
android:height="15dp" />
|
||||
<padding
|
||||
android:bottom="1dp"
|
||||
android:left="2dp"
|
||||
android:right="2dp"
|
||||
android:top="1dp" />
|
||||
</shape>
|
||||
33
app/src/main/res/drawable-anydpi/rndbg_white.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:state_pressed="true">
|
||||
<shape android:shape="rectangle" >
|
||||
<!-- 填充的颜色 -->
|
||||
<solid android:color="@color/colorPrimaryDark" />
|
||||
<!-- 设置按钮的四个角为弧形 -->
|
||||
<!-- android:radius 弧形的半径 -->
|
||||
<corners android:radius="16dip" />
|
||||
<!-- padding:Button里面的文字与Button边界的间隔 -->
|
||||
<padding android:bottom="1dp" android:left="1dp" android:right="1dp" android:top="1dp" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:state_pressed="false">
|
||||
<shape android:shape="rectangle" >
|
||||
<!-- 填充的颜色 -->
|
||||
<solid android:color="#FFFFFF" />
|
||||
<!-- 设置按钮的四个角为弧形 -->
|
||||
<!-- android:radius 弧形的半径 -->
|
||||
<corners android:radius="16dip" />
|
||||
<!-- stroke 设置边框显示 -->
|
||||
<stroke
|
||||
android:dashGap="0dp"
|
||||
android:width="1dp"
|
||||
android:color="@color/colorAccent" />
|
||||
<!-- padding:Button里面的文字与Button边界的间隔 -->
|
||||
<padding android:bottom="1dp" android:left="1dp" android:right="1dp" android:top="1dp" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</selector>
|
||||
12
app/src/main/res/drawable-anydpi/toggle_button.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!--选中样式 -->
|
||||
|
||||
<item android:drawable="@drawable/rndbg" android:state_checked="true"/>
|
||||
|
||||
<!--未选中样式 -->
|
||||
|
||||
<item android:drawable="@drawable/rndbg_white" android:state_checked="false"/>
|
||||
|
||||
</selector>
|
||||
BIN
app/src/main/res/drawable-nodpi/line_colorful.webp
Normal file
|
After Width: | Height: | Size: 166 B |
@@ -1,30 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
||||
49
app/src/main/res/layout/activity_dl.xml
Normal file
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#FCFCFF">
|
||||
|
||||
<include
|
||||
android:id="@+id/dtitle"
|
||||
layout="@layout/widget_titlebar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<top.fumiama.copymanga.view.LazyScrollView
|
||||
android:id="@+id/dllazys"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/dtitle">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ldwn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?android:attr/listDivider"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</LinearLayout>
|
||||
</top.fumiama.copymanga.view.LazyScrollView>
|
||||
|
||||
<include
|
||||
layout="@layout/widget_downloadbar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
35
app/src/main/res/layout/activity_main.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<top.fumiama.copymanga.view.JSWebView
|
||||
android:id="@+id/w"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/pw"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="2dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/fab"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:background="@drawable/rndbg_round"
|
||||
android:foreground="@drawable/ic_dl"
|
||||
android:foregroundGravity="center"
|
||||
android:onClick="onFabClicked"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="@+id/w" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
59
app/src/main/res/layout/activity_viewmanga.xml
Normal file
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/vcp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<include
|
||||
android:id="@+id/vone"
|
||||
layout="@layout/page_imgview"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/vp"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/onec"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:alpha="0"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<include
|
||||
android:id="@+id/infcard"
|
||||
layout="@layout/widget_infodrawer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<include
|
||||
android:id="@+id/oneinfo"
|
||||
layout="@layout/widget_viewmangainfo"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
14
app/src/main/res/layout/button_tbutton.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ToggleButton xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/tbtn"
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:alpha="0.7"
|
||||
android:background="@drawable/toggle_button"
|
||||
android:padding="2dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
6
app/src/main/res/layout/div_h.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<View xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/divider"
|
||||
android:layout_height="1dp"
|
||||
android:background="?android:attr/listDivider" />
|
||||
16
app/src/main/res/layout/line_caption.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tcptn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.06"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
7
app/src/main/res/layout/line_horizonal.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/ltbtn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal" />
|
||||
12
app/src/main/res/layout/page_imgview.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/onecons"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<top.fumiama.copymanga.view.ScaleImageView
|
||||
android:id="@+id/onei"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
67
app/src/main/res/layout/widget_downloadbar.xml
Normal file
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/csdwn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:alpha="0.9">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/cdwn"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="?android:attr/selectableItemBackground"
|
||||
app:cardBackgroundColor="@color/colorBlue"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/pdwn"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:progress="0"
|
||||
app:layout_constraintBottom_toTopOf="@+id/tdwn"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tdwn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:text="0/0"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/pdwn" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="单击此处下载/暂停 长按此处全选/清空 长按某话删除"
|
||||
app:layout_constraintBottom_toTopOf="@+id/pdwn"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
95
app/src/main/res/layout/widget_infodrawer.xml
Normal file
@@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/idc"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:alpha="0.3"
|
||||
android:background="#FCFCFF"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.0">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/idtime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:text="加载中..."
|
||||
android:textColor="#000000"
|
||||
app:layout_constraintBottom_toTopOf="@+id/idtbvh"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.0" />
|
||||
|
||||
<ToggleButton
|
||||
android:id="@+id/idtbfullscreen"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="@drawable/toggle_button"
|
||||
android:textOff="全屏开"
|
||||
android:textOn="全屏关"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/idtbvh"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/idtime"
|
||||
app:layout_constraintVertical_bias="0.0" />
|
||||
|
||||
<ToggleButton
|
||||
android:id="@+id/idtbvh"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="@drawable/toggle_button"
|
||||
android:textOff="横向"
|
||||
android:textOn="竖向"
|
||||
app:layout_constraintEnd_toStartOf="@id/idtbvp"
|
||||
app:layout_constraintStart_toEndOf="@+id/idtbfullscreen"
|
||||
app:layout_constraintTop_toTopOf="@+id/idtbfullscreen" />
|
||||
|
||||
<ToggleButton
|
||||
android:id="@+id/idtbvp"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="@drawable/toggle_button"
|
||||
android:textOff="动画开"
|
||||
android:textOn="动画关"
|
||||
app:layout_constraintEnd_toStartOf="@+id/idtblr"
|
||||
app:layout_constraintStart_toEndOf="@id/idtbvh"
|
||||
app:layout_constraintTop_toTopOf="@+id/idtbfullscreen" />
|
||||
|
||||
<ToggleButton
|
||||
android:id="@+id/idtblr"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="@drawable/toggle_button"
|
||||
android:textOff="←前 后→"
|
||||
android:textOn="←后 前→"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/idtbvp"
|
||||
app:layout_constraintTop_toTopOf="@+id/idtbfullscreen" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
57
app/src/main/res/layout/widget_titlebar.xml
Normal file
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:foreground="?android:attr/selectableItemBackground"
|
||||
app:cardBackgroundColor="#FFFFFF"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:foreground="@drawable/line_colorful"
|
||||
android:foregroundGravity="fill_horizontal|bottom|center">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/ttitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:gravity="start"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/ilogo"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/isearch"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:src="@drawable/ic_edit"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ilogo"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="64dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/ic_launcher_foreground"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
50
app/src/main/res/layout/widget_viewmangainfo.xml
Normal file
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<include
|
||||
android:id="@+id/inftitle"
|
||||
layout="@layout/widget_titlebar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:alpha="0.8"
|
||||
android:background="@drawable/rndbg_white"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/inftitle">
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/infseek"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/inftxtprogress"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/inftxtprogress"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:text="0/0"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/infseek"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 16 KiB |
@@ -1,6 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#6200EE</color>
|
||||
<color name="colorPrimaryDark">#3700B3</color>
|
||||
<color name="colorAccent">#03DAC5</color>
|
||||
<color name="colorPrimary">#FFCC7F</color>
|
||||
<color name="colorPrimaryDark">#8F8F8F</color>
|
||||
<color name="colorAccent">#F6837A</color>
|
||||
<color name="colorRed">#FFCFCB</color>
|
||||
<color name="colorGreen">#C9E6A4</color>
|
||||
<color name="colorBlue">#f2faff</color>
|
||||
<color name="colorBlue1">#00beff</color>
|
||||
<color name="colorBlue2">#81caf8</color>
|
||||
<color name="colorBlue3">#c7eaff</color>
|
||||
</resources>
|
||||
@@ -1,3 +1,10 @@
|
||||
<resources>
|
||||
<string name="app_name">拷贝漫画</string>
|
||||
<string name="web_home">https://copymanga.net</string>
|
||||
<string name="web_home_www">https://www.copymanga.net</string>
|
||||
<string name="web_comic_detail_pc">https://www.copymanga.net/comic</string>
|
||||
|
||||
<string name="pc_ua">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</string>
|
||||
|
||||
<string name="blocked_ad">已屏蔽其他网站页面</string>
|
||||
</resources>
|
||||
@@ -1,10 +1,9 @@
|
||||
<resources>
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<style name="AppTheme" parent="android:Theme.DeviceDefault.Light.NoActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
<item name="android:colorAccent">@color/colorAccent</item>
|
||||
<item name="android:statusBarColor">@android:color/white</item>
|
||||
<item name="android:windowLightStatusBar">true</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@@ -8,6 +8,7 @@ buildscript {
|
||||
dependencies {
|
||||
classpath "com.android.tools.build:gradle:4.0.2"
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.19'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
||||
@@ -18,4 +18,5 @@ android.useAndroidX=true
|
||||
# Automatically convert third-party libraries to use AndroidX
|
||||
android.enableJetifier=true
|
||||
# Kotlin code style for this project: "official" or "obsolete":
|
||||
kotlin.code.style=official
|
||||
kotlin.code.style=official
|
||||
android.enableR8.fullMode=true
|
||||