1
0
mirror of https://github.com/fumiama/copymanga.git synced 2026-06-13 12:20:26 +08:00
正式版发布!
新增
1. 漫画下载页退出多选模式
2. 我的下载反转排序
3. 分类页 日漫/韩漫/美漫/已完结 筛选标签
4. 排行页 男频/女频 筛选菜单
5. 已完结/更新 标签
6. Token 失效时自动退出登录
7. 我的订阅/漫画详情增加云端读到记录
8. 浏览历史增加最新话提示
9. 漫画详情支持取消订阅
修复
1. 下拉刷新无法回到最开头
2. 断网时无法进入下载
优化
1. 卡片翻页加载效率
This commit is contained in:
源文雨
2023-10-29 17:11:50 +09:00
parent 0c470ff912
commit 44c67838ad
33 changed files with 810 additions and 376 deletions

View File

@@ -8,8 +8,8 @@ android {
applicationId 'top.fumiama.copymanga' applicationId 'top.fumiama.copymanga'
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 33 targetSdkVersion 33
versionCode 35 versionCode 36
versionName '2.0.beta23' versionName '2.0.0'
resConfigs 'zh', 'zh-rCN' resConfigs 'zh', 'zh-rCN'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

View File

@@ -2,7 +2,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/> <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<application <application

View File

@@ -2,6 +2,7 @@ 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 android.widget.Toast
import com.google.gson.Gson import com.google.gson.Gson
import kotlinx.android.synthetic.main.activity_login.* import kotlinx.android.synthetic.main.activity_login.*
@@ -30,52 +31,26 @@ class LoginActivity:Activity() {
Toast.makeText(this, R.string.login_null_pwd, Toast.LENGTH_SHORT).show() Toast.makeText(this, R.string.login_null_pwd, Toast.LENGTH_SHORT).show()
return@setOnClickListener return@setOnClickListener
} }
Thread{ Thread {
if (isLogout) { if (isLogout) {
pref.edit()?.apply { MainActivity.member?.logout()
remove("token") runOnUiThread {
remove("user_id") MainActivity.mainWeakReference?.get()?.refreshUserInfo()
remove("username") Toast.makeText(this@LoginActivity, R.string.login_restart_to_apply, Toast.LENGTH_SHORT).show()
remove("nickname") finish()
remove("avatar")
apply()
runOnUiThread {
MainActivity.mainWeakReference?.get()?.refreshUserInfo()
Toast.makeText(this@LoginActivity, R.string.login_restart_to_apply, Toast.LENGTH_SHORT).show()
finish()
}
} }
return@Thread return@Thread
} }
try { val l = MainActivity.member?.login(username, pwd, salt)
CMApi.getLoginConnection(username, pwd, salt)?.apply { Log.d("MyLA", "login return code: ${l?.code}")
Gson().fromJson(inputStream.reader(), LoginInfoStructure::class.java)?.let { data -> if (l?.code == 200) {
if(data.code == 200) { runOnUiThread {
pref.edit()?.apply { MainActivity.mainWeakReference?.get()?.refreshUserInfo()
putString("token", data.results?.token) finish()
putString("user_id", data.results?.user_id) }
putString("username", data.results?.username) return@Thread
putString("nickname", data.results?.nickname)
apply()
DownloadTools.getHttpContent(getString(R.string.memberInfoApiUrl).format(CMApi.myHostApiUrl))?.decodeToString()?.let {
val l = Gson().fromJson(it, LoginInfoStructure::class.java)
if(l.code == 200) {
putString("avatar", l.results.avatar)
apply()
runOnUiThread {
MainActivity.mainWeakReference?.get()?.refreshUserInfo()
}
} 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, data.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() }
} }
runOnUiThread { Toast.makeText(this@LoginActivity, l?.message, Toast.LENGTH_SHORT).show() }
}.start() }.start()
} }
} }

View File

