diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index 1ccd6e4..0c0c338 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -3,20 +3,7 @@ - - - - - - - - - - - - - - + diff --git a/app/build.gradle b/app/build.gradle index 225d9d1..98799bc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -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" diff --git a/app/src/main/java/top/fumiama/copymanga/MainActivity.kt b/app/src/main/java/top/fumiama/copymanga/MainActivity.kt index 033dfba..f8cbd9d 100644 --- a/app/src/main/java/top/fumiama/copymanga/MainActivity.kt +++ b/app/src/main/java/top/fumiama/copymanga/MainActivity.kt @@ -127,7 +127,6 @@ class MainActivity : AppCompatActivity() { isDrawerClosed = false lifecycleScope.launch { withContext(Dispatchers.IO) { - DownloadFragment.currentDir = getExternalFilesDir("") refreshUserInfo() } } diff --git a/app/src/main/java/top/fumiama/copymanga/template/ui/CardList.kt b/app/src/main/java/top/fumiama/copymanga/template/ui/CardList.kt index e899d8b..b6ad3a7 100644 --- a/app/src/main/java/top/fumiama/copymanga/template/ui/CardList.kt +++ b/app/src/main/java/top/fumiama/copymanga/template/ui/CardList.kt @@ -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 = arrayOfNulls(20) - private var index = 0 - private var count = 0 + private var mRows: Array = 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 + } + } + } } } } diff --git a/app/src/main/java/top/fumiama/copymanga/ui/book/BookFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/book/BookFragment.kt index 0c90f57..891d481 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/book/BookFragment.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/book/BookFragment.kt @@ -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 diff --git a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/history/HistoryFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/history/HistoryFragment.kt index 4f3bed4..2d64889 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/history/HistoryFragment.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/history/HistoryFragment.kt @@ -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) } } diff --git a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/shelf/ShelfFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/shelf/ShelfFragment.kt index 82d5d64..5593aa2 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/shelf/ShelfFragment.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/shelf/ShelfFragment.kt @@ -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) } diff --git a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/sort/SortFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/sort/SortFragment.kt index a6e2e0a..f80cbc0 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/sort/SortFragment.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/sort/SortFragment.kt @@ -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 diff --git a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/topic/TopicFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/topic/TopicFragment.kt index 64d5af0..d5299c7 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/topic/TopicFragment.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/topic/TopicFragment.kt @@ -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 diff --git a/app/src/main/java/top/fumiama/copymanga/ui/download/DownloadFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/download/DownloadFragment.kt index a23fdff..1512aa3 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/download/DownloadFragment.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/download/DownloadFragment.kt @@ -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 - } } \ No newline at end of file diff --git a/app/src/main/java/top/fumiama/copymanga/ui/download/NewDownloadFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/download/NewDownloadFragment.kt index 9903819..9a02d5a 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/download/NewDownloadFragment.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/download/NewDownloadFragment.kt @@ -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++ } } diff --git a/app/src/main/java/top/fumiama/copymanga/ui/home/HomeFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/home/HomeFragment.kt index 79cc412..e294a45 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/home/HomeFragment.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/home/HomeFragment.kt @@ -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 + } } } } diff --git a/app/src/main/java/top/fumiama/copymanga/ui/home/HomeHandler.kt b/app/src/main/java/top/fumiama/copymanga/ui/home/HomeHandler.kt index 1b6bf12..f9a7798 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/home/HomeHandler.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/home/HomeHandler.kt @@ -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) : 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) : 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) : 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) : 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) : 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) : 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) : 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) : 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) + } } } } diff --git a/app/src/main/java/top/fumiama/copymanga/ui/vm/ViewMangaActivity.kt b/app/src/main/java/top/fumiama/copymanga/ui/vm/ViewMangaActivity.kt index 01d5832..89d925f 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/vm/ViewMangaActivity.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/vm/ViewMangaActivity.kt @@ -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() } } } diff --git a/app/src/main/res/drawable-anydpi/ic_like.xml b/app/src/main/res/drawable-anydpi/ic_like.xml deleted file mode 100644 index 87c647d..0000000 --- a/app/src/main/res/drawable-anydpi/ic_like.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable-anydpi/ic_like_filled.xml b/app/src/main/res/drawable-anydpi/ic_like_filled.xml deleted file mode 100644 index a4344c9..0000000 --- a/app/src/main/res/drawable-anydpi/ic_like_filled.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/line_word.xml b/app/src/main/res/layout/line_word.xml index 70242ff..4a38973 100644 --- a/app/src/main/res/layout/line_word.xml +++ b/app/src/main/res/layout/line_word.xml @@ -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" /> + android:textSize="16sp" /> + android:layout_height="wrap_content" /> - \ No newline at end of file