1
0
mirror of https://github.com/fumiama/copymanga.git synced 2026-06-05 07:20:23 +08:00
新增
1. shelf, history 未登录提示 (fix #57)
2. 我的下载以KB显示小于1MB漫画
修复
1. 加入书架后立即取消则失败
2. 浅色模式下打开深色阅读背景闪退
3. 主页多次下拉刷新可能闪退
4. 搜索返回后按钮重叠
优化
1. 详情页加载可能的动画卡顿(我的下载)
2. 我的下载只在最前显示前往旧版
3. CardList加载流程
4. 主页加载流程
This commit is contained in:
源文雨
2024-03-15 01:11:32 +09:00
parent 4465759164
commit f0e7802eb2
17 changed files with 327 additions and 299 deletions

View File

@@ -3,20 +3,7 @@
<component name="deploymentTargetDropDown">
<value>
<entry key="app">
<State>
<targetSelectedWithDropDown>
<Target>
<type value="QUICK_BOOT_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="$USER_HOME$/.android/avd/Pixel_3a_API_33_arm64-v8a.avd" />
</Key>
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2024-03-08T06:58:21.703472Z" />
</State>
<State />
</entry>
</value>
</component>

View File

@@ -8,8 +8,8 @@ android {
applicationId 'top.fumiama.copymanga'
minSdkVersion 23
targetSdkVersion 34
versionCode 52
versionName '2.2.4'
versionCode 53
versionName '2.2.5'
resourceConfigurations += ['zh', 'zh-rCN']
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

View File

@@ -127,7 +127,6 @@ class MainActivity : AppCompatActivity() {
isDrawerClosed = false
lifecycleScope.launch {
withContext(Dispatchers.IO) {
DownloadFragment.currentDir = getExternalFilesDir("")
refreshUserInfo()
}
}

View File

@@ -5,6 +5,7 @@ import android.net.Uri
import android.util.Log
import android.view.View
import androidx.fragment.app.Fragment
import com.airbnb.lottie.LottieAnimationView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.model.GlideUrl
import kotlinx.android.synthetic.main.card_book.view.*
@@ -26,89 +27,103 @@ class CardList(
private val cardPerRow: Int
) {
private val that get() = fragment.get()
private var rows:Array<View?> = arrayOfNulls(20)
private var index = 0
private var count = 0
private var mRows: Array<View?> = arrayOfNulls(20)
private var mIndex = 0
private var mCount = 0
private var cardLoadingWaits = AtomicInteger()
var initClickListeners: InitClickListeners? = null
var exitCardList = false
fun reset() {
rows = arrayOfNulls(20)
index = 0
count = 0
mRows = arrayOfNulls(20)
mIndex = 0
mCount = 0
cardLoadingWaits.set(0)
exitCardList = false
}
private suspend fun manageRow() {
if(!exitCardList && count++ % cardPerRow == 0) inflateRow()
Log.d("MyCL", "index: $index, cardPR: $cardPerRow")
private suspend fun manageRow(whenFinish: suspend (index: Int) -> Unit) = withContext(Dispatchers.IO) {
if (exitCardList) return@withContext
if(mCount++ % cardPerRow == 0) {
inflateRow(++mIndex-1, whenFinish)
} else whenFinish(mIndex-1)
}
private suspend fun inflateRow() = withContext(Dispatchers.IO) {
private suspend fun inflateRow(index: Int, whenFinish: suspend (index: Int)->Unit) = withContext(Dispatchers.IO) {
Log.d("MyCL", "inflateRow: $index, cardPR: $cardPerRow")
that?.apply {
layoutInflater.inflate(R.layout.line_horizonal_empty, mydll, false)?.let {
if(exitCardList) return@withContext
it.layoutParams.height = cardHeight + 16
withContext(Dispatchers.Main) withMainContext@ {
if(exitCardList) return@withMainContext
mydll?.addView(it)
}
recycleOneRow(it)
index++
mydll?.apply { post { addView(it) } }
recycleOneRow(it, index)
whenFinish(index)
}
}
}
private suspend fun recycleOneRow(v:View?) = withContext(Dispatchers.IO) {
val relativeIndex = index % 20
if(rows[relativeIndex] == null) rows[relativeIndex] = v
private suspend fun recycleOneRow(v:View?, i: Int) = withContext(Dispatchers.IO) {
val relativeIndex = i % 20
if(mRows[relativeIndex] == null) mRows[relativeIndex] = v
else {
val victim = rows[relativeIndex]
val victim = mRows[relativeIndex]
that?.apply {
withContext(Dispatchers.Main) withMainContext@ {
if(exitCardList) return@withMainContext
mydll?.removeView(victim)
mys?.scrollY = mys?.scrollY?.minus(cardHeight + 16)?:0
}
if(exitCardList) return@withContext
mydll?.apply { post { removeView(victim) } }
mys?.apply { post { scrollY -= cardHeight + 16 } }
}
mRows[relativeIndex] = v
}
}
private fun postPauseLottie(v: LottieAnimationView) {
v.apply {
post {
pauseAnimation()
visibility = View.GONE
}
rows[relativeIndex] = v
}
}
@ExperimentalStdlibApi
suspend 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) =
withContext(Dispatchers.IO) {
if (exitCardList) return@withContext
manageRow()
that?.apply {
layoutInflater.inflate(R.layout.card_book, mydll?.ltbtn, false)?.let {
val card = it.cic
card.name = name
card.append = append
card.headImageUrl = head
card.path = path
card.index = index - 1
card.chapterUUID = chapterUUID
card.pageNumber = pn
card.isFinish = isFinish
card.isNew = isNew
addCard(it)
suspend 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
manageRow { i ->
withContext(Dispatchers.IO) {
that?.apply {
layoutInflater.inflate(R.layout.card_book, mydll?.ltbtn, false)?.let {
val card = it.cic
card.name = name
card.append = append
card.headImageUrl = head
card.path = path
card.index = i
card.chapterUUID = chapterUUID
card.pageNumber = pn
card.isFinish = isFinish
card.isNew = isNew
addCard(it)
}
}
}
}
}
@SuppressLint("SetTextI18n")
@ExperimentalStdlibApi
private suspend fun addCard(cardFrame: View) = withContext(Dispatchers.IO) withIO@ {
private suspend fun addCard(cardFrame: View) = withContext(Dispatchers.IO) {
val card = cardFrame.cic
if (card.index < 0) return@withIO
val name = card.name + (card.append?:"")
if (card.index < 0) throw Exception("minus card index")
Log.d("MyCL", "addCard: into index ${card.index}")
val appendedName = card.name + (card.append?:"")
val head = card.headImageUrl
val file = File(that?.context?.getExternalFilesDir(""), card.name)
if(exitCardList) return@withIO
if(exitCardList) return@withContext
cardFrame.let {
it.tic.apply { post { text = name } }
it.tic.apply { post { text = appendedName } }
if(!file.exists()) {
if(head != null) {
that?.context?.let { context ->
@@ -125,22 +140,12 @@ class CardList(
}, waitMillis) else it.imic.post { g.into(it.imic) }
}
} else {
it.laic.apply {
post {
pauseAnimation()
visibility = View.GONE
}
}
postPauseLottie(it.laic)
it.imic.apply { post { setImageResource(R.drawable.img_defmask) } }
}
} else {
val img = File(file, "head.jpg")
it.laic.apply {
post {
pauseAnimation()
visibility = View.GONE
}
}
postPauseLottie(it.laic)
if(img.exists()) {
it.imic.apply {
post {
@@ -149,13 +154,19 @@ class CardList(
}
} else it.imic.apply { post { setImageResource(R.drawable.img_defmask) } }
}
withContext(Dispatchers.Main) {
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)
rows[card.index % 20]?.ltbtn?.addView(it)
it.layoutParams?.height = cardHeight
it.layoutParams?.width = cardWidth
card.apply {
if(isFinish) it.sgnic.visibility = View.VISIBLE
if(isNew) it.sgnnew.visibility = View.VISIBLE
initClickListeners?.prepareListeners(this, name, path, chapterUUID, pageNumber)
mRows[index % 20]?.ltbtn?.apply {
withContext(Dispatchers.Main) {
if(!exitCardList) {
addView(it)
it.layoutParams?.height = cardHeight
it.layoutParams?.width = cardWidth
}
}
}
}
}
}

View File

@@ -12,7 +12,10 @@ import kotlinx.android.synthetic.main.app_bar_main.*
import kotlinx.android.synthetic.main.card_book.*
import kotlinx.android.synthetic.main.fragment_book.*
import kotlinx.android.synthetic.main.line_booktandb.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import top.fumiama.copymanga.MainActivity
import top.fumiama.copymanga.manga.Book
import top.fumiama.copymanga.manga.Reader
@@ -36,34 +39,8 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) {
fbvp?.setPadding(0, 0, 0, navBarHeight)
if(isFirstInflate) {
arguments?.apply {
if (getBoolean("loadJson")) {
getString("name")?.let { name ->
try {
book = Book(name, {
return@Book getString(it)
}, activity?.getExternalFilesDir("")!!)
} catch (e: Exception) {
e.printStackTrace()
Toast.makeText(context, R.string.null_book, Toast.LENGTH_SHORT).show()
findNavController().popBackStack()
return
}
}
} else getString("path").let {
if (it != null) book = Book(it, { id ->
return@Book getString(id)
}, activity?.getExternalFilesDir("")!!, false)
else {
findNavController().popBackStack()
return
}
}
}
mBookHandler = BookHandler(WeakReference(this))
bookHandler.set(mBookHandler)
lifecycleScope.launch {
prepareHandler()
try {
book?.updateInfo()
} catch (e: Exception) {
@@ -75,10 +52,11 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) {
}
Log.d("MyBF", "read path: ${book?.path}")
for (i in 1..3) {
mBookHandler?.sendEmptyMessage(i)
mBookHandler?.sendEmptyMessageDelayed(i, (i*100).toLong())
}
try {
book?.updateVolumes {
delay(300)
mBookHandler?.sendEmptyMessage(10)
}
} catch (e: Exception) {
@@ -137,6 +115,41 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) {
}
}
private suspend fun prepareHandler() = withContext(Dispatchers.IO) {
arguments?.apply {
if (getBoolean("loadJson")) {
getString("name")?.let { name ->
try {
book = Book(name, {
return@Book getString(it)
}, activity?.getExternalFilesDir("")!!)
} catch (e: Exception) {
e.printStackTrace()
withContext(Dispatchers.Main) {
Toast.makeText(context, R.string.null_book, Toast.LENGTH_SHORT).show()
findNavController().popBackStack()
}
return@withContext
}
}
} else getString("path").let {
if (it != null) book = Book(it, { id ->
return@Book getString(id)
}, activity?.getExternalFilesDir("")!!, false)
else {
withContext(Dispatchers.Main) {
findNavController().popBackStack()
}
return@withContext
}
}
}
withContext(Dispatchers.Main) {
mBookHandler = BookHandler(WeakReference(this@BookFragment))
bookHandler.set(mBookHandler)
}
}
private suspend fun queryCollect() {
MainActivity.shelf?.query(book?.path!!)?.let { b ->
mBookHandler?.collect = b.results?.collect?:-2

View File

@@ -1,9 +1,8 @@
package top.fumiama.copymanga.ui.cardflow.history
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.navigation.fragment.findNavController
import kotlinx.android.synthetic.main.line_lazybooklines.*
import top.fumiama.copymanga.MainActivity
import top.fumiama.copymanga.template.ui.InfoCardLoader
import top.fumiama.copymanga.tools.api.CMApi
@@ -15,7 +14,10 @@ class HistoryFragment : InfoCardLoader(R.layout.fragment_history, R.id.action_na
getString(R.string.historyApiUrl).format(CMApi.myHostApiUrl, page * 21)
override fun onCreate(savedInstanceState: Bundle?) {
if (MainActivity.member?.hasLogin != true) findNavController().popBackStack()
if (MainActivity.member?.hasLogin != true) {
Toast.makeText(context, R.string.noLogin, Toast.LENGTH_SHORT).show()
findNavController().popBackStack()
}
super.onCreate(savedInstanceState)
}
}

View File

@@ -3,11 +3,10 @@ package top.fumiama.copymanga.ui.cardflow.shelf
import android.animation.ObjectAnimator
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.navigation.fragment.findNavController
import kotlinx.android.synthetic.main.anchor_popular.view.*
import kotlinx.android.synthetic.main.line_shelf.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import top.fumiama.copymanga.MainActivity
import top.fumiama.copymanga.template.ui.InfoCardLoader
import top.fumiama.copymanga.tools.api.CMApi
@@ -33,7 +32,10 @@ class ShelfFragment : InfoCardLoader(R.layout.fragment_shelf, R.id.action_nav_su
)
override fun onCreate(savedInstanceState: Bundle?) {
if (MainActivity.member?.hasLogin != true) findNavController().popBackStack()
if (MainActivity.member?.hasLogin != true) {
Toast.makeText(context, R.string.noLogin, Toast.LENGTH_SHORT).show()
findNavController().popBackStack()
}
super.onCreate(savedInstanceState)
}

View File

@@ -41,6 +41,7 @@ class SortFragment : StatusCardFlow(0, R.id.action_nav_sort_to_nav_book, R.layou
override fun setListeners() {
super.setListeners()
lifecycleScope.launch {
setProgress(5)
PausableDownloader(getString(R.string.filterApiUrl).format(CMApi.myHostApiUrl)) {
if(ad?.exit == true) return@PausableDownloader
it.let {
@@ -57,11 +58,13 @@ class SortFragment : StatusCardFlow(0, R.id.action_nav_sort_to_nav_book, R.layou
}
private fun setClasses() {
setProgress(10)
filter?.results?.top?.let { items ->
setMenu(items, line_sort_region) {
region = it
}
}
setProgress(15)
filter?.results?.theme?.let { items ->
setMenu(items, line_sort_class) {
theme = it

View File

@@ -23,7 +23,9 @@ class TopicFragment : InfoCardLoader(R.layout.fragment_topic, R.id.action_nav_to
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch {
setProgress(5)
PausableDownloader(getString(R.string.topicApiUrl).format(CMApi.myHostApiUrl, arguments?.getString("path"))) { data ->
setProgress(10)
withContext(Dispatchers.IO) {
if(ad?.exit == true) return@withContext
data.inputStream().use { i ->
@@ -31,6 +33,7 @@ class TopicFragment : InfoCardLoader(R.layout.fragment_topic, R.id.action_nav_to
Gson().fromJson(r, TopicStructure::class.java)?.apply {
if(ad?.exit == true) return@withContext
withContext(Dispatchers.Main) withMain@ {
setProgress(15)
if(ad?.exit == true) return@withMain
activity?.toolbar?.title = results.title
ftttime.text = results.datetime_created

View File

@@ -7,14 +7,17 @@ import android.util.Log
import android.view.View
import android.widget.ArrayAdapter
import android.widget.Toast
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import kotlinx.android.synthetic.main.app_bar_main.*
import kotlinx.android.synthetic.main.fragment_download.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference
import top.fumiama.copymanga.template.general.NoBackRefreshFragment
import top.fumiama.copymanga.tools.file.FileUtils
import top.fumiama.copymanga.tools.ui.Navigate
import top.fumiama.copymanga.ui.comicdl.ComicDlFragment
import top.fumiama.copymanga.ui.vm.ViewMangaActivity
import top.fumiama.dmzj.copymanga.R
import java.io.File
@@ -27,21 +30,27 @@ class DownloadFragment: NoBackRefreshFragment(R.layout.fragment_download) {
arguments?.getString("title")?.let {
mainWeakReference?.get()?.toolbar?.title = it
}
scanFile(currentDir)
lifecycleScope.launch {
scanFile(arguments?.getString("file")?.let { File(it) }?:context?.getExternalFilesDir("")?:run {
findNavController().popBackStack()
return@launch
})
}
}
}
private fun scanFile(cd: File?) {
private suspend fun scanFile(cd: File): Unit = withContext(Dispatchers.IO) {
val isRoot = cd == context?.getExternalFilesDir("")
val jsonFile = File(cd, "info.bin")
if(isRoot || !jsonFile.exists()) cd?.list()?.sortedArrayWith { o1, o2 ->
if(isRoot || !jsonFile.exists()) cd.listFiles()?.filter { f -> return@filter f.isDirectory }?.map { f -> return@map f.name }?.sortedWith { o1, o2 ->
if(o1.endsWith(".zip") && o2.endsWith(".zip")) (10000*getFloat(o1) - 10000*getFloat(o2) + 0.5).toInt()
else o1[0] - o2[0]
}?.let {
mylv?.apply {
setPadding(0, 0, 0, navBarHeight)
context.let { c ->
adapter = ArrayAdapter(c, android.R.layout.simple_list_item_1, it)
val ad = ArrayAdapter(context, android.R.layout.simple_list_item_1, it)
post {
setPadding(0, 0, 0, navBarHeight)
adapter = ad
setOnItemClickListener { _, _, position, _ ->
val chosenFile = File(cd, it[position])
val chosenJson = File(chosenFile, "info.bin")
@@ -51,8 +60,7 @@ class DownloadFragment: NoBackRefreshFragment(R.layout.fragment_download) {
chosenJson.exists() -> callDownloadFragment(chosenJson)
newJson.exists() -> callDownloadFragment(newJson, true)
chosenFile.isDirectory -> {
currentDir = chosenFile
callSelf(it[position])
callSelf(it[position], chosenFile)
}
chosenFile.name.endsWith(".zip") -> {
Toast.makeText(context, "加载中...", Toast.LENGTH_SHORT).show()
@@ -67,11 +75,18 @@ class DownloadFragment: NoBackRefreshFragment(R.layout.fragment_download) {
}
setOnItemLongClickListener { _, _, position, _ ->
val chosenFile = File(cd, it[position])
Log.d("MyDF", "y: ${getChildAt(0).scrollY}")
AlertDialog.Builder(context)
.setIcon(R.drawable.ic_launcher_foreground).setMessage("删除?")
.setTitle("提示").setPositiveButton(android.R.string.ok) { _, _ ->
if (chosenFile.exists()) FileUtils.recursiveRemove(chosenFile)
scanFile(cd)
lifecycleScope.launch {
withContext(Dispatchers.IO) {
if (chosenFile.exists()) {
FileUtils.recursiveRemove(chosenFile)
scanFile(cd)
}
}
}
}.setNegativeButton(android.R.string.cancel) { _, _ -> }
.show()
true
@@ -95,9 +110,10 @@ class DownloadFragment: NoBackRefreshFragment(R.layout.fragment_download) {
Navigate.safeNavigateTo(findNavController(), R.id.action_nav_download_to_nav_group, bundle)
}
private fun callSelf(title: String){
private fun callSelf(title: String, file: File){
val bundle = Bundle()
bundle.putString("title", title)
bundle.putString("file", file.absolutePath)
Log.d("MyDF", "Call self to $title")
Log.d("MyDF", "root view: $rootView")
Log.d("MyDF", "action_nav_download_self")
@@ -116,8 +132,4 @@ class DownloadFragment: NoBackRefreshFragment(R.layout.fragment_download) {
//Log.d("MyDLL2", newString.toString().toFloat().toString())
return if(newString.isEmpty()) 0f else newString.toString().toFloat()
}
companion object{
var currentDir: File? = null
}
}

View File

@@ -57,7 +57,7 @@ class NewDownloadFragment: MangaPagesFragmentTemplate(R.layout.fragment_newdownl
override suspend fun addPage(): Unit = withContext(Dispatchers.IO) {
super.addPage()
if(isRefresh){
if(isRefresh) {
page = 0
isRefresh = false
}
@@ -111,8 +111,11 @@ class NewDownloadFragment: MangaPagesFragmentTemplate(R.layout.fragment_newdownl
isContentChanged = false
}
Log.d("MyNDF", "Start drawing cards")
cardList?.addCard(oldDlCardName, path = oldDlCardName)
var cnt = 1
var cnt = 0
if(page == 0) {
cardList?.addCard(oldDlCardName, path = oldDlCardName)
cnt = 1
}
val size = sortedBookList?.size?:0
sortedBookList?.let {
for(i in it.listIterator(page)) {
@@ -120,12 +123,16 @@ class NewDownloadFragment: MangaPagesFragmentTemplate(R.layout.fragment_newdownl
page++ // page is actually count
val chosenJson = File(i, "info.bin")
val newJson = File(i, "info.json")
val bookSize = (FileUtils.sizeOf(i)/1048576).toInt()
val bookSize = FileUtils.sizeOf(i).let { sz ->
(sz/1048576).toInt().let { m ->
if (m > 0) "\n${m}MB" else "\n${(sz/1024).toInt()}KB"
}
}
when {
chosenJson.exists() -> continue // unsupported old folder
newJson.exists() -> {
if(cardList?.exitCardList != false) return@withContext
cardList?.addCard(i.name, "\n${bookSize}MB")
cardList?.addCard(i.name, bookSize)
cnt++
}
}

View File

@@ -90,9 +90,9 @@ class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) {
})
setTextHint(android.R.string.search_go)
var lastSearch = ""
setOnQueryTextListener(object : SearchLayout.OnQueryTextListener {
var lastChangeTime = 0L
var lastSearch: String = ""
override fun onQueryTextChange(newText: CharSequence): Boolean {
if (newText.contentEquals("__notice_focus_change__") || newText.contentEquals(lastSearch)) return true
postDelayed({
@@ -121,6 +121,7 @@ class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) {
return true
}
})
setOnMicClickListener(object : SearchLayout.OnMicClickListener {
val types = arrayOf("", "name", "author", "local")
var i = 0
@@ -137,17 +138,25 @@ class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) {
}
})
var isInFocusWaiting = false
setOnFocusChangeListener(object : SearchLayout.OnFocusChangeListener {
override fun onFocusChange(hasFocus: Boolean) {
Log.d("MyHF", "fhs onFocusChange: $hasFocus")
navigationIconSupport = if (hasFocus) {
setTextQuery("__notice_focus_change__", true)
SearchLayout.NavigationIconSupport.ARROW
}
else {
micView.postDelayed({ micView?.visibility = View.VISIBLE }, 233)
SearchLayout.NavigationIconSupport.SEARCH
}
if (isInFocusWaiting) return
isInFocusWaiting = true
postDelayed({
navigationIconSupport = if (hasFocus) {
setTextQuery("__notice_focus_change__", true)
SearchLayout.NavigationIconSupport.ARROW
}
else {
if (lastSearch.isNotEmpty()) {
micView?.visibility = View.VISIBLE
}
SearchLayout.NavigationIconSupport.SEARCH
}
isInFocusWaiting = false
}, 300)
}
})
@@ -165,8 +174,8 @@ class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) {
homeHandler.obtainMessage(-1, true).sendToTarget()
while(!MainActivity.isDrawerClosed) delay(233)
//homeHandler.sendEmptyMessage(6) //removeAllViews
homeHandler.fhib = null
delay(600)
//homeHandler.fhib = null
delay(300)
homeHandler.startLoad()
}
}
@@ -228,42 +237,53 @@ class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) {
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
holder.itemView.lwc.setOnClickListener {
if (query?.isNotEmpty() != true) return@setOnClickListener
val bundle = Bundle()
bundle.putCharSequence("query", query)
bundle.putString("type", type)
Navigate.safeNavigateTo(findNavController(), R.id.action_nav_home_to_nav_search, bundle)
}
holder.itemView.apply { post {
tn.setText(R.string.button_more)
ta.text = "搜索 \"$query\""
tb.text = "$count 条结果"
context?.let {
Glide.with(it).load(R.drawable.img_defmask)
.addListener(GlideHideLottieViewListener(WeakReference(laic)))
.into(imic)
}
cic.isClickable = false
lwc.setOnClickListener {
if (query?.isNotEmpty() != true) return@setOnClickListener
val bundle = Bundle()
bundle.putCharSequence("query", query)
bundle.putString("type", type)
Navigate.safeNavigateTo(findNavController(), R.id.action_nav_home_to_nav_search, bundle)
}
lwc.layoutParams.height = fhs.width / 4
} }
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 = ""
it.forEach { ts ->
t += ts.name + " "
holder.itemView.apply { post {
lwi.visibility = View.VISIBLE
tn.text = name
ta.text = author.let {
var t = ""
it.forEach { ts ->
t += ts.name + " "
}
return@let t
}
return@let t
}
holder.itemView.tb.text = popular.toString()
context?.let {
Glide.with(it)
.load(GlideUrl(CMApi.imageProxy?.wrap(cover)?:cover, CMApi.myGlideHeaders))
.addListener(GlideHideLottieViewListener(WeakReference(holder.itemView.laic)))
.into(holder.itemView.imic)
}
holder.itemView.lwc.setOnClickListener {
val bundle = Bundle()
bundle.putString("path", path_word)
Navigate.safeNavigateTo(findNavController(), R.id.action_nav_home_to_nav_book, bundle)
}
holder.itemView.lwc.layoutParams.height = fhs.width / 4
tb.text = popular.toString()
cic.isClickable = false
context?.let {
Glide.with(it)
.load(GlideUrl(CMApi.imageProxy?.wrap(cover)?:cover, CMApi.myGlideHeaders))
.addListener(GlideHideLottieViewListener(WeakReference(laic)))
.into(imic)
}
lwc.setOnClickListener {
val bundle = Bundle()
bundle.putString("path", path_word)
Navigate.safeNavigateTo(findNavController(), R.id.action_nav_home_to_nav_book, bundle)
}
lwc.layoutParams.height = fhs.width / 4
} }
}
}

View File

@@ -1,6 +1,7 @@
package top.fumiama.copymanga.ui.home
import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.graphics.Color
import android.os.Bundle
import android.os.Message
@@ -45,11 +46,11 @@ class HomeHandler(private val that: WeakReference<HomeFragment>) : AutoDownloadH
) {
private val homeF get() = that.get()
var index: IndexStructure? = null
var fhib: View? = null
var fhib: Banner? = null
get() {
Log.d("MyHH", "Get fhib.")
if (field == null) {
field = homeF?.layoutInflater?.inflate(R.layout.viewpage_banner, homeF?.fhl, false)
field = homeF?.layoutInflater?.inflate(R.layout.viewpage_banner, homeF?.fhl, false) as Banner
homeF?.homeHandler?.sendEmptyMessage(3)
}
return field
@@ -63,7 +64,7 @@ class HomeHandler(private val that: WeakReference<HomeFragment>) : AutoDownloadH
//0 -> setLayouts()
1 -> inflateCardLines()
2 -> homeF?.swiperefresh?.let { setSwipe(it) }
3 -> setBanner(fhib as Banner)
3 -> setBanner(fhib!!)
5 -> setBannerInfo(msg.obj as Banner)
6 -> {
homeF?.fhl?.let {
@@ -76,15 +77,6 @@ class HomeHandler(private val that: WeakReference<HomeFragment>) : AutoDownloadH
}
}
7 -> inflateBanner()
8 -> {
try {
homeF?.fhl?.addView(indexLines[msg.arg1])
} catch (e: Exception) {
e.printStackTrace()
(indexLines[msg.arg1].parent as LinearLayout).removeAllViews()
homeF?.fhl?.addView(indexLines[msg.arg1])
}
}
}
}
@@ -226,11 +218,22 @@ class HomeHandler(private val that: WeakReference<HomeFragment>) : AutoDownloadH
inflateNew()
inflateFinish()
inflateRank()
for(i in indexLines.indices) {
obtainMessage(8, i, 0).sendToTarget()
delay(512)
}
obtainMessage(-1, false).sendToTarget() //closeLoad
homeF?.fhl?.apply { post {
for (i in indexLines.indices) {
try {
addView(indexLines[i])
} catch (e: Exception) {
e.printStackTrace()
(indexLines[i].parent as LinearLayout).apply {
post {
removeAllViews()
homeF?.fhl?.addView(indexLines[i])
}
}
}
}
obtainMessage(-1, false).sendToTarget() //closeLoad
} }
}
}
}
@@ -264,14 +267,17 @@ class HomeHandler(private val that: WeakReference<HomeFragment>) : AutoDownloadH
v.invalidate()
}
@SuppressLint("NotifyDataSetChanged")
private fun setSwipe(sw: SwipeRefreshLayout) {
homeF?.fhov?.swipeRefreshLayout = sw
sw.setOnRefreshListener {
Log.d("MyHFH", "Refresh items.")
homeF?.lifecycleScope?.launch {
withContext(Dispatchers.IO) {
fhib?.isAutoPlay = false
fhib?.adapter?.notifyDataSetChanged()
index = null
//fhib = null
fhib = null
indexLines = arrayOf()
this@HomeHandler.sendEmptyMessage(6) //removeAllViews
delay(300)
@@ -293,13 +299,15 @@ class HomeHandler(private val that: WeakReference<HomeFragment>) : AutoDownloadH
2 -> R.layout.line_2bookline
3 -> R.layout.line_3bookline
else -> return@withContext -1
}, homeF!!.fhl, false)?.apply {
}, null, false)?.apply {
withContext(Dispatchers.Main) {
scanCards(this@apply, comics, finish, isTopic)
rttitle.text = title
ir.setImageResource(iconResId)
setLineHeight(this@apply, c)
if(onClick != null) setOnClickListener { onClick() }
post {
rttitle.text = title
ir.setImageResource(iconResId)
setLineHeight(this@apply, c)
if(onClick != null) setOnClickListener { onClick() }
}
}
indexLines += this
}
@@ -324,8 +332,8 @@ class HomeHandler(private val that: WeakReference<HomeFragment>) : AutoDownloadH
private var cardLoadingWaits = AtomicInteger()
private suspend fun setCards(cv: CardView, pw: String, name: String, img: String, isFinal: Boolean, isTopic: Boolean) = withContext(Dispatchers.Main) {
cv.tic.text = name
private fun setCards(cv: CardView, pw: String, name: String, img: String, isFinal: Boolean, isTopic: Boolean) {
cv.tic.apply { post { text = name } }
homeF?.let {
if(img.startsWith("http")) {
Log.d("MyHH", "load card image: $img")
@@ -336,15 +344,17 @@ class HomeHandler(private val that: WeakReference<HomeFragment>) : AutoDownloadH
})
if (waitMillis > 0) cv.imic.postDelayed({
g.into(cv.imic)
}, waitMillis) else g.into(cv.imic)
}, waitMillis) else cv.imic.post { g.into(cv.imic) }
}
}
if (isFinal) cv.sgnic.visibility = View.VISIBLE
cv.setOnClickListener {
val bundle = Bundle()
bundle.putString("path", pw)
homeF?.findNavController()?.let { nav ->
Navigate.safeNavigateTo(nav, if(isTopic) R.id.action_nav_home_to_nav_topic else R.id.action_nav_home_to_nav_book, bundle)
if (isFinal) cv.sgnic.apply { post { visibility = View.VISIBLE } }
cv.post {
cv.setOnClickListener {
val bundle = Bundle()
bundle.putString("path", pw)
homeF?.findNavController()?.let { nav ->
Navigate.safeNavigateTo(nav, if(isTopic) R.id.action_nav_home_to_nav_topic else R.id.action_nav_home_to_nav_book, bundle)
}
}
}
}

View File

@@ -133,56 +133,52 @@ class ViewMangaActivity : TitleActivityTemplate() {
@SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
val settingsPref = MainActivity.mainWeakReference?.get()?.let { PreferenceManager.getDefaultSharedPreferences(it) }
settingsPref?.getBoolean("settings_cat_vm_sw_always_dark_bg", false)?.let {
if (it) {
Log.d("MyVM", "force dark")
delegate.localNightMode = AppCompatDelegate.MODE_NIGHT_YES
} else {
delegate.localNightMode = AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
}
}
postponeEnterTransition()
setContentView(R.layout.activity_viewmanga)
super.onCreate(null)
va = WeakReference(this@ViewMangaActivity)
//dlZip2View = intent.getStringExtra("callFrom") == "Dl" || p["dlZip2View"] == "true"
//zipFirst = intent.getStringExtra("callFrom") == "zipFirst"
intent.getStringArrayExtra("urlArray")?.let { urlArray = it }
cut = pb["useCut"]
r2l = pb["r2l"]
verticalLoadMaxCount = settingsPref?.getInt("settings_cat_vm_sb_vertical_max", 20)?.let { if(it > 0) it else 20 }?:20
isVertical = pb["vertical"]
notUseVP = pb["noVP"] || isVertical
//url = intent.getStringExtra("url")
handler = VMHandler(this@ViewMangaActivity, if(urlArray.isNotEmpty()) urlArray[position] else "", resources.getStringArray(R.array.weeks))
lifecycleScope.launch {
withContext(Dispatchers.IO) {
val settingsPref = MainActivity.mainWeakReference?.get()?.let { PreferenceManager.getDefaultSharedPreferences(it) }
settingsPref?.getBoolean("settings_cat_vm_sw_always_dark_bg", false)?.let {
if (it) {
Log.d("MyVM", "force dark")
delegate.localNightMode = AppCompatDelegate.MODE_NIGHT_YES
} else {
delegate.localNightMode = AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
}
}
va = WeakReference(this@ViewMangaActivity)
//dlZip2View = intent.getStringExtra("callFrom") == "Dl" || p["dlZip2View"] == "true"
//zipFirst = intent.getStringExtra("callFrom") == "zipFirst"
intent.getStringArrayExtra("urlArray")?.let { urlArray = it }
cut = pb["useCut"]
r2l = pb["r2l"]
verticalLoadMaxCount = settingsPref?.getInt("settings_cat_vm_sb_vertical_max", 20)?.let { if(it > 0) it else 20 }?:20
isVertical = pb["vertical"]
notUseVP = pb["noVP"] || isVertical
//url = intent.getStringExtra("url")
withContext(Dispatchers.Main) {
handler = VMHandler(this@ViewMangaActivity, if(urlArray.isNotEmpty()) urlArray[position] else "", resources.getStringArray(R.array.weeks))
withContext(Dispatchers.IO) {
settingsPref?.getInt("settings_cat_vm_sb_quality", 100)?.let { q = if (it > 0) it else 100 }
tt = TimeThread(handler, VMHandler.SET_NET_INFO, 10000)
tt.canDo = true
tt.start()
volTurnPage = settingsPref?.getBoolean("settings_cat_vm_sw_vol_turn", false)?:false
am = getSystemService(Service.AUDIO_SERVICE) as AudioManager
if (!noCellarAlert) noCellarAlert = settingsPref?.getBoolean("settings_cat_net_sw_use_cellar", false) == true
fullyHideInfo = settingsPref?.getBoolean("settings_cat_vm_sw_hide_info", false) == true
settingsPref?.getInt("settings_cat_vm_sb_quality", 100)?.let { q = if (it > 0) it else 100 }
tt = TimeThread(handler, VMHandler.SET_NET_INFO, 10000)
tt.canDo = true
tt.start()
volTurnPage = settingsPref?.getBoolean("settings_cat_vm_sw_vol_turn", false)?:false
am = getSystemService(Service.AUDIO_SERVICE) as AudioManager
if (!noCellarAlert) noCellarAlert = settingsPref?.getBoolean("settings_cat_net_sw_use_cellar", false) == true
fullyHideInfo = settingsPref?.getBoolean("settings_cat_vm_sw_hide_info", false) == true
Log.d("MyVM", "Now ZipFile is $zipFile")
try {
if (zipFile != null && zipFile?.exists() == true) {
if (!handler.loadFromFile(zipFile!!)) prepareImgFromWeb()
} else prepareImgFromWeb()
} catch (e: Exception) {
e.printStackTrace()
toolsBox.toastError(R.string.load_manga_error)
}
withContext(Dispatchers.Main) {
startPostponedEnterTransition()
ObjectAnimator.ofFloat(vcp, "alpha", 0.1f, 1f).setDuration(1000).start()
}
}
Log.d("MyVM", "Now ZipFile is $zipFile")
try {
if (zipFile != null && zipFile?.exists() == true) {
if (!handler.loadFromFile(zipFile!!)) prepareImgFromWeb()
} else prepareImgFromWeb()
} catch (e: Exception) {
e.printStackTrace()
toolsBox.toastError(R.string.load_manga_error)
}
withContext(Dispatchers.Main) {
startPostponedEnterTransition()
ObjectAnimator.ofFloat(vcp, "alpha", 0.1f, 1f).setDuration(1000).start()
}
}
}

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportHeight="1024"
android:viewportWidth="1024">
<path
android:fillColor="@android:color/holo_red_light"
android:pathData="M668 117C833 117 939 250 939 428c0 138-125 291-372 462a97 97 0 0 1-110 0C210 718 85 566 85 428 85 250 191 117 356 117c60 0 100 21 156 68C568 138 608 117 668 117z m0 63c-41 0-70 15-117 55-2 2-14 12-18 15a32 32 0 0 1-42 0c-4-3-16-14-18-15-47-40-76-55-117-55C230 180 149 281 149 427 149 538 263 675 494 835a32 32 0 0 0 37 0C761 675 875 538 875 427c0-145-81-246-207-246z"/>
</vector>

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportHeight="1024"
android:viewportWidth="1024">
<path
android:fillColor="@android:color/holo_red_light"
android:pathData="M668 117C833 117 939 250 939 428c0 138-125 291-372 462a97 97 0 0 1-110 0C210 718 85 566 85 428 85 250 191 117 356 117c60 0 100 21 156 68C568 138 608 117 668 117z"/>
</vector>

View File

@@ -14,7 +14,6 @@
layout="@layout/card_book_plain"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/lwl"
app:layout_constraintHorizontal_weight="1"
@@ -25,7 +24,7 @@
android:id="@+id/lwl"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="16dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
@@ -37,38 +36,22 @@
android:id="@+id/tn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginEnd="16dp"
android:textColor="?attr/colorOnSurface"
android:textSize="24sp"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="@+id/ta"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:fontFamily="@font/gotham"
android:textColor="?attr/colorOnSurface"
android:textSize="18sp" />
android:textSize="16sp" />
<TextView
android:id="@+id/tb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginBottom="10dp" />
android:layout_height="wrap_content" />
</LinearLayout>
<View
android:id="@+id/vl"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginEnd="16dp"
android:clickable="true"
android:focusable="true"
android:foreground="?android:attr/selectableItemBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>