@@ -45,9 +45,13 @@ import top.fumiama.copymanga.tools.api.CMApi
import top.fumiama.dmzj.copymanga.R import top.fumiama.dmzj.copymanga.R
import top.fumiama.copymanga.tools.api.UITools import top.fumiama.copymanga.tools.api.UITools
import top.fumiama.copymanga.ui.book.BookFragment.Companion.bookHandler import top.fumiama.copymanga.ui.book.BookFragment.Companion.bookHandler
import top.fumiama.copymanga.ui.cardflow.rank.RankFragment
import top.fumiama.copymanga.ui.comicdl.ComicDlFragment import top.fumiama.copymanga.ui.comicdl.ComicDlFragment
import top.fumiama.copymanga.ui.download.DownloadFragment import top.fumiama.copymanga.ui.download.DownloadFragment
import top.fumiama.copymanga.ui.download.NewDownloadFragment
import top.fumiama.copymanga.update.Update import top.fumiama.copymanga.update.Update
import top.fumiama.copymanga.user.Member
import top.fumiama.dmzj.copymanga.BuildConfig
import java.io.File import java.io.File
import java.io.FileInputStream import java.io.FileInputStream
import java.lang.Thread.sleep import java.lang.Thread.sleep
@@ -60,11 +64,16 @@ class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var headPic: File private lateinit var headPic: File
private lateinit var toolsBox: UITools
private var latestDestination = 0
private var isMenuWaiting = false
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
mainWeakReference = WeakReference(this) mainWeakReference = WeakReference(this)
toolsBox = UITools(this)
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
setSupportActionBar(toolbar) setSupportActionBar(toolbar)
@@ -108,10 +117,19 @@ class MainActivity : AppCompatActivity() {
ime = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager ime = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
navController!!.addOnDestinationChangedListener { _, destination, _ -> navController!!.addOnDestinationChangedListener { _, destination, _ ->
latestDestination = destination.id
Log.d("MyMA", "latestDestination: $latestDestination")
if (isMenuWaiting) {
return@addOnDestinationChangedListener
}
isMenuWaiting = true
Log.d("MyMA", "start menu waiting")
Thread { Thread {
sleep(1000) sleep(1000)
isMenuWaiting = false
Log.d("MyMA", "finish menu waiting")
runOnUiThread { runOnUiThread {
when (destination.id) { when (latestDestination) {
R.id.nav_home -> { R.id.nav_home -> {
Log.d("MyMA", "enter home") Log.d("MyMA", "enter home")
menuMain?.findItem(R.id.action_info)?.isVisible = true menuMain?.findItem(R.id.action_info)?.isVisible = true
@@ -130,6 +148,18 @@ class MainActivity : AppCompatActivity() {
menuMain?.findItem(R.id.action_download)?.isVisible = false menuMain?.findItem(R.id.action_download)?.isVisible = false
menuMain?.findItem(R.id.action_sort)?.isVisible = true menuMain?.findItem(R.id.action_sort)?.isVisible = true
} }
R.id.nav_new_download -> {
Log.d("MyMA", "enter new_download")
menuMain?.findItem(R.id.action_info)?.isVisible = false
menuMain?.findItem(R.id.action_download)?.isVisible = false
menuMain?.findItem(R.id.action_sort)?.isVisible = true
}
R.id.nav_rank -> {
Log.d("MyMA", "enter rank")
menuMain?.findItem(R.id.action_info)?.isVisible = false
menuMain?.findItem(R.id.action_download)?.isVisible = false
menuMain?.findItem(R.id.action_sort)?.isVisible = true
}
else -> { else -> {
Log.d("MyMA", "enter others") Log.d("MyMA", "enter others")
menuMain?.findItem(R.id.action_info)?.isVisible = false menuMain?.findItem(R.id.action_info)?.isVisible = false
@@ -149,6 +179,7 @@ class MainActivity : AppCompatActivity() {
return true return true
} }
@OptIn(ExperimentalStdlibApi::class)
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) { return when (item.itemId) {
R.id.action_info -> { R.id.action_info -> {
@@ -161,6 +192,8 @@ class MainActivity : AppCompatActivity() {
} }
R.id.action_sort -> { R.id.action_sort -> {
ComicDlFragment.handler?.sendEmptyMessage(13) ComicDlFragment.handler?.sendEmptyMessage(13)
NewDownloadFragment.wn?.get()?.showReverseInfo(toolsBox)
RankFragment.wr?.get()?.showSexInfo(toolsBox)
true true
} }
else -> super.onOptionsItemSelected(item) else -> super.onOptionsItemSelected(item)
@@ -320,14 +353,14 @@ class MainActivity : AppCompatActivity() {
private fun checkUpdate(ignoreSkip: Boolean) { private fun checkUpdate(ignoreSkip: Boolean) {
Thread{ Thread{
Update.checkUpdate(this, UITools(this), ignoreSkip) Update.checkUpdate(this, toolsBox, ignoreSkip)
}.start() }.start()
} }
private fun showAbout() { private fun showAbout() {
val dl = android.app.AlertDialog.Builder(this) val dl = android.app.AlertDialog.Builder(this)
dl.setMessage(R.string.app_description) dl.setMessage(R.string.app_description)
dl.setTitle(R.string.action_info) dl.setTitle("${getString(R.string.action_info)} ${BuildConfig.VERSION_NAME}")
dl.setIcon(R.mipmap.ic_launcher) dl.setIcon(R.mipmap.ic_launcher)
dl.setPositiveButton(android.R.string.ok) { _, _ -> } dl.setPositiveButton(android.R.string.ok) { _, _ -> }
dl.setNeutralButton(R.string.check_update) {_, _ -> dl.setNeutralButton(R.string.check_update) {_, _ ->
@@ -368,9 +401,22 @@ class MainActivity : AppCompatActivity() {
if (field != null) return field if (field != null) return field
return mainWeakReference?.get()?.let { return mainWeakReference?.get()?.let {
field = Shelf( field = Shelf(
it.getPreferences(Context.MODE_PRIVATE).getString("token", "")?:return@let null, it.getPreferences(Context.MODE_PRIVATE)
it.getString(R.string.shelfOperateApiUrl).format(CMApi.myHostApiUrl), it.getString(R.string.referer), it.getString(R.string.pc_ua) .getString("token", "")?:return@let null) { id ->
) return@Shelf it.getString(id)
}
field
}
}
var member: Member? = null
get() {
if (field != null) return field
return mainWeakReference?.get()?.let {
it.getPreferences(MODE_PRIVATE)?.let { pref ->
field = Member(pref) { id ->
return@Member it.getString(id)
}
}
field field
} }
} }

View File

@@ -0,0 +1,21 @@
package top.fumiama.copymanga.json;
public class BookQueryStructure extends ReturnBase {
public Results results;
public static class Results{
public Browse browse;
public int collect;
public boolean is_lock;
public boolean is_login;
public boolean is_mobile_bind;
public boolean is_vip;
public static class Browse {
public String comic_uuid;
public String comic_id;
public String path_word;
public String chapter_uuid;
public String chapter_id;
public String chapter_name;
}
}
}

View File

@@ -4,5 +4,6 @@ public class FilterStructure extends ReturnBase {
public Results results; public Results results;
public static class Results{ public static class Results{
public ThemeStructure[] theme; public ThemeStructure[] theme;
public ThemeStructure[] top;
} }
} }

View File

@@ -13,4 +13,13 @@ public class HistoryComicStructure {
public String datetime_updated; public String datetime_updated;
public String last_chapter_id; public String last_chapter_id;
public String last_chapter_name; public String last_chapter_name;
public Browse browse;
public static class Browse {
public String comic_uuid;
public String path_word;
public String chapter_uuid;
public String chapter_name;
}
} }

View File

@@ -4,8 +4,11 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.util.Log import android.util.Log
import androidx.core.content.edit import androidx.core.content.edit
import com.google.gson.Gson
import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference
import top.fumiama.copymanga.json.VolumeStructure
import top.fumiama.copymanga.ui.vm.ViewMangaActivity import top.fumiama.copymanga.ui.vm.ViewMangaActivity
import java.io.File
object Reader { object Reader {
fun viewMangaAt(name: String, pos: Int, fromFirstPage: Boolean = false) { fun viewMangaAt(name: String, pos: Int, fromFirstPage: Boolean = false) {
@@ -35,4 +38,23 @@ object Reader {
} }
} }
} }
} fun getComicPathWordInFile(file: File): String {
if(!file.exists()) {
return "N/A:!file.exists()"
}
val jsonFile = File(file, "info.json")
if(!jsonFile.exists()) {
return "N/A:!jsonFile.exists()"
}
Gson().fromJson(jsonFile.readText(), Array<VolumeStructure>::class.java)?.let { volumes ->
if(volumes.isEmpty()) {
return "N/A:volumes.isEmpty()"
}
if(volumes[0].results.list.isEmpty()) {
return "N/A:volumes[0].results.list.isEmpty()"
}
return volumes[0].results.list[0].comic_path_word
}
return "N/A:null_gson"
}
}

View File

@@ -1,11 +1,17 @@
package top.fumiama.copymanga.manga package top.fumiama.copymanga.manga
import android.content.SharedPreferences
import com.google.gson.Gson import com.google.gson.Gson
import top.fumiama.copymanga.json.BookQueryStructure
import top.fumiama.copymanga.json.ReturnBase import top.fumiama.copymanga.json.ReturnBase
import top.fumiama.copymanga.tools.http.DownloadTools import top.fumiama.copymanga.tools.http.DownloadTools
import top.fumiama.dmzj.copymanga.R
class Shelf(private val token: String, private val apiUrl: String, private val referer: String, private val ua: String) { class Shelf(private val token: String, getString: (Int) -> String) {
private val hostUrl: String = getString(R.string.hostUrl)
private val apiUrl: String = getString(R.string.shelfOperateApiUrl).format(hostUrl)
private val queryApiUrl = getString(R.string.bookUserQueryApiUrl)
private val referer: String = getString(R.string.referer)
private val ua: String = getString(R.string.pc_ua)
fun add(comicId: String): String { fun add(comicId: String): String {
if (comicId.isEmpty()) { if (comicId.isEmpty()) {
return "空漫画ID" return "空漫画ID"
@@ -41,4 +47,13 @@ class Shelf(private val token: String, private val apiUrl: String, private val r
)?.decodeToString() ?: return "空回应" )?.decodeToString() ?: return "空回应"
return Gson().fromJson(re, ReturnBase::class.java).message return Gson().fromJson(re, ReturnBase::class.java).message
} }
fun query(pathWord: String): BookQueryStructure {
DownloadTools.getHttpContent(queryApiUrl.format(hostUrl, pathWord), referer, ua)?.let {
return Gson().fromJson(it.decodeToString(), BookQueryStructure::class.java)
}
val b = BookQueryStructure()
b.code = 400
return b
}
} }

View File

@@ -1,16 +1,22 @@
package top.fumiama.copymanga.template.general package top.fumiama.copymanga.template.general
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Bundle import android.os.Bundle
import android.util.JsonReader import android.util.JsonReader
import android.util.Log import android.util.Log
import android.view.View import android.view.View
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import com.liaoinstan.springview.widget.SpringView
import kotlinx.android.synthetic.main.line_header.view.* import kotlinx.android.synthetic.main.line_header.view.*
import kotlinx.android.synthetic.main.line_lazybooklines.* import kotlinx.android.synthetic.main.line_lazybooklines.*
import top.fumiama.copymanga.MainActivity
import top.fumiama.copymanga.template.ui.CardList import top.fumiama.copymanga.template.ui.CardList
import top.fumiama.copymanga.template.handler.MPATHandler
import top.fumiama.copymanga.tools.api.UITools import top.fumiama.copymanga.tools.api.UITools
import top.fumiama.dmzj.copymanga.R
import java.lang.Thread.sleep import java.lang.Thread.sleep
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
@@ -19,23 +25,51 @@ open class MangaPagesFragmentTemplate(inflateRes:Int, val isLazy: Boolean = true
var cardWidth = 0 var cardWidth = 0
var cardHeight = 0 var cardHeight = 0
var cardList: CardList? = null var cardList: CardList? = null
var mh: MPATHandler? = null //var row: View? = null
var row: View? = null
var isEnd = false var isEnd = false
var jsonReaderNow: JsonReader? = null //var jsonReaderNow: JsonReader? = null
var page = 0 var page = 0
var isRefresh = false var isRefresh = false
private val transportStringNull = context?.getString(R.string.TRANSPORT_NULL) ?: "TRANSPORT_NULL"
private val transportStringError = context?.getString(R.string.TRANSPORT_ERROR) ?: "TRANSPORT_ERROR"
private val netInfo: String
get() {
val cm: ConnectivityManager =
context?.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
return cm.getNetworkCapabilities(cm.activeNetwork)?.let {
when {
it.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> return@let context?.getString(
R.string.TRANSPORT_WIFI)
it.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> return@let context?.getString(
R.string.TRANSPORT_CELLULAR)
it.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH) -> return@let context?.getString(
R.string.TRANSPORT_BLUETOOTH)
it.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> return@let context?.getString(
R.string.TRANSPORT_ETHERNET)
it.hasTransport(NetworkCapabilities.TRANSPORT_LOWPAN) -> return@let context?.getString(
R.string.TRANSPORT_LOWPAN)
it.hasTransport(NetworkCapabilities.TRANSPORT_VPN) -> return@let "VPN"
else -> return@let transportStringNull
}
} ?: transportStringError
}
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
if(isFirstInflate) { if(isFirstInflate) {
mh = MPATHandler(WeakReference(this)) if (!forceLoad && (netInfo == transportStringNull || netInfo == transportStringError)) {
findNavController().popBackStack()
return
}
Thread { Thread {
sleep(600) sleep(600)
mh?.sendEmptyMessage(0) MainActivity.mainWeakReference?.get()?.runOnUiThread {
setLayouts()
}
}.start() }.start()
} }
} }
@@ -43,12 +77,11 @@ open class MangaPagesFragmentTemplate(inflateRes:Int, val isLazy: Boolean = true
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
cardList?.exitCardList = true cardList?.exitCardList = true
mh = null //row = null
row = null //jsonReaderNow = null
jsonReaderNow = null
} }
fun setLayouts() { open fun setLayouts() {
val toolsBox = this.context?.let { UITools(it) } val toolsBox = this.context?.let { UITools(it) }
val widthData = toolsBox?.calcWidthFromDp(8, 135) val widthData = toolsBox?.calcWidthFromDp(8, 135)
cardPerRow = widthData?.get(0) ?: 3 cardPerRow = widthData?.get(0) ?: 3
@@ -59,17 +92,47 @@ open class MangaPagesFragmentTemplate(inflateRes:Int, val isLazy: Boolean = true
Log.d("MyMPAT", "Card per row: $cardPerRow") Log.d("MyMPAT", "Card per row: $cardPerRow")
Log.d("MyMPAT", "Card width: $cardWidth") Log.d("MyMPAT", "Card width: $cardWidth")
pageHandler?.initCardList(WeakReference(this)) initCardList(WeakReference(this))
Thread { mh?.sendEmptyMessage(1) }.start() managePage()
pageHandler?.setListeners() setListeners()
//mypl.visibility = View.GONE //mypl.visibility = View.GONE
} }
var pageHandler: PageHandler? = null private fun managePage() {
addPage()
interface PageHandler { if (isLazy) mysp.setListener(object : SpringView.OnFreshListener {
fun addPage() override fun onLoadmore() {
fun initCardList(weakReference: WeakReference<Fragment>) addPage()
fun setListeners() }
override fun onRefresh() {
reset()
Thread {
sleep(600)
MainActivity.mainWeakReference?.get()?.runOnUiThread {
addPage()
}
}.start()
}
})
} }
open fun addPage() {}
open fun onLoadFinish() {
//myp?.visibility = View.GONE
mysp?.onFinishFreshAndLoad()
//mys?.fullScroll(ScrollView.FOCUS_UP)
}
open fun reset() {
mydll.removeAllViews()
isEnd = false
page = 0
cardList?.reset()
mypl?.visibility = View.VISIBLE
}
open fun initCardList(weakReference: WeakReference<Fragment>) {}
open fun setListeners() {}
} }

View File

@@ -1,83 +0,0 @@
package top.fumiama.copymanga.template.handler
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Handler
import android.os.Message
import android.view.View
import android.widget.Toast
import com.liaoinstan.springview.widget.SpringView
import top.fumiama.dmzj.copymanga.R
import kotlinx.android.synthetic.main.line_lazybooklines.*
import top.fumiama.copymanga.template.general.MangaPagesFragmentTemplate
import java.lang.ref.WeakReference
class MPATHandler(private val w: WeakReference<MangaPagesFragmentTemplate>) : Handler() {
private val wa get() = w.get()
private val netinfo: String
get() {
val cm: ConnectivityManager =
wa?.context?.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
return cm.getNetworkCapabilities(cm.activeNetwork)?.let {
when {
it.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> return@let wa?.context?.getString(
R.string.TRANSPORT_WIFI)
it.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> return@let wa?.context?.getString(
R.string.TRANSPORT_CELLULAR)
it.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH) -> return@let wa?.context?.getString(
R.string.TRANSPORT_BLUETOOTH)
it.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> return@let wa?.context?.getString(
R.string.TRANSPORT_ETHERNET)
it.hasTransport(NetworkCapabilities.TRANSPORT_LOWPAN) -> return@let wa?.context?.getString(
R.string.TRANSPORT_LOWPAN)
it.hasTransport(NetworkCapabilities.TRANSPORT_VPN) -> return@let "VPN"
else -> return@let wa?.context?.getString(R.string.TRANSPORT_NULL)
}
} ?: "错误"
}
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
if (wa?.forceLoad == true || netinfo != "无网络" && netinfo != "错误") {
when (msg.what) {
0 -> wa?.setLayouts()
1 -> managePage()
2 -> addPageHandler()
3 -> {
wa?.pageHandler?.addPage()
//wa?.myp?.visibility = View.GONE
wa?.mysp?.onFinishFreshAndLoad()
//wa?.mys?.fullScroll(ScrollView.FOCUS_UP)
}
4 ->{
wa?.mydll?.removeAllViews()
wa?.isEnd = false
wa?.jsonReaderNow = null
wa?.page = 0
wa?.cardList?.reset()
addPageHandler()
wa?.mysp?.onFinishFreshAndLoad()
wa?.mypl?.visibility = View.VISIBLE
}
}
} else Toast.makeText(wa?.context, "${netinfo}链接!", Toast.LENGTH_SHORT).show()
}
private fun managePage() {
addPageHandler()
if (wa?.isLazy == true) wa?.mysp?.setListener(object :SpringView.OnFreshListener{
override fun onLoadmore() {
Thread { this@MPATHandler.sendEmptyMessage(2) }.start()
}
override fun onRefresh() {
Thread { this@MPATHandler.sendEmptyMessage(4) }.start()
}
})
}
private fun addPageHandler() {
//wa?.myp?.visibility = View.VISIBLE
Thread { this.sendEmptyMessage(3) }.start()
}
}

View File

@@ -11,12 +11,14 @@ import top.fumiama.copymanga.json.ReturnBase
import top.fumiama.copymanga.tools.http.DownloadTools import top.fumiama.copymanga.tools.http.DownloadTools
import top.fumiama.copymanga.tools.thread.TimeThread import top.fumiama.copymanga.tools.thread.TimeThread
import java.io.File import java.io.File
import java.lang.Thread.sleep
import java.security.MessageDigest import java.security.MessageDigest
open class AutoDownloadHandler(private val url: String, private val jsonClass: Class<*>, looper: Looper, private val callCheckMsg: Int = -1, private val loadFromCache: Boolean = false, private val customCacheFile: File? = null): Handler(looper) { open class AutoDownloadHandler(private val url: String, private val jsonClass: Class<*>, looper: Looper, private val callCheckMsg: Int = -1, private val loadFromCache: Boolean = false, private val customCacheFile: File? = null): Handler(looper) {
var exit = false var exit = false
private var timeThread: TimeThread? = null private var timeThread: TimeThread? = null
private var checkTimes = 0 private var checkTimes = 0
private var cnt = 0
override fun handleMessage(msg: Message) { override fun handleMessage(msg: Message) {
super.handleMessage(msg) super.handleMessage(msg)
when(msg.what){ when(msg.what){
@@ -72,6 +74,8 @@ open class AutoDownloadHandler(private val url: String, private val jsonClass: C
DownloadTools.getHttpContent(url, null, mainWeakReference?.get()?.getString(R.string.pc_ua)!!).let { DownloadTools.getHttpContent(url, null, mainWeakReference?.get()?.getString(R.string.pc_ua)!!).let {
if(exit) return if(exit) return
if(it == null) { if(it == null) {
if (cnt++>3) return
sleep(1000)
dlThread() dlThread()
return return
} }

View File

@@ -70,7 +70,7 @@ class CardList(
} }
@ExperimentalStdlibApi @ExperimentalStdlibApi
fun addCard(name: String, append: String? = null, head: String? = null, path: String? = null, chapterUUID: String? = null, pn: Int? = null, isFinish: Boolean = false){ fun addCard(name: String, append: String? = null, head: String? = null, path: String? = null, chapterUUID: String? = null, pn: Int? = null, isFinish: Boolean = false, isNew: Boolean = false){
if(exitCardList) return if(exitCardList) return
manageRow() manageRow()
that?.layoutInflater?.inflate(R.layout.card_book, that.mydll.ltbtn, false)?.let { that?.layoutInflater?.inflate(R.layout.card_book, that.mydll.ltbtn, false)?.let {
@@ -83,6 +83,7 @@ class CardList(
card.chapterUUID = chapterUUID card.chapterUUID = chapterUUID
card.pageNumber = pn card.pageNumber = pn
card.isFinish = isFinish card.isFinish = isFinish
card.isNew = isNew
mainWeakReference?.get()?.runOnUiThread{ mainWeakReference?.get()?.runOnUiThread{
if(exitCardList) return@runOnUiThread if(exitCardList) return@runOnUiThread
addCard(it) addCard(it)
@@ -115,6 +116,7 @@ class CardList(
if(img.exists()) it.imic.setImageURI(Uri.fromFile(img)) if(img.exists()) it.imic.setImageURI(Uri.fromFile(img))
} }
if(card.isFinish) it.sgnic.visibility = View.VISIBLE if(card.isFinish) it.sgnic.visibility = View.VISIBLE
if(card.isNew) it.sgnnew.visibility = View.VISIBLE
initClickListeners?.prepareListeners(card, card.name, card.path, card.chapterUUID, card.pageNumber) initClickListeners?.prepareListeners(card, card.name, card.path, card.chapterUUID, card.pageNumber)
rows[card.index % 20]?.ltbtn?.addView(it) rows[card.index % 20]?.ltbtn?.addView(it)
it.layoutParams?.height = cardHeight it.layoutParams?.height = cardHeight

View File

@@ -22,92 +22,103 @@ open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isT
var offset = 0 var offset = 0
private val subUrl get() = getApiUrl() private val subUrl get() = getApiUrl()
var ad: AutoDownloadThread? = null var ad: AutoDownloadThread? = null
init {
pageHandler = object : PageHandler { override fun addPage(){
override fun addPage(){ super.addPage()
ad = AutoDownloadThread(subUrl){ ad = AutoDownloadThread(subUrl) {
if(isRefresh){ if(isRefresh){
page = 0 page = 0
isRefresh = false isRefresh = false
}
if(isTypeBook) {
val bookList = Gson().fromJson(it?.decodeToString(), TypeBookListStructure::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 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 if (isShelfBook) {
val bookList = Gson().fromJson(it?.decodeToString(), ShelfStructure::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 {
val bookList = Gson().fromJson(it?.decodeToString(), BookListStructure::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.name, null, book.cover, book.path_word, null, null, false)
}
offset += results.list.size
}
}
page++
}
}
onLoadFinish()
}
ad?.start()
} }
override fun initCardList(weakReference: WeakReference<Fragment>) { if(isTypeBook) {
cardList = CardList(weakReference, cardWidth, cardHeight, cardPerRow) val bookList = Gson().fromJson(it?.decodeToString(), TypeBookListStructure::class.java)
cardList?.initClickListeners = object : CardList.InitClickListeners { bookList?.apply {
override fun prepareListeners(v: View, name: String, path: String?, chapterUUID: String?, pn: Int?) { Log.d("MyICL", "offset:${results.offset}, total:${results.total}")
v.setOnClickListener { if(results.offset < results.total) {
val bundle = Bundle() if(code == 200) {
bundle.putString("path", path) results.list.forEach { book ->
Navigate.safeNavigateTo(findNavController(), navId, bundle) if(ad?.exit == true) return@AutoDownloadThread
cardList?.addCard(
book?.comic?.name?:"null", null, book?.comic?.cover,
book?.comic?.path_word, null, null,
isFinish = false, isNew = false
)
}
offset += results.list.size
} }
} }
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", "\n最新${book?.last_chapter_name}", book?.comic?.cover,
book?.comic?.path_word, null, null,
book?.comic?.status==1
)
}
offset += results.list.size
}
}
page++
}
} else if (isShelfBook) {
val bookList = Gson().fromJson(it?.decodeToString(), ShelfStructure::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", "\n读到${book?.last_browse?.last_browse_name}", book?.comic?.cover,
book?.comic?.path_word, null, null,
book?.comic?.status==1,
book.comic?.browse?.chapter_uuid != book.comic?.last_chapter_id
)
}
offset += results.list.size
}
}
page++
}
} else {
val bookList = Gson().fromJson(it?.decodeToString(), BookListStructure::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?.name?:"null", null, book?.cover, book?.path_word, null, null, false)
}
offset += results.list.size
}
}
page++
}
}
onLoadFinish()
}
ad?.start()
}
override fun initCardList(weakReference: WeakReference<Fragment>) {
super.initCardList(weakReference)
cardList = CardList(weakReference, cardWidth, cardHeight, cardPerRow)
cardList?.initClickListeners = object : CardList.InitClickListeners {
override fun prepareListeners(v: View, name: String, path: String?, chapterUUID: String?, pn: Int?) {
v.setOnClickListener {
val bundle = Bundle()
bundle.putString("path", path)
Navigate.safeNavigateTo(findNavController(), navId, bundle)
} }
} }
override fun setListeners() { this@InfoCardLoader.setListeners() }
} }
} }
@@ -115,14 +126,18 @@ open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isT
return "" return ""
} }
open fun setListeners(){} override fun onLoadFinish() {
super.onLoadFinish()
open fun onLoadFinish(){
MainActivity.mainWeakReference?.get()?.runOnUiThread { MainActivity.mainWeakReference?.get()?.runOnUiThread {
if(ad?.exit != true) mypl.visibility = View.GONE if(ad?.exit != true) mypl.visibility = View.GONE
} }
} }
override fun reset() {
super.reset()
offset = 0
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
ad?.exit = false ad?.exit = false

View File

@@ -4,7 +4,6 @@ import android.animation.ObjectAnimator
import android.view.View import android.view.View
import kotlinx.android.synthetic.main.anchor_popular.view.* import kotlinx.android.synthetic.main.anchor_popular.view.*
import kotlinx.android.synthetic.main.line_finish.* import kotlinx.android.synthetic.main.line_finish.*
import kotlinx.android.synthetic.main.line_lazybooklines.*
import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference
import top.fumiama.copymanga.tools.api.CMApi import top.fumiama.copymanga.tools.api.CMApi
import top.fumiama.dmzj.copymanga.R import top.fumiama.dmzj.copymanga.R
@@ -40,7 +39,10 @@ open class StatusCardFlow(private val api: Int, nav: Int) : InfoCardLoader(R.lay
} }
Thread{ Thread{
Thread.sleep(400) Thread.sleep(400)
mh?.sendEmptyMessage(4) mainWeakReference?.get()?.runOnUiThread {
reset()
addPage()
}
}.start() }.start()
} }
} }
@@ -59,7 +61,10 @@ open class StatusCardFlow(private val api: Int, nav: Int) : InfoCardLoader(R.lay
} }
Thread { Thread {
Thread.sleep(400) Thread.sleep(400)
mh?.sendEmptyMessage(4) mainWeakReference?.get()?.runOnUiThread {
reset()
addPage()
}
}.start() }.start()
} }
} }

