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

2.0.beta14

1. 完善设置
2. 增加登陆
3. 增加浏览历史页面
4. 修复一些闪退
This commit is contained in:
源文雨
2022-10-18 16:31:44 +08:00
parent 6163725b1f
commit cb5e730eae
24 changed files with 252 additions and 153 deletions

7
.idea/misc.xml generated
View File

@@ -18,19 +18,26 @@
<entry key="app/src/main/res/layout/fragment_book.xml" value="0.49592391304347827" /> <entry key="app/src/main/res/layout/fragment_book.xml" value="0.49592391304347827" />
<entry key="app/src/main/res/layout/fragment_chapters.xml" value="0.49592391304347827" /> <entry key="app/src/main/res/layout/fragment_chapters.xml" value="0.49592391304347827" />
<entry key="app/src/main/res/layout/fragment_download.xml" value="0.49592391304347827" /> <entry key="app/src/main/res/layout/fragment_download.xml" value="0.49592391304347827" />
<entry key="app/src/main/res/layout/fragment_history.xml" value="0.5395833333333333" />
<entry key="app/src/main/res/layout/fragment_home.xml" value="0.4376278118609407" /> <entry key="app/src/main/res/layout/fragment_home.xml" value="0.4376278118609407" />
<entry key="app/src/main/res/layout/fragment_newest.xml" value="0.5395833333333333" />
<entry key="app/src/main/res/layout/fragment_settings.xml" value="0.5255208333333333" /> <entry key="app/src/main/res/layout/fragment_settings.xml" value="0.5255208333333333" />
<entry key="app/src/main/res/layout/line_1bookline.xml" value="0.49592391304347827" /> <entry key="app/src/main/res/layout/line_1bookline.xml" value="0.49592391304347827" />
<entry key="app/src/main/res/layout/line_bookinfo.xml" value="0.49592391304347827" /> <entry key="app/src/main/res/layout/line_bookinfo.xml" value="0.49592391304347827" />
<entry key="app/src/main/res/layout/line_bookinfo_text.xml" value="0.5395833333333333" />
<entry key="app/src/main/res/layout/line_booktandb.xml" value="0.48596014492753625" /> <entry key="app/src/main/res/layout/line_booktandb.xml" value="0.48596014492753625" />
<entry key="app/src/main/res/layout/line_chapter.xml" value="0.48596014492753625" /> <entry key="app/src/main/res/layout/line_chapter.xml" value="0.48596014492753625" />
<entry key="app/src/main/res/layout/line_choice_list.xml" value="0.49592391304347827" /> <entry key="app/src/main/res/layout/line_choice_list.xml" value="0.49592391304347827" />
<entry key="app/src/main/res/layout/line_rank.xml" value="0.5395833333333333" />
<entry key="app/src/main/res/layout/line_sort.xml" value="0.5395833333333333" />
<entry key="app/src/main/res/layout/line_text_info.xml" value="0.49592391304347827" /> <entry key="app/src/main/res/layout/line_text_info.xml" value="0.49592391304347827" />
<entry key="app/src/main/res/layout/line_word.xml" value="0.49592391304347827" /> <entry key="app/src/main/res/layout/line_word.xml" value="0.49592391304347827" />
<entry key="app/src/main/res/layout/nav_header_main.xml" value="0.48596014492753625" /> <entry key="app/src/main/res/layout/nav_header_main.xml" value="0.48596014492753625" />
<entry key="app/src/main/res/layout/viewpage_banner.xml" value="0.49592391304347827" /> <entry key="app/src/main/res/layout/viewpage_banner.xml" value="0.49592391304347827" />
<entry key="app/src/main/res/layout/viewpage_horizonal.xml" value="0.49592391304347827" /> <entry key="app/src/main/res/layout/viewpage_horizonal.xml" value="0.49592391304347827" />
<entry key="app/src/main/res/layout/widget_infodrawer.xml" value="0.5395833333333333" /> <entry key="app/src/main/res/layout/widget_infodrawer.xml" value="0.5395833333333333" />
<entry key="app/src/main/res/menu/activity_main_drawer.xml" value="0.5395833333333333" />
<entry key="app/src/main/res/menu/main.xml" value="0.5395833333333333" />
<entry key="app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml" value="0.5572916666666666" /> <entry key="app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml" value="0.5572916666666666" />
<entry key="app/src/main/res/xml/pref_setting.xml" value="0.6289537712895377" /> <entry key="app/src/main/res/xml/pref_setting.xml" value="0.6289537712895377" />
</map> </map>

View File

@@ -34,11 +34,12 @@
3. 本应用默认使用大陆线路。 3. 本应用默认使用大陆线路。
### 功能 ### 功能
1. 浏览主页、分类、排行、我的下载、标签、作者。 1. 浏览主页、分类、排行、我的下载、浏览历史、标签、作者。
2. 查看、搜索漫画并直接阅读;记录漫画与章节的阅读进度。 2. 查看、搜索漫画并直接阅读;**在本地**记录漫画与章节的阅读进度。
3. 下载漫画。但是由于不可抗力,下载速度较慢且容易出错,这绝对不是优化的原因,绝对不是。 3. 下载漫画。但是由于不可抗力,下载速度较慢且容易出错,这绝对不是优化的原因,绝对不是。
4. 阅读下载的漫画。 4. 阅读下载的漫画。
5. 检查更新。 5. 检查更新。
6. 登录。
### 未实现功能 ### 未实现功能
未在上表列出的官方`APP`的其他功能。 未在上表列出的官方`APP`的其他功能。

