mirror of
https://github.com/fumiama/copymanga.git
synced 2026-06-05 07:20:23 +08:00
v2.0.2
新增 1. 搜索可以加载更多 修复 1. 服务器错误数据导致的闪退(#34) 2. 保存封面超时导致的闪退(870551a6) 优化 1. 更新 targetSdkVersion 到 34(870551a6) 2. 搜索支持嵌套滚动 3. 底部按导航栏高度垫高 4. 升级 Gson 库
This commit is contained in:
@@ -8,8 +8,8 @@ android {
|
||||
applicationId 'top.fumiama.copymanga'
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 34
|
||||
versionCode 37
|
||||
versionName '2.0.1'
|
||||
versionCode 38
|
||||
versionName '2.0.2'
|
||||
resConfigs 'zh', 'zh-rCN'
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
@@ -69,7 +69,7 @@ dependencies {
|
||||
implementation 'com.to.aboomy:pager2banner:1.0.1'
|
||||
implementation 'com.github.bumptech.glide:glide:4.14.2'
|
||||
annotationProcessor 'com.github.bumptech.glide:compiler:4.14.2'
|
||||
implementation 'com.google.code.gson:gson:2.9.1'
|
||||
implementation 'com.google.code.gson:gson:2.10.1'
|
||||
implementation 'com.github.vovaksenov99:OverscrollableScrollView:1.0'
|
||||
implementation 'com.liaoinstan.springview:library:1.7.0'
|
||||
implementation 'com.github.zawadz88.materialpopupmenu:material-popup-menu:4.0.1'
|
||||
|
||||
@@ -91,6 +91,8 @@ open class MangaPagesFragmentTemplate(inflateRes:Int, val isLazy: Boolean = true
|
||||
Log.d("MyMPAT", "Card per row: $cardPerRow")
|
||||
Log.d("MyMPAT", "Card width: $cardWidth")
|
||||
|
||||
mydll?.setPadding(0, 0, 0, navBarHeight)
|
||||
|
||||
initCardList(WeakReference(this))
|
||||
managePage()
|
||||
setListeners()
|
||||
|
||||
@@ -6,11 +6,13 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import top.fumiama.copymanga.tools.ui.UITools
|
||||
|
||||
open class NoBackRefreshFragment(private val layoutToLoad: Int): Fragment() {
|
||||
private var _rootView: View? = null
|
||||
val rootView: View get() = _rootView!!
|
||||
var isFirstInflate = true
|
||||
var navBarHeight = 0
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
@@ -24,6 +26,7 @@ open class NoBackRefreshFragment(private val layoutToLoad: Int): Fragment() {
|
||||
isFirstInflate = false
|
||||
Log.d("MyNBRF", "not first inflate")
|
||||
}
|
||||
navBarHeight = context?.let { UITools.getNavigationBarHeight(it) } ?: 0
|
||||
return rootView
|
||||
}
|
||||
override fun onDestroy() {
|
||||
|
||||
@@ -113,14 +113,25 @@ class UITools(that: Context?, w: WeakReference<Activity>? = null) {
|
||||
val totalWidth = ((zis?.resources?.displayMetrics?.widthPixels?:1080)-marginPx)/numPerRow
|
||||
return listOf(numPerRow, w, totalWidth)
|
||||
}
|
||||
fun toHexStr(byteArray: ByteArray) =
|
||||
with(StringBuilder()) {
|
||||
byteArray.forEach {
|
||||
val hex = it.toInt() and (0xFF)
|
||||
val hexStr = Integer.toHexString(hex)
|
||||
if (hexStr.length == 1) append("0").append(hexStr)
|
||||
else append(hexStr)
|
||||
companion object {
|
||||
fun toHexStr(byteArray: ByteArray) =
|
||||
with(StringBuilder()) {
|
||||
byteArray.forEach {
|
||||
val hex = it.toInt() and (0xFF)
|
||||
val hexStr = Integer.toHexString(hex)
|
||||
if (hexStr.length == 1) append("0").append(hexStr)
|
||||
else append(hexStr)
|
||||
}
|
||||
toString()
|
||||
}
|
||||
fun getNavigationBarHeight(context: Context): Int {
|
||||
val resources = context.resources
|
||||
val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
|
||||
return if (resourceId > 0) {
|
||||
resources.getDimensionPixelSize(resourceId)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.google.gson.Gson
|
||||
import kotlinx.android.synthetic.main.fragment_book.*
|
||||
import kotlinx.android.synthetic.main.line_bookinfo_text.*
|
||||
import kotlinx.android.synthetic.main.line_booktandb.*
|
||||
import top.fumiama.copymanga.MainActivity
|
||||
@@ -30,6 +31,7 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
ComicDlFragment.exit = false
|
||||
fbl?.setPadding(0, 0, 0, navBarHeight)
|
||||
|
||||
if(isFirstInflate) {
|
||||
var path = ""
|
||||
|
||||
@@ -385,19 +385,24 @@ class BookHandler(private val th: WeakReference<BookFragment>, val path: String)
|
||||
File(mangaFolder, "grps.json").writeText(Gson().toJson(keys))
|
||||
that?.apply {
|
||||
Thread {
|
||||
sleep(1000)
|
||||
if (exit) return@Thread
|
||||
File(mangaFolder, "head.jpg").let { head ->
|
||||
val fo = head.outputStream()
|
||||
try {
|
||||
imic.drawable.toBitmap().compress(Bitmap.CompressFormat.JPEG, 90, fo)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
that?.activity?.runOnUiThread {
|
||||
Toast.makeText(that?.context, R.string.download_cover_timeout, Toast.LENGTH_SHORT).show()
|
||||
var cnt = 0
|
||||
var success = false
|
||||
while (cnt++ < 10 && !success) {
|
||||
sleep(1000)
|
||||
if (exit) return@Thread
|
||||
File(mangaFolder, "head.jpg").let { head ->
|
||||
val fo = head.outputStream()
|
||||
try {
|
||||
imic.drawable.toBitmap().compress(Bitmap.CompressFormat.JPEG, 90, fo)
|
||||
success = true
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
fo.close()
|
||||
}
|
||||
fo.close()
|
||||
}
|
||||
if (!success) that?.activity?.runOnUiThread {
|
||||
Toast.makeText(that?.context, R.string.download_cover_timeout, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package top.fumiama.copymanga.ui.cardflow.search
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import top.fumiama.copymanga.template.ui.InfoCardLoader
|
||||
import top.fumiama.copymanga.tools.api.CMApi
|
||||
import top.fumiama.dmzj.copymanga.R
|
||||
|
||||
@ExperimentalStdlibApi
|
||||
class SearchFragment : InfoCardLoader(R.layout.fragment_search, R.id.action_nav_search_to_nav_book) {
|
||||
private var query: String? = null
|
||||
private var type: String? = null
|
||||
override fun getApiUrl() =
|
||||
getString(R.string.searchApiUrl).format(CMApi.myHostApiUrl, page * 21, query, type)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
if (isFirstInflate) {
|
||||
query = arguments?.getCharSequence("query")?.toString()
|
||||
type = arguments?.getString("type")
|
||||
Log.d("MySF", "get query=$query, type=$type")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import android.os.Looper
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import com.google.gson.Gson
|
||||
import kotlinx.android.synthetic.main.fragment_dlcomic.*
|
||||
import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference
|
||||
import top.fumiama.copymanga.json.ChapterStructure
|
||||
import top.fumiama.copymanga.json.VolumeStructure
|
||||
@@ -22,6 +23,7 @@ class ComicDlFragment: NoBackRefreshFragment(R.layout.fragment_dlcomic) {
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
exit = false
|
||||
ldwn?.setPadding(0, 0, 0, navBarHeight)
|
||||
if(isFirstInflate){
|
||||
when {
|
||||
arguments?.getBoolean("callFromOldDL", false) == true -> initOldComicData()
|
||||
|
||||
@@ -38,7 +38,8 @@ class DownloadFragment: NoBackRefreshFragment(R.layout.fragment_download) {
|
||||
if(o1.endsWith(".zip") && o2.endsWith(".zip")) (10000*getFloat(o1) - 10000*getFloat(o2) + 0.5).toInt()
|
||||
else o1[0] - o2[0]
|
||||
}?.let {
|
||||
mylv.apply {
|
||||
mylv?.apply {
|
||||
setPadding(0, 0, 0, navBarHeight)
|
||||
context.let { c ->
|
||||
adapter = ArrayAdapter(c, android.R.layout.simple_list_item_1, it)
|
||||
setOnItemClickListener { _, _, position, _ ->
|
||||
|
||||
@@ -30,6 +30,7 @@ import top.fumiama.copymanga.template.general.NoBackRefreshFragment
|
||||
import top.fumiama.copymanga.template.http.AutoDownloadThread
|
||||
import top.fumiama.copymanga.tools.api.CMApi
|
||||
import top.fumiama.copymanga.tools.ui.Navigate
|
||||
import top.fumiama.copymanga.tools.ui.UITools
|
||||
import top.fumiama.dmzj.copymanga.R
|
||||
import java.lang.Thread.sleep
|
||||
import java.lang.ref.WeakReference
|
||||
@@ -37,6 +38,7 @@ import java.lang.ref.WeakReference
|
||||
class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) {
|
||||
lateinit var homeHandler: HomeHandler
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
if(isFirstInflate) {
|
||||
@@ -47,8 +49,13 @@ class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) {
|
||||
resources.getColor(R.color.colorGreen, theme))
|
||||
swiperefresh?.isEnabled = true
|
||||
|
||||
fhs.apply {
|
||||
fhl?.setPadding(0, 0, 0, navBarHeight)
|
||||
|
||||
fhs?.apply {
|
||||
isNestedScrollingEnabled = true
|
||||
val recyclerView = findViewById<RecyclerView>(R.id.search_recycler_view)
|
||||
recyclerView.isNestedScrollingEnabled = true
|
||||
recyclerView.setPadding(0, 0, 0, navBarHeight)
|
||||
setAdapterLayoutManager(LinearLayoutManager(context))
|
||||
val adapter = ListViewHolder(recyclerView).RecyclerViewAdapter()
|
||||
setAdapter(adapter)
|
||||
@@ -182,7 +189,9 @@ class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) {
|
||||
inner class RecyclerViewAdapter :
|
||||
RecyclerView.Adapter<ListViewHolder>() {
|
||||
private var results: BookListStructure? = null
|
||||
var type = ""
|
||||
var type = ""
|
||||
private var query: CharSequence? = null
|
||||
private var count = 0
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder {
|
||||
return ListViewHolder(
|
||||
LayoutInflater.from(parent.context)
|
||||
@@ -193,7 +202,21 @@ class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) {
|
||||
@SuppressLint("ClickableViewAccessibility", "SetTextI18n")
|
||||
override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
|
||||
Log.d("MyMain", "Bind open at $position")
|
||||
if (position == itemCount-1) {
|
||||
holder.itemView.tn.setText(R.string.button_more)
|
||||
holder.itemView.ta.text = "搜索 \"$query\""
|
||||
holder.itemView.tb.text = "共 $count 条结果"
|
||||
holder.itemView.lwi.visibility = View.INVISIBLE
|
||||
if (query?.isNotEmpty() == true) holder.itemView.lwc.setOnClickListener {
|
||||
val bundle = Bundle()
|
||||
bundle.putCharSequence("query", query)
|
||||
bundle.putString("type", type)
|
||||
Navigate.safeNavigateTo(findNavController(), R.id.action_nav_home_to_nav_search, bundle)
|
||||
}
|
||||
return
|
||||
}
|
||||
results?.results?.list?.get(position)?.apply {
|
||||
holder.itemView.lwi.visibility = View.VISIBLE
|
||||
holder.itemView.tn.text = name
|
||||
holder.itemView.ta.text = author.let {
|
||||
var t = ""
|
||||
@@ -215,12 +238,14 @@ class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) {
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount() = results?.results?.list?.size?:0
|
||||
override fun getItemCount() = (results?.results?.list?.size?:0)+1
|
||||
|
||||
fun refresh(query: CharSequence) {
|
||||
fun refresh(q: CharSequence) {
|
||||
query = q
|
||||
mainWeakReference?.get()?.apply {
|
||||
AutoDownloadThread(getString(R.string.searchApiUrl).format(CMApi.myHostApiUrl, 0, query, type)) {
|
||||
results = Gson().fromJson(it?.decodeToString(), BookListStructure::class.java)
|
||||
count = results?.results?.total?:0
|
||||
runOnUiThread { notifyDataSetChanged() }
|
||||
}.start()
|
||||
}
|
||||
|
||||
@@ -4,12 +4,14 @@ import android.animation.ObjectAnimator
|
||||
import android.graphics.Rect
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.Window
|
||||
import androidx.annotation.Keep
|
||||
import androidx.preference.EditTextPreference
|
||||
import androidx.preference.EditTextPreferenceDialogFragmentCompat
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import top.fumiama.copymanga.tools.ui.UITools
|
||||
import top.fumiama.dmzj.copymanga.R
|
||||
import java.lang.Thread.sleep
|
||||
|
||||
@@ -18,6 +20,13 @@ class SettingsFragment: PreferenceFragmentCompat() {
|
||||
setPreferencesFromResource(R.xml.pref_setting, rootKey)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
context?.let { c ->
|
||||
view.setPadding(0, 0, 0, UITools.getNavigationBarHeight(c))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDisplayPreferenceDialog(preference: Preference) {
|
||||
if (preference is EditTextPreference) {
|
||||
Log.d("MySF", "preference is EditTextPreference")
|
||||
@@ -41,7 +50,7 @@ class SettingsFragment: PreferenceFragmentCompat() {
|
||||
Log.d("MySF", "diff: $diff")
|
||||
}
|
||||
Log.d("MySF", "diff out while: $diff")
|
||||
if (diff == 0) return@Thread
|
||||
if (diff <= 0) return@Thread
|
||||
Log.d("MySF", "f.dialog is ${f.dialog}")
|
||||
f.activity?.runOnUiThread {
|
||||
f.dialog?.window?.apply {
|
||||
|
||||
@@ -47,7 +47,7 @@ object Update {
|
||||
}
|
||||
}) {
|
||||
val md5 = msg.substringAfterLast("md5:")
|
||||
if (md5 == toolsBox.toHexStr(
|
||||
if (md5 == UITools.toHexStr(
|
||||
MessageDigest.getInstance("MD5").digest(it)
|
||||
)
|
||||
) {
|
||||
|
||||
@@ -13,8 +13,7 @@
|
||||
android:id="@+id/fbl"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/global_content_padding_bottom"/>
|
||||
android:orientation="vertical"/>
|
||||
</top.fumiama.copymanga.views.OverScrollView>
|
||||
|
||||
<ProgressBar
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
android:id="@+id/ldwn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/global_content_padding_bottom"/>
|
||||
android:orientation="vertical"/>
|
||||
</top.fumiama.copymanga.views.LazyScrollView>
|
||||
|
||||
<include
|
||||
|
||||
@@ -3,5 +3,4 @@
|
||||
android:id="@+id/mylv"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:nestedScrollingEnabled="true"
|
||||
android:paddingBottom="@dimen/global_content_padding_bottom"/>
|
||||
android:nestedScrollingEnabled="true"/>
|
||||
|
||||
@@ -28,8 +28,7 @@
|
||||
android:id="@+id/fhl"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/global_content_padding_bottom">
|
||||
android:orientation="vertical">
|
||||
|
||||
</LinearLayout>
|
||||
</top.fumiama.copymanga.views.ScrollRefreshView>
|
||||
|
||||
10
app/src/main/res/layout/fragment_search.xml
Normal file
10
app/src/main/res/layout/fragment_search.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<include
|
||||
layout="@layout/line_lazybooklines"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -25,8 +25,7 @@
|
||||
android:id="@+id/mydll"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/global_content_padding_bottom"/>
|
||||
android:orientation="vertical"/>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
</com.liaoinstan.springview.widget.SpringView>
|
||||
|
||||
@@ -45,6 +45,13 @@
|
||||
app:exitAnim="@anim/slide_out_left"
|
||||
app:popEnterAnim="@anim/slide_out_left_exit"
|
||||
app:popExitAnim="@anim/slide_in_right_exit"/>
|
||||
<action
|
||||
android:id="@+id/action_nav_home_to_nav_search"
|
||||
app:destination="@id/nav_search"
|
||||
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
|
||||
@@ -217,7 +224,7 @@
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_newest"
|
||||
android:name="top.fumiama.copymanga.ui.cardflow.newest.NewestFragment"
|
||||
android:name="top.fumiama.copymanga.ui.cardflow.search.SearchFragment"
|
||||
android:label="@string/new_list"
|
||||
tools:layout="@layout/fragment_newest" >
|
||||
<action
|
||||
@@ -284,4 +291,18 @@
|
||||
app:popEnterAnim="@anim/slide_out_left_exit"
|
||||
app:popExitAnim="@anim/slide_in_right_exit"/>
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_search"
|
||||
android:name="top.fumiama.copymanga.ui.cardflow.search.SearchFragment"
|
||||
android:label="@string/page_search"
|
||||
tools:layout="@layout/fragment_search" >
|
||||
<action
|
||||
android:id="@+id/action_nav_search_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>
|
||||
</navigation>
|
||||
@@ -21,6 +21,7 @@
|
||||
<string name="page_chapter">章节内容</string>
|
||||
<string name="page_group">漫画下载</string>
|
||||
<string name="page_topic">专题系列</string>
|
||||
<string name="page_search">漫画搜索</string>
|
||||
<string name="check_update">检查更新</string>
|
||||
<string name="set_search_types">设置搜索类别</string>
|
||||
|
||||
@@ -37,6 +38,7 @@
|
||||
<string name="text_null">N/A</string>
|
||||
<string name="null_book">获取图书信息失败</string>
|
||||
<string name="web_error">网络错误</string>
|
||||
<string name="download_cover_failed">保存封面失败</string>
|
||||
<string name="download_cover_timeout">保存封面超时</string>
|
||||
|
||||
<string name="mainPageApiUrl">https://%1$s/api/v3/h5/homeIndex?platform=3</string>
|
||||
@@ -93,6 +95,7 @@
|
||||
<string name="button_sub">加入书架</string>
|
||||
<string name="button_sub_subscribed">已加书架</string>
|
||||
<string name="button_start">开始阅读</string>
|
||||
<string name="button_more">更多</string>
|
||||
|
||||
<string name="text_format_hit">热度 %1$d</string>
|
||||
<string name="text_format_stat">状态 %1$s</string>
|
||||
|
||||
Reference in New Issue
Block a user