View File

@@ -11,4 +11,12 @@ object FileUtils {
} }
f.delete() f.delete()
} }
fun sizeOf(f: File): Long{
var size = 0L
if (f.isDirectory) f.listFiles()?.apply {
for (i in this)
size += if (i.isDirectory) sizeOf(i) else i.length()
}
return size
}
} }

View File

@@ -1,5 +1,6 @@
package top.fumiama.copymanga.ui.book package top.fumiama.copymanga.ui.book
import android.annotation.SuppressLint
import android.content.Context.MODE_PRIVATE import android.content.Context.MODE_PRIVATE
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
@@ -7,6 +8,7 @@ import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import com.google.gson.Gson import com.google.gson.Gson
import kotlinx.android.synthetic.main.line_bookinfo_text.*
import kotlinx.android.synthetic.main.line_booktandb.* import kotlinx.android.synthetic.main.line_booktandb.*
import top.fumiama.copymanga.MainActivity import top.fumiama.copymanga.MainActivity
import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference
@@ -100,18 +102,49 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) {
} }
} }
@SuppressLint("SetTextI18n")
fun setAddToShelf() { fun setAddToShelf() {
if(bookHandler?.chapterNames?.isNotEmpty() == true) if(bookHandler?.chapterNames?.isNotEmpty() == true) {
val b = MainActivity.shelf?.query(bookHandler?.path!!)
bookHandler?.collect = b?.results?.collect?:-2
Log.d("MyBF", "get collect of ${bookHandler?.path} = ${bookHandler?.collect}")
b?.results?.browse?.chapter_name?.let { name ->
btsub.text = "${btsub.text} ${getString(R.string.text_format_cloud_read_to).format(name)}"
}
bookHandler?.collect?.let { collect ->
if (collect > 0) {
this@BookFragment.lbbsub.setText(R.string.button_sub_subscribed)
}
}
bookHandler?.book?.results?.comic?.let { comic -> bookHandler?.book?.results?.comic?.let { comic ->
this@BookFragment.lbbsub.setOnClickListener { this@BookFragment.lbbsub.setOnClickListener {
if (this@BookFragment.lbbsub.text != getString(R.string.button_sub)) {
bookHandler?.collect?.let { collect ->
if (collect < 0) return@setOnClickListener
Thread{
val re = MainActivity.shelf?.del(collect)
mainWeakReference?.get()?.runOnUiThread {
Toast.makeText(context, re, Toast.LENGTH_SHORT).show()
if (re == "请求成功") {
this@BookFragment.lbbsub.setText(R.string.button_sub)
}
}
}.start()
}
return@setOnClickListener
}
Thread{ Thread{
val re = MainActivity.shelf?.add(comic.uuid) val re = MainActivity.shelf?.add(comic.uuid)
mainWeakReference?.get()?.runOnUiThread { mainWeakReference?.get()?.runOnUiThread {
Toast.makeText(context, re, Toast.LENGTH_SHORT).show() Toast.makeText(context, re, Toast.LENGTH_SHORT).show()
if (re == "修改成功") {
this@BookFragment.lbbsub.setText(R.string.button_sub_subscribed)
}
} }
}.start() }.start()
} }
} }
}
} }
fun navigate2dl(){ fun navigate2dl(){

View File

@@ -43,7 +43,7 @@ import java.io.File
import java.lang.Thread.sleep import java.lang.Thread.sleep
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
class BookHandler(private val th: WeakReference<BookFragment>, private val path: String) class BookHandler(private val th: WeakReference<BookFragment>, val path: String)
: AutoDownloadHandler(th.get()?.getString(R.string.bookInfoApiUrl)?.format(CMApi.myHostApiUrl, path)?: "", : AutoDownloadHandler(th.get()?.getString(R.string.bookInfoApiUrl)?.format(CMApi.myHostApiUrl, path)?: "",
BookInfoStructure::class.java, BookInfoStructure::class.java,
Looper.myLooper()!!){ Looper.myLooper()!!){
@@ -62,6 +62,7 @@ class BookHandler(private val th: WeakReference<BookFragment>, private val path:
var cnts = intArrayOf() var cnts = intArrayOf()
var vols: Array<VolumeStructure>? = null var vols: Array<VolumeStructure>? = null
var chapterNames = arrayOf<String>() var chapterNames = arrayOf<String>()
var collect: Int = -1
private val divider get() = that?.layoutInflater?.inflate(R.layout.div_h, that?.fbl, false) private val divider get() = that?.layoutInflater?.inflate(R.layout.div_h, that?.fbl, false)
override fun handleMessage(msg: Message) { override fun handleMessage(msg: Message) {
@@ -133,8 +134,8 @@ class BookHandler(private val th: WeakReference<BookFragment>, private val path:
fbl.addView(fbibinfo) fbl.addView(fbibinfo)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
(fbibinfo!!.parent as LinearLayout).removeAllViews() (fbibinfo?.parent as LinearLayout?)?.removeAllViews()
fbl.addView(fbibinfo) fbl?.addView(fbibinfo)
} }
book?.results?.comic?.cover?.let { cover -> book?.results?.comic?.cover?.let { cover ->
val load = Glide.with(this).load( val load = Glide.with(this).load(
@@ -145,8 +146,8 @@ class BookHandler(private val th: WeakReference<BookFragment>, private val path:
?.let { it2 -> RequestOptions.bitmapTransform(it2) } ?.let { it2 -> RequestOptions.bitmapTransform(it2) }
?.let { it3 -> load.apply(it3).into(lbibg) } ?.let { it3 -> load.apply(it3).into(lbibg) }
} }
imf.visibility = View.GONE imf?.visibility = View.GONE
fbl.addView(divider) fbl?.addView(divider)
} }
} }

View File

@@ -1,23 +1,52 @@
package top.fumiama.copymanga.ui.cardflow.rank package top.fumiama.copymanga.ui.cardflow.rank
import android.os.Bundle
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import kotlinx.android.synthetic.main.fragment_rank.* import kotlinx.android.synthetic.main.fragment_rank.*
import kotlinx.android.synthetic.main.line_rank.view.* import kotlinx.android.synthetic.main.line_rank.view.*
import top.fumiama.copymanga.MainActivity
import top.fumiama.copymanga.template.ui.InfoCardLoader import top.fumiama.copymanga.template.ui.InfoCardLoader
import top.fumiama.copymanga.tools.api.CMApi import top.fumiama.copymanga.tools.api.CMApi
import top.fumiama.copymanga.tools.api.UITools
import top.fumiama.copymanga.ui.download.NewDownloadFragment
import top.fumiama.dmzj.copymanga.R import top.fumiama.dmzj.copymanga.R
import java.lang.Thread.sleep import java.lang.Thread.sleep
import java.lang.ref.WeakReference
@ExperimentalStdlibApi @ExperimentalStdlibApi
class RankFragment : InfoCardLoader(R.layout.fragment_rank, R.id.action_nav_rank_to_nav_book, true) { class RankFragment : InfoCardLoader(R.layout.fragment_rank, R.id.action_nav_rank_to_nav_book, true) {
private val sortWay = listOf("day", "week", "month", "total") private val sortWay = listOf("day", "week", "month", "total")
private var sortValue = 0 private var sortValue = 0
private val audienceWay = listOf("", "male", "female")
private var audience = 0 // 0 all 1 male 2 female
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
wr = WeakReference(this)
}
override fun onPause() {
super.onPause()
ad?.exit = true
}
override fun onResume() {
super.onResume()
ad?.exit = true
}
override fun onDestroy() {
super.onDestroy()
wr = null
ad?.exit = true
}
override fun getApiUrl() = override fun getApiUrl() =
getString(R.string.rankApiUrl).format( getString(R.string.rankApiUrl).format(
CMApi.myHostApiUrl, CMApi.myHostApiUrl,
page * 21, page * 21,
sortWay[sortValue] sortWay[sortValue],
audienceWay[audience]
) )
override fun setListeners() { override fun setListeners() {
@@ -37,7 +66,41 @@ class RankFragment : InfoCardLoader(R.layout.fragment_rank, R.id.action_nav_rank
sortValue = value sortValue = value
Thread{ Thread{
sleep(400) sleep(400)
if(ad?.exit != true) mh?.sendEmptyMessage(4) if(ad?.exit != true) MainActivity.mainWeakReference?.get()?.runOnUiThread {
reset()
addPage()
}
}.start() }.start()
} }
fun showSexInfo(toolsBox: UITools) {
if (ad?.exit != false) return
toolsBox.buildInfo("切换类型", "选择一种想筛选的漫画类型",
"男频", "全部", "女频", {
audience = 1
reset()
Thread {
sleep(600)
addPage()
}.start()
}, {
audience = 0
reset()
Thread {
sleep(600)
addPage()
}.start()
}, {
audience = 2
reset()
Thread {
sleep(600)
addPage()
}.start()
})
}
companion object {
var wr: WeakReference<RankFragment>? = null
}
} }

View File

@@ -3,6 +3,7 @@ package top.fumiama.copymanga.ui.cardflow.shelf
import android.animation.ObjectAnimator import android.animation.ObjectAnimator
import kotlinx.android.synthetic.main.anchor_popular.view.* import kotlinx.android.synthetic.main.anchor_popular.view.*
import kotlinx.android.synthetic.main.line_shelf.* import kotlinx.android.synthetic.main.line_shelf.*
import top.fumiama.copymanga.MainActivity
import top.fumiama.copymanga.template.ui.InfoCardLoader import top.fumiama.copymanga.template.ui.InfoCardLoader
import top.fumiama.copymanga.tools.api.CMApi import top.fumiama.copymanga.tools.api.CMApi
import top.fumiama.dmzj.copymanga.R import top.fumiama.dmzj.copymanga.R
@@ -47,7 +48,10 @@ class ShelfFragment : InfoCardLoader(R.layout.fragment_shelf, R.id.action_nav_su
} }
Thread { Thread {
sleep(400) sleep(400)
mh?.sendEmptyMessage(4) MainActivity.mainWeakReference?.get()?.runOnUiThread {
reset()
addPage()
}
}.start() }.start()
} }
} }
@@ -65,7 +69,10 @@ class ShelfFragment : InfoCardLoader(R.layout.fragment_shelf, R.id.action_nav_su
} }
Thread { Thread {
sleep(400) sleep(400)
mh?.sendEmptyMessage(4) MainActivity.mainWeakReference?.get()?.runOnUiThread {
reset()
addPage()
}
}.start() }.start()
} }
} }
@@ -83,7 +90,10 @@ class ShelfFragment : InfoCardLoader(R.layout.fragment_shelf, R.id.action_nav_su
} }
Thread { Thread {
sleep(400) sleep(400)
mh?.sendEmptyMessage(4) MainActivity.mainWeakReference?.get()?.runOnUiThread {
reset()
addPage()
}
}.start() }.start()
} }
} }