View File

@@ -9,8 +9,8 @@ android {
applicationId 'top.fumiama.copymanga' applicationId 'top.fumiama.copymanga'
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 33 targetSdkVersion 33
versionCode 25 versionCode 26
versionName '2.0.beta13' versionName '2.0.beta14'
resConfigs 'zh', 'zh-rCN' resConfigs 'zh', 'zh-rCN'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -66,9 +66,9 @@ dependencies {
implementation 'com.afollestad.material-dialogs:input:3.3.0' implementation 'com.afollestad.material-dialogs:input:3.3.0'
implementation 'com.github.yalantis:ucrop:2.2.6' implementation 'com.github.yalantis:ucrop:2.2.6'
implementation 'com.to.aboomy:pager2banner:1.0.1' implementation 'com.to.aboomy:pager2banner:1.0.1'
implementation 'com.github.bumptech.glide:glide:4.12.0' implementation 'com.github.bumptech.glide:glide:4.14.2'
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.14.2'
implementation 'com.google.code.gson:gson:2.8.9' implementation 'com.google.code.gson:gson:2.9.1'
implementation 'com.github.vovaksenov99:OverscrollableScrollView:1.0' implementation 'com.github.vovaksenov99:OverscrollableScrollView:1.0'
implementation 'com.liaoinstan.springview:library:1.7.0' implementation 'com.liaoinstan.springview:library:1.7.0'
implementation 'com.github.zawadz88.materialpopupmenu:material-popup-menu:4.0.1' implementation 'com.github.zawadz88.materialpopupmenu:material-popup-menu:4.0.1'

View File

@@ -2,11 +2,56 @@ package top.fumiama.copymanga
import android.app.Activity import android.app.Activity
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.widget.Toast
import com.google.gson.Gson
import kotlinx.android.synthetic.main.activity_login.*
import top.fumiama.copymanga.json.BookListStructure
import top.fumiama.copymanga.json.LoginInfoStructure
import top.fumiama.copymanga.tools.api.CMApi
import top.fumiama.copymanga.tools.http.DownloadTools
import top.fumiama.dmzj.copymanga.R import top.fumiama.dmzj.copymanga.R
import kotlin.random.Random
import kotlin.random.nextUInt
class LoginActivity:Activity() { class LoginActivity:Activity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login) setContentView(R.layout.activity_login)
alblogin.setOnClickListener {
val salt = Random.nextInt(10000)
altusrnm.text?.toString()?.let { username ->
altpwd.text?.toString()?.let { pwd ->
Thread{
try {
CMApi.getLoginConnection(username, pwd, salt)?.apply {
Gson().fromJson(inputStream.reader(), LoginInfoStructure::class.java)?.let {
if(it.code == 200) {
MainActivity.mainWeakReference?.get()?.getPreferences(MODE_PRIVATE)?.edit()?.apply {
putString("token", it.results?.token)
putString("user_id", it.results?.user_id)
putString("username", it.results?.username)
putString("nickname", it.results?.nickname)
apply()
DownloadTools.getHttpContent(getString(R.string.memberInfoApiUrl))?.decodeToString()?.let {
val l = Gson().fromJson(it, LoginInfoStructure::class.java)
if(l.code == 200) {
putString("avatar", l.results.avatar)
apply()
} else runOnUiThread { Toast.makeText(this@LoginActivity, l.message, Toast.LENGTH_SHORT).show() }
}
runOnUiThread { finish() }
}?:runOnUiThread { Toast.makeText(this@LoginActivity, R.string.login_get_conn_failed, Toast.LENGTH_SHORT).show() }
} else runOnUiThread { Toast.makeText(this@LoginActivity, it.message, Toast.LENGTH_SHORT).show() }
}
disconnect()
}?:runOnUiThread { Toast.makeText(this, R.string.login_get_conn_failed, Toast.LENGTH_SHORT).show() }
}catch (e: Exception) {
runOnUiThread { Toast.makeText(this, e.localizedMessage, Toast.LENGTH_SHORT).show() }
}
}.start()
}?:Toast.makeText(this, R.string.login_null_pwd, Toast.LENGTH_SHORT).show()
}?:Toast.makeText(this, R.string.login_null_username, Toast.LENGTH_SHORT).show()
}
} }
} }

View File

@@ -32,6 +32,7 @@ import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.input.input import com.afollestad.materialdialogs.input.input
import com.bumptech.glide.Glide
import com.yalantis.ucrop.UCrop import com.yalantis.ucrop.UCrop
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.app_bar_main.* import kotlinx.android.synthetic.main.app_bar_main.*
@@ -86,6 +87,13 @@ class MainActivity : AppCompatActivity() {
Log.d("MyMain", "onDrawerOpened") Log.d("MyMain", "onDrawerOpened")
isDrawerClosed = false isDrawerClosed = false
DownloadFragment.currentDir = getExternalFilesDir("") DownloadFragment.currentDir = getExternalFilesDir("")
getPreferences(MODE_PRIVATE)?.apply {
val name = getString("nickname", getString("username", ""))
val avatar = getString("avatar", "")
if(name != "") navttitle.text = name
else navttitle.setText(R.string.noLogin)
if(avatar != "") Glide.with(this@MainActivity).load(avatar).into(navhicon)
}
} }
override fun onDrawerSlide(drawerView: View, slideOffset: Float) {} override fun onDrawerSlide(drawerView: View, slideOffset: Float) {}

View File

@@ -0,0 +1,16 @@
package top.fumiama.copymanga.json;
public class HistoryBookListStructure extends ReturnBase {
public Results results;
public static class Results {
public ListItem[] list;
public int total;
public int limit;
public int offset;
}
public static class ListItem {
public String last_chapter_id;
public String last_chapter_name;
public HistoryComicStructure comic;
}
}

View File

@@ -0,0 +1,16 @@
package top.fumiama.copymanga.json;
public class HistoryComicStructure {
public String uuid;
public boolean b_display;
public String name;
public String path_word;
public ThemeStructure[] author;
public ThemeStructure[] theme;
public String cover;
public int status;
public int popular;
public String datetime_updated;
public String last_chapter_id;
public String last_chapter_name;
}

View File

@@ -0,0 +1,12 @@
package top.fumiama.copymanga.json;
public class LoginInfoStructure extends ReturnBase{
public Results results;
public static class Results {
public String token;
public String user_id;
public String username;
public String nickname;
public String avatar;
}
}

View File

@@ -2,6 +2,7 @@ package top.fumiama.copymanga.manga
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.util.Log
import androidx.core.content.edit import androidx.core.content.edit
import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference
import top.fumiama.copymanga.ui.vm.ViewMangaActivity import top.fumiama.copymanga.ui.vm.ViewMangaActivity
@@ -12,7 +13,8 @@ object Reader {
getPreferences(Context.MODE_PRIVATE)?.edit { getPreferences(Context.MODE_PRIVATE)?.edit {
putInt(name, pos) putInt(name, pos)
apply() apply()
} Log.d("MyR", "记录 $name 阅读到第 ${pos+1}")
}?: Log.d("MyR", "无法获得main pref")
ViewMangaActivity.dlhandler = null ViewMangaActivity.dlhandler = null
ViewMangaActivity.position = pos ViewMangaActivity.position = pos
ViewMangaActivity.comicName = name ViewMangaActivity.comicName = name

View File

@@ -7,13 +7,14 @@ import androidx.fragment.app.Fragment
import androidx.navigation.Navigation import androidx.navigation.Navigation
import com.google.gson.Gson import com.google.gson.Gson
import top.fumiama.copymanga.json.BookListStructure import top.fumiama.copymanga.json.BookListStructure
import top.fumiama.copymanga.json.HistoryBookListStructure
import top.fumiama.copymanga.json.TypeBookListStructure import top.fumiama.copymanga.json.TypeBookListStructure
import top.fumiama.copymanga.template.general.MangaPagesFragmentTemplate import top.fumiama.copymanga.template.general.MangaPagesFragmentTemplate
import top.fumiama.copymanga.template.http.AutoDownloadThread import top.fumiama.copymanga.template.http.AutoDownloadThread
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
@ExperimentalStdlibApi @ExperimentalStdlibApi
open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isTypeBook: Boolean = false): MangaPagesFragmentTemplate(inflateRes) { open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isTypeBook: Boolean = false,private val isHistoryBook: Boolean = false): MangaPagesFragmentTemplate(inflateRes) {
var offset = 0 var offset = 0
private val subUrl get() = getApiUrl() private val subUrl get() = getApiUrl()
var ad: AutoDownloadThread? = null var ad: AutoDownloadThread? = null
@@ -40,6 +41,21 @@ open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isT
} }
page++ page++
} }
} else if(isHistoryBook) {
val bookList = Gson().fromJson(it?.decodeToString(), HistoryBookListStructure::class.java)
bookList?.apply {
Log.d("MyICL", "offset:${results.offset}, total:${results.total}")
if(results.offset < results.total) {
if(code == 200) {
results.list.forEach{ book ->
if(ad?.exit == true) return@AutoDownloadThread
cardList.addCard(book.comic.name, null, book.comic.cover, book.comic.path_word, null, null, false)
}
offset += results.list.size
}
}
page++
}
} else { } else {
val bookList = Gson().fromJson(it?.decodeToString(), BookListStructure::class.java) val bookList = Gson().fromJson(it?.decodeToString(), BookListStructure::class.java)
bookList?.apply { bookList?.apply {

View File

@@ -1,10 +1,13 @@
package top.fumiama.copymanga.tools.api package top.fumiama.copymanga.tools.api
import android.util.Base64
import com.bumptech.glide.load.model.LazyHeaders import com.bumptech.glide.load.model.LazyHeaders
import top.fumiama.dmzj.copymanga.R import top.fumiama.dmzj.copymanga.R
import top.fumiama.copymanga.MainActivity import top.fumiama.copymanga.MainActivity
import top.fumiama.copymanga.tools.http.DownloadTools
import top.fumiama.copymanga.ui.settings.SettingsFragment.Companion.settingsPref import top.fumiama.copymanga.ui.settings.SettingsFragment.Companion.settingsPref
import java.io.File import java.io.File
import java.net.URLEncoder
object CMApi { object CMApi {
var myGlideHeaders: LazyHeaders? = null var myGlideHeaders: LazyHeaders? = null
@@ -23,4 +26,15 @@ object CMApi {
fun getZipFile(exDir: File?, manga: String, caption: CharSequence, name: CharSequence) = File(exDir, "$manga/$caption/$name.zip") fun getZipFile(exDir: File?, manga: String, caption: CharSequence, name: CharSequence) = File(exDir, "$manga/$caption/$name.zip")
fun getApiUrl(id: Int, arg1: String?, arg2: String?) = MainActivity.mainWeakReference?.get()?.getString(id)?.let { String.format(it, arg1, arg2) } fun getApiUrl(id: Int, arg1: String?, arg2: String?) = MainActivity.mainWeakReference?.get()?.getString(id)?.let { String.format(it, arg1, arg2) }
fun getApiUrl(id: Int, arg1: String?, arg2: String?, arg3: Int? = 0) = MainActivity.mainWeakReference?.get()?.getString(id)?.let { String.format(it, arg1, arg2, arg3) } fun getApiUrl(id: Int, arg1: String?, arg2: String?, arg3: Int? = 0) = MainActivity.mainWeakReference?.get()?.getString(id)?.let { String.format(it, arg1, arg2, arg3) }
} fun getLoginConnection(username: String, pwd: String, salt: Int) = MainActivity.mainWeakReference?.get()?.getString(R.string.loginApiUrl)?.let {
DownloadTools.getConnection(it, "POST")?.apply {
doOutput = true
setRequestProperty("content-type", "application/x-www-form-urlencoded;charset=utf-8")
setRequestProperty("platform", "3")
setRequestProperty("accept", "application/json")
val r = if(settingsPref?.getBoolean("", false) == false) "1" else "0"
val pwdb64 = Base64.encode("$pwd-$salt".toByteArray(), Base64.DEFAULT).decodeToString()
outputStream.write("username=${URLEncoder.encode(username)}&password=$pwdb64&salt=$salt&platform=3&authorization=Token+&version=1.4.4&source=copyApp&region=$r&webp=1".toByteArray())
}
}
}

View File

@@ -1,10 +1,12 @@
package top.fumiama.copymanga.tools.http package top.fumiama.copymanga.tools.http
import android.content.Context
import android.util.Log import android.util.Log
import top.fumiama.copymanga.MainActivity
import top.fumiama.copymanga.tools.ssl.AllTrustManager import top.fumiama.copymanga.tools.ssl.AllTrustManager
import top.fumiama.copymanga.tools.ssl.IgnoreHostNameVerifier import top.fumiama.copymanga.tools.ssl.IgnoreHostNameVerifier
import top.fumiama.copymanga.ui.settings.SettingsFragment.Companion.settingsPref import top.fumiama.copymanga.ui.settings.SettingsFragment.Companion.settingsPref
import java.io.File import top.fumiama.dmzj.copymanga.R
import java.net.HttpURLConnection import java.net.HttpURLConnection
import java.net.URL import java.net.URL
import java.net.URLEncoder import java.net.URLEncoder
@@ -27,13 +29,25 @@ object DownloadTools {
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.socketFactory) HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.socketFactory)
} }
private fun getConnection(url: String?, method: String = "GET") = fun getConnection(url: String?, method: String = "GET", refer: String? = null, ua: String? = null) =
url?.let { url?.let {
val connection = URL(url).openConnection() as HttpURLConnection val connection = URL(url).openConnection() as HttpURLConnection
connection.requestMethod = method connection.requestMethod = method
connection.connectTimeout = 20000 connection.connectTimeout = 20000
connection.readTimeout = 20000 connection.readTimeout = 20000
connection connection.apply {
ua?.let { setRequestProperty("user-agent", it) }
refer?.let { setRequestProperty("referer", it) }
setRequestProperty("source", "copyApp")
setRequestProperty("webp", "1")
setRequestProperty("region", if(settingsPref?.getBoolean("", false) == false) "1" else "0")
MainActivity.mainWeakReference?.get()?.getPreferences(Context.MODE_PRIVATE)?.getString("token", "")?.let {
if(it != "") setRequestProperty("authorization", "Token $it")
else setRequestProperty("authorization", "Token")
}
setRequestProperty("host", url.substringAfter("://").substringBefore("/"))
setRequestProperty("platform", "3")
}
} }
fun getHttpContent(Url: String, refer: String? = null, ua: String? = null): ByteArray? { fun getHttpContent(Url: String, refer: String? = null, ua: String? = null): ByteArray? {
@@ -41,15 +55,7 @@ object DownloadTools {
var ret: ByteArray? = null var ret: ByteArray? = null
val task = FutureTask(Callable { val task = FutureTask(Callable {
try { try {
getConnection(Url)?.apply { getConnection(Url, "GET", refer, ua)?.apply {
refer?.let { setRequestProperty("referer", it) }
setRequestProperty("source", "copyApp")
setRequestProperty("webp", "1")
setRequestProperty("region", if(settingsPref?.getBoolean("", false) == false) "1" else "0")
setRequestProperty("authorization", "Token")
setRequestProperty("platform", "3")
ua?.let { setRequestProperty("User-agent", it) }
ret = inputStream.readBytes() ret = inputStream.readBytes()
disconnect() disconnect()
} }
@@ -67,37 +73,15 @@ object 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 = getConnection(Url)
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
}
}
fun getHttpContent(Url: String, readSize: Int, refer: String? = "https://api.copymanga.com"): ByteArray? { fun getHttpContent(Url: String, readSize: Int, refer: String? = "https://api.copymanga.com"): ByteArray? {
Log.d("Mydl", "getHttp: $Url") Log.d("Mydl", "getHttp: $Url")
var ret: ByteArray? = null var ret: ByteArray? = null
val task = FutureTask(Callable { val task = FutureTask(Callable {
try { try {
val connection = getConnection(Url) val connection = getConnection(Url, "GET", refer)?.apply {
refer?.let { connection?.setRequestProperty("referer", it) } ret = inputStream.readBytes()
disconnect()
}
val ci = connection?.inputStream val ci = connection?.inputStream
if(readSize > 0) { if(readSize > 0) {
@@ -126,8 +110,10 @@ object DownloadTools {
var ret: ByteArray? = null var ret: ByteArray? = null
val task = FutureTask(Callable { val task = FutureTask(Callable {
try { try {
val connection = getConnection(it) val connection = getConnection(it, "GET", refer)?.apply {
refer?.let { connection?.setRequestProperty("referer", it) } ret = inputStream.readBytes()
disconnect()
}
val ci = connection?.inputStream val ci = connection?.inputStream
ret = ci?.readBytes() ret = ci?.readBytes()
@@ -148,33 +134,4 @@ object DownloadTools {
return@replace URLEncoder.encode(match.value, "UTF-8") return@replace URLEncoder.encode(match.value, "UTF-8")
} }
} }
fun downloadUsingUrlRet(url: String?, f: File, refer: String?): Boolean {
Log.d("Mydl", "Ret Get url: $url, File: $f")
val task = FutureTask(Callable {
val connection = getConnection(replaceChineseCharacters(url))
if(refer != null) connection?.setRequestProperty("referer", refer)
if (f.exists()) f.delete()
else f.parentFile?.mkdirs()
f.parentFile?.let {
if (!it.canRead()) it.setReadable(true)
if (!it.canWrite()) it.setWritable(true)
}
val ci = connection?.inputStream
val fo = f.outputStream()
ci?.buffered()?.copyTo(fo)
fo.close()
ci?.close()
connection?.disconnect()
return@Callable true
})
Thread(task).start()
return try {
task.get()
} catch (ex: Exception) {
ex.printStackTrace()
false
}
}
} }

View File

@@ -54,7 +54,7 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) {
} }
fun setStartRead() { fun setStartRead() {
mainWeakReference?.get()?.apply { if(bookHandler.chapterNames.isNotEmpty()) mainWeakReference?.get()?.apply {
bookHandler.book?.results?.comic?.name?.let { name -> bookHandler.book?.results?.comic?.name?.let { name ->
getPreferences(MODE_PRIVATE).getInt(name, -1).let { p -> getPreferences(MODE_PRIVATE).getInt(name, -1).let { p ->
this@BookFragment.lbbstart.apply { this@BookFragment.lbbstart.apply {

View File

@@ -253,19 +253,19 @@ class BookHandler(that: WeakReference<BookFragment>, private val path: String)
line = layoutInflater.inflate(R.layout.line_chapter, that.fbl, false) line = layoutInflater.inflate(R.layout.line_chapter, that.fbl, false)
line?.lcc?.apply { line?.lcc?.apply {
lct.text = it.name lct.text = it.name
setOnClickListener { _ -> Reader.viewMangaAt(it.name, i) } setOnClickListener { Reader.viewMangaAt(book!!.results.comic.name, i) }
} }
fbl?.addView(line) fbl?.addView(line)
} else { } else {
line = layoutInflater.inflate(R.layout.line_2chapters, that.fbl, false) line = layoutInflater.inflate(R.layout.line_2chapters, that.fbl, false)
line?.l2cl?.apply { line?.l2cl?.apply {
lct.text = it.name lct.text = it.name
setOnClickListener { _ -> Reader.viewMangaAt(it.name, i) } setOnClickListener { Reader.viewMangaAt(book!!.results.comic.name, i) }
} }
} }
} else line?.l2cr?.apply { } else line?.l2cr?.apply {
lct.text = it.name lct.text = it.name
setOnClickListener { _ -> Reader.viewMangaAt(it.name, i) } setOnClickListener { Reader.viewMangaAt(book!!.results.comic.name, i) }
fbl?.addView(line) fbl?.addView(line)
line = null line = null
} }

View File

@@ -0,0 +1,22 @@
package top.fumiama.copymanga.ui.cardflow.history
import android.view.View
import kotlinx.android.synthetic.main.line_lazybooklines.*
import top.fumiama.copymanga.MainActivity
import top.fumiama.copymanga.template.ui.InfoCardLoader
import top.fumiama.dmzj.copymanga.R
@OptIn(ExperimentalStdlibApi::class)
class HistoryFragment : InfoCardLoader(R.layout.fragment_history, R.id.action_nav_history_to_nav_book, isHistoryBook = true) {
override fun getApiUrl() =
getString(R.string.historyApiUrl).let {
String.format(it, page * 21)
}
override fun onLoadFinish() {
super.onLoadFinish()
MainActivity.mainWeakReference?.get()?.runOnUiThread {
mypl.visibility = View.GONE
}
}
}

View File

@@ -1,19 +0,0 @@
package top.fumiama.copymanga.ui.history
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import kotlinx.android.synthetic.main.fragment_history.*
import top.fumiama.dmzj.copymanga.R
class HistoryFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_history, container, false)
}
}

View File

@@ -2,19 +2,17 @@ package top.fumiama.copymanga.ui.settings
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.preference.SeekBarPreference
import top.fumiama.dmzj.copymanga.R import top.fumiama.dmzj.copymanga.R
class SettingsFragment: PreferenceFragmentCompat() { class SettingsFragment: PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.pref_setting, rootKey) setPreferencesFromResource(R.xml.pref_setting, rootKey)
settingsPref = context?.let { PreferenceManager.getDefaultSharedPreferences(it) } if(settingsPref == null) settingsPref = context?.let { PreferenceManager.getDefaultSharedPreferences(it) }
} }
companion object { companion object {
var settingsPref: SharedPreferences? = null var settingsPref: SharedPreferences? = SettingsFragment().context?.let {PreferenceManager.getDefaultSharedPreferences(it)}
} }
} }

View File

@@ -25,9 +25,7 @@ import kotlinx.android.synthetic.main.line_header.view.*
import kotlinx.android.synthetic.main.page_imgview.* import kotlinx.android.synthetic.main.page_imgview.*
import kotlinx.android.synthetic.main.page_imgview.view.* import kotlinx.android.synthetic.main.page_imgview.view.*
import kotlinx.android.synthetic.main.page_scrollimgview.* import kotlinx.android.synthetic.main.page_scrollimgview.*
import kotlinx.android.synthetic.main.page_scrollimgview.view.*
import kotlinx.android.synthetic.main.widget_infodrawer.* import kotlinx.android.synthetic.main.widget_infodrawer.*
import kotlinx.android.synthetic.main.widget_infodrawer.view.*
import kotlinx.android.synthetic.main.widget_titlebar.* import kotlinx.android.synthetic.main.widget_titlebar.*
import kotlinx.android.synthetic.main.widget_titlebar.view.* import kotlinx.android.synthetic.main.widget_titlebar.view.*
import kotlinx.android.synthetic.main.widget_viewmangainfo.* import kotlinx.android.synthetic.main.widget_viewmangainfo.*
@@ -43,7 +41,7 @@ import java.io.ByteArrayOutputStream
import java.io.File import java.io.File
import java.io.InputStream import java.io.InputStream
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import java.util.* import top.fumiama.copymanga.ui.settings.SettingsFragment.Companion.settingsPref
import java.util.concurrent.FutureTask import java.util.concurrent.FutureTask
import java.util.zip.ZipFile import java.util.zip.ZipFile
@@ -96,16 +94,16 @@ class ViewMangaActivity : TitleActivityTemplate() {
//zipFirst = intent.getStringExtra("callFrom") == "zipFirst" //zipFirst = intent.getStringExtra("callFrom") == "zipFirst"
cut = pb["useCut"] cut = pb["useCut"]
r2l = pb["r2l"] r2l = pb["r2l"]
verticalLoadMaxCount = p["verticalMax"].let { if(it > 0) it else 20 } verticalLoadMaxCount = settingsPref?.getInt("settings_cat_vm_sb_vertical_max", 20)?.let { if(it > 0) it else 20 }?:20
isVertical = pb["vertical"] isVertical = pb["vertical"]
notUseVP = pb["noVP"] || isVertical notUseVP = pb["noVP"] || isVertical
//url = intent.getStringExtra("url") //url = intent.getStringExtra("url")
handler = VMHandler(this, if(urlArray.isNotEmpty()) urlArray[position] else "") handler = VMHandler(this, if(urlArray.isNotEmpty()) urlArray[position] else "")
p["quality"].let { q = if (it > 0) it else 100 } settingsPref?.getInt("settings_cat_vm_sb_quality", 100)?.let { q = if (it > 0) it else 100 }
tt = TimeThread(handler, 22) tt = TimeThread(handler, 22)
tt.canDo = true tt.canDo = true
tt.start() tt.start()
volTurnPage = pb["volturn"] volTurnPage = settingsPref?.getBoolean("settings_cat_vm_sw_vol_turn", false)?:false
am = getSystemService(Service.AUDIO_SERVICE) as AudioManager am = getSystemService(Service.AUDIO_SERVICE) as AudioManager
Log.d("MyVM", "Now ZipFile is $zipFile") Log.d("MyVM", "Now ZipFile is $zipFile")

View File

@@ -79,7 +79,7 @@
android:layout_marginTop="4dp" android:layout_marginTop="4dp"
android:fontFamily="@font/calibri" android:fontFamily="@font/calibri"
android:gravity="center" android:gravity="center"
android:text="This is the third-party app for manga reading" android:text="A third-party app for manga reading"
android:textColor="#9affffff" android:textColor="#9affffff"
android:textSize="10sp" /> android:textSize="10sp" />
@@ -102,9 +102,10 @@
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:id="@+id/altusrnm"
android:drawableEnd="@drawable/ic_email_white_24dp" android:drawableEnd="@drawable/ic_email_white_24dp"
android:fontFamily="@font/calibri" android:fontFamily="@font/calibri"
android:hint="Email" android:hint="Username"
android:maxLines="1" android:maxLines="1"
android:textSize="16sp" /> android:textSize="16sp" />
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
@@ -117,6 +118,7 @@
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:id="@+id/altpwd"
android:drawableEnd="@drawable/ic_lock_white_24dp" android:drawableEnd="@drawable/ic_lock_white_24dp"
android:drawablePadding="16dp" android:drawablePadding="16dp"
android:fontFamily="@font/calibri" android:fontFamily="@font/calibri"
@@ -137,6 +139,7 @@
<Button <Button
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/alblogin"
android:layout_marginLeft="16dp" android:layout_marginLeft="16dp"
android:background="@drawable/buttonshapewhitebg" android:background="@drawable/buttonshapewhitebg"
android:fontFamily="@font/calibri" android:fontFamily="@font/calibri"

View File

@@ -1,22 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <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:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
tools:context="top.fumiama.copymanga.ui.history.HistoryFragment">
<TextView <include
android:id="@+id/text_history" layout="@layout/line_lazybooklines"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent" />
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:textAlignment="center"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -83,9 +83,17 @@
<fragment <fragment
android:id="@+id/nav_history" android:id="@+id/nav_history"
android:name="top.fumiama.copymanga.ui.history.HistoryFragment" android:name="top.fumiama.copymanga.ui.cardflow.history.HistoryFragment"
android:label="@string/menu_history" android:label="@string/menu_history"
tools:layout="@layout/fragment_history" /> tools:layout="@layout/fragment_history" >
<action
android:id="@+id/action_nav_history_to_nav_book"
app:destination="@id/nav_book"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_out_left_exit"
app:popExitAnim="@anim/slide_in_right_exit"/>
</fragment>
<fragment <fragment
android:id="@+id/nav_download" android:id="@+id/nav_download"

View File

@@ -30,22 +30,26 @@
<string name="null_book">获取图书信息失败</string> <string name="null_book">获取图书信息失败</string>
<string name="web_error">网络错误</string> <string name="web_error">网络错误</string>
<string name="mainPageApiUrl">https://api.copymanga.info/api/v3/h5/homeIndex?platform=3&amp;format=json</string> <string name="mainPageApiUrl">https://api.copymanga.info/api/v3/h5/homeIndex?platform=3</string>
<string name="referUrl">"https://api.copymanga.info"</string> <string name="referUrl">"https://api.copymanga.info"</string>
<string name="rankApiUrl">https://api.copymanga.info/api/v3/ranks?limit=21&amp;offset=%1$d&amp;date_type=%2$s&amp;platform=3&amp;format=json</string> <string name="hostUrl">"api.copymanga.info"</string>
<string name="searchApiUrl">https://api.copymanga.info/api/v3/search/comic?limit=21&amp;offset=%1$d&amp;q=%2$s&amp;q_type=%3$s&amp;platform=3&amp;format=json</string> <string name="rankApiUrl">https://api.copymanga.info/api/v3/ranks?limit=21&amp;offset=%1$d&amp;date_type=%2$s&amp;platform=3</string>
<string name="filterApiUrl">https://api.copymanga.info/api/v3/h5/filterIndex/comic/tags?platform=3&amp;format=json</string> <string name="searchApiUrl">https://api.copymanga.info/api/v3/search/comic?limit=21&amp;offset=%1$d&amp;q=%2$s&amp;q_type=%3$s&amp;platform=3</string>
<string name="sortApiUrl">https://api.copymanga.info/api/v3/comics?limit=21&amp;offset=%1$d&amp;ordering=%2$s&amp;theme=%3$s&amp;platform=3&amp;format=json</string> <string name="filterApiUrl">https://api.copymanga.info/api/v3/h5/filterIndex/comic/tags?platform=3</string>
<string name="bookInfoApiUrl">https://api.copymanga.info/api/v3/comic2/%1$s?platform=3&amp;format=json</string> <string name="sortApiUrl">https://api.copymanga.info/api/v3/comics?limit=21&amp;offset=%1$d&amp;ordering=%2$s&amp;theme=%3$s&amp;platform=3</string>
<string name="groupInfoApiUrl">https://api.copymanga.info/api/v3/comic/%1$s/group/%2$s/chapters?limit=100&amp;offset=%3$d&amp;platform=3&amp;format=json</string> <string name="bookInfoApiUrl">https://api.copymanga.info/api/v3/comic2/%1$s?platform=3</string>
<string name="chapterInfoApiUrl">https://api.copymanga.info/api/v3/comic/%1$s/chapter2/%2$s?platform=3&amp;format=json</string> <string name="groupInfoApiUrl">https://api.copymanga.info/api/v3/comic/%1$s/group/%2$s/chapters?limit=100&amp;offset=%3$d&amp;platform=3</string>
<string name="topicApiUrl">https://api.copymanga.info/api/v3/topic/%1$s?platform=3&amp;format=json</string> <string name="chapterInfoApiUrl">https://api.copymanga.info/api/v3/comic/%1$s/chapter2/%2$s?platform=3</string>
<string name="topicContentApiUrl">https://api.copymanga.info/api/v3/topic/%1$s/contents?type=%2$d&amp;limit=21&amp;offset=%3$d&amp;platform=3&amp;format=json</string> <string name="topicApiUrl">https://api.copymanga.info/api/v3/topic/%1$s?platform=3</string>
<string name="recommendApiUrl">https://api.copymanga.info/api/v3/recs?pos=3200102&amp;limit=21&amp;offset=%1$d&amp;platform=3&amp;format=json</string> <string name="topicContentApiUrl">https://api.copymanga.info/api/v3/topic/%1$s/contents?type=%2$d&amp;limit=21&amp;offset=%3$d&amp;platform=3</string>
<string name="newestApiUrl">https://api.copymanga.info/api/v3/update/newest?limit=21&amp;offset=%1$d&amp;platform=3&amp;format=json</string> <string name="recommendApiUrl">https://api.copymanga.info/api/v3/recs?pos=3200102&amp;limit=21&amp;offset=%1$d&amp;platform=3</string>
<string name="finishApiUrl">https://api.copymanga.info/api/v3/comics?limit=21&amp;offset=%1$d&amp;ordering=%2$s&amp;top=finish&amp;platform=3&amp;format=json</string> <string name="newestApiUrl">https://api.copymanga.info/api/v3/update/newest?limit=21&amp;offset=%1$d&amp;platform=3</string>
<string name="authorApiUrl">https://api.copymanga.info/api/v3/comics?limit=21&amp;offset=%1$d&amp;ordering=%2$s&amp;author=%3$s&amp;platform=3&amp;format=json</string> <string name="finishApiUrl">https://api.copymanga.info/api/v3/comics?limit=21&amp;offset=%1$d&amp;ordering=%2$s&amp;top=finish&amp;platform=3</string>
<string name="captionApiUrl">https://api.copymanga.info/api/v3/comics?limit=21&amp;offset=%1$d&amp;ordering=%2$s&amp;theme=%3$s&amp;platform=3&amp;format=json</string> <string name="authorApiUrl">https://api.copymanga.info/api/v3/comics?limit=21&amp;offset=%1$d&amp;ordering=%2$s&amp;author=%3$s&amp;platform=3</string>
<string name="captionApiUrl">https://api.copymanga.info/api/v3/comics?limit=21&amp;offset=%1$d&amp;ordering=%2$s&amp;theme=%3$s&amp;platform=3</string>
<string name="loginApiUrl">https://api.copymanga.info/api/v3/login?platform=3</string>
<string name="memberInfoApiUrl">https://api.copymanga.info/api/v3/member/info?platform=3</string>
<string name="historyApiUrl">https://api.copymanga.info/api/v3/member/browse/comics?limit=21&amp;offset=%1$d&amp;platform=3</string>
<string name="complete">已完结</string> <string name="complete">已完结</string>
@@ -56,7 +60,7 @@
<string name="TRANSPORT_LOWPAN">LOWPAN</string> <string name="TRANSPORT_LOWPAN">LOWPAN</string>
<string name="TRANSPORT_NULL">无网络</string> <string name="TRANSPORT_NULL">无网络</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="pc_ua">Dart/2.16 (dart:io)</string>
<string name="menu_update_time">更新时间</string> <string name="menu_update_time">更新时间</string>
<string name="menu_hot">热度</string> <string name="menu_hot">热度</string>
@@ -92,4 +96,9 @@
<string name="settings_cat_vm_sm_vertical_max">默认为20</string> <string name="settings_cat_vm_sm_vertical_max">默认为20</string>
<string name="settings_cat_vm_sb_quality">图片质量</string> <string name="settings_cat_vm_sb_quality">图片质量</string>
<string name="settings_cat_vm_sm_quality">默认为100</string> <string name="settings_cat_vm_sm_quality">默认为100</string>
<string name="login_null_username">用户名为空</string>
<string name="login_null_pwd">密码为空</string>
<string name="login_get_conn_failed">连接失败</string>
</resources> </resources>

View File

@@ -22,7 +22,6 @@
app:title="@string/settings_cat_vm_sw_vol_turn" /> app:title="@string/settings_cat_vm_sw_vol_turn" />
<SeekBarPreference <SeekBarPreference
android:defaultValue="20" android:defaultValue="20"
app:defaultValue="true"
app:iconSpaceReserved="false" app:iconSpaceReserved="false"
app:key="settings_cat_vm_sb_vertical_max" app:key="settings_cat_vm_sb_vertical_max"
app:showSeekBarValue="true" app:showSeekBarValue="true"
@@ -30,7 +29,6 @@
app:title="@string/settings_cat_vm_sb_vertical_max" /> app:title="@string/settings_cat_vm_sb_vertical_max" />
<SeekBarPreference <SeekBarPreference
android:defaultValue="100" android:defaultValue="100"
app:defaultValue="true"
app:iconSpaceReserved="false" app:iconSpaceReserved="false"
app:key="settings_cat_vm_sb_quality" app:key="settings_cat_vm_sb_quality"
app:showSeekBarValue="true" app:showSeekBarValue="true"