View File

@@ -15,8 +15,9 @@ import java.lang.Thread.sleep
@ExperimentalStdlibApi @ExperimentalStdlibApi
class SortFragment : InfoCardLoader(R.layout.fragment_sort, R.id.action_nav_sort_to_nav_book) { class SortFragment : InfoCardLoader(R.layout.fragment_sort, R.id.action_nav_sort_to_nav_book) {
private val sortWay = listOf("-datetime_updated", "datetime_updated", "-popular", "popular") private val sortWay = listOf("datetime_updated", "-datetime_updated", "-popular", "popular")
private var theme = -1 private var theme = -1
private var region = -1
private var sortValue = 0 private var sortValue = 0
private var filter: FilterStructure? = null private var filter: FilterStructure? = null
@@ -25,7 +26,8 @@ class SortFragment : InfoCardLoader(R.layout.fragment_sort, R.id.action_nav_sort
CMApi.myHostApiUrl, CMApi.myHostApiUrl,
page * 21, page * 21,
sortWay[sortValue], sortWay[sortValue],
if(theme >= 0) (filter?.results?.theme?.get(theme)?.path_word ?: "") else "" if(theme >= 0) (filter?.results?.theme?.get(theme)?.path_word ?: "") else "",
if(region >= 0) (filter?.results?.top?.get(region)?.path_word ?: "") else "",
) )
override fun setListeners() { override fun setListeners() {
@@ -57,12 +59,57 @@ class SortFragment : InfoCardLoader(R.layout.fragment_sort, R.id.action_nav_sort
} }
Thread{ Thread{
sleep(400) sleep(400)
mh?.sendEmptyMessage(4) mainWeakReference?.get()?.runOnUiThread {
reset()
addPage()
}
}.start() }.start()
} }
} }
private fun setClasses(){ private fun setClasses(){
filter?.results?.top?.let { items ->
if(ad?.exit == true) return@let
line_sort_region.apt.text = "全部"
line_sort_region.setOnClickListener {
val popupMenu = popupMenu {
style = R.style.Widget_MPM_Menu_Dark_CustomBackground
section {
item {
label = "全部"
labelColor = it.apt.currentTextColor
callback = {
region = -1
it.apt.text = "全部"
Thread{
sleep(400)
mainWeakReference?.get()?.runOnUiThread {
reset()
addPage()
}
}.start()
}
}
for(i in items.indices) item {
label = items[i].name
labelColor = it.apt.currentTextColor
callback = { //optional
it.apt.text = label
region = i
Thread{
sleep(400)
mainWeakReference?.get()?.runOnUiThread {
reset()
addPage()
}
}.start()
}
}
}
}
this.context?.let { it1 -> popupMenu.show(it1, it) }
}
}
filter?.results?.theme?.let { items -> filter?.results?.theme?.let { items ->
if(ad?.exit == true) return@let if(ad?.exit == true) return@let
line_sort_class.apt.text = "全部" line_sort_class.apt.text = "全部"
@@ -78,7 +125,10 @@ class SortFragment : InfoCardLoader(R.layout.fragment_sort, R.id.action_nav_sort
it.apt.text = "全部" it.apt.text = "全部"
Thread{ Thread{
sleep(400) sleep(400)
mh?.sendEmptyMessage(4) mainWeakReference?.get()?.runOnUiThread {
reset()
addPage()
}
}.start() }.start()
} }
} }
@@ -90,7 +140,10 @@ class SortFragment : InfoCardLoader(R.layout.fragment_sort, R.id.action_nav_sort
theme = i theme = i
Thread{ Thread{
sleep(400) sleep(400)
mh?.sendEmptyMessage(4) mainWeakReference?.get()?.runOnUiThread {
reset()
addPage()
}
}.start() }.start()
} }
} }
@@ -114,7 +167,10 @@ class SortFragment : InfoCardLoader(R.layout.fragment_sort, R.id.action_nav_sort
} }
Thread { Thread {
sleep(400) sleep(400)
mh?.sendEmptyMessage(4) mainWeakReference?.get()?.runOnUiThread {
reset()
addPage()
}
}.start() }.start()
} }
} }

View File

@@ -210,14 +210,12 @@ class ComicDlHandler(looper: Looper, private val th: WeakReference<ComicDlFragme
if (downloading || checkedChapter == 0) { if (downloading || checkedChapter == 0) {
mangaDlTools.wait = !mangaDlTools.wait!! mangaDlTools.wait = !mangaDlTools.wait!!
} else { } else {
if(!downloading) { downloading = true
downloading = true Thread {
Thread { sendEmptyMessage(9)
sendEmptyMessage(9) finishMap = arrayOfNulls(tbtnlist.size)
finishMap = arrayOfNulls(tbtnlist.size) downloadChapterPages()
downloadChapterPages() }.start()
}.start()
} else mangaDlTools.wait = false
} }
} }
} }
@@ -252,6 +250,11 @@ class ComicDlHandler(looper: Looper, private val th: WeakReference<ComicDlFragme
} }
private fun showMultiSelectInfo() { private fun showMultiSelectInfo() {
if(multiSelect) {
toolsBox.buildInfo("退出多选模式?", "退出后只能对单个漫画进行长按删除",
"确定", null, "取消", { multiSelect = false })
return
}
toolsBox.buildInfo("进入多选模式?", "之后可以对已下载漫画进行批量删除/重新下载", toolsBox.buildInfo("进入多选模式?", "之后可以对已下载漫画进行批量删除/重新下载",
"确定", null, "取消", { multiSelect = true }) "确定", null, "取消", { multiSelect = true })
} }

View File

@@ -1,5 +1,6 @@
package top.fumiama.copymanga.ui.download package top.fumiama.copymanga.ui.download
import android.app.Activity
import android.app.AlertDialog import android.app.AlertDialog
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
@@ -9,105 +10,135 @@ import androidx.navigation.fragment.findNavController
import com.google.gson.Gson import com.google.gson.Gson
import kotlinx.android.synthetic.main.line_lazybooklines.* import kotlinx.android.synthetic.main.line_lazybooklines.*
import top.fumiama.copymanga.MainActivity import top.fumiama.copymanga.MainActivity
import top.fumiama.copymanga.manga.Reader
import top.fumiama.copymanga.template.general.MangaPagesFragmentTemplate import top.fumiama.copymanga.template.general.MangaPagesFragmentTemplate
import top.fumiama.copymanga.template.ui.CardList import top.fumiama.copymanga.template.ui.CardList
import top.fumiama.copymanga.tools.api.Navigate import top.fumiama.copymanga.tools.api.Navigate
import top.fumiama.copymanga.tools.api.UITools
import top.fumiama.copymanga.tools.file.FileUtils import top.fumiama.copymanga.tools.file.FileUtils
import top.fumiama.copymanga.ui.comicdl.ComicDlFragment import top.fumiama.copymanga.ui.comicdl.ComicDlFragment
import top.fumiama.dmzj.copymanga.R import top.fumiama.dmzj.copymanga.R
import java.io.File import java.io.File
import java.lang.Thread.sleep
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
@OptIn(ExperimentalStdlibApi::class) @OptIn(ExperimentalStdlibApi::class)
class NewDownloadFragment: MangaPagesFragmentTemplate(R.layout.fragment_newdownload) { class NewDownloadFragment: MangaPagesFragmentTemplate(R.layout.fragment_newdownload, forceLoad = true) {
private var sortedBookList: List<File>? = null private var sortedBookList: List<File>? = null
private val oldDlCardName = MainActivity.mainWeakReference?.get()?.getString(R.string.old_download_card_name)!! private val oldDlCardName = MainActivity.mainWeakReference?.get()?.getString(R.string.old_download_card_name)!!
private val extDir = MainActivity.mainWeakReference?.get()?.getExternalFilesDir("") private val extDir = MainActivity.mainWeakReference?.get()?.getExternalFilesDir("")
init { private var isReverse = false
pageHandler = object : PageHandler { private var isContentChanged = false
override fun addPage() { private var exit = false
if(!isEnd) { override fun onCreate(savedInstanceState: Bundle?) {
if(sortedBookList == null) { super.onCreate(savedInstanceState)
Log.d("MyNDF", "Sorting books...") wn = WeakReference(this)
sortedBookList = extDir?.listFiles()?.sorted() }
}
Log.d("MyNDF", "Start drawing cards") override fun onPause() {
cardList?.addCard(oldDlCardName, path = oldDlCardName) super.onPause()
sortedBookList?.let { exit = true
for(i in it.listIterator(page)) { }
override fun onResume() {
super.onResume()
exit = false
}
override fun onDestroy() {
super.onDestroy()
wn = null
exit = true
}
override fun addPage() {
super.addPage()
if(!isEnd) {
if(sortedBookList == null || isContentChanged) {
Log.d("MyNDF", "Sorting books...")
sortedBookList = extDir?.listFiles()?.sortedBy {
return@sortedBy Reader.getComicPathWordInFile(it)
}
if (isReverse) {
Log.d("MyNDF", "reversed...")
sortedBookList = sortedBookList?.asReversed()
}
isContentChanged = false
}
Log.d("MyNDF", "Start drawing cards")
cardList?.addCard(oldDlCardName, path = oldDlCardName)
sortedBookList?.let {
for(i in it.listIterator(page)) {
if(cardList?.exitCardList != false) return
page++ // page is actually count
val chosenJson = File(i, "info.bin")
val newJson = File(i, "info.json")
val bookSize = (FileUtils.sizeOf(i)/1048576).toInt()
when {
chosenJson.exists() -> continue // unsupported old folder
newJson.exists() -> {
if(cardList?.exitCardList != false) return if(cardList?.exitCardList != false) return
page++ // page is actually count cardList?.addCard(i.name, "\n${bookSize}MB")
val chosenJson = File(i, "info.bin")
val newJson = File(i, "info.json")
val bookSize = (sizeOf(i)/1048576).toInt()
when{
chosenJson.exists() -> continue // unsupported old folder
newJson.exists() -> {
if(cardList?.exitCardList != false) return
cardList?.addCard(i.name, " ${bookSize}MB")
}
}
}
if(page >= it.size) {
isEnd = true
} }
} }
} }
onLoadFinish() if(page >= it.size) {
} isEnd = true
override fun initCardList(weakReference: WeakReference<Fragment>) {
cardList = CardList(weakReference, cardWidth, cardHeight, cardPerRow)
cardList?.initClickListeners = object : CardList.InitClickListeners {
override fun prepareListeners(v: View, name: String, path: String?, chapterUUID: String?, pn: Int?) {
v.setOnClickListener {
if(name==oldDlCardName && path == oldDlCardName) {
Navigate.safeNavigateTo(findNavController(), R.id.action_nav_new_download_to_nav_download)
return@setOnClickListener
}
callDownloadFragment(name)
}
v.setOnLongClickListener {
if (name == oldDlCardName && path == oldDlCardName) {
return@setOnLongClickListener false
}
val chosenFile = File(extDir, name)
AlertDialog.Builder(context)
.setIcon(R.drawable.ic_launcher_foreground)
.setTitle(R.string.new_download_card_option_hint)
.setItems(arrayOf("删除", "前往")) { d, p ->
d.cancel()
when (p) {
0 -> {
AlertDialog.Builder(context)
.setIcon(R.drawable.ic_launcher_foreground).setMessage("删除下载的此漫画吗?")
.setTitle("提示").setPositiveButton(android.R.string.ok) { _, _ ->
if (chosenFile.exists()) Thread {
FileUtils.recursiveRemove(chosenFile)
MainActivity.mainWeakReference?.get()?.runOnUiThread {
it.visibility = View.INVISIBLE
}
}.start()
}.setNegativeButton(android.R.string.cancel) { _, _ -> }
.show()
}
1 -> {
val bundle = Bundle()
bundle.putBoolean("loadJson", true)
bundle.putString("name", name)
Navigate.safeNavigateTo(findNavController(), R.id.action_nav_new_download_to_nav_book, bundle)
}
}
}
.show()
true
}
}
} }
} }
}
onLoadFinish()
}
override fun setListeners() {} override fun initCardList(weakReference: WeakReference<Fragment>) {
super.initCardList(weakReference)
cardList = CardList(weakReference, cardWidth, cardHeight, cardPerRow)
cardList?.initClickListeners = object : CardList.InitClickListeners {
override fun prepareListeners(v: View, name: String, path: String?, chapterUUID: String?, pn: Int?) {
v.setOnClickListener {
if(name==oldDlCardName && path == oldDlCardName) {
Navigate.safeNavigateTo(findNavController(), R.id.action_nav_new_download_to_nav_download)
return@setOnClickListener
}
callDownloadFragment(name)
}
v.setOnLongClickListener {
if (name == oldDlCardName && path == oldDlCardName) {
return@setOnLongClickListener false
}
val chosenFile = File(extDir, name)
AlertDialog.Builder(context)
.setIcon(R.drawable.ic_launcher_foreground)
.setTitle(R.string.new_download_card_option_hint)
.setItems(arrayOf("删除", "前往")) { d, p ->
d.cancel()
when (p) {
0 -> {
AlertDialog.Builder(context)
.setIcon(R.drawable.ic_launcher_foreground).setMessage("删除下载的此漫画吗?")
.setTitle("提示").setPositiveButton(android.R.string.ok) { _, _ ->
if (chosenFile.exists()) Thread {
FileUtils.recursiveRemove(chosenFile)
MainActivity.mainWeakReference?.get()?.runOnUiThread {
it.visibility = View.INVISIBLE
}
}.start()
}.setNegativeButton(android.R.string.cancel) { _, _ -> }
.show()
}
1 -> {
val bundle = Bundle()
bundle.putBoolean("loadJson", true)
bundle.putString("name", name)
Navigate.safeNavigateTo(findNavController(), R.id.action_nav_new_download_to_nav_book, bundle)
}
}
}
.show()
true
}
}
} }
} }
@@ -122,21 +153,29 @@ class NewDownloadFragment: MangaPagesFragmentTemplate(R.layout.fragment_newdownl
Navigate.safeNavigateTo(findNavController(), R.id.action_nav_new_download_to_nav_group, bundle) Navigate.safeNavigateTo(findNavController(), R.id.action_nav_new_download_to_nav_group, bundle)
} }
private fun onLoadFinish() { fun showReverseInfo(toolsBox: UITools) {
if (exit) return
toolsBox.buildInfo("反转排序", "将按当前顺序的倒序显示下载的漫画",
"确定", null, "取消", {
isReverse = !isReverse
isContentChanged = true
reset()
Thread {
sleep(600)
addPage()
}.start()
}
)
}
override fun onLoadFinish() {
super.onLoadFinish()
MainActivity.mainWeakReference?.get()?.runOnUiThread { MainActivity.mainWeakReference?.get()?.runOnUiThread {
if(cardList?.exitCardList != false) return@runOnUiThread
mypl.visibility = View.GONE mypl.visibility = View.GONE
} }
} }
companion object { companion object {
fun sizeOf(f: File):Long{ var wn: WeakReference<NewDownloadFragment>? = null
var size = 0L
if (f.isDirectory) f.listFiles()?.apply {
for (i in this)
size += if (i.isDirectory) sizeOf(i) else i.length()
}
return size
}
} }
} }

View File

@@ -22,6 +22,7 @@ import kotlinx.android.synthetic.main.card_book_plain.view.*
import kotlinx.android.synthetic.main.fragment_home.* import kotlinx.android.synthetic.main.fragment_home.*
import kotlinx.android.synthetic.main.line_word.view.* import kotlinx.android.synthetic.main.line_word.view.*
import kotlinx.android.synthetic.main.viewpage_horizonal.view.* import kotlinx.android.synthetic.main.viewpage_horizonal.view.*
import top.fumiama.copymanga.MainActivity
import top.fumiama.copymanga.MainActivity.Companion.ime import top.fumiama.copymanga.MainActivity.Companion.ime
import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference
import top.fumiama.copymanga.json.BookListStructure import top.fumiama.copymanga.json.BookListStructure
@@ -40,10 +41,11 @@ class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
if(isFirstInflate) { if(isFirstInflate) {
val theme = resources.newTheme() val theme = resources.newTheme()
swiperefresh.setColorSchemeColors( swiperefresh?.setColorSchemeColors(
resources.getColor(R.color.colorAccent, theme), resources.getColor(R.color.colorAccent, theme),
resources.getColor(R.color.colorBlue2, theme), resources.getColor(R.color.colorBlue2, theme),
resources.getColor(R.color.colorGreen, theme)) resources.getColor(R.color.colorGreen, theme))
swiperefresh?.isEnabled = true
fhs.apply { fhs.apply {
val recyclerView = findViewById<RecyclerView>(R.id.search_recycler_view) val recyclerView = findViewById<RecyclerView>(R.id.search_recycler_view)
@@ -133,6 +135,10 @@ class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
val l = MainActivity.member?.refreshAvatar()
if (l?.code != 200) {
MainActivity.member?.logout()
}
homeHandler = HomeHandler(WeakReference(this)) homeHandler = HomeHandler(WeakReference(this))
} }

View File

@@ -50,15 +50,12 @@ class HomeHandler(private val that: WeakReference<HomeFragment>) : AutoDownloadH
} }
return field return field
} }
var indexLines = arrayOf<View>() private var indexLines = arrayOf<View>()
override fun handleMessage(msg: Message) { override fun handleMessage(msg: Message) {
super.handleMessage(msg) super.handleMessage(msg)
when (msg.what) { when (msg.what) {
-1 -> { -1 -> homeF?.swiperefresh?.isRefreshing = msg.obj as Boolean
homeF?.swiperefresh?.isEnabled = msg.obj as Boolean
homeF?.swiperefresh?.isRefreshing = msg.obj as Boolean
}
//0 -> setLayouts() //0 -> setLayouts()
1 -> inflateCardLines() 1 -> inflateCardLines()

View File

@@ -439,18 +439,18 @@ class ViewMangaActivity : TitleActivityTemplate() {
else { else {
val zip = ZipFile(zipFile) val zip = ZipFile(zipFile)
try { try {
if (q == 100) BitmapFactory.decodeStream(zip.getInputStream(zip.getEntry("${position}.jpg"))) if (q == 100) BitmapFactory.decodeStream(zip.getInputStream(zip.getEntry("${position}.webp")))
else { else {
val out = ByteArrayOutputStream() val out = ByteArrayOutputStream()
BitmapFactory.decodeStream(zip.getInputStream(zip.getEntry("${position}.jpg")))?.compress(Bitmap.CompressFormat.JPEG, q, out) BitmapFactory.decodeStream(zip.getInputStream(zip.getEntry("${position}.webp")))?.compress(Bitmap.CompressFormat.JPEG, q, out)
BitmapFactory.decodeStream(ByteArrayInputStream(out.toByteArray())) BitmapFactory.decodeStream(ByteArrayInputStream(out.toByteArray()))
} }
} catch (e: Exception) { } catch (e: Exception) {
try { try {
if (q == 100) BitmapFactory.decodeStream(zip.getInputStream(zip.getEntry("${position}.webp"))) if (q == 100) BitmapFactory.decodeStream(zip.getInputStream(zip.getEntry("${position}.jpg")))
else { else {
val out = ByteArrayOutputStream() val out = ByteArrayOutputStream()
BitmapFactory.decodeStream(zip.getInputStream(zip.getEntry("${position}.webp")))?.compress(Bitmap.CompressFormat.JPEG, q, out) BitmapFactory.decodeStream(zip.getInputStream(zip.getEntry("${position}.jpg")))?.compress(Bitmap.CompressFormat.JPEG, q, out)
BitmapFactory.decodeStream(ByteArrayInputStream(out.toByteArray())) BitmapFactory.decodeStream(ByteArrayInputStream(out.toByteArray()))
} }
} catch (e: Exception) { } catch (e: Exception) {

View File

@@ -10,8 +10,8 @@ import android.widget.Toast
import androidx.core.content.FileProvider import androidx.core.content.FileProvider
import androidx.core.content.edit import androidx.core.content.edit
import kotlinx.android.synthetic.main.dialog_progress.view.* import kotlinx.android.synthetic.main.dialog_progress.view.*
import top.fumiama.copymanga.tools.file.PropertiesTools
import top.fumiama.copymanga.tools.api.UITools import top.fumiama.copymanga.tools.api.UITools
import top.fumiama.dmzj.copymanga.BuildConfig
import top.fumiama.dmzj.copymanga.R import top.fumiama.dmzj.copymanga.R
import java.io.File import java.io.File
import java.security.MessageDigest import java.security.MessageDigest
@@ -27,7 +27,7 @@ object Update {
} }
} }
val kanban = SimpleKanban(client, "fumiama") val kanban = SimpleKanban(client, "fumiama")
val msg = kanban[packageManager.getPackageInfo(packageName, 0).versionCode] val msg = kanban[BuildConfig.VERSION_CODE]
if(msg != "null") { if(msg != "null") {
val verNum = msg.substringBefore('\n').toIntOrNull() val verNum = msg.substringBefore('\n').toIntOrNull()
val skipNum = activity.getPreferences(MODE_PRIVATE).getInt("skipVersion", 0) val skipNum = activity.getPreferences(MODE_PRIVATE).getInt("skipVersion", 0)

View File

@@ -0,0 +1,69 @@
package top.fumiama.copymanga.user
import android.content.SharedPreferences
import android.widget.Toast
import com.google.gson.Gson
import top.fumiama.copymanga.MainActivity
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
class Member(private val pref: SharedPreferences, private val getString: (Int) -> String) {
fun login(username: String, pwd: String, salt: Int): LoginInfoStructure {
try {
CMApi.getLoginConnection(username, pwd, salt)?.apply {
Gson().fromJson(inputStream.reader(), LoginInfoStructure::class.java)?.let { data ->
disconnect()
if(data.code == 200) {
pref.edit()?.apply {
putString("token", data.results?.token)
putString("user_id", data.results?.user_id)
putString("username", data.results?.username)
putString("nickname", data.results?.nickname)
apply()
return refreshAvatar()
}
}
return data
}
}
val l = LoginInfoStructure()
l.code = 400
l.message = getString(R.string.login_get_conn_failed)
return l
} catch (e: Exception) {
val l = LoginInfoStructure()
l.code = 400
l.message = e.localizedMessage
return l
}
}
fun refreshAvatar() : LoginInfoStructure {
DownloadTools.getHttpContent(getString(R.string.memberInfoApiUrl).format(
CMApi.myHostApiUrl))?.decodeToString()?.let {
val l = Gson().fromJson(it, LoginInfoStructure::class.java)
if(l.code == 200) pref.edit()?.apply {
putString("avatar", l.results.avatar)
apply()
}
return l
}
val l = LoginInfoStructure()
l.code = 400
l.message = getString(R.string.login_get_avatar_failed)
return l
}
fun logout() {
pref.edit()?.apply {
remove("token")
remove("user_id")
remove("username")
remove("nickname")
remove("avatar")
apply()
}
}
}

View File

@@ -16,6 +16,7 @@ class MangaCardView:CardView {
//var uuid: String? = null //var uuid: String? = null
var path: String? = null var path: String? = null
var isFinish = false var isFinish = false
var isNew = false
var index = 0 var index = 0
var chapterUUID: String? = null var chapterUUID: String? = null
var pageNumber: Int? = null var pageNumber: Int? = null

View File

@@ -1,6 +1,7 @@
<?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: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">
@@ -86,7 +87,21 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0" app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toEndOf="parent" app:layout_constraintStart_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<include
android:id="@+id/sgnnew"
layout="@layout/widget_newmark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/sgnic"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</top.fumiama.copymanga.views.MangaCardView> </top.fumiama.copymanga.views.MangaCardView>

View File

@@ -19,10 +19,20 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/line_sort_time" app:layout_constraintEnd_toStartOf="@+id/line_sort_region"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<include
android:id="@+id/line_sort_region"
layout="@layout/anchor_popular"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/line_sort_time"
app:layout_constraintStart_toEndOf="@+id/line_sort_class"
app:layout_constraintTop_toTopOf="parent" />
<include <include
android:id="@+id/line_sort_time" android:id="@+id/line_sort_time"
layout="@layout/anchor_popular" layout="@layout/anchor_popular"
@@ -30,7 +40,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/line_sort_hot" app:layout_constraintEnd_toStartOf="@+id/line_sort_hot"
app:layout_constraintStart_toEndOf="@+id/line_sort_class" app:layout_constraintStart_toEndOf="@+id/line_sort_region"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<include <include

View File

@@ -0,0 +1,24 @@
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0.9"
android:background="@drawable/rndbg_error">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="2dp"
android:layout_marginEnd="48dp"
android:layout_marginBottom="2dp"
android:text="更新"
android:textColor="#000000"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -42,11 +42,12 @@
<string name="mainPageApiUrl">https://%1$s/api/v3/h5/homeIndex?platform=3</string> <string name="mainPageApiUrl">https://%1$s/api/v3/h5/homeIndex?platform=3</string>
<string name="referUrl">https://%1$s</string> <string name="referUrl">https://%1$s</string>
<string name="hostUrl">&hosturl;</string> <string name="hostUrl">&hosturl;</string>
<string name="rankApiUrl">https://%1$s/api/v3/ranks?limit=21&amp;offset=%2$d&amp;date_type=%3$s&amp;platform=3</string> <string name="rankApiUrl">https://%1$s/api/v3/ranks?limit=21&amp;offset=%2$d&amp;date_type=%3$s&amp;audience_type=%4$s&amp;platform=3</string>
<string name="searchApiUrl">https://%1$s/api/v3/search/comic?limit=21&amp;offset=%2$d&amp;q=%3$s&amp;q_type=%4$s&amp;platform=3</string> <string name="searchApiUrl">https://%1$s/api/v3/search/comic?limit=21&amp;offset=%2$d&amp;q=%3$s&amp;q_type=%4$s&amp;platform=3</string>
<string name="filterApiUrl">https://%1$s/api/v3/h5/filterIndex/comic/tags?platform=3</string> <string name="filterApiUrl">https://%1$s/api/v3/h5/filter/comic/tags?platform=3</string>
<string name="sortApiUrl">https://%1$s/api/v3/comics?limit=21&amp;offset=%2$d&amp;ordering=%3$s&amp;theme=%4$s&amp;platform=3</string> <string name="sortApiUrl">https://%1$s/api/v3/comics?limit=21&amp;offset=%2$d&amp;ordering=%3$s&amp;theme=%4$s&amp;top=%5$s&amp;platform=3</string>
<string name="bookInfoApiUrl">https://%1$s/api/v3/comic2/%2$s?platform=3</string> <string name="bookInfoApiUrl">https://%1$s/api/v3/comic2/%2$s?platform=3</string>
<string name="bookUserQueryApiUrl">https://%1$s/api/v3/comic2/%2$s/query?platform=3</string>
<string name="groupInfoApiUrl">https://%1$s/api/v3/comic/%2$s/group/%3$s/chapters?limit=100&amp;offset=%4$d&amp;platform=3</string> <string name="groupInfoApiUrl">https://%1$s/api/v3/comic/%2$s/group/%3$s/chapters?limit=100&amp;offset=%4$d&amp;platform=3</string>
<string name="chapterInfoApiUrl">https://%1$s/api/v3/comic/%2$s/chapter2/%3$s?platform=3</string> <string name="chapterInfoApiUrl">https://%1$s/api/v3/comic/%2$s/chapter2/%3$s?platform=3</string>
<string name="topicApiUrl">https://%1$s/api/v3/topic/%2$s?platform=3</string> <string name="topicApiUrl">https://%1$s/api/v3/topic/%2$s?platform=3</string>
@@ -78,6 +79,7 @@
<string name="TRANSPORT_ETHERNET">以太网</string> <string name="TRANSPORT_ETHERNET">以太网</string>
<string name="TRANSPORT_LOWPAN">LOWPAN</string> <string name="TRANSPORT_LOWPAN">LOWPAN</string>
<string name="TRANSPORT_NULL">无网络</string> <string name="TRANSPORT_NULL">无网络</string>
<string name="TRANSPORT_ERROR">网络错误</string>
<string name="pc_ua">COPY/2.0.7</string> <string name="pc_ua">COPY/2.0.7</string>
<string name="app_ver">2.0.7</string> <string name="app_ver">2.0.7</string>
@@ -89,10 +91,12 @@
<string name="menu_read_time">阅读时间</string> <string name="menu_read_time">阅读时间</string>
<string name="button_sub">加入书架</string> <string name="button_sub">加入书架</string>
<string name="button_sub_subscribed">已加书架</string>
<string name="button_start">开始阅读</string> <string name="button_start">开始阅读</string>
<string name="text_format_hit">热度 %1$d</string> <string name="text_format_hit">热度 %1$d</string>
<string name="text_format_stat">状态 %1$s</string> <string name="text_format_stat">状态 %1$s</string>
<string name="text_format_cloud_read_to">云端读到 %1$s</string>
<string name="topics_series">专题系列</string> <string name="topics_series">专题系列</string>
<string name="manga_rec">漫画推荐</string> <string name="manga_rec">漫画推荐</string>
@@ -135,7 +139,8 @@
<string name="login_null_username">用户名为空</string> <string name="login_null_username">用户名为空</string>
<string name="login_null_pwd">密码为空</string> <string name="login_null_pwd">密码为空</string>
<string name="login_get_conn_failed">连接失败</string> <string name="login_get_conn_failed">登录失败</string>
<string name="login_get_avatar_failed">刷新头像失败</string>
<string name="login_restart_to_apply">重启应用以彻底退出登录</string> <string name="login_restart_to_apply">重启应用以彻底退出登录</string>
<string name="old_download_card_name">前往旧版下载</string> <string name="old_download_card_name">前往旧版下载</string>