From 7f5f183d327c963ea2072710b9caac0afd8a6f39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Sat, 9 Mar 2024 00:28:00 +0900 Subject: [PATCH] =?UTF-8?q?v2.1.3=20=E6=96=B0=E5=A2=9E=201.=20=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E9=A1=B5=E6=A0=87=E8=AE=B0=E5=B7=B2=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?=E7=AB=A0=E8=8A=82=202.=20=E8=AF=A6=E6=83=85=E9=A1=B5=E4=BB=A5t?= =?UTF-8?q?ab=E5=8C=BA=E5=88=86=E5=8D=B7=E6=A0=87=203.=20=E4=BB=A5?= =?UTF-8?q?=E6=B7=B1=E6=B5=85=E6=A0=87=E7=A4=BA=E5=BD=93=E5=89=8D=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E7=9A=84tab=20=E4=BF=AE=E5=A4=8D=201.=20=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E9=A1=B5=E5=8A=A0=E8=BD=BD=E7=BB=93=E6=9D=9F=E6=97=B6?= =?UTF-8?q?=E5=8D=A1=E9=A1=BF=202.=20=E6=9F=90=E4=BA=9B=E6=BC=AB=E7=94=BB?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E5=8F=98=E6=9B=B4=E6=B8=85=E6=99=B0=E5=BA=A6?= =?UTF-8?q?=203.=20=E5=85=A8=E6=96=B0=E4=B8=8A=E6=9E=B6=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E9=94=99=E8=AF=AF=204.=20=E4=B8=93=E9=A2=98=E7=B3=BB=E5=88=97?= =?UTF-8?q?=E6=9C=89=E6=97=B6=E7=AE=80=E4=BB=8B=E4=B8=8D=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=20=E4=BC=98=E5=8C=96=201.=20=E6=9B=BF=E6=8D=A2=E5=BC=83?= =?UTF-8?q?=E7=94=A8API=202.=20=E6=90=BA=E7=A8=8B=E5=8C=96:=20=E6=A3=80?= =?UTF-8?q?=E6=9F=A5=E6=9B=B4=E6=96=B0,=20=E8=8F=9C=E5=8D=95=E5=88=87?= =?UTF-8?q?=E6=8D=A2,=20=E8=AF=A6=E6=83=85=E9=A1=B5=203.=20StatusCardFlow?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E6=8E=92=E5=BA=8F=204.=20CardList=E5=8A=A0?= =?UTF-8?q?=E8=BD=BD=E9=80=9F=E5=BA=A6=20=E5=8D=87=E7=BA=A7=201.=20?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=BA=93=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/deploymentTargetDropDown.xml | 23 + .idea/dictionaries/fumiama.xml | 1 + .idea/gradle.xml | 4 +- .idea/migrations.xml | 10 + .../shelved.patch | 2454 +++++++++++++++++ ...Update_at_2024_3_9__12_23_AM__Changes_.xml | 4 + app/build.gradle | 19 +- .../top/fumiama/copymanga/LoginActivity.kt | 1 + .../top/fumiama/copymanga/MainActivity.kt | 146 +- .../copymanga/json/ComicStructure.java | 5 +- .../java/top/fumiama/copymanga/manga/Shelf.kt | 27 +- .../fumiama/copymanga/template/ui/CardList.kt | 2 +- .../copymanga/template/ui/InfoCardLoader.kt | 15 +- .../copymanga/template/ui/StatusCardFlow.kt | 75 +- .../copymanga/template/ui/ThemeCardFlow.kt | 11 +- .../top/fumiama/copymanga/tools/api/CMApi.kt | 2 +- .../copymanga/tools/http/Resolution.kt | 2 +- .../tools/ui/GlideHideLottieViewListener.kt | 8 +- .../fumiama/copymanga/ui/book/BookFragment.kt | 65 +- .../fumiama/copymanga/ui/book/BookHandler.kt | 200 +- .../ui/cardflow/finish/FinishFragment.kt | 12 +- .../ui/cardflow/newest/NewestFragment.kt | 3 - .../ui/cardflow/rank/RankFragment.kt | 3 +- .../ui/cardflow/shelf/ShelfFragment.kt | 98 +- .../ui/cardflow/sort/SortFragment.kt | 60 +- .../ui/cardflow/topic/TopicFragment.kt | 8 +- .../ui/download/NewDownloadFragment.kt | 101 +- .../fumiama/copymanga/update/SimpleKanban.kt | 12 +- .../top/fumiama/copymanga/update/Update.kt | 146 +- .../java/top/fumiama/copymanga/user/Member.kt | 2 +- .../main/res/drawable-anydpi/ic_circle.xml | 10 + app/src/main/res/drawable-anydpi/ic_data.xml | 10 + app/src/main/res/drawable-anydpi/ic_hot.xml | 10 + app/src/main/res/drawable-anydpi/ic_image.xml | 10 + .../main/res/drawable-anydpi/ic_success.xml | 10 + app/src/main/res/layout/card_book.xml | 1 - app/src/main/res/layout/fragment_book.xml | 29 +- app/src/main/res/layout/line_bookinfo.xml | 18 +- .../main/res/layout/line_bookinfo_text.xml | 8 +- app/src/main/res/layout/line_chapter.xml | 2 +- app/src/main/res/layout/page_nested_list.xml | 13 + .../main/res/navigation/mobile_navigation.xml | 2 +- app/src/main/res/values/strings.xml | 9 +- build.gradle | 4 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 45 files changed, 3173 insertions(+), 484 deletions(-) create mode 100644 .idea/deploymentTargetDropDown.xml create mode 100644 .idea/migrations.xml create mode 100644 .idea/shelf/Uncommitted_changes_before_Update_at_2024_3_9,_12_23_AM_[Changes]/shelved.patch create mode 100644 .idea/shelf/Uncommitted_changes_before_Update_at_2024_3_9__12_23_AM__Changes_.xml create mode 100644 app/src/main/res/drawable-anydpi/ic_circle.xml create mode 100644 app/src/main/res/drawable-anydpi/ic_data.xml create mode 100644 app/src/main/res/drawable-anydpi/ic_hot.xml create mode 100644 app/src/main/res/drawable-anydpi/ic_image.xml create mode 100644 app/src/main/res/drawable-anydpi/ic_success.xml create mode 100644 app/src/main/res/layout/page_nested_list.xml diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml new file mode 100644 index 0000000..1ccd6e4 --- /dev/null +++ b/.idea/deploymentTargetDropDown.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/dictionaries/fumiama.xml b/.idea/dictionaries/fumiama.xml index b79f8e3..9904d8f 100644 --- a/.idea/dictionaries/fumiama.xml +++ b/.idea/dictionaries/fumiama.xml @@ -4,6 +4,7 @@ imgs lowpan nisi + reilia \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 757f88e..0897082 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -4,10 +4,8 @@ +\ No newline at end of file +Index: app/src/main/res/layout/card_book.xml +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>\n\n\n \n\n \n\n \n\n \n\n \n\n \n\n \n \n\n \n\n \n\n \n \n +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/app/src/main/res/layout/card_book.xml b/app/src/main/res/layout/card_book.xml +--- a/app/src/main/res/layout/card_book.xml (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/app/src/main/res/layout/card_book.xml (date 1709904811979) +@@ -78,7 +78,6 @@ + android:layout_marginEnd="16dp" + android:layout_marginBottom="4dp" + android:gravity="center_horizontal" +- android:text="获取标题失败" + android:textAppearance="@style/TextAppearance.AppCompat.Body1" + android:textColor="@android:color/white" + android:textSize="12sp" +Index: app/src/main/java/top/fumiama/copymanga/LoginActivity.kt +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>package top.fumiama.copymanga\n\nimport android.os.Bundle\nimport android.util.Log\nimport android.widget.Toast\nimport androidx.appcompat.app.AppCompatActivity\nimport androidx.lifecycle.lifecycleScope\nimport kotlinx.android.synthetic.main.activity_login.*\nimport kotlinx.coroutines.launch\nimport top.fumiama.dmzj.copymanga.R\nimport kotlin.random.Random\n\n\nclass LoginActivity : AppCompatActivity() {\n override fun onCreate(savedInstanceState: Bundle?) {\n super.onCreate(savedInstanceState)\n setContentView(R.layout.activity_login)\n val pref = MainActivity.mainWeakReference?.get()?.getPreferences(MODE_PRIVATE) ?: return\n val isLogout = pref.getString(\"token\", null) != null\n if (isLogout) {\n alblogin.setText(R.string.logout)\n }\n alblogin.setOnClickListener {\n lifecycleScope.launch {\n val salt = Random.nextInt(10000)\n val username = altusrnm.text?.toString() ?: run {\n Toast.makeText(\n this@LoginActivity,\n R.string.login_null_username,\n Toast.LENGTH_SHORT\n ).show()\n return@launch\n }\n val pwd = altpwd.text?.toString() ?: run {\n Toast.makeText(this@LoginActivity, R.string.login_null_pwd, Toast.LENGTH_SHORT)\n .show()\n return@launch\n }\n if (isLogout) {\n MainActivity.member?.logout()\n MainActivity.mainWeakReference?.get()?.refreshUserInfo()\n Toast.makeText(\n this@LoginActivity,\n R.string.login_restart_to_apply,\n Toast.LENGTH_SHORT\n ).show()\n finish()\n return@launch\n }\n val l = MainActivity.member?.login(username, pwd, salt)\n Log.d(\"MyLA\", \"login return code: ${l?.code}\")\n if (l?.code == 200) {\n MainActivity.mainWeakReference?.get()?.refreshUserInfo()\n finish()\n return@launch\n }\n Toast.makeText(this@LoginActivity, l?.message, Toast.LENGTH_SHORT).show()\n }\n }\n }\n}\n +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/app/src/main/java/top/fumiama/copymanga/LoginActivity.kt b/app/src/main/java/top/fumiama/copymanga/LoginActivity.kt +--- a/app/src/main/java/top/fumiama/copymanga/LoginActivity.kt (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/app/src/main/java/top/fumiama/copymanga/LoginActivity.kt (date 1709886202030) +@@ -19,6 +19,7 @@ + val isLogout = pref.getString("token", null) != null + if (isLogout) { + alblogin.setText(R.string.logout) ++ altusrnm.setText(pref.getString("username", "N/A")) + } + alblogin.setOnClickListener { + lifecycleScope.launch { +Index: app/src/main/res/layout/line_chapter.xml +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>\n\n\n \n\n \n +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/app/src/main/res/layout/line_chapter.xml b/app/src/main/res/layout/line_chapter.xml +--- a/app/src/main/res/layout/line_chapter.xml (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/app/src/main/res/layout/line_chapter.xml (date 1709899238798) +@@ -15,7 +15,7 @@ + android:layout_marginStart="@dimen/nav_header_vertical_spacing" + android:layout_marginTop="@dimen/nav_header_vertical_spacing" + android:layout_marginBottom="@dimen/nav_header_vertical_spacing" +- android:background="@drawable/ic_list" ++ android:background="@drawable/ic_circle" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0.0" +Index: app/src/main/res/drawable-anydpi/ic_success.xml +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/app/src/main/res/drawable-anydpi/ic_success.xml b/app/src/main/res/drawable-anydpi/ic_success.xml +new file mode 100644 +--- /dev/null (date 1709898923840) ++++ b/app/src/main/res/drawable-anydpi/ic_success.xml (date 1709898923840) +@@ -0,0 +1,10 @@ ++ ++ ++ ++ +\ No newline at end of file +Index: app/src/main/java/top/fumiama/copymanga/MainActivity.kt +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>package top.fumiama.copymanga\n\nimport android.Manifest\nimport android.annotation.SuppressLint\nimport android.content.Context\nimport android.content.Intent\nimport android.content.pm.PackageManager\nimport android.graphics.Bitmap\nimport android.graphics.BitmapFactory\nimport android.net.Uri\nimport android.os.Build\nimport android.os.Bundle\nimport android.provider.MediaStore\nimport android.util.Log\nimport android.view.Menu\nimport android.view.MenuItem\nimport android.view.View\nimport android.view.inputmethod.InputMethodManager\nimport android.widget.TextView\nimport android.widget.Toast\nimport androidx.appcompat.app.AlertDialog\nimport androidx.appcompat.app.AppCompatActivity\nimport androidx.core.app.ActivityCompat\nimport androidx.core.content.ContextCompat\nimport androidx.core.content.edit\nimport androidx.core.net.toUri\nimport androidx.drawerlayout.widget.DrawerLayout\nimport androidx.navigation.NavController\nimport androidx.navigation.findNavController\nimport androidx.navigation.ui.AppBarConfiguration\nimport androidx.navigation.ui.navigateUp\nimport androidx.navigation.ui.setupActionBarWithNavController\nimport androidx.navigation.ui.setupWithNavController\nimport com.afollestad.materialdialogs.MaterialDialog\nimport com.afollestad.materialdialogs.input.input\nimport com.bumptech.glide.Glide\nimport com.bumptech.glide.load.resource.bitmap.CircleCrop\nimport com.bumptech.glide.request.RequestOptions\nimport com.yalantis.ucrop.UCrop\nimport kotlinx.android.synthetic.main.activity_main.*\nimport kotlinx.android.synthetic.main.app_bar_main.*\nimport kotlinx.android.synthetic.main.nav_header_main.*\nimport top.fumiama.copymanga.manga.Shelf\nimport top.fumiama.copymanga.tools.ui.UITools\nimport top.fumiama.copymanga.ui.book.BookFragment.Companion.bookHandler\nimport top.fumiama.copymanga.ui.cardflow.rank.RankFragment\nimport top.fumiama.copymanga.ui.comicdl.ComicDlFragment\nimport top.fumiama.copymanga.ui.download.DownloadFragment\nimport top.fumiama.copymanga.ui.download.NewDownloadFragment\nimport top.fumiama.copymanga.update.Update\nimport top.fumiama.copymanga.user.Member\nimport top.fumiama.dmzj.copymanga.BuildConfig\nimport top.fumiama.dmzj.copymanga.R\nimport java.io.File\nimport java.io.FileInputStream\nimport java.lang.Thread.sleep\nimport java.lang.ref.WeakReference\n\nclass MainActivity : AppCompatActivity() {\n private var menuMain: Menu? = null\n private var navController: NavController? = null\n\n private lateinit var appBarConfiguration: AppBarConfiguration\n private lateinit var headPic: File\n lateinit var toolsBox: UITools\n\n private var latestDestination = 0\n private var isMenuWaiting = false\n\n override fun onCreate(savedInstanceState: Bundle?) {\n super.onCreate(null)\n\n // must init before setContentView because HomeF need them to init\n mainWeakReference = WeakReference(this)\n toolsBox = UITools(this)\n\n setContentView(R.layout.activity_main)\n setSupportActionBar(toolbar)\n coordiv.layoutParams.height = UITools.getStatusBarHeight(this)\n\n navController = findNavController(R.id.nav_host_fragment)\n appBarConfiguration = AppBarConfiguration(\n setOf(\n R.id.nav_home,\n R.id.nav_sort,\n R.id.nav_rank,\n R.id.nav_sub,\n R.id.nav_history,\n R.id.nav_new_download,\n R.id.nav_settings\n ), drawer_layout\n )\n setupActionBarWithNavController(navController!!, appBarConfiguration)\n nav_view.setupWithNavController(navController!!)\n\n headPic = File(getExternalFilesDir(\"\"), \"headPic\")\n drawer_layout.addDrawerListener(object : DrawerLayout.DrawerListener {\n override fun onDrawerClosed(drawerView: View) {\n Log.d(\"MyMain\", \"onDrawerClosed\")\n isDrawerClosed = true\n }\n\n override fun onDrawerOpened(drawerView: View) {\n Log.d(\"MyMain\", \"onDrawerOpened\")\n isDrawerClosed = false\n DownloadFragment.currentDir = getExternalFilesDir(\"\")\n refreshUserInfo()\n }\n\n override fun onDrawerSlide(drawerView: View, slideOffset: Float) {}\n override fun onDrawerStateChanged(newState: Int) {}\n })\n checkUpdate(false)\n\n ime = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager\n\n navController!!.addOnDestinationChangedListener { _, destination, _ ->\n latestDestination = destination.id\n Log.d(\"MyMA\", \"latestDestination: $latestDestination\")\n if (isMenuWaiting) {\n return@addOnDestinationChangedListener\n }\n isMenuWaiting = true\n Log.d(\"MyMA\", \"start menu waiting\")\n Thread {\n sleep(1000)\n isMenuWaiting = false\n Log.d(\"MyMA\", \"finish menu waiting\")\n runOnUiThread {\n when (latestDestination) {\n R.id.nav_home -> {\n Log.d(\"MyMA\", \"enter home\")\n menuMain?.findItem(R.id.action_info)?.isVisible = true\n menuMain?.findItem(R.id.action_download)?.isVisible = false\n menuMain?.findItem(R.id.action_sort)?.isVisible = false\n }\n R.id.nav_book -> {\n Log.d(\"MyMA\", \"enter book\")\n menuMain?.findItem(R.id.action_info)?.isVisible = false\n menuMain?.findItem(R.id.action_download)?.isVisible = true\n menuMain?.findItem(R.id.action_sort)?.isVisible = false\n }\n R.id.nav_group -> {\n Log.d(\"MyMA\", \"enter group\")\n menuMain?.findItem(R.id.action_info)?.isVisible = false\n menuMain?.findItem(R.id.action_download)?.isVisible = false\n menuMain?.findItem(R.id.action_sort)?.isVisible = true\n }\n R.id.nav_new_download -> {\n Log.d(\"MyMA\", \"enter new_download\")\n menuMain?.findItem(R.id.action_info)?.isVisible = false\n menuMain?.findItem(R.id.action_download)?.isVisible = false\n menuMain?.findItem(R.id.action_sort)?.isVisible = true\n }\n R.id.nav_rank -> {\n Log.d(\"MyMA\", \"enter rank\")\n menuMain?.findItem(R.id.action_info)?.isVisible = false\n menuMain?.findItem(R.id.action_download)?.isVisible = false\n menuMain?.findItem(R.id.action_sort)?.isVisible = true\n }\n else -> {\n Log.d(\"MyMA\", \"enter others\")\n menuMain?.findItem(R.id.action_info)?.isVisible = false\n menuMain?.findItem(R.id.action_download)?.isVisible = false\n menuMain?.findItem(R.id.action_sort)?.isVisible = false\n }\n }\n }\n }.start()\n }\n }\n\n override fun onCreateOptionsMenu(menu: Menu): Boolean {\n // Inflate the menu; this adds items to the action bar if it is present.\n menuInflater.inflate(R.menu.main, menu)\n menuMain = menu\n return true\n }\n\n @OptIn(ExperimentalStdlibApi::class)\n override fun onOptionsItemSelected(item: MenuItem): Boolean {\n return when (item.itemId) {\n R.id.action_info -> {\n showAbout()\n true\n }\n R.id.action_download -> {\n bookHandler?.sendEmptyMessage(6)\n true\n }\n R.id.action_sort -> {\n ComicDlFragment.handler?.sendEmptyMessage(13)\n NewDownloadFragment.wn?.get()?.showReverseInfo(toolsBox)\n RankFragment.wr?.get()?.showSexInfo(toolsBox)\n true\n }\n else -> super.onOptionsItemSelected(item)\n }\n }\n\n override fun onSupportNavigateUp(): Boolean {\n val navController = findNavController(R.id.nav_host_fragment)\n\n checkHeadPicture()\n if (headPic.exists()) navhbg.setOnLongClickListener {\n if (headPic.exists()) {\n val dl = AlertDialog.Builder(this)\n dl.setMessage(R.string.clearHeadImgMsg)\n dl.setPositiveButton(android.R.string.ok) { _, _ ->\n if (headPic.exists()) headPic.delete()\n navhbg.setImageResource(R.drawable.illust_57793944_20190427_134853)\n }\n dl.show()\n }\n true\n }\n navtinfo.text = getPreferences(MODE_PRIVATE).getString(\"navTextInfo\", getString(R.string.navTextInfo))\n return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()\n }\n\n @Deprecated(\"Deprecated in Java\")\n override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {\n super.onActivityResult(requestCode, resultCode, data)\n if (resultCode == RESULT_OK) when (requestCode) {\n UCrop.REQUEST_CROP -> {\n val fi = headPic.inputStream()\n navhbg.setImageBitmap(BitmapFactory.decodeStream(fi))\n fi.close()\n }\n MSG_CROP_IMAGE -> {\n data?.data?.let {\n saveFile(it)\n cropImageUri()\n }\n }\n }\n }\n\n override fun onRequestPermissionsResult(\n requestCode: Int,\n permissions: Array,\n grantResults: IntArray\n ) {\n super.onRequestPermissionsResult(requestCode, permissions, grantResults)\n when (requestCode) {\n MSG_CROP_IMAGE -> {\n if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) pickPicture()\n else Toast.makeText(this, R.string.permissionDenied, Toast.LENGTH_SHORT).show()\n }\n }\n }\n\n fun refreshUserInfo() {\n getPreferences(MODE_PRIVATE)?.apply {\n val name = getString(\"nickname\", getString(\"username\", \"\"))\n val avatar = getString(\"avatar\", \"\")\n if(name != \"\") navttitle.text = name\n else navttitle.setText(R.string.noLogin)\n if(avatar != \"\")\n Glide.with(this@MainActivity).load(avatar)\n .apply(RequestOptions.bitmapTransform(CircleCrop()))\n .into(navhicon)\n }\n }\n\n private fun checkReadPermission(): Boolean {\n return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N && ContextCompat.checkSelfPermission(\n this,\n Manifest.permission.READ_EXTERNAL_STORAGE\n ) != PackageManager.PERMISSION_GRANTED\n ) {\n ActivityCompat.requestPermissions(\n this,\n arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), MSG_CROP_IMAGE\n )\n false\n } else true\n }\n\n @SuppressLint(\"IntentReset\")\n private fun pickPicture() {\n val i = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)\n i.type = \"image/*\"\n startActivityForResult(i, MSG_CROP_IMAGE)\n }\n\n private fun saveFile(uri: Uri) {\n //val f = File(getExternalFilesDir(\"\"), \"headPic\")\n val fd = contentResolver.openFileDescriptor(uri, \"r\")\n fd?.fileDescriptor?.let {\n val fi = FileInputStream(it)\n val fo = headPic.outputStream()\n fi.copyTo(fo)\n fi.close()\n fo.close()\n }\n fd?.close()\n }\n\n private fun checkHeadPicture() {\n //val hp = File(getExternalFilesDir(\"\"), \"headPic\")\n if (headPic.exists()) navhbg.setImageURI(headPic.toUri())\n }\n\n private fun cropImageUri() {\n val op = UCrop.Options()\n val r = navhbg.width.toFloat() / navhbg.height.toFloat()\n Log.d(\"MyMain\", \"Img info: (${navhbg.width}, ${navhbg.height})\")\n Log.d(\"MyMain\", \"Result code: ${UCrop.REQUEST_CROP}\")\n if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {\n op.setCompressionFormat(Bitmap.CompressFormat.WEBP_LOSSY)\n } else {\n op.setCompressionFormat(Bitmap.CompressFormat.WEBP)\n }\n op.setStatusBarColor(resources.getColor(R.color.colorPrimaryDark, theme))\n op.setToolbarColor(resources.getColor(R.color.colorPrimary, theme))\n op.setActiveControlsWidgetColor(resources.getColor(R.color.colorAccent, theme))\n UCrop.of(headPic.toUri(), headPic.toUri())\n .withAspectRatio(r, 1F)\n .withMaxResultSize(navhbg.width, navhbg.height)\n .withOptions(op)\n .start(this)\n }\n\n private fun checkUpdate(ignoreSkip: Boolean) {\n Thread{\n Update.checkUpdate(this, toolsBox, ignoreSkip)\n }.start()\n }\n\n private fun showAbout() {\n val dl = android.app.AlertDialog.Builder(this)\n dl.setMessage(R.string.app_description)\n dl.setTitle(\"${getString(R.string.action_info)} ${BuildConfig.VERSION_NAME}\")\n dl.setIcon(R.mipmap.ic_launcher)\n dl.setPositiveButton(android.R.string.ok) { _, _ -> }\n dl.setNeutralButton(R.string.check_update) {_, _ ->\n checkUpdate(true)\n }\n dl.show()\n }\n\n @SuppressLint(\"CheckResult\")\n fun onNavTInfoClicked(it: View) {\n MaterialDialog(this).show {\n input(prefill = (it as TextView).text) { _, charSequence ->\n it.text = charSequence\n getPreferences(MODE_PRIVATE).edit {\n putString(\"navTextInfo\", charSequence.toString())\n apply()\n }\n }\n positiveButton(android.R.string.ok)\n title(R.string.navTextInfoInputHint)\n }\n }\n\n fun onNavHBgClicked(v: View) {\n if (checkReadPermission()) pickPicture()\n }\n\n fun startLoginActivity(v: View){\n startActivity(Intent(this, LoginActivity::class.java))\n }\n\n companion object{\n var mainWeakReference: WeakReference? = null\n var isDrawerClosed = true\n var ime: InputMethodManager? = null\n const val MSG_CROP_IMAGE = 1\n var shelf: Shelf? = null\n get() {\n if (field != null) return field\n return mainWeakReference?.get()?.let {\n field = Shelf(\n it.getPreferences(Context.MODE_PRIVATE)\n .getString(\"token\", \"\")?:return@let null) { id ->\n return@Shelf it.getString(id)\n }\n field\n }\n }\n var member: Member? = null\n get() {\n if (field != null) return field\n return mainWeakReference?.get()?.let {\n it.getPreferences(MODE_PRIVATE)?.let { pref ->\n field = Member(pref) { id ->\n return@Member it.getString(id)\n }\n }\n field\n }\n }\n }\n} +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/app/src/main/java/top/fumiama/copymanga/MainActivity.kt b/app/src/main/java/top/fumiama/copymanga/MainActivity.kt +--- a/app/src/main/java/top/fumiama/copymanga/MainActivity.kt (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/app/src/main/java/top/fumiama/copymanga/MainActivity.kt (date 1709887113979) +@@ -2,6 +2,7 @@ + + import android.Manifest + import android.annotation.SuppressLint ++import android.app.Activity + import android.content.Context + import android.content.Intent + import android.content.pm.PackageManager +@@ -18,6 +19,7 @@ + import android.view.inputmethod.InputMethodManager + import android.widget.TextView + import android.widget.Toast ++import androidx.activity.result.contract.ActivityResultContracts + import androidx.appcompat.app.AlertDialog + import androidx.appcompat.app.AppCompatActivity + import androidx.core.app.ActivityCompat +@@ -25,6 +27,7 @@ + import androidx.core.content.edit + import androidx.core.net.toUri + import androidx.drawerlayout.widget.DrawerLayout ++import androidx.lifecycle.lifecycleScope + import androidx.navigation.NavController + import androidx.navigation.findNavController + import androidx.navigation.ui.AppBarConfiguration +@@ -40,6 +43,9 @@ + import kotlinx.android.synthetic.main.activity_main.* + import kotlinx.android.synthetic.main.app_bar_main.* + import kotlinx.android.synthetic.main.nav_header_main.* ++import kotlinx.coroutines.Dispatchers ++import kotlinx.coroutines.launch ++import kotlinx.coroutines.withContext + import top.fumiama.copymanga.manga.Shelf + import top.fumiama.copymanga.tools.ui.UITools + import top.fumiama.copymanga.ui.book.BookFragment.Companion.bookHandler +@@ -64,7 +70,6 @@ + private lateinit var headPic: File + lateinit var toolsBox: UITools + +- private var latestDestination = 0 + private var isMenuWaiting = false + + override fun onCreate(savedInstanceState: Bundle?) { +@@ -114,6 +119,7 @@ + + ime = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + ++ var latestDestination: Int + navController!!.addOnDestinationChangedListener { _, destination, _ -> + latestDestination = destination.id + Log.d("MyMA", "latestDestination: $latestDestination") +@@ -122,51 +128,16 @@ + } + isMenuWaiting = true + Log.d("MyMA", "start menu waiting") +- Thread { +- sleep(1000) +- isMenuWaiting = false +- Log.d("MyMA", "finish menu waiting") +- runOnUiThread { +- when (latestDestination) { +- R.id.nav_home -> { +- Log.d("MyMA", "enter home") +- menuMain?.findItem(R.id.action_info)?.isVisible = true +- menuMain?.findItem(R.id.action_download)?.isVisible = false +- menuMain?.findItem(R.id.action_sort)?.isVisible = false +- } +- R.id.nav_book -> { +- Log.d("MyMA", "enter book") +- menuMain?.findItem(R.id.action_info)?.isVisible = false +- menuMain?.findItem(R.id.action_download)?.isVisible = true +- menuMain?.findItem(R.id.action_sort)?.isVisible = false +- } +- R.id.nav_group -> { +- Log.d("MyMA", "enter group") +- menuMain?.findItem(R.id.action_info)?.isVisible = false +- menuMain?.findItem(R.id.action_download)?.isVisible = false +- menuMain?.findItem(R.id.action_sort)?.isVisible = true +- } +- R.id.nav_new_download -> { +- Log.d("MyMA", "enter new_download") +- menuMain?.findItem(R.id.action_info)?.isVisible = false +- menuMain?.findItem(R.id.action_download)?.isVisible = false +- menuMain?.findItem(R.id.action_sort)?.isVisible = true +- } +- R.id.nav_rank -> { +- Log.d("MyMA", "enter rank") +- menuMain?.findItem(R.id.action_info)?.isVisible = false +- menuMain?.findItem(R.id.action_download)?.isVisible = false +- menuMain?.findItem(R.id.action_sort)?.isVisible = true +- } +- else -> { +- Log.d("MyMA", "enter others") +- menuMain?.findItem(R.id.action_info)?.isVisible = false +- menuMain?.findItem(R.id.action_download)?.isVisible = false +- menuMain?.findItem(R.id.action_sort)?.isVisible = false +- } +- } +- } +- }.start() ++ lifecycleScope.launch { ++ withContext(Dispatchers.IO) { ++ sleep(1000) ++ withContext(Dispatchers.Main) { ++ isMenuWaiting = false ++ Log.d("MyMA", "finish menu waiting") ++ changeMenuList(latestDestination) ++ } ++ } ++ } + } + } + +@@ -218,24 +189,6 @@ + return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp() + } + +- @Deprecated("Deprecated in Java") +- override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { +- super.onActivityResult(requestCode, resultCode, data) +- if (resultCode == RESULT_OK) when (requestCode) { +- UCrop.REQUEST_CROP -> { +- val fi = headPic.inputStream() +- navhbg.setImageBitmap(BitmapFactory.decodeStream(fi)) +- fi.close() +- } +- MSG_CROP_IMAGE -> { +- data?.data?.let { +- saveFile(it) +- cropImageUri() +- } +- } +- } +- } +- + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, +@@ -263,6 +216,47 @@ + } + } + ++ private fun changeMenuList(latestDestination: Int) { ++ when (latestDestination) { ++ R.id.nav_home -> { ++ Log.d("MyMA", "enter home") ++ menuMain?.findItem(R.id.action_info)?.isVisible = true ++ menuMain?.findItem(R.id.action_download)?.isVisible = false ++ menuMain?.findItem(R.id.action_sort)?.isVisible = false ++ } ++ R.id.nav_book -> { ++ Log.d("MyMA", "enter book") ++ menuMain?.findItem(R.id.action_info)?.isVisible = false ++ menuMain?.findItem(R.id.action_download)?.isVisible = true ++ menuMain?.findItem(R.id.action_sort)?.isVisible = false ++ } ++ R.id.nav_group -> { ++ Log.d("MyMA", "enter group") ++ menuMain?.findItem(R.id.action_info)?.isVisible = false ++ menuMain?.findItem(R.id.action_download)?.isVisible = false ++ menuMain?.findItem(R.id.action_sort)?.isVisible = true ++ } ++ R.id.nav_new_download -> { ++ Log.d("MyMA", "enter new_download") ++ menuMain?.findItem(R.id.action_info)?.isVisible = false ++ menuMain?.findItem(R.id.action_download)?.isVisible = false ++ menuMain?.findItem(R.id.action_sort)?.isVisible = true ++ } ++ R.id.nav_rank -> { ++ Log.d("MyMA", "enter rank") ++ menuMain?.findItem(R.id.action_info)?.isVisible = false ++ menuMain?.findItem(R.id.action_download)?.isVisible = false ++ menuMain?.findItem(R.id.action_sort)?.isVisible = true ++ } ++ else -> { ++ Log.d("MyMA", "enter others") ++ menuMain?.findItem(R.id.action_info)?.isVisible = false ++ menuMain?.findItem(R.id.action_download)?.isVisible = false ++ menuMain?.findItem(R.id.action_sort)?.isVisible = false ++ } ++ } ++ } ++ + private fun checkReadPermission(): Boolean { + return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N && ContextCompat.checkSelfPermission( + this, +@@ -277,11 +271,18 @@ + } else true + } + ++ private var pickerLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> ++ if (result.resultCode == Activity.RESULT_OK) result.data?.data?.let { ++ saveFile(it) ++ cropImageUri() ++ } else Toast.makeText(this, R.string.err_pick_img, Toast.LENGTH_SHORT).show() ++ } ++ + @SuppressLint("IntentReset") + private fun pickPicture() { + val i = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) + i.type = "image/*" +- startActivityForResult(i, MSG_CROP_IMAGE) ++ pickerLauncher.launch(i) + } + + private fun saveFile(uri: Uri) { +@@ -302,11 +303,18 @@ + if (headPic.exists()) navhbg.setImageURI(headPic.toUri()) + } + ++ private var cropLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> ++ if (result.resultCode == Activity.RESULT_OK) { ++ val fi = headPic.inputStream() ++ navhbg.setImageBitmap(BitmapFactory.decodeStream(fi)) ++ fi.close() ++ } else Toast.makeText(this, R.string.err_crop_img, Toast.LENGTH_SHORT).show() ++ } ++ + private fun cropImageUri() { + val op = UCrop.Options() + val r = navhbg.width.toFloat() / navhbg.height.toFloat() + Log.d("MyMain", "Img info: (${navhbg.width}, ${navhbg.height})") +- Log.d("MyMain", "Result code: ${UCrop.REQUEST_CROP}") + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + op.setCompressionFormat(Bitmap.CompressFormat.WEBP_LOSSY) + } else { +@@ -315,17 +323,17 @@ + op.setStatusBarColor(resources.getColor(R.color.colorPrimaryDark, theme)) + op.setToolbarColor(resources.getColor(R.color.colorPrimary, theme)) + op.setActiveControlsWidgetColor(resources.getColor(R.color.colorAccent, theme)) +- UCrop.of(headPic.toUri(), headPic.toUri()) ++ cropLauncher.launch(UCrop.of(headPic.toUri(), headPic.toUri()) + .withAspectRatio(r, 1F) + .withMaxResultSize(navhbg.width, navhbg.height) + .withOptions(op) +- .start(this) ++ .getIntent(this)) + } + + private fun checkUpdate(ignoreSkip: Boolean) { +- Thread{ +- Update.checkUpdate(this, toolsBox, ignoreSkip) +- }.start() ++ lifecycleScope.launch { ++ Update.checkUpdate(this@MainActivity, toolsBox, ignoreSkip) ++ } + } + + private fun showAbout() { +Index: app/src/main/java/top/fumiama/copymanga/ui/download/NewDownloadFragment.kt +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>package top.fumiama.copymanga.ui.download\n\nimport android.app.AlertDialog\nimport android.content.Intent\nimport android.os.Bundle\nimport android.provider.DocumentsContract\nimport android.util.Log\nimport android.view.View\nimport android.widget.Toast\nimport androidx.core.content.FileProvider\nimport androidx.core.net.toUri\nimport androidx.fragment.app.Fragment\nimport androidx.navigation.fragment.findNavController\nimport androidx.preference.PreferenceManager\nimport kotlinx.android.synthetic.main.line_lazybooklines.*\nimport top.fumiama.copymanga.MainActivity\nimport top.fumiama.copymanga.manga.Reader\nimport top.fumiama.copymanga.template.general.MangaPagesFragmentTemplate\nimport top.fumiama.copymanga.template.ui.CardList\nimport top.fumiama.copymanga.tools.ui.Navigate\nimport top.fumiama.copymanga.tools.ui.UITools\nimport top.fumiama.copymanga.tools.file.FileUtils\nimport top.fumiama.copymanga.ui.comicdl.ComicDlFragment\nimport top.fumiama.dmzj.copymanga.R\nimport java.io.File\nimport java.lang.Thread.sleep\nimport java.lang.ref.WeakReference\n\n@OptIn(ExperimentalStdlibApi::class)\nclass NewDownloadFragment: MangaPagesFragmentTemplate(R.layout.fragment_newdownload, forceLoad = true) {\n private var sortedBookList: List? = null\n private val oldDlCardName = MainActivity.mainWeakReference?.get()?.getString(R.string.old_download_card_name)!!\n private val extDir = MainActivity.mainWeakReference?.get()?.getExternalFilesDir(\"\")\n private var isReverse = false\n private var isContentChanged = false\n private var exit = false\n private var showAll = false\n override fun onCreate(savedInstanceState: Bundle?) {\n super.onCreate(savedInstanceState)\n wn = WeakReference(this)\n val settingsPref = MainActivity.mainWeakReference?.get()?.let { PreferenceManager.getDefaultSharedPreferences(it) }\n showAll = settingsPref?.getBoolean(\"settings_cat_md_sw_show_0m_manga\", false)?:false\n }\n\n override fun onPause() {\n super.onPause()\n exit = true\n }\n\n override fun onResume() {\n super.onResume()\n exit = false\n }\n\n override fun onDestroy() {\n super.onDestroy()\n wn = null\n exit = true\n }\n\n override fun addPage() {\n super.addPage()\n if(isRefresh){\n page = 0\n isRefresh = false\n }\n if(!isEnd) {\n if(sortedBookList == null || isContentChanged) {\n Log.d(\"MyNDF\", \"Sorting books...\")\n sortedBookList = extDir?.listFiles()?.sortedBy {\n return@sortedBy Reader.getComicPathWordInFile(it)\n }\n if (isReverse) {\n Log.d(\"MyNDF\", \"reversed...\")\n sortedBookList = sortedBookList?.asReversed()\n }\n if (!showAll) {\n sortedBookList = sortedBookList?.filter {\n return@filter FileUtils.sizeOf(it) / 1048576 > 0\n }\n }\n isContentChanged = false\n }\n Log.d(\"MyNDF\", \"Start drawing cards\")\n cardList?.addCard(oldDlCardName, path = oldDlCardName)\n var cnt = 1\n sortedBookList?.let {\n for(i in it.listIterator(page)) {\n if(cardList?.exitCardList != false) return\n page++ // page is actually count\n val chosenJson = File(i, \"info.bin\")\n val newJson = File(i, \"info.json\")\n val bookSize = (FileUtils.sizeOf(i)/1048576).toInt()\n when {\n chosenJson.exists() -> continue // unsupported old folder\n newJson.exists() -> {\n if(cardList?.exitCardList != false) return\n cardList?.addCard(i.name, \"\\n${bookSize}MB\")\n cnt++\n }\n }\n if (cnt >= 21) break\n }\n if(page >= it.size) {\n isEnd = true\n }\n }\n }\n onLoadFinish()\n }\n\n override fun initCardList(weakReference: WeakReference) {\n super.initCardList(weakReference)\n cardList = CardList(weakReference, cardWidth, cardHeight, cardPerRow)\n cardList?.initClickListeners = object : CardList.InitClickListeners {\n override fun prepareListeners(v: View, name: String, path: String?, chapterUUID: String?, pn: Int?) {\n v.setOnClickListener {\n if(name==oldDlCardName && path == oldDlCardName) {\n Navigate.safeNavigateTo(findNavController(), R.id.action_nav_new_download_to_nav_download)\n return@setOnClickListener\n }\n callDownloadFragment(name)\n }\n v.setOnLongClickListener {\n if (name == oldDlCardName && path == oldDlCardName) {\n return@setOnLongClickListener false\n }\n val chosenFile = File(extDir, name)\n AlertDialog.Builder(context)\n .setIcon(R.drawable.ic_launcher_foreground)\n .setTitle(R.string.new_download_card_option_hint)\n .setItems(arrayOf(\"删除数据\", \"前往详情\")) { d, p ->\n d.cancel()\n when (p) {\n 0 -> {\n AlertDialog.Builder(context)\n .setIcon(R.drawable.ic_launcher_foreground).setMessage(\"删除下载的漫画${name}吗?\")\n .setTitle(\"提示\").setPositiveButton(android.R.string.ok) { _, _ ->\n if (chosenFile.exists()) Thread {\n FileUtils.recursiveRemove(chosenFile)\n activity?.runOnUiThread {\n it.visibility = View.INVISIBLE\n }\n }.start()\n }.setNegativeButton(android.R.string.cancel) { _, _ -> }\n .show()\n }\n 1 -> {\n val bundle = Bundle()\n bundle.putBoolean(\"loadJson\", true)\n bundle.putString(\"name\", name)\n Navigate.safeNavigateTo(findNavController(), R.id.action_nav_new_download_to_nav_book, bundle)\n }\n }\n }\n .show()\n\n true\n }\n }\n }\n }\n\n private fun callDownloadFragment(name: String){\n val bundle = Bundle()\n Log.d(\"MyNDF\", \"Call dl and is new.\")\n bundle.putBoolean(\"loadJson\", true)\n bundle.putString(\"name\", name)\n ComicDlFragment.json = File(File(extDir, name), \"info.json\").readText()\n Log.d(\"MyNDF\", \"root view: $rootView\")\n Log.d(\"MyNDF\", \"action_nav_new_download_to_nav_group\")\n Navigate.safeNavigateTo(findNavController(), R.id.action_nav_new_download_to_nav_group, bundle)\n }\n\n fun showReverseInfo(toolsBox: UITools) {\n if (exit) return\n toolsBox.buildInfo(\"反转排序\", \"将按当前顺序的倒序显示下载的漫画\",\n \"确定\", null, \"取消\", {\n isReverse = !isReverse\n isContentChanged = true\n reset()\n Thread {\n sleep(600)\n addPage()\n }.start()\n }\n )\n }\n\n override fun onLoadFinish() {\n super.onLoadFinish()\n activity?.runOnUiThread {\n mypl.visibility = View.GONE\n }\n }\n\n companion object {\n var wn: WeakReference? = null\n }\n}\n +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +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 +--- a/app/src/main/java/top/fumiama/copymanga/ui/download/NewDownloadFragment.kt (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/app/src/main/java/top/fumiama/copymanga/ui/download/NewDownloadFragment.kt (date 1709909463888) +@@ -10,9 +10,13 @@ + import androidx.core.content.FileProvider + import androidx.core.net.toUri + import androidx.fragment.app.Fragment ++import androidx.lifecycle.lifecycleScope + import androidx.navigation.fragment.findNavController + import androidx.preference.PreferenceManager + import kotlinx.android.synthetic.main.line_lazybooklines.* ++import kotlinx.coroutines.Dispatchers ++import kotlinx.coroutines.launch ++import kotlinx.coroutines.withContext + import top.fumiama.copymanga.MainActivity + import top.fumiama.copymanga.manga.Reader + import top.fumiama.copymanga.template.general.MangaPagesFragmentTemplate +@@ -64,49 +68,53 @@ + page = 0 + isRefresh = false + } +- if(!isEnd) { +- if(sortedBookList == null || isContentChanged) { +- Log.d("MyNDF", "Sorting books...") +- sortedBookList = extDir?.listFiles()?.sortedBy { +- return@sortedBy Reader.getComicPathWordInFile(it) +- } +- if (isReverse) { +- Log.d("MyNDF", "reversed...") +- sortedBookList = sortedBookList?.asReversed() +- } +- if (!showAll) { +- sortedBookList = sortedBookList?.filter { +- return@filter FileUtils.sizeOf(it) / 1048576 > 0 +- } +- } +- isContentChanged = false +- } +- Log.d("MyNDF", "Start drawing cards") +- cardList?.addCard(oldDlCardName, path = oldDlCardName) +- var cnt = 1 +- sortedBookList?.let { +- for(i in it.listIterator(page)) { +- if(cardList?.exitCardList != false) return +- page++ // page is actually count +- val chosenJson = File(i, "info.bin") +- val newJson = File(i, "info.json") +- val bookSize = (FileUtils.sizeOf(i)/1048576).toInt() +- when { +- chosenJson.exists() -> continue // unsupported old folder +- newJson.exists() -> { +- if(cardList?.exitCardList != false) return +- cardList?.addCard(i.name, "\n${bookSize}MB") +- cnt++ +- } +- } +- if (cnt >= 21) break +- } +- if(page >= it.size) { +- isEnd = true +- } +- } +- } +- onLoadFinish() ++ lifecycleScope.launch { ++ withContext(Dispatchers.IO) { ++ if(!isEnd) { ++ if(sortedBookList == null || isContentChanged) { ++ Log.d("MyNDF", "Sorting books...") ++ sortedBookList = extDir?.listFiles()?.sortedBy { ++ return@sortedBy Reader.getComicPathWordInFile(it) ++ } ++ if (isReverse) { ++ Log.d("MyNDF", "reversed...") ++ sortedBookList = sortedBookList?.asReversed() ++ } ++ if (!showAll) { ++ sortedBookList = sortedBookList?.filter { ++ return@filter FileUtils.sizeOf(it) / 1048576 > 0 ++ } ++ } ++ isContentChanged = false ++ } ++ Log.d("MyNDF", "Start drawing cards") ++ cardList?.addCard(oldDlCardName, path = oldDlCardName) ++ var cnt = 1 ++ sortedBookList?.let { ++ for(i in it.listIterator(page)) { ++ if(cardList?.exitCardList != false) return@withContext ++ page++ // page is actually count ++ val chosenJson = File(i, "info.bin") ++ val newJson = File(i, "info.json") ++ val bookSize = (FileUtils.sizeOf(i)/1048576).toInt() ++ when { ++ chosenJson.exists() -> continue // unsupported old folder ++ newJson.exists() -> { ++ if(cardList?.exitCardList != false) return@withContext ++ cardList?.addCard(i.name, "\n${bookSize}MB") ++ cnt++ ++ } ++ } ++ if (cnt >= 21) break ++ } ++ if(page >= it.size) { ++ isEnd = true ++ } ++ } ++ } ++ onLoadFinish() ++ } ++ } + } + + override fun initCardList(weakReference: WeakReference) { +@@ -136,12 +144,14 @@ + AlertDialog.Builder(context) + .setIcon(R.drawable.ic_launcher_foreground).setMessage("删除下载的漫画${name}吗?") + .setTitle("提示").setPositiveButton(android.R.string.ok) { _, _ -> +- if (chosenFile.exists()) Thread { +- FileUtils.recursiveRemove(chosenFile) +- activity?.runOnUiThread { +- it.visibility = View.INVISIBLE ++ if (chosenFile.exists()) lifecycleScope.launch { ++ withContext(Dispatchers.IO) { ++ FileUtils.recursiveRemove(chosenFile) ++ withContext(Dispatchers.Main) { ++ it.visibility = View.INVISIBLE ++ } + } +- }.start() ++ } + }.setNegativeButton(android.R.string.cancel) { _, _ -> } + .show() + } +Index: app/src/main/res/layout/line_bookinfo.xml +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>\n\n\n \n\n \n\n \n\n \n \n +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/app/src/main/res/layout/line_bookinfo.xml b/app/src/main/res/layout/line_bookinfo.xml +--- a/app/src/main/res/layout/line_bookinfo.xml (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/app/src/main/res/layout/line_bookinfo.xml (date 1709897914592) +@@ -27,22 +27,32 @@ + layout="@layout/card_book" + android:layout_width="@dimen/book_card_width" + android:layout_height="0dp" +- app:layout_constraintBottom_toBottomOf="parent" ++ app:layout_constraintBottom_toBottomOf="@+id/lbitb" + app:layout_constraintEnd_toStartOf="@+id/lbitb" + app:layout_constraintHorizontal_weight="1" + app:layout_constraintStart_toStartOf="parent" +- app:layout_constraintTop_toTopOf="parent" +- app:layout_constraintVertical_bias="0.499" /> ++ app:layout_constraintTop_toTopOf="parent" /> + + ++ ++ + + +\ No newline at end of file +Index: build.gradle +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>// Top-level build file where you can add configuration options common to all sub-projects/modules.\nbuildscript {\n ext.kotlin_version = '1.7.10'\n repositories {\n google()\n jcenter()\n mavenCentral()\n mavenCentral()\n maven { url 'https://maven.google.com' }\n maven { url \"https://jitpack.io\" }\n }\n dependencies {\n classpath 'com.android.tools.build:gradle:8.1.1'\n classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version\"\n\n // NOTE: Do not place your application dependencies here; they belong\n // in the individual module build.gradle files\n }\n}\n\nallprojects {\n repositories {\n google()\n jcenter()\n mavenCentral()\n maven { url \"https://jitpack.io\" }\n }\n}\n\ntask clean(type: Delete) {\n delete rootProject.buildDir\n}\n +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/build.gradle b/build.gradle +--- a/build.gradle (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/build.gradle (date 1709881875422) +@@ -10,7 +10,7 @@ + maven { url "https://jitpack.io" } + } + dependencies { +- classpath 'com.android.tools.build:gradle:8.1.1' ++ classpath 'com.android.tools.build:gradle:8.2.2' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + + // NOTE: Do not place your application dependencies here; they belong +@@ -27,6 +27,6 @@ + } + } + +-task clean(type: Delete) { ++tasks.register('clean', Delete) { + delete rootProject.buildDir + } +Index: app/src/main/res/drawable-anydpi/ic_circle.xml +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/app/src/main/res/drawable-anydpi/ic_circle.xml b/app/src/main/res/drawable-anydpi/ic_circle.xml +new file mode 100644 +--- /dev/null (date 1709899198517) ++++ b/app/src/main/res/drawable-anydpi/ic_circle.xml (date 1709899198517) +@@ -0,0 +1,10 @@ ++ ++ ++ ++ +\ No newline at end of file +Index: app/src/main/res/layout/page_nested_list.xml +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/app/src/main/res/layout/page_nested_list.xml b/app/src/main/res/layout/page_nested_list.xml +new file mode 100644 +--- /dev/null (date 1709903119912) ++++ b/app/src/main/res/layout/page_nested_list.xml (date 1709903119912) +@@ -0,0 +1,13 @@ ++ ++ ++ ++ ++ +\ No newline at end of file +Index: gradle/wrapper/gradle-wrapper.properties +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>#Fri Sep 04 18:15:43 CST 2020\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-8.0-all.zip\n +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>ISO-8859-1 +=================================================================== +diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties +--- a/gradle/wrapper/gradle-wrapper.properties (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/gradle/wrapper/gradle-wrapper.properties (date 1709880931213) +@@ -3,4 +3,4 @@ + distributionPath=wrapper/dists + zipStoreBase=GRADLE_USER_HOME + zipStorePath=wrapper/dists +-distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-all.zip ++distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-all.zip +Index: app/src/main/java/top/fumiama/copymanga/ui/book/BookFragment.kt +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>package top.fumiama.copymanga.ui.book\n\nimport android.annotation.SuppressLint\nimport android.content.Context.MODE_PRIVATE\nimport android.os.Bundle\nimport android.util.Log\nimport android.view.View\nimport android.widget.Toast\nimport androidx.navigation.fragment.findNavController\nimport com.google.gson.Gson\nimport kotlinx.android.synthetic.main.app_bar_main.*\nimport kotlinx.android.synthetic.main.fragment_book.*\nimport kotlinx.android.synthetic.main.line_bookinfo_text.*\nimport kotlinx.android.synthetic.main.line_booktandb.*\nimport top.fumiama.copymanga.MainActivity\nimport top.fumiama.copymanga.MainActivity.Companion.mainWeakReference\nimport top.fumiama.copymanga.json.VolumeStructure\nimport top.fumiama.copymanga.manga.Reader\nimport top.fumiama.copymanga.template.general.NoBackRefreshFragment\nimport top.fumiama.copymanga.tools.ui.Navigate\nimport top.fumiama.copymanga.ui.comicdl.ComicDlFragment\nimport top.fumiama.dmzj.copymanga.R\nimport java.io.File\nimport java.lang.Thread.sleep\nimport java.lang.ref.WeakReference\n\nclass BookFragment: NoBackRefreshFragment(R.layout.fragment_book) {\n var isOnPause = false\n private var mBookHandler: BookHandler? = null\n\n override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n super.onViewCreated(view, savedInstanceState)\n\n ComicDlFragment.exit = false\n fbl?.setPadding(0, 0, 0, navBarHeight)\n\n if(isFirstInflate) {\n var path = \"\"\n arguments?.apply {\n if (getBoolean(\"loadJson\")) {\n getString(\"name\")?.let { name ->\n mainWeakReference?.get()?.getExternalFilesDir(\"\")?.let {\n Gson().fromJson(File(File(it, name), \"info.json\").readText(), Array::class.java)\n }?.apply {\n if (isEmpty() || get(0).results.list.isEmpty()) {\n findNavController().popBackStack()\n return\n }\n else {\n path = get(0).results.list[0].comic_path_word\n }\n }\n }\n } else getString(\"path\").let {\n if (it != null) path = it\n else {\n findNavController().popBackStack()\n return\n }\n }\n }\n mBookHandler = BookHandler(WeakReference(this), path)\n Log.d(\"MyBF\", \"read path: $path\")\n bookHandler = mBookHandler\n Thread {\n sleep(600)\n mBookHandler?.startLoad()\n }.start()\n } else {\n bookHandler = mBookHandler\n }\n }\n\n override fun onResume() {\n super.onResume()\n isOnPause = false\n bookHandler = mBookHandler\n mainWeakReference?.get()?.apply {\n toolbar.title = mBookHandler?.book?.results?.comic?.name\n }\n setStartRead()\n }\n\n override fun onPause() {\n super.onPause()\n isOnPause = true\n }\n\n override fun onDestroy() {\n super.onDestroy()\n mBookHandler?.destroy()\n mBookHandler?.ads?.forEach {\n it.exit = true\n }\n bookHandler = null\n }\n\n fun setStartRead() {\n if(mBookHandler?.chapterNames?.isNotEmpty() == true) mainWeakReference?.get()?.apply {\n mBookHandler?.book?.results?.comic?.let { comic ->\n getPreferences(MODE_PRIVATE).getInt(comic.name, -1).let { p ->\n this@BookFragment.lbbstart.apply {\n var i = 0\n if(p >= 0) {\n text = mBookHandler!!.chapterNames[p]\n i = p\n }\n setOnClickListener {\n mBookHandler?.urlArray?.let {\n Reader.viewMangaAt(comic.name, i, it)\n }\n }\n }\n }\n }\n }\n }\n\n @SuppressLint(\"SetTextI18n\")\n fun setAddToShelf() {\n if(mBookHandler?.chapterNames?.isNotEmpty() == true) {\n val b = MainActivity.shelf?.query(mBookHandler?.path!!)\n mBookHandler?.collect = b?.results?.collect?:-2\n Log.d(\"MyBF\", \"get collect of ${mBookHandler?.path} = ${mBookHandler?.collect}\")\n b?.results?.browse?.chapter_name?.let { name ->\n btsub.text = \"${btsub.text} ${getString(R.string.text_format_cloud_read_to).format(name)}\"\n }\n mBookHandler?.collect?.let { collect ->\n if (collect > 0) {\n this@BookFragment.lbbsub.setText(R.string.button_sub_subscribed)\n }\n }\n mBookHandler?.book?.results?.comic?.let { comic ->\n this@BookFragment.lbbsub.setOnClickListener {\n if (this@BookFragment.lbbsub.text != getString(R.string.button_sub)) {\n mBookHandler?.collect?.let { collect ->\n if (collect < 0) return@setOnClickListener\n Thread{\n val re = MainActivity.shelf?.del(collect)\n activity?.runOnUiThread {\n Toast.makeText(context, re, Toast.LENGTH_SHORT).show()\n if (re == \"请求成功\") {\n this@BookFragment.lbbsub.setText(R.string.button_sub)\n }\n }\n }.start()\n }\n return@setOnClickListener\n }\n Thread{\n val re = MainActivity.shelf?.add(comic.uuid)\n activity?.runOnUiThread {\n Toast.makeText(context, re, Toast.LENGTH_SHORT).show()\n if (re == \"修改成功\") {\n this@BookFragment.lbbsub.setText(R.string.button_sub_subscribed)\n }\n }\n }.start()\n }\n }\n }\n }\n\n fun navigate2dl(){\n val bundle = Bundle()\n bundle.putString(\"path\", arguments?.getString(\"path\")?:\"null\")\n bundle.putString(\"name\", mBookHandler!!.book?.results?.comic?.name)\n if(mBookHandler!!.vols != null) {\n bundle.putBoolean(\"loadJson\", true)\n }\n bundle.putStringArray(\"group\", mBookHandler!!.gpws)\n bundle.putStringArray(\"groupNames\", mBookHandler!!.keys)\n bundle.putIntArray(\"count\", mBookHandler!!.cnts)\n findNavController().let {\n Navigate.safeNavigateTo(it, R.id.action_nav_book_to_nav_group, bundle)\n }\n }\n\n companion object {\n var bookHandler: BookHandler? = null\n }\n} +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +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 +--- a/app/src/main/java/top/fumiama/copymanga/ui/book/BookFragment.kt (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/app/src/main/java/top/fumiama/copymanga/ui/book/BookFragment.kt (date 1709903835366) +@@ -6,14 +6,18 @@ + import android.util.Log + import android.view.View + import android.widget.Toast ++import androidx.lifecycle.lifecycleScope + import androidx.navigation.fragment.findNavController + import com.google.gson.Gson + 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_bookinfo_text.* + import kotlinx.android.synthetic.main.line_booktandb.* ++import kotlinx.coroutines.Dispatchers ++import kotlinx.coroutines.launch ++import kotlinx.coroutines.withContext + import top.fumiama.copymanga.MainActivity +-import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference + import top.fumiama.copymanga.json.VolumeStructure + import top.fumiama.copymanga.manga.Reader + import top.fumiama.copymanga.template.general.NoBackRefreshFragment +@@ -32,14 +36,14 @@ + super.onViewCreated(view, savedInstanceState) + + ComicDlFragment.exit = false +- fbl?.setPadding(0, 0, 0, navBarHeight) ++ fbvp?.setPadding(0, 0, 0, navBarHeight) + + if(isFirstInflate) { + var path = "" + arguments?.apply { + if (getBoolean("loadJson")) { + getString("name")?.let { name -> +- mainWeakReference?.get()?.getExternalFilesDir("")?.let { ++ activity?.getExternalFilesDir("")?.let { + Gson().fromJson(File(File(it, name), "info.json").readText(), Array::class.java) + }?.apply { + if (isEmpty() || get(0).results.list.isEmpty()) { +@@ -62,10 +66,12 @@ + mBookHandler = BookHandler(WeakReference(this), path) + Log.d("MyBF", "read path: $path") + bookHandler = mBookHandler +- Thread { +- sleep(600) +- mBookHandler?.startLoad() +- }.start() ++ lifecycleScope.launch { ++ withContext(Dispatchers.IO) { ++ sleep(600) ++ mBookHandler?.startLoad() ++ } ++ } + } else { + bookHandler = mBookHandler + } +@@ -75,7 +81,7 @@ + super.onResume() + isOnPause = false + bookHandler = mBookHandler +- mainWeakReference?.get()?.apply { ++ activity?.apply { + toolbar.title = mBookHandler?.book?.results?.comic?.name + } + setStartRead() +@@ -96,7 +102,7 @@ + } + + fun setStartRead() { +- if(mBookHandler?.chapterNames?.isNotEmpty() == true) mainWeakReference?.get()?.apply { ++ if(mBookHandler?.chapterNames?.isNotEmpty() == true) activity?.apply { + mBookHandler?.book?.results?.comic?.let { comic -> + getPreferences(MODE_PRIVATE).getInt(comic.name, -1).let { p -> + this@BookFragment.lbbstart.apply { +@@ -118,12 +124,13 @@ + + @SuppressLint("SetTextI18n") + fun setAddToShelf() { +- if(mBookHandler?.chapterNames?.isNotEmpty() == true) { ++ if(mBookHandler?.chapterNames?.isNotEmpty() != true) return ++ lifecycleScope.launch { + val b = MainActivity.shelf?.query(mBookHandler?.path!!) + mBookHandler?.collect = b?.results?.collect?:-2 + Log.d("MyBF", "get collect of ${mBookHandler?.path} = ${mBookHandler?.collect}") +- b?.results?.browse?.chapter_name?.let { name -> +- btsub.text = "${btsub.text} ${getString(R.string.text_format_cloud_read_to).format(name)}" ++ tic.text = b?.results?.browse?.chapter_name?.let { name -> ++ getString(R.string.text_format_cloud_read_to).format(name) + } + mBookHandler?.collect?.let { collect -> + if (collect > 0) { +@@ -132,30 +139,24 @@ + } + mBookHandler?.book?.results?.comic?.let { comic -> + this@BookFragment.lbbsub.setOnClickListener { +- if (this@BookFragment.lbbsub.text != getString(R.string.button_sub)) { +- mBookHandler?.collect?.let { collect -> +- if (collect < 0) return@setOnClickListener +- Thread{ ++ lifecycleScope.launch clickLaunch@ { ++ if (this@BookFragment.lbbsub.text != getString(R.string.button_sub)) { ++ mBookHandler?.collect?.let { collect -> ++ if (collect < 0) return@clickLaunch + val re = MainActivity.shelf?.del(collect) +- activity?.runOnUiThread { +- Toast.makeText(context, re, Toast.LENGTH_SHORT).show() +- if (re == "请求成功") { +- this@BookFragment.lbbsub.setText(R.string.button_sub) +- } +- } +- }.start() ++ Toast.makeText(context, re, Toast.LENGTH_SHORT).show() ++ if (re == "请求成功") { ++ this@BookFragment.lbbsub.setText(R.string.button_sub) ++ } ++ } ++ return@clickLaunch + } +- return@setOnClickListener +- } +- Thread{ + val re = MainActivity.shelf?.add(comic.uuid) +- activity?.runOnUiThread { +- Toast.makeText(context, re, Toast.LENGTH_SHORT).show() +- if (re == "修改成功") { +- this@BookFragment.lbbsub.setText(R.string.button_sub_subscribed) +- } +- } +- }.start() ++ Toast.makeText(context, re, Toast.LENGTH_SHORT).show() ++ if (re == "修改成功") { ++ this@BookFragment.lbbsub.setText(R.string.button_sub_subscribed) ++ } ++ } + } + } + } +Index: app/src/main/java/top/fumiama/copymanga/update/SimpleKanban.kt +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>package top.fumiama.copymanga.update\n\nimport android.util.Log\n\nclass SimpleKanban(private val client: Client, private val pwd: String) { //must run in thread\n private val raw: ByteArray?\n get() {\n var times = 3\n var re: ByteArray\n var firstRecv: ByteArray\n do {\n re = byteArrayOf()\n if(client.initConnect()) {\n client.sendMessage(\"${pwd}catquit\")\n client.receiveRawMessage(33) //Welcome to simple kanban server.\n try {\n firstRecv = client.receiveRawMessage(4) //le\n val length = convert2Int(firstRecv)\n Log.d(\"MySK\", \"Msg len: $length\")\n if(firstRecv.size > 4) re += firstRecv.copyOfRange(4, firstRecv.size)\n re += client.receiveRawMessage(length - re.size, setProgress = true)\n break\n } catch (e: Exception) {\n e.printStackTrace()\n }\n client.closeConnect()\n }\n } while (times-- > 0)\n return if(re.isEmpty()) null else re\n }\n\n private fun convert2Int(buffer: ByteArray) =\n (buffer[3].toInt() and 0xff shl 24) or\n (buffer[2].toInt() and 0xff shl 16) or\n (buffer[1].toInt() and 0xff shl 8) or\n (buffer[0].toInt() and 0xff)\n\n fun fetchRaw(doOnLoadFailure: ()->Unit = {\n Log.d(\"MySD\", \"Fetch dict failed\")\n }, doOnLoadSuccess: (data: ByteArray)->Unit = {\n Log.d(\"MySD\", \"Fetch dict success\")\n }) {\n raw?.apply {\n doOnLoadSuccess(this)\n }?:doOnLoadFailure()\n }\n\n operator fun get(version: Int): String =\n if(client.initConnect()) {\n client.sendMessage(\"${pwd}get${version}quit\")\n client.receiveRawMessage(36) //Welcome to simple kanban server. get\n val r = try {\n val firstRecv = client.receiveRawMessage(4)\n if(firstRecv.decodeToString() == \"null\") \"null\"\n else {\n val length = convert2Int(firstRecv)\n Log.d(\"MySK\", \"Msg len: $length\")\n var re = byteArrayOf()\n if(firstRecv.size > 4) re += firstRecv.copyOfRange(4, firstRecv.size)\n re += client.receiveRawMessage(length - re.size)\n if(re.isNotEmpty()) re.decodeToString() else \"null\"\n }\n } catch (e: Exception){\n e.printStackTrace()\n \"null\"\n }\n client.closeConnect()\n r\n } else \"null\"\n} +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/app/src/main/java/top/fumiama/copymanga/update/SimpleKanban.kt b/app/src/main/java/top/fumiama/copymanga/update/SimpleKanban.kt +--- a/app/src/main/java/top/fumiama/copymanga/update/SimpleKanban.kt (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/app/src/main/java/top/fumiama/copymanga/update/SimpleKanban.kt (date 1709886316131) +@@ -7,17 +7,17 @@ + get() { + var times = 3 + var re: ByteArray +- var firstRecv: ByteArray ++ var firstReceived: ByteArray + do { + re = byteArrayOf() + if(client.initConnect()) { + client.sendMessage("${pwd}catquit") + client.receiveRawMessage(33) //Welcome to simple kanban server. + try { +- firstRecv = client.receiveRawMessage(4) //le +- val length = convert2Int(firstRecv) ++ firstReceived = client.receiveRawMessage(4) //le ++ val length = convert2Int(firstReceived) + Log.d("MySK", "Msg len: $length") +- if(firstRecv.size > 4) re += firstRecv.copyOfRange(4, firstRecv.size) ++ if(firstReceived.size > 4) re += firstReceived.copyOfRange(4, firstReceived.size) + re += client.receiveRawMessage(length - re.size, setProgress = true) + break + } catch (e: Exception) { +@@ -35,9 +35,9 @@ + (buffer[1].toInt() and 0xff shl 8) or + (buffer[0].toInt() and 0xff) + +- fun fetchRaw(doOnLoadFailure: ()->Unit = { ++ suspend fun fetchRaw(doOnLoadFailure: suspend ()->Unit = { + Log.d("MySD", "Fetch dict failed") +- }, doOnLoadSuccess: (data: ByteArray)->Unit = { ++ }, doOnLoadSuccess: suspend (data: ByteArray)->Unit = { + Log.d("MySD", "Fetch dict success") + }) { + raw?.apply { +Index: .idea/gradle.xml +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>\n\n \n \n \n \n +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/.idea/gradle.xml b/.idea/gradle.xml +--- a/.idea/gradle.xml (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/.idea/gradle.xml (date 1709880886968) +@@ -4,10 +4,8 @@ + + \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n \n\n \n \n \n \n \n\n \n \n\n \n \n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n\n \n \n \n +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml +--- a/app/src/main/res/navigation/mobile_navigation.xml (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/app/src/main/res/navigation/mobile_navigation.xml (date 1709906072716) +@@ -224,7 +224,7 @@ + + + UTF-8 +=================================================================== +diff --git a/app/src/main/res/drawable-anydpi/ic_hot.xml b/app/src/main/res/drawable-anydpi/ic_hot.xml +new file mode 100644 +--- /dev/null (date 1709889333999) ++++ b/app/src/main/res/drawable-anydpi/ic_hot.xml (date 1709889333999) +@@ -0,0 +1,10 @@ ++ ++ ++ ++ +\ No newline at end of file +Index: app/src/main/java/top/fumiama/copymanga/ui/cardflow/rank/RankFragment.kt +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>package top.fumiama.copymanga.ui.cardflow.rank\n\nimport android.os.Bundle\nimport com.google.android.material.tabs.TabLayout\nimport kotlinx.android.synthetic.main.fragment_rank.*\nimport kotlinx.android.synthetic.main.line_rank.view.*\nimport top.fumiama.copymanga.MainActivity\nimport top.fumiama.copymanga.template.ui.InfoCardLoader\nimport top.fumiama.copymanga.tools.api.CMApi\nimport top.fumiama.copymanga.tools.ui.UITools\nimport top.fumiama.dmzj.copymanga.R\nimport java.lang.Thread.sleep\nimport java.lang.ref.WeakReference\n\n@ExperimentalStdlibApi\nclass RankFragment : InfoCardLoader(R.layout.fragment_rank, R.id.action_nav_rank_to_nav_book, true) {\n private val sortWay = listOf(\"day\", \"week\", \"month\", \"total\")\n private var sortValue = 0\n private val audienceWay = listOf(\"\", \"male\", \"female\")\n private var audience = 0 // 0 all 1 male 2 female\n\n override fun onCreate(savedInstanceState: Bundle?) {\n super.onCreate(savedInstanceState)\n wr = WeakReference(this)\n }\n\n override fun onPause() {\n super.onPause()\n ad?.exit = true\n }\n\n override fun onResume() {\n super.onResume()\n ad?.exit = true\n }\n\n override fun onDestroy() {\n super.onDestroy()\n wr = null\n ad?.exit = true\n }\n\n override fun getApiUrl() =\n getString(R.string.rankApiUrl).format(\n CMApi.myHostApiUrl,\n page * 21,\n sortWay[sortValue],\n audienceWay[audience]\n )\n\n override fun setListeners() {\n super.setListeners()\n frlai.lrt.addOnTabSelectedListener(object: TabLayout.OnTabSelectedListener {\n override fun onTabReselected(tab: TabLayout.Tab?) {}\n\n override fun onTabSelected(tab: TabLayout.Tab?) {\n setSortValue(tab?.position?:0)\n }\n\n override fun onTabUnselected(tab: TabLayout.Tab?) {}\n })\n }\n\n private fun setSortValue(value: Int) {\n sortValue = value\n Thread{\n sleep(400)\n if(ad?.exit != true) activity?.runOnUiThread {\n reset()\n addPage()\n }\n }.start()\n }\n\n fun showSexInfo(toolsBox: UITools) {\n if (ad?.exit != false) return\n toolsBox.buildInfo(\"切换类型\", \"选择一种想筛选的漫画类型\",\n \"男频\", \"全部\", \"女频\", {\n audience = 1\n reset()\n Thread {\n sleep(600)\n addPage()\n }.start()\n }, {\n audience = 0\n reset()\n Thread {\n sleep(600)\n addPage()\n }.start()\n }, {\n audience = 2\n reset()\n Thread {\n sleep(600)\n addPage()\n }.start()\n })\n }\n\n companion object {\n var wr: WeakReference? = null\n }\n}\n +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/rank/RankFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/rank/RankFragment.kt +--- a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/rank/RankFragment.kt (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/rank/RankFragment.kt (date 1709908862385) +@@ -13,7 +13,7 @@ + import java.lang.ref.WeakReference + + @ExperimentalStdlibApi +-class RankFragment : InfoCardLoader(R.layout.fragment_rank, R.id.action_nav_rank_to_nav_book, true) { ++class RankFragment : InfoCardLoader(R.layout.fragment_rank, R.id.action_nav_rank_to_nav_book, isTypeBook = true) { + private val sortWay = listOf("day", "week", "month", "total") + private var sortValue = 0 + private val audienceWay = listOf("", "male", "female") +Index: app/src/main/java/top/fumiama/copymanga/template/ui/CardList.kt +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>package top.fumiama.copymanga.template.ui\n\nimport android.annotation.SuppressLint\nimport android.net.Uri\nimport android.util.Log\nimport android.view.View\nimport androidx.fragment.app.Fragment\nimport com.bumptech.glide.Glide\nimport com.bumptech.glide.load.model.GlideUrl\nimport kotlinx.android.synthetic.main.card_book.*\nimport kotlinx.android.synthetic.main.card_book.view.*\nimport kotlinx.android.synthetic.main.line_horizonal_empty.view.*\nimport kotlinx.android.synthetic.main.line_lazybooklines.*\nimport top.fumiama.copymanga.tools.api.CMApi\nimport top.fumiama.copymanga.tools.ui.GlideHideLottieViewListener\nimport top.fumiama.dmzj.copymanga.R\nimport java.io.File\nimport java.lang.ref.WeakReference\nimport java.util.concurrent.atomic.AtomicInteger\n\nclass CardList(\n private val fragment: WeakReference,\n private val cardWidth: Int,\n private val cardHeight: Int,\n private val cardPerRow: Int\n) {\n private val that get() = fragment.get()\n private var rows:Array = arrayOfNulls(20)\n private var index = 0\n private var count = 0\n private var cardLoadingWaits = AtomicInteger()\n var initClickListeners: InitClickListeners? = null\n var exitCardList = false\n\n fun reset(){\n rows = arrayOfNulls(20)\n index = 0\n count = 0\n exitCardList = false\n }\n\n private fun manageRow() {\n if(!exitCardList && count++ % cardPerRow == 0) inflateRow()\n Log.d(\"MyCL\", \"index: $index, cardPR: $cardPerRow\")\n }\n\n private fun inflateRow(){\n that?.apply {\n layoutInflater.inflate(R.layout.line_horizonal_empty, mydll, false)?.let {\n if(exitCardList) return\n it.layoutParams.height = cardHeight + 16\n activity?.runOnUiThread {\n if(exitCardList) return@runOnUiThread\n mydll?.addView(it)\n }\n recycleOneRow(it)\n index++\n }\n }\n }\n private fun recycleOneRow(v:View?){\n val relativeIndex = index % 20\n if(rows[relativeIndex] == null) rows[relativeIndex] = v\n else {\n val victim = rows[relativeIndex]\n that?.apply {\n activity?.runOnUiThread {\n if(exitCardList) return@runOnUiThread\n mydll?.removeView(victim)\n mys?.scrollY = mys?.scrollY?.minus(cardHeight + 16)?:0\n }\n }\n rows[relativeIndex] = v\n }\n }\n\n @ExperimentalStdlibApi\n 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) {\n if (exitCardList) return\n manageRow()\n that?.apply {\n layoutInflater.inflate(R.layout.card_book, mydll?.ltbtn, false)?.let {\n val card = it.cic\n card.name = name\n card.append = append\n card.headImageUrl = head\n card.path = path\n card.index = index - 1\n card.chapterUUID = chapterUUID\n card.pageNumber = pn\n card.isFinish = isFinish\n card.isNew = isNew\n activity?.runOnUiThread {\n if (exitCardList) return@runOnUiThread\n addCard(it)\n }\n }\n }\n }\n\n @SuppressLint(\"SetTextI18n\")\n @ExperimentalStdlibApi\n fun addCard(cardFrame: View) {\n val card = cardFrame.cic\n if (card.index < 0) return\n val name = card.name + (card.append?:\"\")\n val head = card.headImageUrl\n val file = File(that?.context?.getExternalFilesDir(\"\"), card.name)\n if(exitCardList) return\n cardFrame.let {\n it.tic.text = name\n if(!file.exists()){\n if(head != null) {\n that?.context?.let { context ->\n val waitMillis = cardLoadingWaits.getAndIncrement().toLong()*200\n val g = Glide.with(context).load(\n GlideUrl(CMApi.proxy?.wrap(head)?:head, CMApi.myGlideHeaders)\n ).addListener(GlideHideLottieViewListener(WeakReference(it.laic)) {\n if (exitCardList) return@GlideHideLottieViewListener\n cardLoadingWaits.decrementAndGet()\n })\n if (waitMillis > 0) it.imic.postDelayed({\n if (exitCardList) return@postDelayed\n g.into(it.imic)\n }, waitMillis) else g.into(it.imic)\n }\n } else {\n it.laic.pauseAnimation()\n it.laic.visibility = View.GONE\n it.imic.setImageResource(R.drawable.img_defmask)\n }\n } else {\n val img = File(file, \"head.jpg\")\n it.laic.pauseAnimation()\n it.laic.visibility = View.GONE\n if(img.exists()) {\n it.imic.setImageURI(Uri.fromFile(img))\n } else {\n it.imic.setImageResource(R.drawable.img_defmask)\n }\n }\n if(card.isFinish) it.sgnic.visibility = View.VISIBLE\n if(card.isNew) it.sgnnew.visibility = View.VISIBLE\n initClickListeners?.prepareListeners(card, card.name, card.path, card.chapterUUID, card.pageNumber)\n rows[card.index % 20]?.ltbtn?.addView(it)\n it.layoutParams?.height = cardHeight\n it.layoutParams?.width = cardWidth\n }\n }\n interface InitClickListeners{\n fun prepareListeners(v: View, name: String, path: String?, chapterUUID: String?, pn: Int?)\n }\n} +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +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 +--- a/app/src/main/java/top/fumiama/copymanga/template/ui/CardList.kt (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/app/src/main/java/top/fumiama/copymanga/template/ui/CardList.kt (date 1709908106372) +@@ -36,6 +36,7 @@ + rows = arrayOfNulls(20) + index = 0 + count = 0 ++ cardLoadingWaits.set(0) + exitCardList = false + } + +Index: app/src/main/java/top/fumiama/copymanga/ui/cardflow/sort/SortFragment.kt +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>package top.fumiama.copymanga.ui.cardflow.sort\n\nimport android.animation.ObjectAnimator\nimport com.github.zawadz88.materialpopupmenu.popupMenu\nimport com.google.gson.Gson\nimport kotlinx.android.synthetic.main.anchor_popular.view.*\nimport kotlinx.android.synthetic.main.line_sort.*\nimport top.fumiama.copymanga.MainActivity.Companion.mainWeakReference\nimport top.fumiama.copymanga.json.FilterStructure\nimport top.fumiama.copymanga.template.http.AutoDownloadThread\nimport top.fumiama.copymanga.template.ui.InfoCardLoader\nimport top.fumiama.copymanga.tools.api.CMApi\nimport top.fumiama.dmzj.copymanga.R\nimport java.lang.Thread.sleep\n\n@ExperimentalStdlibApi\nclass SortFragment : InfoCardLoader(R.layout.fragment_sort, R.id.action_nav_sort_to_nav_book) {\n private val sortWay = listOf(\"-datetime_updated\", \"datetime_updated\", \"-popular\", \"popular\")\n private var theme = -1\n private var region = -1\n private var sortValue = 0\n private var filter: FilterStructure? = null\n\n override fun getApiUrl() =\n getString(R.string.sortApiUrl).format(\n CMApi.myHostApiUrl,\n page * 21,\n sortWay[sortValue],\n if(theme >= 0) (filter?.results?.theme?.get(theme)?.path_word ?: \"\") else \"\",\n if(region >= 0) (filter?.results?.top?.get(region)?.path_word ?: \"\") else \"\",\n )\n\n override fun setListeners() {\n super.setListeners()\n setUpdate()\n setHot()\n AutoDownloadThread(getString(R.string.filterApiUrl).format(CMApi.myHostApiUrl)) {\n if(ad?.exit == true) return@AutoDownloadThread\n it?.let {\n filter = Gson().fromJson(it.inputStream().reader(), FilterStructure::class.java)\n if(ad?.exit == true) return@AutoDownloadThread\n activity?.runOnUiThread{\n if(ad?.exit != true) setClasses()\n }\n }\n }.start()\n }\n\n private fun setUpdate(){\n if(ad?.exit == true) return\n line_sort_time.apt.setText(R.string.menu_update_time)\n line_sort_time.setOnClickListener {\n sortValue = if(it.apim.rotation == 0f) {\n ObjectAnimator.ofFloat(it.apim, \"rotation\", 0f, 180f).setDuration(233).start()\n 1\n }else{\n ObjectAnimator.ofFloat(it.apim, \"rotation\", 180f, 0f).setDuration(233).start()\n 0\n }\n Thread{\n sleep(400)\n activity?.runOnUiThread {\n reset()\n addPage()\n }\n }.start()\n }\n }\n\n private fun setClasses(){\n filter?.results?.top?.let { items ->\n if(ad?.exit == true) return@let\n line_sort_region.apt.text = \"全部\"\n line_sort_region.setOnClickListener {\n val popupMenu = popupMenu {\n style = R.style.Widget_MPM_Menu_Dark_CustomBackground\n section {\n item {\n label = \"全部\"\n labelColor = it.apt.currentTextColor\n callback = {\n region = -1\n it.apt.text = \"全部\"\n Thread{\n sleep(400)\n activity?.runOnUiThread {\n reset()\n addPage()\n }\n }.start()\n }\n }\n for(i in items.indices) item {\n label = items[i].name\n labelColor = it.apt.currentTextColor\n callback = { //optional\n it.apt.text = label\n region = i\n Thread{\n sleep(400)\n activity?.runOnUiThread {\n reset()\n addPage()\n }\n }.start()\n }\n }\n }\n }\n this.context?.let { it1 -> popupMenu.show(it1, it) }\n }\n }\n filter?.results?.theme?.let { items ->\n if(ad?.exit == true) return@let\n line_sort_class.apt.text = \"全部\"\n line_sort_class.setOnClickListener {\n val popupMenu = popupMenu {\n style = R.style.Widget_MPM_Menu_Dark_CustomBackground\n section {\n item {\n label = \"全部\"\n labelColor = it.apt.currentTextColor\n callback = {\n theme = -1\n it.apt.text = \"全部\"\n Thread{\n sleep(400)\n activity?.runOnUiThread {\n reset()\n addPage()\n }\n }.start()\n }\n }\n for(i in items.indices) item {\n label = items[i].name\n labelColor = it.apt.currentTextColor\n callback = { //optional\n it.apt.text = label\n theme = i\n Thread{\n sleep(400)\n activity?.runOnUiThread {\n reset()\n addPage()\n }\n }.start()\n }\n }\n }\n }\n this.context?.let { it1 -> popupMenu.show(it1, it) }\n }\n }\n }\n\n private fun setHot() {\n if(ad?.exit == true) return\n line_sort_hot.apt.setText(R.string.menu_hot)\n line_sort_hot.setOnClickListener {\n sortValue = if (it.apim.rotation == 0f) {\n ObjectAnimator.ofFloat(it.apim, \"rotation\", 0f, 180f).setDuration(233).start()\n 3\n } else {\n ObjectAnimator.ofFloat(it.apim, \"rotation\", 180f, 0f).setDuration(233).start()\n 2\n }\n Thread {\n sleep(400)\n activity?.runOnUiThread {\n reset()\n addPage()\n }\n }.start()\n }\n }\n} +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +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 +--- a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/sort/SortFragment.kt (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/sort/SortFragment.kt (date 1709908962128) +@@ -1,24 +1,22 @@ + package top.fumiama.copymanga.ui.cardflow.sort + +-import android.animation.ObjectAnimator ++import android.os.Bundle ++import android.view.View + import com.github.zawadz88.materialpopupmenu.popupMenu + import com.google.gson.Gson + import kotlinx.android.synthetic.main.anchor_popular.view.* + import kotlinx.android.synthetic.main.line_sort.* +-import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference + import top.fumiama.copymanga.json.FilterStructure + import top.fumiama.copymanga.template.http.AutoDownloadThread +-import top.fumiama.copymanga.template.ui.InfoCardLoader ++import top.fumiama.copymanga.template.ui.StatusCardFlow + import top.fumiama.copymanga.tools.api.CMApi + import top.fumiama.dmzj.copymanga.R + import java.lang.Thread.sleep + + @ExperimentalStdlibApi +-class SortFragment : InfoCardLoader(R.layout.fragment_sort, R.id.action_nav_sort_to_nav_book) { +- private val sortWay = listOf("-datetime_updated", "datetime_updated", "-popular", "popular") ++class SortFragment : StatusCardFlow(0, R.id.action_nav_sort_to_nav_book, R.layout.fragment_sort) { + private var theme = -1 + private var region = -1 +- private var sortValue = 0 + private var filter: FilterStructure? = null + + override fun getApiUrl() = +@@ -30,10 +28,14 @@ + if(region >= 0) (filter?.results?.top?.get(region)?.path_word ?: "") else "", + ) + ++ override fun onViewCreated(view: View, savedInstanceState: Bundle?) { ++ super.onViewCreated(view, savedInstanceState) ++ lineUpdate = line_sort_time ++ lineHot = line_sort_hot ++ } ++ + override fun setListeners() { + super.setListeners() +- setUpdate() +- setHot() + AutoDownloadThread(getString(R.string.filterApiUrl).format(CMApi.myHostApiUrl)) { + if(ad?.exit == true) return@AutoDownloadThread + it?.let { +@@ -45,27 +47,6 @@ + } + }.start() + } +- +- private fun setUpdate(){ +- if(ad?.exit == true) return +- line_sort_time.apt.setText(R.string.menu_update_time) +- line_sort_time.setOnClickListener { +- sortValue = if(it.apim.rotation == 0f) { +- ObjectAnimator.ofFloat(it.apim, "rotation", 0f, 180f).setDuration(233).start() +- 1 +- }else{ +- ObjectAnimator.ofFloat(it.apim, "rotation", 180f, 0f).setDuration(233).start() +- 0 +- } +- Thread{ +- sleep(400) +- activity?.runOnUiThread { +- reset() +- addPage() +- } +- }.start() +- } +- } + + private fun setClasses(){ + filter?.results?.top?.let { items -> +@@ -153,25 +134,4 @@ + } + } + } +- +- private fun setHot() { +- if(ad?.exit == true) return +- line_sort_hot.apt.setText(R.string.menu_hot) +- line_sort_hot.setOnClickListener { +- sortValue = if (it.apim.rotation == 0f) { +- ObjectAnimator.ofFloat(it.apim, "rotation", 0f, 180f).setDuration(233).start() +- 3 +- } else { +- ObjectAnimator.ofFloat(it.apim, "rotation", 180f, 0f).setDuration(233).start() +- 2 +- } +- Thread { +- sleep(400) +- activity?.runOnUiThread { +- reset() +- addPage() +- } +- }.start() +- } +- } + } +\ No newline at end of file +Index: app/src/main/java/top/fumiama/copymanga/template/ui/ThemeCardFlow.kt +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>package top.fumiama.copymanga.template.ui\n\nimport android.os.Bundle\nimport kotlinx.android.synthetic.main.app_bar_main.*\nimport top.fumiama.copymanga.MainActivity.Companion.mainWeakReference\nimport top.fumiama.copymanga.tools.api.CMApi\n\n@ExperimentalStdlibApi\nopen class ThemeCardFlow(private val api: Int, nav: Int) : StatusCardFlow(0, nav) {\n private var theme = \"\"\n override fun getApiUrl() =\n getString(api).format(\n CMApi.myHostApiUrl,\n page * 21,\n sortWay[sortValue],\n theme\n )\n\n override fun onCreate(savedInstanceState: Bundle?) {\n super.onCreate(savedInstanceState)\n arguments?.apply {\n getString(\"path\")?.apply { theme = this }\n getString(\"name\")?.apply {\n mainWeakReference?.get()?.toolbar?.title = this\n }\n }\n }\n\n override fun onResume() {\n super.onResume()\n arguments?.getString(\"name\")?.apply {\n mainWeakReference?.get()?.toolbar?.title = this\n }\n }\n} +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/app/src/main/java/top/fumiama/copymanga/template/ui/ThemeCardFlow.kt b/app/src/main/java/top/fumiama/copymanga/template/ui/ThemeCardFlow.kt +--- a/app/src/main/java/top/fumiama/copymanga/template/ui/ThemeCardFlow.kt (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/app/src/main/java/top/fumiama/copymanga/template/ui/ThemeCardFlow.kt (date 1709907861458) +@@ -1,12 +1,17 @@ + package top.fumiama.copymanga.template.ui + + import android.os.Bundle ++import android.view.LayoutInflater ++import android.view.View ++import android.view.ViewGroup + import kotlinx.android.synthetic.main.app_bar_main.* ++import kotlinx.android.synthetic.main.line_finish.* + import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference + import top.fumiama.copymanga.tools.api.CMApi ++import top.fumiama.dmzj.copymanga.R + + @ExperimentalStdlibApi +-open class ThemeCardFlow(private val api: Int, nav: Int) : StatusCardFlow(0, nav) { ++open class ThemeCardFlow(private val api: Int, nav: Int) : StatusCardFlow(0, nav, R.layout.fragment_statuscardflow) { + private var theme = "" + override fun getApiUrl() = + getString(api).format( +@@ -26,6 +31,12 @@ + } + } + ++ override fun onViewCreated(view: View, savedInstanceState: Bundle?) { ++ super.onViewCreated(view, savedInstanceState) ++ lineUpdate = line_finish_time ++ lineHot = line_finish_pop ++ } ++ + override fun onResume() { + super.onResume() + arguments?.getString("name")?.apply { +Index: app/src/main/java/top/fumiama/copymanga/tools/api/CMApi.kt +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>package top.fumiama.copymanga.tools.api\n\nimport android.util.Base64\nimport androidx.preference.PreferenceManager\nimport com.bumptech.glide.load.model.LazyHeaders\nimport top.fumiama.dmzj.copymanga.R\nimport top.fumiama.copymanga.MainActivity\nimport top.fumiama.copymanga.tools.http.DownloadTools\nimport top.fumiama.copymanga.tools.http.Proxy\nimport top.fumiama.copymanga.tools.http.Resolution\nimport java.io.File\nimport java.net.URLEncoder\n\nobject CMApi {\n var proxy = if(Proxy.useImageProxy) Proxy(R.string.imgProxyApiUrl, R.string.imgProxyApiPrefix, R.string.imgProxyKeyID) else null\n var resolution = Resolution(Regex(\"\\\\.c\\\\d+x\\\\.\"))\n var myGlideHeaders: LazyHeaders? = null\n get() {\n MainActivity.mainWeakReference?.get()?.let {\n PreferenceManager.getDefaultSharedPreferences(it).apply {\n if(field === null)\n field = LazyHeaders.Builder()\n .addHeader(\"referer\", MainActivity.mainWeakReference?.get()?.getString(R.string.referer)!!)\n .addHeader(\"User-Agent\", MainActivity.mainWeakReference?.get()?.getString(R.string.pc_ua)!!)\n .addHeader(\"source\", \"copyApp\")\n .addHeader(\"webp\", \"1\")\n .addHeader(\"version\", MainActivity.mainWeakReference?.get()?.getString(R.string.app_ver)!!)\n .addHeader(\"region\", if(!getBoolean(\"settings_cat_net\", false)) \"1\" else \"0\")\n .addHeader(\"platform\", \"3\")\n .build()\n }\n }\n return field\n }\n var myHostApiUrl: String = \"\"\n get() {\n if(field != \"\") return field\n MainActivity.mainWeakReference?.get()?.let {\n PreferenceManager.getDefaultSharedPreferences(it).apply {\n getString(\"settings_cat_net_et_api_url\", \"\")?.let { host ->\n if(host != \"\") {\n field = host\n return host\n }\n }\n }\n field = it.getString(R.string.hostUrl)\n }\n return field\n }\n\n fun getZipFile(exDir: File?, manga: String, caption: CharSequence, name: CharSequence) = File(exDir, \"$manga/$caption/$name.zip\")\n fun getChapterInfoApiUrl(arg1: String?, arg2: String?) =\n MainActivity.mainWeakReference?.get()?.getString(R.string.chapterInfoApiUrl)?.format(myHostApiUrl, arg1, arg2)\n fun getGroupInfoApiUrl(arg1: String?, arg2: String?, arg3: Int? = 0) =\n MainActivity.mainWeakReference?.get()?.getString(R.string.groupInfoApiUrl)?.format(myHostApiUrl, arg1, arg2, arg3)\n fun getLoginConnection(username: String, pwd: String, salt: Int) =\n MainActivity.mainWeakReference?.get()?.getString(R.string.loginApiUrl)?.format(myHostApiUrl)?.let {\n DownloadTools.getConnection(it, \"POST\")?.apply {\n MainActivity.mainWeakReference?.get()?.let {\n PreferenceManager.getDefaultSharedPreferences(it).apply {\n doOutput = true\n setRequestProperty(\"content-type\", \"application/x-www-form-urlencoded;charset=utf-8\")\n setRequestProperty(\"platform\", \"3\")\n setRequestProperty(\"accept\", \"application/json\")\n val r = if(!getBoolean(\"settings_cat_net_sw_use_foreign\", false)) \"1\" else \"0\"\n val pwdb64 = Base64.encode(\"$pwd-$salt\".toByteArray(), Base64.DEFAULT).decodeToString()\n outputStream.write(\"username=${URLEncoder.encode(username)}&password=$pwdb64&salt=$salt&platform=3&authorization=Token+&version=1.4.4&source=copyApp®ion=$r&webp=1\".toByteArray())\n }\n }\n }\n }\n }\n +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/app/src/main/java/top/fumiama/copymanga/tools/api/CMApi.kt b/app/src/main/java/top/fumiama/copymanga/tools/api/CMApi.kt +--- a/app/src/main/java/top/fumiama/copymanga/tools/api/CMApi.kt (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/app/src/main/java/top/fumiama/copymanga/tools/api/CMApi.kt (date 1709890277655) +@@ -13,7 +13,7 @@ + + object CMApi { + var proxy = if(Proxy.useImageProxy) Proxy(R.string.imgProxyApiUrl, R.string.imgProxyApiPrefix, R.string.imgProxyKeyID) else null +- var resolution = Resolution(Regex("\\.c\\d+x\\.")) ++ var resolution = Resolution(Regex("c\\d+x\\.")) + var myGlideHeaders: LazyHeaders? = null + get() { + MainActivity.mainWeakReference?.get()?.let { +Index: app/build.gradle +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>apply plugin: 'com.android.application'\napply plugin: 'kotlin-android'\napply plugin: 'kotlin-android-extensions'\n\nandroid {\n defaultConfig {\n compileSdk 34\n applicationId 'top.fumiama.copymanga'\n minSdkVersion 23\n targetSdkVersion 34\n versionCode 45\n versionName '2.1.2'\n resConfigs 'zh', 'zh-rCN'\n\n testInstrumentationRunner \"androidx.test.runner.AndroidJUnitRunner\"\n }\n\n aaptOptions {\n cruncherEnabled = false\n }\n\n buildTypes {\n release {\n minifyEnabled true\n shrinkResources true\n proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\n }\n /*winrelease {\n minifyEnabled true\n shrinkResources true\n proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\n }\n debug{\n minifyEnabled true\n shrinkResources true\n proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'\n }*/\n }\n compileOptions {\n sourceCompatibility JavaVersion.VERSION_11\n targetCompatibility JavaVersion.VERSION_11\n }\n kotlinOptions {\n jvmTarget = '11'\n }\n bundle{\n density{\n enableSplit = true\n }\n language{\n enableSplit = false\n }\n }\n namespace 'top.fumiama.dmzj.copymanga'\n}\n\ndependencies {\n implementation 'androidx.core:core-ktx:1.12.0'\n implementation 'androidx.appcompat:appcompat:1.6.1'\n implementation 'androidx.legacy:legacy-support-v4:1.0.0'\n implementation 'com.google.android.material:material:1.11.0'\n implementation 'androidx.constraintlayout:constraintlayout:2.1.4'\n implementation 'androidx.navigation:navigation-fragment-ktx:2.7.6'\n implementation 'androidx.navigation:navigation-ui-ktx:2.7.6'\n testImplementation 'junit:junit:4.13.2'\n implementation \"androidx.preference:preference-ktx:1.2.1\"\n implementation 'com.afollestad.material-dialogs:input:3.3.0'\n implementation 'com.github.yalantis:ucrop:2.2.6'\n implementation 'com.to.aboomy:pager2banner:1.0.1'\n implementation 'com.github.bumptech.glide:glide:4.14.2'\n annotationProcessor 'com.github.bumptech.glide:compiler:4.14.2'\n implementation 'com.google.code.gson:gson:2.10.1'\n implementation 'com.github.vovaksenov99:OverscrollableScrollView:1.0'\n implementation 'com.liaoinstan.springview:library:1.7.0'\n implementation 'com.github.zawadz88.materialpopupmenu:material-popup-menu:4.0.1'\n implementation 'com.lapism:search:2.4.1@aar'\n implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0'\n implementation 'com.airbnb.android:lottie:6.3.0'\n}\n +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/app/build.gradle b/app/build.gradle +--- a/app/build.gradle (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/app/build.gradle (date 1709911026401) +@@ -8,16 +8,13 @@ + applicationId 'top.fumiama.copymanga' + minSdkVersion 23 + targetSdkVersion 34 +- versionCode 45 +- versionName '2.1.2' +- resConfigs 'zh', 'zh-rCN' ++ versionCode 46 ++ versionName '2.1.3' ++ resourceConfigurations += ['zh', 'zh-rCN'] + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + +- aaptOptions { +- cruncherEnabled = false +- } + + buildTypes { + release { +@@ -60,20 +57,20 @@ + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation 'com.google.android.material:material:1.11.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' +- implementation 'androidx.navigation:navigation-fragment-ktx:2.7.6' +- implementation 'androidx.navigation:navigation-ui-ktx:2.7.6' ++ implementation 'androidx.navigation:navigation-fragment-ktx:2.7.7' ++ implementation 'androidx.navigation:navigation-ui-ktx:2.7.7' + testImplementation 'junit:junit:4.13.2' + implementation "androidx.preference:preference-ktx:1.2.1" + implementation 'com.afollestad.material-dialogs:input:3.3.0' + implementation 'com.github.yalantis:ucrop:2.2.6' + 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.github.bumptech.glide:glide:4.16.0' ++ annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0' + 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' + implementation 'com.lapism:search:2.4.1@aar' + implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0' +- implementation 'com.airbnb.android:lottie:6.3.0' ++ implementation 'com.airbnb.android:lottie:6.4.0' + } +Index: app/src/main/java/top/fumiama/copymanga/template/ui/InfoCardLoader.kt +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>package top.fumiama.copymanga.template.ui\n\nimport android.os.Bundle\nimport android.util.Log\nimport android.view.View\nimport androidx.fragment.app.Fragment\nimport androidx.navigation.fragment.findNavController\nimport com.google.gson.Gson\nimport kotlinx.android.synthetic.main.line_lazybooklines.*\nimport top.fumiama.copymanga.MainActivity\nimport top.fumiama.copymanga.json.BookListStructure\nimport top.fumiama.copymanga.json.HistoryBookListStructure\nimport top.fumiama.copymanga.json.ShelfStructure\nimport top.fumiama.copymanga.json.TypeBookListStructure\nimport top.fumiama.copymanga.template.general.MangaPagesFragmentTemplate\nimport top.fumiama.copymanga.template.http.AutoDownloadThread\nimport top.fumiama.copymanga.tools.ui.Navigate\nimport java.lang.ref.WeakReference\n\n@ExperimentalStdlibApi\nopen class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isTypeBook: Boolean = false, private val isHistoryBook: Boolean = false, private val isShelfBook: Boolean = false): MangaPagesFragmentTemplate(inflateRes) {\n var offset = 0\n private val subUrl get() = getApiUrl()\n var ad: AutoDownloadThread? = null\n\n override fun addPage(){\n super.addPage()\n ad = AutoDownloadThread(subUrl) {\n if (it == null) {\n activity?.runOnUiThread {\n findNavController().popBackStack()\n }\n return@AutoDownloadThread\n }\n if(isRefresh){\n page = 0\n isRefresh = false\n }\n if(isTypeBook) {\n val bookList = Gson().fromJson(it?.decodeToString(), TypeBookListStructure::class.java)\n bookList?.apply {\n Log.d(\"MyICL\", \"offset:${results.offset}, total:${results.total}\")\n if(results.offset < results.total) {\n if(code == 200) {\n results.list.forEach { book ->\n if(ad?.exit == true) return@AutoDownloadThread\n cardList?.addCard(\n book?.comic?.name?:\"null\", null, book?.comic?.cover,\n book?.comic?.path_word, null, null,\n isFinish = false, isNew = false\n )\n }\n offset += results.list.size\n }\n }\n page++\n }\n } else if(isHistoryBook) {\n val bookList = Gson().fromJson(it?.decodeToString(), HistoryBookListStructure::class.java)\n bookList?.apply {\n Log.d(\"MyICL\", \"offset:${results?.offset}, total:${results?.total}\")\n if(results.offset < results.total) {\n if(code == 200) {\n results?.list?.forEach{ book ->\n if(ad?.exit == true) return@AutoDownloadThread\n cardList?.addCard(\n book?.comic?.name?:\"null\", \"\\n最新${book?.last_chapter_name}\", book?.comic?.cover,\n book?.comic?.path_word, null, null,\n book?.comic?.status==1\n )\n }\n offset += results.list.size\n }\n }\n page++\n }\n } else if (isShelfBook) {\n val bookList = Gson().fromJson(it?.decodeToString(), ShelfStructure::class.java)\n bookList?.apply {\n Log.d(\"MyICL\", \"offset:${results?.offset}, total:${results?.total}\")\n if(results.offset < results.total) {\n if(code == 200) {\n results?.list?.forEach{ book ->\n if(ad?.exit == true) return@AutoDownloadThread\n cardList?.addCard(\n book?.comic?.name?:\"null\", \"\\n读到${book?.last_browse?.last_browse_name}\", book?.comic?.cover,\n book?.comic?.path_word, null, null,\n book?.comic?.status==1,\n book.comic?.browse?.chapter_uuid != book.comic?.last_chapter_id\n )\n }\n offset += results.list.size\n }\n }\n page++\n }\n } else {\n val bookList = Gson().fromJson(it?.decodeToString(), BookListStructure::class.java)\n bookList?.apply {\n Log.d(\"MyICL\", \"offset:${results?.offset}, total:${results?.total}\")\n if(results.offset < results.total) {\n if(code == 200) {\n results?.list?.forEach{ book ->\n if(ad?.exit == true) return@AutoDownloadThread\n cardList?.addCard(book?.name?:\"null\", null, book?.cover, book?.path_word, null, null, false)\n }\n offset += results.list.size\n }\n }\n page++\n }\n }\n onLoadFinish()\n }\n ad?.start()\n }\n override fun initCardList(weakReference: WeakReference) {\n super.initCardList(weakReference)\n cardList = CardList(weakReference, cardWidth, cardHeight, cardPerRow)\n cardList?.initClickListeners = object : CardList.InitClickListeners {\n override fun prepareListeners(v: View, name: String, path: String?, chapterUUID: String?, pn: Int?) {\n v.setOnClickListener {\n val bundle = Bundle()\n bundle.putString(\"path\", path)\n Navigate.safeNavigateTo(findNavController(), navId, bundle)\n }\n }\n }\n }\n\n open fun getApiUrl(): String{\n return \"\"\n }\n\n override fun onLoadFinish() {\n super.onLoadFinish()\n activity?.runOnUiThread {\n if(ad?.exit != true) mypl.visibility = View.GONE\n }\n }\n\n override fun reset() {\n super.reset()\n offset = 0\n }\n\n override fun onCreate(savedInstanceState: Bundle?) {\n super.onCreate(savedInstanceState)\n ad?.exit = false\n }\n\n override fun onResume() {\n super.onResume()\n ad?.exit = false\n }\n\n override fun onDestroy() {\n super.onDestroy()\n ad?.exit = true\n }\n} +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/app/src/main/java/top/fumiama/copymanga/template/ui/InfoCardLoader.kt b/app/src/main/java/top/fumiama/copymanga/template/ui/InfoCardLoader.kt +--- a/app/src/main/java/top/fumiama/copymanga/template/ui/InfoCardLoader.kt (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/app/src/main/java/top/fumiama/copymanga/template/ui/InfoCardLoader.kt (date 1709904313295) +@@ -25,8 +25,8 @@ + + override fun addPage(){ + super.addPage() +- ad = AutoDownloadThread(subUrl) { +- if (it == null) { ++ ad = AutoDownloadThread(subUrl) { data -> ++ if (data == null) { + activity?.runOnUiThread { + findNavController().popBackStack() + } +@@ -37,7 +37,7 @@ + isRefresh = false + } + if(isTypeBook) { +- val bookList = Gson().fromJson(it?.decodeToString(), TypeBookListStructure::class.java) ++ val bookList = Gson().fromJson(data?.decodeToString(), TypeBookListStructure::class.java) + bookList?.apply { + Log.d("MyICL", "offset:${results.offset}, total:${results.total}") + if(results.offset < results.total) { +@@ -56,7 +56,7 @@ + page++ + } + } else if(isHistoryBook) { +- val bookList = Gson().fromJson(it?.decodeToString(), HistoryBookListStructure::class.java) ++ val bookList = Gson().fromJson(data?.decodeToString(), HistoryBookListStructure::class.java) + bookList?.apply { + Log.d("MyICL", "offset:${results?.offset}, total:${results?.total}") + if(results.offset < results.total) { +@@ -75,7 +75,7 @@ + page++ + } + } else if (isShelfBook) { +- val bookList = Gson().fromJson(it?.decodeToString(), ShelfStructure::class.java) ++ val bookList = Gson().fromJson(data?.decodeToString(), ShelfStructure::class.java) + bookList?.apply { + Log.d("MyICL", "offset:${results?.offset}, total:${results?.total}") + if(results.offset < results.total) { +@@ -83,7 +83,7 @@ + results?.list?.forEach{ book -> + if(ad?.exit == true) return@AutoDownloadThread + cardList?.addCard( +- book?.comic?.name?:"null", "\n读到${book?.last_browse?.last_browse_name}", book?.comic?.cover, ++ book?.comic?.name?:"null", "\n${book?.last_browse?.last_browse_name?.let { "读到$it" }?:"未读"}", book?.comic?.cover, + book?.comic?.path_word, null, null, + book?.comic?.status==1, + book.comic?.browse?.chapter_uuid != book.comic?.last_chapter_id +@@ -95,7 +95,7 @@ + page++ + } + } else { +- val bookList = Gson().fromJson(it?.decodeToString(), BookListStructure::class.java) ++ val bookList = Gson().fromJson(data?.decodeToString(), BookListStructure::class.java) + bookList?.apply { + Log.d("MyICL", "offset:${results?.offset}, total:${results?.total}") + if(results.offset < results.total) { +Index: app/src/main/java/top/fumiama/copymanga/template/ui/StatusCardFlow.kt +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>package top.fumiama.copymanga.template.ui\n\nimport android.animation.ObjectAnimator\nimport android.view.View\nimport kotlinx.android.synthetic.main.anchor_popular.view.*\nimport kotlinx.android.synthetic.main.line_finish.*\nimport top.fumiama.copymanga.MainActivity.Companion.mainWeakReference\nimport top.fumiama.copymanga.tools.api.CMApi\nimport top.fumiama.dmzj.copymanga.R\n\n@ExperimentalStdlibApi\nopen class StatusCardFlow(private val api: Int, nav: Int) : InfoCardLoader(R.layout.fragment_statuscardflow, nav) {\n val sortWay = listOf(\"-datetime_updated\", \"datetime_updated\", \"popular\", \"-popular\")\n var sortValue = 0\n\n override fun getApiUrl() =\n getString(api).format(\n CMApi.myHostApiUrl,\n page * 21,\n sortWay[sortValue]\n )\n\n override fun setListeners() {\n super.setListeners()\n setUpdate(line_finish_time)\n setHot(line_finish_pop)\n }\n\n open fun setUpdate(that: View) {\n that.apply {\n apt.setText(R.string.menu_update_time)\n setOnClickListener {\n sortValue = if(apim.rotation == 0f) {\n ObjectAnimator.ofFloat(apim, \"rotation\", 0f, 180f).setDuration(233).start()\n 1\n }else{\n ObjectAnimator.ofFloat(apim, \"rotation\", 180f, 0f).setDuration(233).start()\n 0\n }\n Thread{\n Thread.sleep(400)\n activity?.runOnUiThread {\n reset()\n addPage()\n }\n }.start()\n }\n }\n }\n\n open fun setHot(that: View) {\n that.apply {\n apt.setText(R.string.menu_hot)\n setOnClickListener {\n sortValue = if (apim.rotation == 0f) {\n ObjectAnimator.ofFloat(apim, \"rotation\", 0f, 180f).setDuration(233).start()\n 3\n } else {\n ObjectAnimator.ofFloat(apim, \"rotation\", 180f, 0f).setDuration(233).start()\n 2\n }\n Thread {\n Thread.sleep(400)\n activity?.runOnUiThread {\n reset()\n addPage()\n }\n }.start()\n }\n }\n }\n} +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/app/src/main/java/top/fumiama/copymanga/template/ui/StatusCardFlow.kt b/app/src/main/java/top/fumiama/copymanga/template/ui/StatusCardFlow.kt +--- a/app/src/main/java/top/fumiama/copymanga/template/ui/StatusCardFlow.kt (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/app/src/main/java/top/fumiama/copymanga/template/ui/StatusCardFlow.kt (date 1709908862388) +@@ -3,15 +3,18 @@ + import android.animation.ObjectAnimator + import android.view.View + import kotlinx.android.synthetic.main.anchor_popular.view.* +-import kotlinx.android.synthetic.main.line_finish.* +-import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference + import top.fumiama.copymanga.tools.api.CMApi + import top.fumiama.dmzj.copymanga.R + + @ExperimentalStdlibApi +-open class StatusCardFlow(private val api: Int, nav: Int) : InfoCardLoader(R.layout.fragment_statuscardflow, nav) { +- val sortWay = listOf("-datetime_updated", "datetime_updated", "popular", "-popular") ++open class StatusCardFlow(private val api: Int, nav: Int, inflateRes: Int, ++ isTypeBook: Boolean = false, ++ isHistoryBook: Boolean = false, ++ isShelfBook: Boolean = false) : InfoCardLoader(inflateRes, nav, isTypeBook, isHistoryBook, isShelfBook) { ++ val sortWay = listOf("-datetime_updated", "datetime_updated", "-popular", "popular") + var sortValue = 0 ++ var lineUpdate: View? = null ++ var lineHot: View? = null + + override fun getApiUrl() = + getString(api).format( +@@ -22,21 +25,17 @@ + + override fun setListeners() { + super.setListeners() +- setUpdate(line_finish_time) +- setHot(line_finish_pop) ++ lineUpdate?.let { setUpdate(it) } ++ lineHot?.let { setHot(it) } ++ lineUpdate?.alpha = 1f ++ lineHot?.alpha = 0.5f + } + + open fun setUpdate(that: View) { + that.apply { + apt.setText(R.string.menu_update_time) + setOnClickListener { +- sortValue = if(apim.rotation == 0f) { +- ObjectAnimator.ofFloat(apim, "rotation", 0f, 180f).setDuration(233).start() +- 1 +- }else{ +- ObjectAnimator.ofFloat(apim, "rotation", 180f, 0f).setDuration(233).start() +- 0 +- } ++ sortValue = triggerLine(false) + Thread{ + Thread.sleep(400) + activity?.runOnUiThread { +@@ -52,13 +51,7 @@ + that.apply { + apt.setText(R.string.menu_hot) + setOnClickListener { +- sortValue = if (apim.rotation == 0f) { +- ObjectAnimator.ofFloat(apim, "rotation", 0f, 180f).setDuration(233).start() +- 3 +- } else { +- ObjectAnimator.ofFloat(apim, "rotation", 180f, 0f).setDuration(233).start() +- 2 +- } ++ sortValue = triggerLine(true) + Thread { + Thread.sleep(400) + activity?.runOnUiThread { +@@ -69,4 +62,46 @@ + } + } + } ++ ++ open fun triggerLine(isHot: Boolean): Int { ++ val hot = lineHot?:return 0 ++ val update = lineUpdate?:return 0 ++ if(sortValue >= 2) { ++ if (isHot) { ++ return if (hot.apim.rotation == 0f) { ++ ObjectAnimator.ofFloat(hot.apim, "rotation", 0f, 180f).setDuration(233).start() ++ 3 ++ } else { ++ ObjectAnimator.ofFloat(hot.apim, "rotation", 180f, 0f).setDuration(233).start() ++ 2 ++ } ++ } else { ++ update.alpha = 1f ++ hot.alpha = 0.5f ++ return if(update.apim.rotation == 0f) { ++ 0 ++ } else { ++ 1 ++ } ++ } ++ } else { ++ if (!isHot) { ++ return if(update.apim.rotation == 0f) { ++ ObjectAnimator.ofFloat(update.apim, "rotation", 0f, 180f).setDuration(233).start() ++ 1 ++ }else{ ++ ObjectAnimator.ofFloat(update.apim, "rotation", 180f, 0f).setDuration(233).start() ++ 0 ++ } ++ } else { ++ hot.alpha = 1f ++ update.alpha = 0.5f ++ return if (hot.apim.rotation == 0f) { ++ 2 ++ } else { ++ 3 ++ } ++ } ++ } ++ } + } +\ No newline at end of file +Index: app/src/main/java/top/fumiama/copymanga/ui/cardflow/shelf/ShelfFragment.kt +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>package top.fumiama.copymanga.ui.cardflow.shelf\n\nimport android.animation.ObjectAnimator\nimport android.os.Bundle\nimport androidx.navigation.fragment.findNavController\nimport kotlinx.android.synthetic.main.anchor_popular.view.*\nimport kotlinx.android.synthetic.main.line_shelf.*\nimport top.fumiama.copymanga.MainActivity\nimport top.fumiama.copymanga.template.ui.InfoCardLoader\nimport top.fumiama.copymanga.tools.api.CMApi\nimport top.fumiama.dmzj.copymanga.R\nimport java.lang.Thread.sleep\n\n@ExperimentalStdlibApi\nclass ShelfFragment : InfoCardLoader(R.layout.fragment_shelf, R.id.action_nav_sub_to_nav_book, isShelfBook = true) {\n private val sortWay = listOf(\n \"-datetime_updated\",\n \"datetime_updated\",\n \"-datetime_modifier\",\n \"datetime_modifier\",\n \"-datetime_browse\",\n \"datetime_browse\"\n )\n private var sortValue = 0\n\n override fun getApiUrl() =\n getString(R.string.shelfApiUrl).format(\n CMApi.myHostApiUrl,\n page * 21,\n sortWay[sortValue]\n )\n\n override fun onCreate(savedInstanceState: Bundle?) {\n if (MainActivity.member?.hasLogin != true) findNavController().popBackStack()\n super.onCreate(savedInstanceState)\n }\n\n override fun setListeners() {\n super.setListeners()\n setUpdate()\n setModify()\n setBrowse()\n }\n\n private fun setUpdate() {\n if (ad?.exit == true) return\n line_shelf_updated.apt.setText(R.string.menu_update_time)\n line_shelf_updated.setOnClickListener {\n sortValue = if (it.apim.rotation == 0f) {\n ObjectAnimator.ofFloat(it.apim, \"rotation\", 0f, 180f).setDuration(233).start()\n 1\n } else {\n ObjectAnimator.ofFloat(it.apim, \"rotation\", 180f, 0f).setDuration(233).start()\n 0\n }\n Thread {\n sleep(400)\n activity?.runOnUiThread {\n reset()\n addPage()\n }\n }.start()\n }\n }\n\n private fun setModify() {\n if (ad?.exit == true) return\n line_shelf_modifier.apt.setText(R.string.menu_add_time)\n line_shelf_modifier.setOnClickListener {\n sortValue = if (it.apim.rotation == 0f) {\n ObjectAnimator.ofFloat(it.apim, \"rotation\", 0f, 180f).setDuration(233).start()\n 3\n } else {\n ObjectAnimator.ofFloat(it.apim, \"rotation\", 180f, 0f).setDuration(233).start()\n 2\n }\n Thread {\n sleep(400)\n activity?.runOnUiThread {\n reset()\n addPage()\n }\n }.start()\n }\n }\n\n private fun setBrowse() {\n if (ad?.exit == true) return\n line_shelf_browse.apt.setText(R.string.menu_read_time)\n line_shelf_browse.setOnClickListener {\n sortValue = if (it.apim.rotation == 0f) {\n ObjectAnimator.ofFloat(it.apim, \"rotation\", 0f, 180f).setDuration(233).start()\n 5\n } else {\n ObjectAnimator.ofFloat(it.apim, \"rotation\", 180f, 0f).setDuration(233).start()\n 4\n }\n Thread {\n sleep(400)\n activity?.runOnUiThread {\n reset()\n addPage()\n }\n }.start()\n }\n }\n} +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +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 +--- a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/shelf/ShelfFragment.kt (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/shelf/ShelfFragment.kt (date 1709910426026) +@@ -2,9 +2,14 @@ + + import android.animation.ObjectAnimator + import android.os.Bundle ++import android.view.View ++import androidx.lifecycle.lifecycleScope + 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.launch ++import kotlinx.coroutines.withContext + import top.fumiama.copymanga.MainActivity + import top.fumiama.copymanga.template.ui.InfoCardLoader + import top.fumiama.copymanga.tools.api.CMApi +@@ -37,6 +42,7 @@ + + override fun setListeners() { + super.setListeners() ++ fade() + setUpdate() + setModify() + setBrowse() +@@ -46,20 +52,10 @@ + if (ad?.exit == true) return + line_shelf_updated.apt.setText(R.string.menu_update_time) + line_shelf_updated.setOnClickListener { +- sortValue = if (it.apim.rotation == 0f) { +- ObjectAnimator.ofFloat(it.apim, "rotation", 0f, 180f).setDuration(233).start() +- 1 +- } else { +- ObjectAnimator.ofFloat(it.apim, "rotation", 180f, 0f).setDuration(233).start() +- 0 +- } +- Thread { +- sleep(400) +- activity?.runOnUiThread { +- reset() +- addPage() +- } +- }.start() ++ val same = sortValue in 0..1 ++ sortValue = rotate(it.apim, same, 0) ++ if (!same) fade() ++ resetDelayed() + } + } + +@@ -67,20 +63,10 @@ + if (ad?.exit == true) return + line_shelf_modifier.apt.setText(R.string.menu_add_time) + line_shelf_modifier.setOnClickListener { +- sortValue = if (it.apim.rotation == 0f) { +- ObjectAnimator.ofFloat(it.apim, "rotation", 0f, 180f).setDuration(233).start() +- 3 +- } else { +- ObjectAnimator.ofFloat(it.apim, "rotation", 180f, 0f).setDuration(233).start() +- 2 +- } +- Thread { +- sleep(400) +- activity?.runOnUiThread { +- reset() +- addPage() +- } +- }.start() ++ val same = sortValue in 2..3 ++ sortValue = rotate(it.apim, same, 2) ++ if (!same) fade() ++ resetDelayed() + } + } + +@@ -88,20 +74,60 @@ + if (ad?.exit == true) return + line_shelf_browse.apt.setText(R.string.menu_read_time) + line_shelf_browse.setOnClickListener { +- sortValue = if (it.apim.rotation == 0f) { +- ObjectAnimator.ofFloat(it.apim, "rotation", 0f, 180f).setDuration(233).start() +- 5 ++ val same = sortValue>=4 ++ sortValue = rotate(it.apim, same, 4) ++ if (!same) fade() ++ resetDelayed() ++ } ++ } ++ ++ private fun rotate(img: View, isSameSlot: Boolean, offset: Int): Int { ++ return if (isSameSlot) { ++ if (img.rotation == 0f) { ++ ObjectAnimator.ofFloat(img, "rotation", 0f, 180f).setDuration(233).start() ++ offset+1 + } else { +- ObjectAnimator.ofFloat(it.apim, "rotation", 180f, 0f).setDuration(233).start() +- 4 ++ ObjectAnimator.ofFloat(img, "rotation", 180f, 0f).setDuration(233).start() ++ offset + } +- Thread { ++ } else { ++ if (img.rotation == 0f) { ++ offset ++ } else { ++ offset+1 ++ } ++ } ++ } ++ ++ private fun fade() { ++ when(sortValue) { ++ 0, 1 -> { ++ line_shelf_updated.alpha = 1f ++ line_shelf_modifier.alpha = 0.5f ++ line_shelf_browse.alpha = 0.5f ++ } ++ 2, 3 -> { ++ line_shelf_updated.alpha = 0.5f ++ line_shelf_modifier.alpha = 1f ++ line_shelf_browse.alpha = 0.5f ++ } ++ 4, 5 -> { ++ line_shelf_updated.alpha = 0.5f ++ line_shelf_modifier.alpha = 0.5f ++ line_shelf_browse.alpha = 1f ++ } ++ } ++ } ++ ++ private fun resetDelayed() { ++ lifecycleScope.launch { ++ withContext(Dispatchers.IO) { + sleep(400) +- activity?.runOnUiThread { ++ withContext(Dispatchers.Main) { + reset() + addPage() + } +- }.start() ++ } + } + } + } +\ No newline at end of file +Index: app/src/main/java/top/fumiama/copymanga/json/ComicStructure.java +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>package top.fumiama.copymanga.json;\n\npublic class ComicStructure {\n public String uuid;\n public String name;\n public String alias;\n public ValueDisplayPair status;\n public ThemeStructure[] theme;\n public String path_word;\n public ThemeStructure[] author;\n public int img_type;\n public String brief;\n public String datetime_updated;\n public String cover;\n public int popular;\n}\n +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/app/src/main/java/top/fumiama/copymanga/json/ComicStructure.java b/app/src/main/java/top/fumiama/copymanga/json/ComicStructure.java +--- a/app/src/main/java/top/fumiama/copymanga/json/ComicStructure.java (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/app/src/main/java/top/fumiama/copymanga/json/ComicStructure.java (date 1709888745347) +@@ -4,11 +4,12 @@ + public String uuid; + public String name; + public String alias; ++ public int img_type; ++ public ValueDisplayPair region; + public ValueDisplayPair status; + public ThemeStructure[] theme; + public String path_word; + public ThemeStructure[] author; +- public int img_type; + public String brief; + public String datetime_updated; + public String cover; +Index: app/src/main/res/drawable-anydpi/ic_image.xml +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/app/src/main/res/drawable-anydpi/ic_image.xml b/app/src/main/res/drawable-anydpi/ic_image.xml +new file mode 100644 +--- /dev/null (date 1709889633320) ++++ b/app/src/main/res/drawable-anydpi/ic_image.xml (date 1709889633320) +@@ -0,0 +1,10 @@ ++ ++ ++ ++ +\ No newline at end of file +Index: app/src/main/java/top/fumiama/copymanga/ui/cardflow/topic/TopicFragment.kt +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.BaseRevisionTextPatchEP +<+>package top.fumiama.copymanga.ui.cardflow.topic\n\nimport android.os.Bundle\nimport com.google.gson.Gson\nimport kotlinx.android.synthetic.main.app_bar_main.*\nimport kotlinx.android.synthetic.main.fragment_topic.*\nimport top.fumiama.copymanga.MainActivity.Companion.mainWeakReference\nimport top.fumiama.copymanga.json.TopicStructure\nimport top.fumiama.copymanga.template.http.AutoDownloadThread\nimport top.fumiama.copymanga.template.ui.InfoCardLoader\nimport top.fumiama.copymanga.tools.api.CMApi\nimport top.fumiama.dmzj.copymanga.R\n\n@ExperimentalStdlibApi\nclass TopicFragment : InfoCardLoader(R.layout.fragment_topic, R.id.action_nav_topic_to_nav_book) {\n private var type = 1\n override fun getApiUrl() =\n getString(R.string.topicContentApiUrl).format(CMApi.myHostApiUrl, arguments?.getString(\"path\"), type, offset)\n\n override fun onCreate(savedInstanceState: Bundle?) {\n super.onCreate(savedInstanceState)\n AutoDownloadThread(getString(R.string.topicApiUrl).format(CMApi.myHostApiUrl, arguments?.getString(\"path\"))) { data ->\n if(ad?.exit == true) return@AutoDownloadThread\n data?.apply {\n val r = inputStream().reader()\n val topic = Gson().fromJson(r, TopicStructure::class.java)\n topic?.apply {\n if(ad?.exit != false) return@AutoDownloadThread\n activity?.let {\n it.runOnUiThread {\n if(ad?.exit != false) return@runOnUiThread\n it.toolbar.title = results.title\n ftttime.text = results.datetime_created\n fttintro.text = results.intro\n type = results.type\n }\n }\n }\n }\n }.start()\n }\n} +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +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 +--- a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/topic/TopicFragment.kt (revision 229d5b2088d8ccb7c11e4a5760a6c133ec95b101) ++++ b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/topic/TopicFragment.kt (date 1709906325403) +@@ -23,12 +23,11 @@ + if(ad?.exit == true) return@AutoDownloadThread + data?.apply { + val r = inputStream().reader() +- val topic = Gson().fromJson(r, TopicStructure::class.java) +- topic?.apply { +- if(ad?.exit != false) return@AutoDownloadThread ++ Gson().fromJson(r, TopicStructure::class.java)?.apply { ++ if(ad?.exit == true) return@AutoDownloadThread + activity?.let { + it.runOnUiThread { +- if(ad?.exit != false) return@runOnUiThread ++ if(ad?.exit == true) return@runOnUiThread + it.toolbar.title = results.title + ftttime.text = results.datetime_created + fttintro.text = results.intro +Index: app/src/main/res/drawable-anydpi/ic_data.xml +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/app/src/main/res/drawable-anydpi/ic_data.xml b/app/src/main/res/drawable-anydpi/ic_data.xml +new file mode 100644 +--- /dev/null (date 1709889542283) ++++ b/app/src/main/res/drawable-anydpi/ic_data.xml (date 1709889542283) +@@ -0,0 +1,10 @@ ++ ++ ++ ++ +\ No newline at end of file diff --git a/.idea/shelf/Uncommitted_changes_before_Update_at_2024_3_9__12_23_AM__Changes_.xml b/.idea/shelf/Uncommitted_changes_before_Update_at_2024_3_9__12_23_AM__Changes_.xml new file mode 100644 index 0000000..007eed3 --- /dev/null +++ b/.idea/shelf/Uncommitted_changes_before_Update_at_2024_3_9__12_23_AM__Changes_.xml @@ -0,0 +1,4 @@ + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 289a7dd..4c9f419 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,16 +8,13 @@ android { applicationId 'top.fumiama.copymanga' minSdkVersion 23 targetSdkVersion 34 - versionCode 45 - versionName '2.1.2' - resConfigs 'zh', 'zh-rCN' + versionCode 46 + versionName '2.1.3' + resourceConfigurations += ['zh', 'zh-rCN'] testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } - aaptOptions { - cruncherEnabled = false - } buildTypes { release { @@ -60,20 +57,20 @@ dependencies { implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'com.google.android.material:material:1.11.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation 'androidx.navigation:navigation-fragment-ktx:2.7.6' - implementation 'androidx.navigation:navigation-ui-ktx:2.7.6' + implementation 'androidx.navigation:navigation-fragment-ktx:2.7.7' + implementation 'androidx.navigation:navigation-ui-ktx:2.7.7' testImplementation 'junit:junit:4.13.2' implementation "androidx.preference:preference-ktx:1.2.1" implementation 'com.afollestad.material-dialogs:input:3.3.0' implementation 'com.github.yalantis:ucrop:2.2.6' 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.github.bumptech.glide:glide:4.16.0' + annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0' 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' implementation 'com.lapism:search:2.4.1@aar' implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0' - implementation 'com.airbnb.android:lottie:6.3.0' + implementation 'com.airbnb.android:lottie:6.4.0' } diff --git a/app/src/main/java/top/fumiama/copymanga/LoginActivity.kt b/app/src/main/java/top/fumiama/copymanga/LoginActivity.kt index ee29040..8f6cc38 100644 --- a/app/src/main/java/top/fumiama/copymanga/LoginActivity.kt +++ b/app/src/main/java/top/fumiama/copymanga/LoginActivity.kt @@ -19,6 +19,7 @@ class LoginActivity : AppCompatActivity() { val isLogout = pref.getString("token", null) != null if (isLogout) { alblogin.setText(R.string.logout) + altusrnm.setText(pref.getString("username", "N/A")) } alblogin.setOnClickListener { lifecycleScope.launch { diff --git a/app/src/main/java/top/fumiama/copymanga/MainActivity.kt b/app/src/main/java/top/fumiama/copymanga/MainActivity.kt index 7cee5bf..07b4942 100644 --- a/app/src/main/java/top/fumiama/copymanga/MainActivity.kt +++ b/app/src/main/java/top/fumiama/copymanga/MainActivity.kt @@ -2,6 +2,7 @@ package top.fumiama.copymanga import android.Manifest import android.annotation.SuppressLint +import android.app.Activity import android.content.Context import android.content.Intent import android.content.pm.PackageManager @@ -18,6 +19,7 @@ import android.view.View import android.view.inputmethod.InputMethodManager import android.widget.TextView import android.widget.Toast +import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat @@ -25,6 +27,7 @@ import androidx.core.content.ContextCompat import androidx.core.content.edit import androidx.core.net.toUri import androidx.drawerlayout.widget.DrawerLayout +import androidx.lifecycle.lifecycleScope import androidx.navigation.NavController import androidx.navigation.findNavController import androidx.navigation.ui.AppBarConfiguration @@ -40,6 +43,9 @@ import com.yalantis.ucrop.UCrop import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.app_bar_main.* import kotlinx.android.synthetic.main.nav_header_main.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import top.fumiama.copymanga.manga.Shelf import top.fumiama.copymanga.tools.ui.UITools import top.fumiama.copymanga.ui.book.BookFragment.Companion.bookHandler @@ -64,7 +70,6 @@ class MainActivity : AppCompatActivity() { private lateinit var headPic: File lateinit var toolsBox: UITools - private var latestDestination = 0 private var isMenuWaiting = false override fun onCreate(savedInstanceState: Bundle?) { @@ -114,6 +119,7 @@ class MainActivity : AppCompatActivity() { ime = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + var latestDestination: Int navController!!.addOnDestinationChangedListener { _, destination, _ -> latestDestination = destination.id Log.d("MyMA", "latestDestination: $latestDestination") @@ -122,51 +128,16 @@ class MainActivity : AppCompatActivity() { } isMenuWaiting = true Log.d("MyMA", "start menu waiting") - Thread { - sleep(1000) - isMenuWaiting = false - Log.d("MyMA", "finish menu waiting") - runOnUiThread { - when (latestDestination) { - R.id.nav_home -> { - Log.d("MyMA", "enter home") - menuMain?.findItem(R.id.action_info)?.isVisible = true - menuMain?.findItem(R.id.action_download)?.isVisible = false - menuMain?.findItem(R.id.action_sort)?.isVisible = false - } - R.id.nav_book -> { - Log.d("MyMA", "enter book") - menuMain?.findItem(R.id.action_info)?.isVisible = false - menuMain?.findItem(R.id.action_download)?.isVisible = true - menuMain?.findItem(R.id.action_sort)?.isVisible = false - } - R.id.nav_group -> { - Log.d("MyMA", "enter group") - menuMain?.findItem(R.id.action_info)?.isVisible = false - menuMain?.findItem(R.id.action_download)?.isVisible = false - menuMain?.findItem(R.id.action_sort)?.isVisible = true - } - R.id.nav_new_download -> { - Log.d("MyMA", "enter new_download") - menuMain?.findItem(R.id.action_info)?.isVisible = false - menuMain?.findItem(R.id.action_download)?.isVisible = false - menuMain?.findItem(R.id.action_sort)?.isVisible = true - } - R.id.nav_rank -> { - Log.d("MyMA", "enter rank") - menuMain?.findItem(R.id.action_info)?.isVisible = false - menuMain?.findItem(R.id.action_download)?.isVisible = false - menuMain?.findItem(R.id.action_sort)?.isVisible = true - } - else -> { - Log.d("MyMA", "enter others") - menuMain?.findItem(R.id.action_info)?.isVisible = false - menuMain?.findItem(R.id.action_download)?.isVisible = false - menuMain?.findItem(R.id.action_sort)?.isVisible = false - } + lifecycleScope.launch { + withContext(Dispatchers.IO) { + sleep(1000) + withContext(Dispatchers.Main) { + isMenuWaiting = false + Log.d("MyMA", "finish menu waiting") + changeMenuList(latestDestination) } } - }.start() + } } } @@ -218,24 +189,6 @@ class MainActivity : AppCompatActivity() { return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp() } - @Deprecated("Deprecated in Java") - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - if (resultCode == RESULT_OK) when (requestCode) { - UCrop.REQUEST_CROP -> { - val fi = headPic.inputStream() - navhbg.setImageBitmap(BitmapFactory.decodeStream(fi)) - fi.close() - } - MSG_CROP_IMAGE -> { - data?.data?.let { - saveFile(it) - cropImageUri() - } - } - } - } - override fun onRequestPermissionsResult( requestCode: Int, permissions: Array, @@ -263,6 +216,47 @@ class MainActivity : AppCompatActivity() { } } + private fun changeMenuList(latestDestination: Int) { + when (latestDestination) { + R.id.nav_home -> { + Log.d("MyMA", "enter home") + menuMain?.findItem(R.id.action_info)?.isVisible = true + menuMain?.findItem(R.id.action_download)?.isVisible = false + menuMain?.findItem(R.id.action_sort)?.isVisible = false + } + R.id.nav_book -> { + Log.d("MyMA", "enter book") + menuMain?.findItem(R.id.action_info)?.isVisible = false + menuMain?.findItem(R.id.action_download)?.isVisible = true + menuMain?.findItem(R.id.action_sort)?.isVisible = false + } + R.id.nav_group -> { + Log.d("MyMA", "enter group") + menuMain?.findItem(R.id.action_info)?.isVisible = false + menuMain?.findItem(R.id.action_download)?.isVisible = false + menuMain?.findItem(R.id.action_sort)?.isVisible = true + } + R.id.nav_new_download -> { + Log.d("MyMA", "enter new_download") + menuMain?.findItem(R.id.action_info)?.isVisible = false + menuMain?.findItem(R.id.action_download)?.isVisible = false + menuMain?.findItem(R.id.action_sort)?.isVisible = true + } + R.id.nav_rank -> { + Log.d("MyMA", "enter rank") + menuMain?.findItem(R.id.action_info)?.isVisible = false + menuMain?.findItem(R.id.action_download)?.isVisible = false + menuMain?.findItem(R.id.action_sort)?.isVisible = true + } + else -> { + Log.d("MyMA", "enter others") + menuMain?.findItem(R.id.action_info)?.isVisible = false + menuMain?.findItem(R.id.action_download)?.isVisible = false + menuMain?.findItem(R.id.action_sort)?.isVisible = false + } + } + } + private fun checkReadPermission(): Boolean { return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N && ContextCompat.checkSelfPermission( this, @@ -277,11 +271,18 @@ class MainActivity : AppCompatActivity() { } else true } + private var pickerLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + if (result.resultCode == Activity.RESULT_OK) result.data?.data?.let { + saveFile(it) + cropImageUri() + } else Toast.makeText(this, R.string.err_pick_img, Toast.LENGTH_SHORT).show() + } + @SuppressLint("IntentReset") private fun pickPicture() { val i = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) i.type = "image/*" - startActivityForResult(i, MSG_CROP_IMAGE) + pickerLauncher.launch(i) } private fun saveFile(uri: Uri) { @@ -302,11 +303,18 @@ class MainActivity : AppCompatActivity() { if (headPic.exists()) navhbg.setImageURI(headPic.toUri()) } + private var cropLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + if (result.resultCode == Activity.RESULT_OK) { + val fi = headPic.inputStream() + navhbg.setImageBitmap(BitmapFactory.decodeStream(fi)) + fi.close() + } else Toast.makeText(this, R.string.err_crop_img, Toast.LENGTH_SHORT).show() + } + private fun cropImageUri() { val op = UCrop.Options() val r = navhbg.width.toFloat() / navhbg.height.toFloat() Log.d("MyMain", "Img info: (${navhbg.width}, ${navhbg.height})") - Log.d("MyMain", "Result code: ${UCrop.REQUEST_CROP}") if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { op.setCompressionFormat(Bitmap.CompressFormat.WEBP_LOSSY) } else { @@ -315,17 +323,17 @@ class MainActivity : AppCompatActivity() { op.setStatusBarColor(resources.getColor(R.color.colorPrimaryDark, theme)) op.setToolbarColor(resources.getColor(R.color.colorPrimary, theme)) op.setActiveControlsWidgetColor(resources.getColor(R.color.colorAccent, theme)) - UCrop.of(headPic.toUri(), headPic.toUri()) + cropLauncher.launch(UCrop.of(headPic.toUri(), headPic.toUri()) .withAspectRatio(r, 1F) .withMaxResultSize(navhbg.width, navhbg.height) .withOptions(op) - .start(this) + .getIntent(this)) } private fun checkUpdate(ignoreSkip: Boolean) { - Thread{ - Update.checkUpdate(this, toolsBox, ignoreSkip) - }.start() + lifecycleScope.launch { + Update.checkUpdate(this@MainActivity, toolsBox, ignoreSkip) + } } private fun showAbout() { diff --git a/app/src/main/java/top/fumiama/copymanga/json/ComicStructure.java b/app/src/main/java/top/fumiama/copymanga/json/ComicStructure.java index a0cd262..db97b86 100644 --- a/app/src/main/java/top/fumiama/copymanga/json/ComicStructure.java +++ b/app/src/main/java/top/fumiama/copymanga/json/ComicStructure.java @@ -3,12 +3,13 @@ package top.fumiama.copymanga.json; public class ComicStructure { public String uuid; public String name; - public String alias; + //public String alias; + public int img_type; + public ValueDisplayPair region; public ValueDisplayPair status; public ThemeStructure[] theme; public String path_word; public ThemeStructure[] author; - public int img_type; public String brief; public String datetime_updated; public String cover; diff --git a/app/src/main/java/top/fumiama/copymanga/manga/Shelf.kt b/app/src/main/java/top/fumiama/copymanga/manga/Shelf.kt index 818278e..8974803 100644 --- a/app/src/main/java/top/fumiama/copymanga/manga/Shelf.kt +++ b/app/src/main/java/top/fumiama/copymanga/manga/Shelf.kt @@ -1,6 +1,8 @@ package top.fumiama.copymanga.manga import com.google.gson.Gson +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext import top.fumiama.copymanga.json.BookQueryStructure import top.fumiama.copymanga.json.ReturnBase import top.fumiama.copymanga.tools.http.DownloadTools @@ -12,9 +14,9 @@ class Shelf(private val token: String, getString: (Int) -> String) { private val queryApiUrl = getString(R.string.bookUserQueryApiUrl) private val referer: String = getString(R.string.referer) private val ua: String = getString(R.string.pc_ua) - fun add(comicId: String): String { + suspend fun add(comicId: String): String = withContext(Dispatchers.IO) { if (comicId.isEmpty()) { - return "空漫画ID" + return@withContext "空漫画ID" } val body = buildString { append("comic_id=") @@ -25,13 +27,13 @@ class Shelf(private val token: String, getString: (Int) -> String) { } val re = DownloadTools.requestWithBody( "$apiUrl?platform=3", "POST", body.encodeToByteArray(), referer, ua - )?.decodeToString() ?: return "空回应" - return Gson().fromJson(re, ReturnBase::class.java).message + )?.decodeToString() ?: return@withContext "空回应" + return@withContext Gson().fromJson(re, ReturnBase::class.java).message } - fun del(vararg bookIds: Int): String { + suspend fun del(vararg bookIds: Int): String = withContext(Dispatchers.IO) { if (bookIds.isEmpty()) { - return "空ID列表" + return@withContext "空ID列表" } val body = buildString { bookIds.forEach { @@ -44,16 +46,13 @@ class Shelf(private val token: String, getString: (Int) -> String) { } val re = DownloadTools.requestWithBody( "${apiUrl}s?platform=3", "DELETE", body.encodeToByteArray(), referer, ua - )?.decodeToString() ?: return "空回应" - return Gson().fromJson(re, ReturnBase::class.java).message + )?.decodeToString() ?: return@withContext "空回应" + return@withContext Gson().fromJson(re, ReturnBase::class.java).message } - fun query(pathWord: String): BookQueryStructure { - DownloadTools.getHttpContent(queryApiUrl.format(hostUrl, pathWord), referer, ua)?.let { - return Gson().fromJson(it.decodeToString(), BookQueryStructure::class.java) + suspend fun query(pathWord: String): BookQueryStructure? = withContext(Dispatchers.IO) { + return@withContext DownloadTools.getHttpContent(queryApiUrl.format(hostUrl, pathWord), referer, ua)?.let { + Gson().fromJson(it.decodeToString(), BookQueryStructure::class.java) } - val b = BookQueryStructure() - b.code = 400 - return b } } 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 811b934..7f9b742 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 @@ -7,7 +7,6 @@ import android.view.View import androidx.fragment.app.Fragment import com.bumptech.glide.Glide import com.bumptech.glide.load.model.GlideUrl -import kotlinx.android.synthetic.main.card_book.* import kotlinx.android.synthetic.main.card_book.view.* import kotlinx.android.synthetic.main.line_horizonal_empty.view.* import kotlinx.android.synthetic.main.line_lazybooklines.* @@ -36,6 +35,7 @@ class CardList( rows = arrayOfNulls(20) index = 0 count = 0 + cardLoadingWaits.set(0) exitCardList = false } diff --git a/app/src/main/java/top/fumiama/copymanga/template/ui/InfoCardLoader.kt b/app/src/main/java/top/fumiama/copymanga/template/ui/InfoCardLoader.kt index 286d0b3..1d8c55e 100644 --- a/app/src/main/java/top/fumiama/copymanga/template/ui/InfoCardLoader.kt +++ b/app/src/main/java/top/fumiama/copymanga/template/ui/InfoCardLoader.kt @@ -7,7 +7,6 @@ import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import com.google.gson.Gson import kotlinx.android.synthetic.main.line_lazybooklines.* -import top.fumiama.copymanga.MainActivity import top.fumiama.copymanga.json.BookListStructure import top.fumiama.copymanga.json.HistoryBookListStructure import top.fumiama.copymanga.json.ShelfStructure @@ -25,8 +24,8 @@ open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isT override fun addPage(){ super.addPage() - ad = AutoDownloadThread(subUrl) { - if (it == null) { + ad = AutoDownloadThread(subUrl) { data -> + if (data == null) { activity?.runOnUiThread { findNavController().popBackStack() } @@ -37,7 +36,7 @@ open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isT isRefresh = false } if(isTypeBook) { - val bookList = Gson().fromJson(it?.decodeToString(), TypeBookListStructure::class.java) + val bookList = Gson().fromJson(data.decodeToString(), TypeBookListStructure::class.java) bookList?.apply { Log.d("MyICL", "offset:${results.offset}, total:${results.total}") if(results.offset < results.total) { @@ -56,7 +55,7 @@ open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isT page++ } } else if(isHistoryBook) { - val bookList = Gson().fromJson(it?.decodeToString(), HistoryBookListStructure::class.java) + val bookList = Gson().fromJson(data.decodeToString(), HistoryBookListStructure::class.java) bookList?.apply { Log.d("MyICL", "offset:${results?.offset}, total:${results?.total}") if(results.offset < results.total) { @@ -75,7 +74,7 @@ open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isT page++ } } else if (isShelfBook) { - val bookList = Gson().fromJson(it?.decodeToString(), ShelfStructure::class.java) + val bookList = Gson().fromJson(data.decodeToString(), ShelfStructure::class.java) bookList?.apply { Log.d("MyICL", "offset:${results?.offset}, total:${results?.total}") if(results.offset < results.total) { @@ -83,7 +82,7 @@ open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isT results?.list?.forEach{ book -> if(ad?.exit == true) return@AutoDownloadThread cardList?.addCard( - book?.comic?.name?:"null", "\n读到${book?.last_browse?.last_browse_name}", book?.comic?.cover, + book?.comic?.name?:"null", "\n${book?.last_browse?.last_browse_name?.let { "读到$it" }?:"未读"}", book?.comic?.cover, book?.comic?.path_word, null, null, book?.comic?.status==1, book.comic?.browse?.chapter_uuid != book.comic?.last_chapter_id @@ -95,7 +94,7 @@ open class InfoCardLoader(inflateRes:Int, private val navId:Int, private val isT page++ } } else { - val bookList = Gson().fromJson(it?.decodeToString(), BookListStructure::class.java) + val bookList = Gson().fromJson(data.decodeToString(), BookListStructure::class.java) bookList?.apply { Log.d("MyICL", "offset:${results?.offset}, total:${results?.total}") if(results.offset < results.total) { diff --git a/app/src/main/java/top/fumiama/copymanga/template/ui/StatusCardFlow.kt b/app/src/main/java/top/fumiama/copymanga/template/ui/StatusCardFlow.kt index f66b858..16f78bc 100644 --- a/app/src/main/java/top/fumiama/copymanga/template/ui/StatusCardFlow.kt +++ b/app/src/main/java/top/fumiama/copymanga/template/ui/StatusCardFlow.kt @@ -3,15 +3,18 @@ package top.fumiama.copymanga.template.ui import android.animation.ObjectAnimator import android.view.View import kotlinx.android.synthetic.main.anchor_popular.view.* -import kotlinx.android.synthetic.main.line_finish.* -import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference import top.fumiama.copymanga.tools.api.CMApi import top.fumiama.dmzj.copymanga.R @ExperimentalStdlibApi -open class StatusCardFlow(private val api: Int, nav: Int) : InfoCardLoader(R.layout.fragment_statuscardflow, nav) { - val sortWay = listOf("-datetime_updated", "datetime_updated", "popular", "-popular") +open class StatusCardFlow(private val api: Int, nav: Int, inflateRes: Int, + isTypeBook: Boolean = false, + isHistoryBook: Boolean = false, + isShelfBook: Boolean = false) : InfoCardLoader(inflateRes, nav, isTypeBook, isHistoryBook, isShelfBook) { + val sortWay = listOf("-datetime_updated", "datetime_updated", "-popular", "popular") var sortValue = 0 + var lineUpdate: View? = null + var lineHot: View? = null override fun getApiUrl() = getString(api).format( @@ -22,21 +25,17 @@ open class StatusCardFlow(private val api: Int, nav: Int) : InfoCardLoader(R.lay override fun setListeners() { super.setListeners() - setUpdate(line_finish_time) - setHot(line_finish_pop) + lineUpdate?.let { setUpdate(it) } + lineHot?.let { setHot(it) } + lineUpdate?.alpha = 1f + lineHot?.alpha = 0.5f } open fun setUpdate(that: View) { that.apply { apt.setText(R.string.menu_update_time) setOnClickListener { - sortValue = if(apim.rotation == 0f) { - ObjectAnimator.ofFloat(apim, "rotation", 0f, 180f).setDuration(233).start() - 1 - }else{ - ObjectAnimator.ofFloat(apim, "rotation", 180f, 0f).setDuration(233).start() - 0 - } + sortValue = triggerLine(false) Thread{ Thread.sleep(400) activity?.runOnUiThread { @@ -52,13 +51,7 @@ open class StatusCardFlow(private val api: Int, nav: Int) : InfoCardLoader(R.lay that.apply { apt.setText(R.string.menu_hot) setOnClickListener { - sortValue = if (apim.rotation == 0f) { - ObjectAnimator.ofFloat(apim, "rotation", 0f, 180f).setDuration(233).start() - 3 - } else { - ObjectAnimator.ofFloat(apim, "rotation", 180f, 0f).setDuration(233).start() - 2 - } + sortValue = triggerLine(true) Thread { Thread.sleep(400) activity?.runOnUiThread { @@ -69,4 +62,46 @@ open class StatusCardFlow(private val api: Int, nav: Int) : InfoCardLoader(R.lay } } } + + open fun triggerLine(isHot: Boolean): Int { + val hot = lineHot?:return 0 + val update = lineUpdate?:return 0 + if(sortValue >= 2) { + if (isHot) { + return if (hot.apim.rotation == 0f) { + ObjectAnimator.ofFloat(hot.apim, "rotation", 0f, 180f).setDuration(233).start() + 3 + } else { + ObjectAnimator.ofFloat(hot.apim, "rotation", 180f, 0f).setDuration(233).start() + 2 + } + } else { + update.alpha = 1f + hot.alpha = 0.5f + return if(update.apim.rotation == 0f) { + 0 + } else { + 1 + } + } + } else { + if (!isHot) { + return if(update.apim.rotation == 0f) { + ObjectAnimator.ofFloat(update.apim, "rotation", 0f, 180f).setDuration(233).start() + 1 + }else{ + ObjectAnimator.ofFloat(update.apim, "rotation", 180f, 0f).setDuration(233).start() + 0 + } + } else { + hot.alpha = 1f + update.alpha = 0.5f + return if (hot.apim.rotation == 0f) { + 2 + } else { + 3 + } + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/top/fumiama/copymanga/template/ui/ThemeCardFlow.kt b/app/src/main/java/top/fumiama/copymanga/template/ui/ThemeCardFlow.kt index 0d91cca..e26a2f5 100644 --- a/app/src/main/java/top/fumiama/copymanga/template/ui/ThemeCardFlow.kt +++ b/app/src/main/java/top/fumiama/copymanga/template/ui/ThemeCardFlow.kt @@ -1,12 +1,15 @@ package top.fumiama.copymanga.template.ui import android.os.Bundle +import android.view.View import kotlinx.android.synthetic.main.app_bar_main.* +import kotlinx.android.synthetic.main.line_finish.* import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference import top.fumiama.copymanga.tools.api.CMApi +import top.fumiama.dmzj.copymanga.R @ExperimentalStdlibApi -open class ThemeCardFlow(private val api: Int, nav: Int) : StatusCardFlow(0, nav) { +open class ThemeCardFlow(private val api: Int, nav: Int) : StatusCardFlow(0, nav, R.layout.fragment_statuscardflow) { private var theme = "" override fun getApiUrl() = getString(api).format( @@ -26,6 +29,12 @@ open class ThemeCardFlow(private val api: Int, nav: Int) : StatusCardFlow(0, nav } } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + lineUpdate = line_finish_time + lineHot = line_finish_pop + } + override fun onResume() { super.onResume() arguments?.getString("name")?.apply { diff --git a/app/src/main/java/top/fumiama/copymanga/tools/api/CMApi.kt b/app/src/main/java/top/fumiama/copymanga/tools/api/CMApi.kt index fb41924..904e2ab 100644 --- a/app/src/main/java/top/fumiama/copymanga/tools/api/CMApi.kt +++ b/app/src/main/java/top/fumiama/copymanga/tools/api/CMApi.kt @@ -13,7 +13,7 @@ import java.net.URLEncoder object CMApi { var proxy = if(Proxy.useImageProxy) Proxy(R.string.imgProxyApiUrl, R.string.imgProxyApiPrefix, R.string.imgProxyKeyID) else null - var resolution = Resolution(Regex("\\.c\\d+x\\.")) + var resolution = Resolution(Regex("c\\d+x\\.")) var myGlideHeaders: LazyHeaders? = null get() { MainActivity.mainWeakReference?.get()?.let { diff --git a/app/src/main/java/top/fumiama/copymanga/tools/http/Resolution.kt b/app/src/main/java/top/fumiama/copymanga/tools/http/Resolution.kt index 3bfd27c..ed9a82d 100644 --- a/app/src/main/java/top/fumiama/copymanga/tools/http/Resolution.kt +++ b/app/src/main/java/top/fumiama/copymanga/tools/http/Resolution.kt @@ -16,5 +16,5 @@ class Resolution(private val original: Regex) { } return 1500 } - fun wrap(u: String) : String = u.replace(original, ".c${imageResolution}x.") + fun wrap(u: String) : String = u.replace(original, "c${imageResolution}x.") } diff --git a/app/src/main/java/top/fumiama/copymanga/tools/ui/GlideHideLottieViewListener.kt b/app/src/main/java/top/fumiama/copymanga/tools/ui/GlideHideLottieViewListener.kt index 647eaad..33b9c9d 100644 --- a/app/src/main/java/top/fumiama/copymanga/tools/ui/GlideHideLottieViewListener.kt +++ b/app/src/main/java/top/fumiama/copymanga/tools/ui/GlideHideLottieViewListener.kt @@ -13,17 +13,17 @@ class GlideHideLottieViewListener(private val wla: WeakReference?, + target: Target, isFirstResource: Boolean ): Boolean { return false } override fun onResourceReady( - resource: Drawable?, - model: Any?, + resource: Drawable, + model: Any, target: Target?, - dataSource: DataSource?, + dataSource: DataSource, isFirstResource: Boolean ): Boolean { wla.get()?.apply { 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 d10b449..b73fa00 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 @@ -6,14 +6,18 @@ import android.os.Bundle import android.util.Log import android.view.View import android.widget.Toast +import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController import com.google.gson.Gson 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_bookinfo_text.* import kotlinx.android.synthetic.main.line_booktandb.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import top.fumiama.copymanga.MainActivity -import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference import top.fumiama.copymanga.json.VolumeStructure import top.fumiama.copymanga.manga.Reader import top.fumiama.copymanga.template.general.NoBackRefreshFragment @@ -32,14 +36,14 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) { super.onViewCreated(view, savedInstanceState) ComicDlFragment.exit = false - fbl?.setPadding(0, 0, 0, navBarHeight) + fbvp?.setPadding(0, 0, 0, navBarHeight) if(isFirstInflate) { var path = "" arguments?.apply { if (getBoolean("loadJson")) { getString("name")?.let { name -> - mainWeakReference?.get()?.getExternalFilesDir("")?.let { + activity?.getExternalFilesDir("")?.let { Gson().fromJson(File(File(it, name), "info.json").readText(), Array::class.java) }?.apply { if (isEmpty() || get(0).results.list.isEmpty()) { @@ -62,10 +66,12 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) { mBookHandler = BookHandler(WeakReference(this), path) Log.d("MyBF", "read path: $path") bookHandler = mBookHandler - Thread { - sleep(600) - mBookHandler?.startLoad() - }.start() + lifecycleScope.launch { + withContext(Dispatchers.IO) { + sleep(600) + mBookHandler?.startLoad() + } + } } else { bookHandler = mBookHandler } @@ -75,7 +81,7 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) { super.onResume() isOnPause = false bookHandler = mBookHandler - mainWeakReference?.get()?.apply { + activity?.apply { toolbar.title = mBookHandler?.book?.results?.comic?.name } setStartRead() @@ -96,7 +102,7 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) { } fun setStartRead() { - if(mBookHandler?.chapterNames?.isNotEmpty() == true) mainWeakReference?.get()?.apply { + if(mBookHandler?.chapterNames?.isNotEmpty() == true) activity?.apply { mBookHandler?.book?.results?.comic?.let { comic -> getPreferences(MODE_PRIVATE).getInt(comic.name, -1).let { p -> this@BookFragment.lbbstart.apply { @@ -118,12 +124,13 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) { @SuppressLint("SetTextI18n") fun setAddToShelf() { - if(mBookHandler?.chapterNames?.isNotEmpty() == true) { + if(mBookHandler?.chapterNames?.isNotEmpty() != true) return + lifecycleScope.launch { val b = MainActivity.shelf?.query(mBookHandler?.path!!) mBookHandler?.collect = b?.results?.collect?:-2 Log.d("MyBF", "get collect of ${mBookHandler?.path} = ${mBookHandler?.collect}") - b?.results?.browse?.chapter_name?.let { name -> - btsub.text = "${btsub.text} ${getString(R.string.text_format_cloud_read_to).format(name)}" + tic.text = b?.results?.browse?.chapter_name?.let { name -> + getString(R.string.text_format_cloud_read_to).format(name) } mBookHandler?.collect?.let { collect -> if (collect > 0) { @@ -132,30 +139,24 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) { } mBookHandler?.book?.results?.comic?.let { comic -> this@BookFragment.lbbsub.setOnClickListener { - if (this@BookFragment.lbbsub.text != getString(R.string.button_sub)) { - mBookHandler?.collect?.let { collect -> - if (collect < 0) return@setOnClickListener - Thread{ + lifecycleScope.launch clickLaunch@ { + if (this@BookFragment.lbbsub.text != getString(R.string.button_sub)) { + mBookHandler?.collect?.let { collect -> + if (collect < 0) return@clickLaunch val re = MainActivity.shelf?.del(collect) - activity?.runOnUiThread { - Toast.makeText(context, re, Toast.LENGTH_SHORT).show() - if (re == "请求成功") { - this@BookFragment.lbbsub.setText(R.string.button_sub) - } + Toast.makeText(context, re, Toast.LENGTH_SHORT).show() + if (re == "请求成功") { + this@BookFragment.lbbsub.setText(R.string.button_sub) } - }.start() - } - return@setOnClickListener - } - Thread{ - val re = MainActivity.shelf?.add(comic.uuid) - activity?.runOnUiThread { - Toast.makeText(context, re, Toast.LENGTH_SHORT).show() - if (re == "修改成功") { - this@BookFragment.lbbsub.setText(R.string.button_sub_subscribed) } + return@clickLaunch } - }.start() + val re = MainActivity.shelf?.add(comic.uuid) + Toast.makeText(context, re, Toast.LENGTH_SHORT).show() + if (re == "修改成功") { + this@BookFragment.lbbsub.setText(R.string.button_sub_subscribed) + } + } } } } diff --git a/app/src/main/java/top/fumiama/copymanga/ui/book/BookHandler.kt b/app/src/main/java/top/fumiama/copymanga/ui/book/BookHandler.kt index 80bddef..5317835 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/book/BookHandler.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/book/BookHandler.kt @@ -6,13 +6,18 @@ import android.os.Looper import android.os.Message import android.util.Log import android.view.View +import android.view.ViewGroup +import android.widget.LinearLayout import android.widget.TextView import android.widget.Toast import androidx.core.graphics.drawable.toBitmap +import androidx.core.widget.NestedScrollView import androidx.navigation.fragment.findNavController +import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide import com.bumptech.glide.load.model.GlideUrl import com.bumptech.glide.request.RequestOptions +import com.google.android.material.tabs.TabLayoutMediator import com.google.gson.Gson import kotlinx.android.synthetic.main.app_bar_main.* import kotlinx.android.synthetic.main.card_book.* @@ -22,6 +27,7 @@ import kotlinx.android.synthetic.main.line_bookinfo.* import kotlinx.android.synthetic.main.line_bookinfo_text.* import kotlinx.android.synthetic.main.line_caption.view.* import kotlinx.android.synthetic.main.line_chapter.view.* +import kotlinx.android.synthetic.main.page_nested_list.view.* import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference import top.fumiama.copymanga.json.BookInfoStructure import top.fumiama.copymanga.json.ChapterStructure @@ -62,7 +68,7 @@ class BookHandler(private val th: WeakReference, val path: String) var vols: Array? = null var chapterNames = arrayOf() var collect: Int = -1 - private val divider get() = that?.layoutInflater?.inflate(R.layout.div_h, that?.fbl, false) + private val divider get() = that?.layoutInflater?.inflate(R.layout.div_h, that?.lbl, false) var urlArray = arrayOf() @@ -73,10 +79,7 @@ class BookHandler(private val th: WeakReference, val path: String) 1 -> setCover() 2 -> setTexts() 3 -> setAuthorsAndTags() - //4 -> setOverScale() 6 -> if(complete) that?.navigate2dl() - 7 -> setVolumes() - 8 -> that?.apply { fbl?.addView(msg.obj as View) } 9 -> endSetLayouts() } } @@ -127,11 +130,6 @@ class BookHandler(private val th: WeakReference, val path: String) Log.d("MyBH", "Set complete: true") } - /*private fun setOverScale() { - if (exit) return - that?.fbov?.setScaleView(that!!.fbapp) - }*/ - private fun setCover() { if (exit) return that?.apply { @@ -144,63 +142,69 @@ class BookHandler(private val th: WeakReference, val path: String) ?.let { it2 -> RequestOptions.bitmapTransform(it2) } ?.let { it3 -> load.apply(it3).into(lbibg) } } - imf?.visibility = View.GONE + //imf?.visibility = View.GONE //fbl?.addView(divider) } } - private fun getThemeSeq(authors: Array): CharSequence{ + /*private fun getThemeSeq(authors: Array): CharSequence{ var re = "" for(author in authors) re += author.name + ' ' return re - } + }*/ - private fun setTexts(){ + private fun setTexts() { if (exit) return //that?.tic?.text = book?.name - that?.tic?.visibility = View.GONE + //that?.tic?.visibility = View.GONE mainWeakReference?.get()?.toolbar?.title = book?.results?.comic?.name - that?.btauth?.text = book?.results?.comic?.author?.let { getThemeSeq(it) } - that?.bttag?.text = book?.results?.comic?.theme?.let { getThemeSeq(it) } - that?.bthit?.text = that?.getString(R.string.text_format_hit)?.let { String.format( - it, + that?.btauth?.text = that?.getString(R.string.text_format_region)?.format( + book?.results?.comic?.region?.display + ) + that?.bttag?.text = that?.getString(R.string.text_format_img_type)?.format(when(book?.results?.comic?.img_type) { + 1 -> "条漫" + 2 -> "普通" + else -> "未知类型${book?.results?.comic?.img_type}" + }) + that?.bthit?.text = that?.getString(R.string.text_format_hit)?.format( book?.results?.comic?.popular - ) }?:"" - that?.btsub?.text = that?.getString(R.string.text_format_stat)?.let { String.format( - it, + ) + that?.btsub?.text = that?.getString(R.string.text_format_stat)?.format( book?.results?.comic?.status?.display - ) }?:"" + ) that?.bttime?.text = book?.results?.comic?.datetime_updated - val v = that?.layoutInflater?.inflate(R.layout.line_text_info, that?.fbl, false) + val v = that?.layoutInflater?.inflate(R.layout.line_text_info, that?.lbl, false) (v as TextView).text = book?.results?.comic?.brief - that?.fbl?.addView(v) - that?.fbl?.addView(divider) + that?.lbl?.addView(v) + that?.lbl?.addView(divider) } private fun setTheme(caption: String, themeStructure: Array, nav: Int) { that?.apply { - val t = layoutInflater.inflate(R.layout.line_caption, fbl, false) + val t = layoutInflater.inflate(R.layout.line_caption, lbl, false) t.tcptn.text = caption - fbl.addView(t) - fbl.addView(layoutInflater.inflate(R.layout.div_h, fbl, false)) + lbl.addView(t) + lbl.addView(layoutInflater.inflate(R.layout.div_h, lbl, false)) } var line: View? = null val last = themeStructure.size - 1 themeStructure.onEachIndexed { i, it -> if(line == null) { if(i == last) { - line = that?.layoutInflater?.inflate(R.layout.line_chapter, that!!.fbl, false) + line = that?.layoutInflater?.inflate(R.layout.line_chapter, that!!.lbl, false) line?.lcc?.apply { lct.text = it.name + lci.setBackgroundResource(R.drawable.ic_list) setOnClickListener { _ -> loadVolume(it.name, it.path_word, nav) } } - that?.fbl?.addView(line) + that?.lbl?.addView(line) } else { - line = that?.layoutInflater?.inflate(R.layout.line_2chapters, that!!.fbl, false) + line = that?.layoutInflater?.inflate(R.layout.line_2chapters, that!!.lbl, false) line?.l2cl?.apply { lct.text = it.name + lci.setBackgroundResource(R.drawable.ic_list) setOnClickListener { _ -> loadVolume(it.name, it.path_word, nav) } @@ -208,10 +212,11 @@ class BookHandler(private val th: WeakReference, val path: String) } } else line?.l2cr?.apply { lct.text = it.name + lci.setBackgroundResource(R.drawable.ic_list) setOnClickListener { _ -> loadVolume(it.name, it.path_word, nav) } - that?.fbl?.addView(line) + that?.lbl?.addView(line) line = null } } @@ -228,7 +233,7 @@ class BookHandler(private val th: WeakReference, val path: String) R.id.action_nav_book_to_nav_author ) } - fbl.addView(layoutInflater.inflate(R.layout.div_h, fbl, false)) + lbl.addView(layoutInflater.inflate(R.layout.div_h, lbl, false)) theme?.let { setTheme( getString(R.string.caption), @@ -240,11 +245,68 @@ class BookHandler(private val th: WeakReference, val path: String) } } - private fun addVolumesView(v: View) { - obtainMessage(8, v).sendToTarget() + private fun addVolumesView(l: LinearLayout, v: View) { + that?.activity?.runOnUiThread { + l.addView(v) + } } - private fun setVolumes() = Thread { + private fun setVolume(fbl: LinearLayout, p: Int) = Thread { + if (exit) return@Thread + that?.apply { + book?.results?.apply { + var i = 0 + for (j in 0 until p) { + i += vols?.get(j)?.results?.list?.size?:0 + } + var last = i-1 + vols?.get(p)?.let { v -> + if(exit) return@Thread + var line: View? = null + last += v.results.list.size + v.results.list.forEach { + val f = CMApi.getZipFile(context?.getExternalFilesDir(""), comic.name, keys[p], it.name) + Log.d("MyBH", "i = $i, last=$last, add chapter ${it.name}, line is null: ${line == null}") + that?.isOnPause?.let { isOnPause -> + while (isOnPause && !exit) sleep(1000) + if (exit) return@Thread + }?:return@Thread + if(line == null) { + if(i == last) { + line = layoutInflater.inflate(R.layout.line_chapter, fbl, false) + line?.lcc?.apply { + lct.text = it.name + if (f.exists()) lci.setBackgroundResource(R.drawable.ic_success) + Log.d("MyBH", "add last single chapter ${it.name}") + val index = i + setOnClickListener { Reader.viewMangaAt(comic.name, index, urlArray) } + } + line?.let { l -> addVolumesView(fbl, l) } + } else { + line = layoutInflater.inflate(R.layout.line_2chapters, fbl, false) + line?.l2cl?.apply { + lct.text = it.name + if (f.exists()) lci.setBackgroundResource(R.drawable.ic_success) + val index = i + setOnClickListener { Reader.viewMangaAt(comic.name, index, urlArray) } + } + } + } else line?.l2cr?.apply { + lct.text = it.name + if (f.exists()) lci.setBackgroundResource(R.drawable.ic_success) + val index = i + setOnClickListener { Reader.viewMangaAt(comic.name, index, urlArray) } + line?.let { l -> addVolumesView(fbl, l) } + line = null + } + i++ + } + } + } + } + }.start() + + private fun setViewManga() = Thread { if (exit) return@Thread that?.apply { book?.results?.apply { @@ -255,58 +317,26 @@ class BookHandler(private val th: WeakReference, val path: String) var last = -1 vols?.forEachIndexed { groupIndex, v -> if(exit) return@Thread - addVolumesView(layoutInflater.inflate(R.layout.div_h, fbl, false)) - val t = layoutInflater.inflate(R.layout.line_caption, fbl, false) - t.tcptn.text = keys[groupIndex] - addVolumesView(t) - addVolumesView(layoutInflater.inflate(R.layout.div_h, fbl, false)) - var line: View? = null last += v.results.list.size v.results.list.forEach { urlArray += CMApi.getChapterInfoApiUrl( comic.path_word, it.uuid )?:"" - ViewMangaActivity.fileArray += CMApi.getZipFile(context?.getExternalFilesDir(""), comic.name, keys[groupIndex], it.name) + val f = CMApi.getZipFile(context?.getExternalFilesDir(""), comic.name, keys[groupIndex], it.name) + ViewMangaActivity.fileArray += f chapterNames += it.name ViewMangaActivity.uuidArray += it.uuid - Log.d("MyBH", "i = $i, last=$last, add chapter ${it.name}, line is null: ${line == null}") that?.isOnPause?.let { isOnPause -> while (isOnPause && !exit) sleep(1000) if (exit) return@Thread }?:return@Thread - if(line == null) { - if(i == last) { - line = layoutInflater.inflate(R.layout.line_chapter, that!!.fbl, false) - line?.lcc?.apply { - lct.text = it.name - Log.d("MyBH", "add last single chapter ${it.name}") - val index = i - setOnClickListener { Reader.viewMangaAt(comic.name, index, urlArray) } - } - line?.let { l -> addVolumesView(l) } - - } else { - line = layoutInflater.inflate(R.layout.line_2chapters, that!!.fbl, false) - line?.l2cl?.apply { - lct.text = it.name - val index = i - setOnClickListener { Reader.viewMangaAt(comic.name, index, urlArray) } - } - } - } else line?.l2cr?.apply { - lct.text = it.name - val index = i - setOnClickListener { Reader.viewMangaAt(comic.name, index, urlArray) } - line?.let { l -> addVolumesView(l) } - line = null - } i++ } } - sendEmptyMessage(9) // end set layout } } + sendEmptyMessage(9) // end set layout }.start() private fun loadVolume(name: String, path: String, nav: Int){ @@ -375,10 +405,18 @@ class BookHandler(private val th: WeakReference, val path: String) c++ } if (volumes.size == gpws.size) { - that?.activity?.runOnUiThread { - saveVolumes(volumes) - sendEmptyMessage(7) + saveVolumes(volumes) + that?.fbtab?.let { tab -> + that?.fbvp?.let { vp -> + that?.activity?.runOnUiThread { + vp.adapter = ViewData(vp).RecyclerViewAdapter() + TabLayoutMediator(tab, vp) { t, p -> + t.text = keys[p] + }.attach() + } + } } + setViewManga() } }.start() @@ -417,4 +455,18 @@ class BookHandler(private val th: WeakReference, val path: String) } vols = volumes } + + inner class ViewData(itemView: View): RecyclerView.ViewHolder(itemView) { + inner class RecyclerViewAdapter: RecyclerView.Adapter() { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewData { + return ViewData(that?.layoutInflater?.inflate(R.layout.page_nested_list, parent, false) as NestedScrollView) + } + + override fun onBindViewHolder(holder: ViewData, position: Int) { + setVolume(holder.itemView.fbl, position) + } + + override fun getItemCount(): Int = keys.size + } + } } diff --git a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/finish/FinishFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/finish/FinishFragment.kt index 1b77baf..a7e58d9 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/finish/FinishFragment.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/finish/FinishFragment.kt @@ -1,7 +1,17 @@ package top.fumiama.copymanga.ui.cardflow.finish +import android.os.Bundle +import android.view.View import top.fumiama.copymanga.template.ui.StatusCardFlow import top.fumiama.dmzj.copymanga.R +import kotlinx.android.synthetic.main.line_finish.* @ExperimentalStdlibApi -class FinishFragment : StatusCardFlow(R.string.finishApiUrl, R.id.action_nav_finish_to_nav_book) \ No newline at end of file +class FinishFragment : StatusCardFlow( + R.string.finishApiUrl, R.id.action_nav_finish_to_nav_book, R.layout.fragment_statuscardflow) { + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + lineUpdate = line_finish_time + lineHot = line_finish_pop + } +} diff --git a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/newest/NewestFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/newest/NewestFragment.kt index f87a4e4..f67ecf6 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/newest/NewestFragment.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/newest/NewestFragment.kt @@ -1,8 +1,5 @@ package top.fumiama.copymanga.ui.cardflow.newest -import android.view.View -import kotlinx.android.synthetic.main.line_lazybooklines.* -import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference import top.fumiama.copymanga.template.ui.InfoCardLoader import top.fumiama.copymanga.tools.api.CMApi import top.fumiama.dmzj.copymanga.R diff --git a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/rank/RankFragment.kt b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/rank/RankFragment.kt index cac0a6e..cbc24f4 100644 --- a/app/src/main/java/top/fumiama/copymanga/ui/cardflow/rank/RankFragment.kt +++ b/app/src/main/java/top/fumiama/copymanga/ui/cardflow/rank/RankFragment.kt @@ -4,7 +4,6 @@ import android.os.Bundle import com.google.android.material.tabs.TabLayout import kotlinx.android.synthetic.main.fragment_rank.* import kotlinx.android.synthetic.main.line_rank.view.* -import top.fumiama.copymanga.MainActivity import top.fumiama.copymanga.template.ui.InfoCardLoader import top.fumiama.copymanga.tools.api.CMApi import top.fumiama.copymanga.tools.ui.UITools @@ -13,7 +12,7 @@ import java.lang.Thread.sleep import java.lang.ref.WeakReference @ExperimentalStdlibApi -class RankFragment : InfoCardLoader(R.layout.fragment_rank, R.id.action_nav_rank_to_nav_book, true) { +class RankFragment : InfoCardLoader(R.layout.fragment_rank, R.id.action_nav_rank_to_nav_book, isTypeBook = true) { private val sortWay = listOf("day", "week", "month", "total") private var sortValue = 0 private val audienceWay = listOf("", "male", "female") 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 078c149..e6820a1 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 @@ -2,9 +2,14 @@ package top.fumiama.copymanga.ui.cardflow.shelf import android.animation.ObjectAnimator import android.os.Bundle +import android.view.View +import androidx.lifecycle.lifecycleScope 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.launch +import kotlinx.coroutines.withContext import top.fumiama.copymanga.MainActivity import top.fumiama.copymanga.template.ui.InfoCardLoader import top.fumiama.copymanga.tools.api.CMApi @@ -37,6 +42,7 @@ class ShelfFragment : InfoCardLoader(R.layout.fragment_shelf, R.id.action_nav_su override fun setListeners() { super.setListeners() + fade() setUpdate() setModify() setBrowse() @@ -46,20 +52,10 @@ class ShelfFragment : InfoCardLoader(R.layout.fragment_shelf, R.id.action_nav_su if (ad?.exit == true) return line_shelf_updated.apt.setText(R.string.menu_update_time) line_shelf_updated.setOnClickListener { - sortValue = if (it.apim.rotation == 0f) { - ObjectAnimator.ofFloat(it.apim, "rotation", 0f, 180f).setDuration(233).start() - 1 - } else { - ObjectAnimator.ofFloat(it.apim, "rotation", 180f, 0f).setDuration(233).start() - 0 - } - Thread { - sleep(400) - activity?.runOnUiThread { - reset() - addPage() - } - }.start() + val same = sortValue in 0..1 + sortValue = rotate(it.apim, same, 0) + if (!same) fade() + resetDelayed() } } @@ -67,20 +63,10 @@ class ShelfFragment : InfoCardLoader(R.layout.fragment_shelf, R.id.action_nav_su if (ad?.exit == true) return line_shelf_modifier.apt.setText(R.string.menu_add_time) line_shelf_modifier.setOnClickListener { - sortValue = if (it.apim.rotation == 0f) { - ObjectAnimator.ofFloat(it.apim, "rotation", 0f, 180f).setDuration(233).start() - 3 - } else { - ObjectAnimator.ofFloat(it.apim, "rotation", 180f, 0f).setDuration(233).start() - 2 - } - Thread { - sleep(400) - activity?.runOnUiThread { - reset() - addPage() - } - }.start() + val same = sortValue in 2..3 + sortValue = rotate(it.apim, same, 2) + if (!same) fade() + resetDelayed() } } @@ -88,20 +74,60 @@ class ShelfFragment : InfoCardLoader(R.layout.fragment_shelf, R.id.action_nav_su if (ad?.exit == true) return line_shelf_browse.apt.setText(R.string.menu_read_time) line_shelf_browse.setOnClickListener { - sortValue = if (it.apim.rotation == 0f) { - ObjectAnimator.ofFloat(it.apim, "rotation", 0f, 180f).setDuration(233).start() - 5 + val same = sortValue>=4 + sortValue = rotate(it.apim, same, 4) + if (!same) fade() + resetDelayed() + } + } + + private fun rotate(img: View, isSameSlot: Boolean, offset: Int): Int { + return if (isSameSlot) { + if (img.rotation == 0f) { + ObjectAnimator.ofFloat(img, "rotation", 0f, 180f).setDuration(233).start() + offset+1 } else { - ObjectAnimator.ofFloat(it.apim, "rotation", 180f, 0f).setDuration(233).start() - 4 + ObjectAnimator.ofFloat(img, "rotation", 180f, 0f).setDuration(233).start() + offset } - Thread { + } else { + if (img.rotation == 0f) { + offset + } else { + offset+1 + } + } + } + + private fun fade() { + when(sortValue) { + 0, 1 -> { + line_shelf_updated.alpha = 1f + line_shelf_modifier.alpha = 0.5f + line_shelf_browse.alpha = 0.5f + } + 2, 3 -> { + line_shelf_updated.alpha = 0.5f + line_shelf_modifier.alpha = 1f + line_shelf_browse.alpha = 0.5f + } + 4, 5 -> { + line_shelf_updated.alpha = 0.5f + line_shelf_modifier.alpha = 0.5f + line_shelf_browse.alpha = 1f + } + } + } + + private fun resetDelayed() { + lifecycleScope.launch { + withContext(Dispatchers.IO) { sleep(400) - activity?.runOnUiThread { + withContext(Dispatchers.Main) { reset() addPage() } - }.start() + } } } } \ No newline at end of file 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 9adbf95..426346c 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 @@ -1,24 +1,22 @@ package top.fumiama.copymanga.ui.cardflow.sort -import android.animation.ObjectAnimator +import android.os.Bundle +import android.view.View import com.github.zawadz88.materialpopupmenu.popupMenu import com.google.gson.Gson import kotlinx.android.synthetic.main.anchor_popular.view.* import kotlinx.android.synthetic.main.line_sort.* -import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference import top.fumiama.copymanga.json.FilterStructure import top.fumiama.copymanga.template.http.AutoDownloadThread -import top.fumiama.copymanga.template.ui.InfoCardLoader +import top.fumiama.copymanga.template.ui.StatusCardFlow import top.fumiama.copymanga.tools.api.CMApi import top.fumiama.dmzj.copymanga.R import java.lang.Thread.sleep @ExperimentalStdlibApi -class SortFragment : InfoCardLoader(R.layout.fragment_sort, R.id.action_nav_sort_to_nav_book) { - private val sortWay = listOf("-datetime_updated", "datetime_updated", "-popular", "popular") +class SortFragment : StatusCardFlow(0, R.id.action_nav_sort_to_nav_book, R.layout.fragment_sort) { private var theme = -1 private var region = -1 - private var sortValue = 0 private var filter: FilterStructure? = null override fun getApiUrl() = @@ -30,10 +28,14 @@ class SortFragment : InfoCardLoader(R.layout.fragment_sort, R.id.action_nav_sort if(region >= 0) (filter?.results?.top?.get(region)?.path_word ?: "") else "", ) + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + lineUpdate = line_sort_time + lineHot = line_sort_hot + } + override fun setListeners() { super.setListeners() - setUpdate() - setHot() AutoDownloadThread(getString(R.string.filterApiUrl).format(CMApi.myHostApiUrl)) { if(ad?.exit == true) return@AutoDownloadThread it?.let { @@ -46,27 +48,6 @@ class SortFragment : InfoCardLoader(R.layout.fragment_sort, R.id.action_nav_sort }.start() } - private fun setUpdate(){ - if(ad?.exit == true) return - line_sort_time.apt.setText(R.string.menu_update_time) - line_sort_time.setOnClickListener { - sortValue = if(it.apim.rotation == 0f) { - ObjectAnimator.ofFloat(it.apim, "rotation", 0f, 180f).setDuration(233).start() - 1 - }else{ - ObjectAnimator.ofFloat(it.apim, "rotation", 180f, 0f).setDuration(233).start() - 0 - } - Thread{ - sleep(400) - activity?.runOnUiThread { - reset() - addPage() - } - }.start() - } - } - private fun setClasses(){ filter?.results?.top?.let { items -> if(ad?.exit == true) return@let @@ -153,25 +134,4 @@ class SortFragment : InfoCardLoader(R.layout.fragment_sort, R.id.action_nav_sort } } } - - private fun setHot() { - if(ad?.exit == true) return - line_sort_hot.apt.setText(R.string.menu_hot) - line_sort_hot.setOnClickListener { - sortValue = if (it.apim.rotation == 0f) { - ObjectAnimator.ofFloat(it.apim, "rotation", 0f, 180f).setDuration(233).start() - 3 - } else { - ObjectAnimator.ofFloat(it.apim, "rotation", 180f, 0f).setDuration(233).start() - 2 - } - Thread { - sleep(400) - activity?.runOnUiThread { - reset() - addPage() - } - }.start() - } - } } \ No newline at end of file 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 86c91ad..0e5bcad 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 @@ -4,7 +4,6 @@ import android.os.Bundle import com.google.gson.Gson import kotlinx.android.synthetic.main.app_bar_main.* import kotlinx.android.synthetic.main.fragment_topic.* -import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference import top.fumiama.copymanga.json.TopicStructure import top.fumiama.copymanga.template.http.AutoDownloadThread import top.fumiama.copymanga.template.ui.InfoCardLoader @@ -23,12 +22,11 @@ class TopicFragment : InfoCardLoader(R.layout.fragment_topic, R.id.action_nav_to if(ad?.exit == true) return@AutoDownloadThread data?.apply { val r = inputStream().reader() - val topic = Gson().fromJson(r, TopicStructure::class.java) - topic?.apply { - if(ad?.exit != false) return@AutoDownloadThread + Gson().fromJson(r, TopicStructure::class.java)?.apply { + if(ad?.exit == true) return@AutoDownloadThread activity?.let { it.runOnUiThread { - if(ad?.exit != false) return@runOnUiThread + if(ad?.exit == true) return@runOnUiThread it.toolbar.title = results.title ftttime.text = results.datetime_created fttintro.text = results.intro 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 dd4b90f..75ee719 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 @@ -1,25 +1,24 @@ package top.fumiama.copymanga.ui.download import android.app.AlertDialog -import android.content.Intent import android.os.Bundle -import android.provider.DocumentsContract import android.util.Log import android.view.View -import android.widget.Toast -import androidx.core.content.FileProvider -import androidx.core.net.toUri import androidx.fragment.app.Fragment +import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController import androidx.preference.PreferenceManager import kotlinx.android.synthetic.main.line_lazybooklines.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import top.fumiama.copymanga.MainActivity import top.fumiama.copymanga.manga.Reader import top.fumiama.copymanga.template.general.MangaPagesFragmentTemplate import top.fumiama.copymanga.template.ui.CardList +import top.fumiama.copymanga.tools.file.FileUtils import top.fumiama.copymanga.tools.ui.Navigate import top.fumiama.copymanga.tools.ui.UITools -import top.fumiama.copymanga.tools.file.FileUtils import top.fumiama.copymanga.ui.comicdl.ComicDlFragment import top.fumiama.dmzj.copymanga.R import java.io.File @@ -64,49 +63,53 @@ class NewDownloadFragment: MangaPagesFragmentTemplate(R.layout.fragment_newdownl page = 0 isRefresh = false } - if(!isEnd) { - if(sortedBookList == null || isContentChanged) { - Log.d("MyNDF", "Sorting books...") - sortedBookList = extDir?.listFiles()?.sortedBy { - return@sortedBy Reader.getComicPathWordInFile(it) - } - if (isReverse) { - Log.d("MyNDF", "reversed...") - sortedBookList = sortedBookList?.asReversed() - } - if (!showAll) { - sortedBookList = sortedBookList?.filter { - return@filter FileUtils.sizeOf(it) / 1048576 > 0 + lifecycleScope.launch { + withContext(Dispatchers.IO) { + if(!isEnd) { + if(sortedBookList == null || isContentChanged) { + Log.d("MyNDF", "Sorting books...") + sortedBookList = extDir?.listFiles()?.sortedBy { + return@sortedBy Reader.getComicPathWordInFile(it) + } + if (isReverse) { + Log.d("MyNDF", "reversed...") + sortedBookList = sortedBookList?.asReversed() + } + if (!showAll) { + sortedBookList = sortedBookList?.filter { + return@filter FileUtils.sizeOf(it) / 1048576 > 0 + } + } + isContentChanged = false } - } - isContentChanged = false - } - Log.d("MyNDF", "Start drawing cards") - cardList?.addCard(oldDlCardName, path = oldDlCardName) - var cnt = 1 - sortedBookList?.let { - for(i in it.listIterator(page)) { - if(cardList?.exitCardList != false) return - page++ // page is actually count - val chosenJson = File(i, "info.bin") - val newJson = File(i, "info.json") - val bookSize = (FileUtils.sizeOf(i)/1048576).toInt() - when { - chosenJson.exists() -> continue // unsupported old folder - newJson.exists() -> { - if(cardList?.exitCardList != false) return - cardList?.addCard(i.name, "\n${bookSize}MB") - cnt++ + Log.d("MyNDF", "Start drawing cards") + cardList?.addCard(oldDlCardName, path = oldDlCardName) + var cnt = 1 + sortedBookList?.let { + for(i in it.listIterator(page)) { + if(cardList?.exitCardList != false) return@withContext + page++ // page is actually count + val chosenJson = File(i, "info.bin") + val newJson = File(i, "info.json") + val bookSize = (FileUtils.sizeOf(i)/1048576).toInt() + when { + chosenJson.exists() -> continue // unsupported old folder + newJson.exists() -> { + if(cardList?.exitCardList != false) return@withContext + cardList?.addCard(i.name, "\n${bookSize}MB") + cnt++ + } + } + if (cnt >= 21) break + } + if(page >= it.size) { + isEnd = true } } - if (cnt >= 21) break - } - if(page >= it.size) { - isEnd = true } + onLoadFinish() } } - onLoadFinish() } override fun initCardList(weakReference: WeakReference) { @@ -136,12 +139,14 @@ class NewDownloadFragment: MangaPagesFragmentTemplate(R.layout.fragment_newdownl AlertDialog.Builder(context) .setIcon(R.drawable.ic_launcher_foreground).setMessage("删除下载的漫画${name}吗?") .setTitle("提示").setPositiveButton(android.R.string.ok) { _, _ -> - if (chosenFile.exists()) Thread { - FileUtils.recursiveRemove(chosenFile) - activity?.runOnUiThread { - it.visibility = View.INVISIBLE + if (chosenFile.exists()) lifecycleScope.launch { + withContext(Dispatchers.IO) { + FileUtils.recursiveRemove(chosenFile) + withContext(Dispatchers.Main) { + it.visibility = View.INVISIBLE + } } - }.start() + } }.setNegativeButton(android.R.string.cancel) { _, _ -> } .show() } diff --git a/app/src/main/java/top/fumiama/copymanga/update/SimpleKanban.kt b/app/src/main/java/top/fumiama/copymanga/update/SimpleKanban.kt index 68f0fba..a03c9e4 100644 --- a/app/src/main/java/top/fumiama/copymanga/update/SimpleKanban.kt +++ b/app/src/main/java/top/fumiama/copymanga/update/SimpleKanban.kt @@ -7,17 +7,17 @@ class SimpleKanban(private val client: Client, private val pwd: String) { //mu get() { var times = 3 var re: ByteArray - var firstRecv: ByteArray + var firstReceived: ByteArray do { re = byteArrayOf() if(client.initConnect()) { client.sendMessage("${pwd}catquit") client.receiveRawMessage(33) //Welcome to simple kanban server. try { - firstRecv = client.receiveRawMessage(4) //le - val length = convert2Int(firstRecv) + firstReceived = client.receiveRawMessage(4) //le + val length = convert2Int(firstReceived) Log.d("MySK", "Msg len: $length") - if(firstRecv.size > 4) re += firstRecv.copyOfRange(4, firstRecv.size) + if(firstReceived.size > 4) re += firstReceived.copyOfRange(4, firstReceived.size) re += client.receiveRawMessage(length - re.size, setProgress = true) break } catch (e: Exception) { @@ -35,9 +35,9 @@ class SimpleKanban(private val client: Client, private val pwd: String) { //mu (buffer[1].toInt() and 0xff shl 8) or (buffer[0].toInt() and 0xff) - fun fetchRaw(doOnLoadFailure: ()->Unit = { + suspend fun fetchRaw(doOnLoadFailure: suspend ()->Unit = { Log.d("MySD", "Fetch dict failed") - }, doOnLoadSuccess: (data: ByteArray)->Unit = { + }, doOnLoadSuccess: suspend (data: ByteArray)->Unit = { Log.d("MySD", "Fetch dict success") }) { raw?.apply { diff --git a/app/src/main/java/top/fumiama/copymanga/update/Update.kt b/app/src/main/java/top/fumiama/copymanga/update/Update.kt index f1f6f79..31376ec 100644 --- a/app/src/main/java/top/fumiama/copymanga/update/Update.kt +++ b/app/src/main/java/top/fumiama/copymanga/update/Update.kt @@ -1,15 +1,21 @@ package top.fumiama.copymanga.update import android.app.Activity +import android.content.Context import android.content.Context.MODE_PRIVATE import android.content.Intent import android.net.Uri import android.os.Build import android.util.Log import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity import androidx.core.content.FileProvider import androidx.core.content.edit +import androidx.lifecycle.lifecycleScope import kotlinx.android.synthetic.main.dialog_progress.view.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import top.fumiama.copymanga.tools.ui.UITools import top.fumiama.dmzj.copymanga.BuildConfig import top.fumiama.dmzj.copymanga.R @@ -17,8 +23,10 @@ import java.io.File import java.security.MessageDigest object Update { - fun checkUpdate(activity: Activity, toolsBox: UITools, ignoreSkip: Boolean = false) = activity.apply{ + suspend fun checkUpdate(activity: AppCompatActivity, toolsBox: UITools, ignoreSkip: Boolean = false) = activity.apply{ val client = Client("reilia.fumiama.top", 13212) + val kanban = SimpleKanban(client, "fumiama") + val progressBar = layoutInflater.inflate(R.layout.dialog_progress, null, false) val progressHandler = object : Client.Progress{ override fun notify(progressPercentage: Int) { @@ -26,69 +34,85 @@ object Update { progressBar.dpp.progress = progressPercentage } } - val kanban = SimpleKanban(client, "fumiama") - val msg = kanban[BuildConfig.VERSION_CODE] - if(msg != "null") { - val verNum = msg.substringBefore('\n').toIntOrNull() - val skipNum = getPreferences(MODE_PRIVATE).getInt("skipVersion", 0) - Log.d("MyUP", "Ver:$verNum, skip: $skipNum") - if(verNum != null) { - if(msg.contains("md5:")) { - if(skipNum < verNum || ignoreSkip) runOnUiThread { - toolsBox.buildInfo("看板", msg.substringAfter('\n').substringBeforeLast('\n'), "下载新版", "跳过该版", "取消", { - val info = toolsBox.buildAlertWithView("下载进度", progressBar, "隐藏") - client.progress = progressHandler - Thread { - kanban.fetchRaw({ - runOnUiThread { - Toast.makeText(this, "下载失败", Toast.LENGTH_SHORT).show() - client.progress = null - } - }) { - val md5 = msg.substringAfterLast("md5:") - if (md5 == UITools.toHexStr( - MessageDigest.getInstance("MD5").digest(it) - ) - ) { - runOnUiThread { - Toast.makeText(this, "下载成功", Toast.LENGTH_SHORT).show() - info.dismiss() - } - val f = File(externalCacheDir, "new.apk") - f.writeBytes(it) - install(f, this) - } else runOnUiThread { - Toast.makeText(this, "文件损坏", Toast.LENGTH_SHORT).show() - info.dismiss() - } - client.progress = null - } - }.start() - }, { - getPreferences(MODE_PRIVATE).edit { - putInt("skipVersion", verNum) - apply() - } - }) - } - } else runOnUiThread { - toolsBox.buildInfo("看板", msg.substringAfter('\n'), "知道了") - } + val msg = message(kanban) + if (msg == "null") { + if(ignoreSkip) withContext(Dispatchers.Main) { + Toast.makeText(this@apply, "无更新", Toast.LENGTH_SHORT).show() } - } else if(ignoreSkip) runOnUiThread { - Toast.makeText(this, "无更新", Toast.LENGTH_SHORT).show() + return@apply + } + + val verNum = msg.substringBefore('\n').toIntOrNull() + val skipNum = getPreferences(MODE_PRIVATE).getInt("skipVersion", 0) + Log.d("MyUP", "Ver:$verNum, skip: $skipNum") + if (verNum == null) return@apply + + if(!msg.contains("md5:")) { + withContext(Dispatchers.Main) { + toolsBox.buildInfo("看板", msg.substringAfter('\n'), "知道了") + } + return@apply + } + if(skipNum < verNum || ignoreSkip) { + toolsBox.buildInfo("看板", msg.substringAfter('\n').substringBeforeLast('\n'), "下载新版", "跳过该版", "取消", { + val info = toolsBox.buildAlertWithView("下载进度", progressBar, "隐藏") + client.progress = progressHandler + lifecycleScope.launch { + fetch(client, kanban, this@apply) { + lifecycleScope.launch { + val md5 = msg.substringAfterLast("md5:") + if (md5 == UITools.toHexStr( + MessageDigest.getInstance("MD5").digest(it) + ) + ) { + Toast.makeText(this@apply, "下载成功", Toast.LENGTH_SHORT).show() + info.dismiss() + install(it, this@apply) + } else runOnUiThread { + Toast.makeText(this@apply, "文件损坏", Toast.LENGTH_SHORT).show() + info.dismiss() + } + client.progress = null + } + } + } + }, { + getPreferences(MODE_PRIVATE).edit { + putInt("skipVersion", verNum) + apply() + } + }) } } - private fun install(apkFile: File, activity: Activity) = activity.apply{ - val intent = Intent(Intent.ACTION_VIEW) - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - val contentUri: Uri = FileProvider.getUriForFile(this, "$packageName.fileprovider", apkFile) - intent.setDataAndType(contentUri, "application/vnd.android.package-archive") - } else intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive") - startActivity(intent) + private suspend fun message(kanban: SimpleKanban) = withContext(Dispatchers.IO) { + return@withContext kanban[BuildConfig.VERSION_CODE] } -} \ No newline at end of file + + private suspend fun fetch(client: Client, kanban: SimpleKanban, context: Context, doOnLoadSuccess: (data: ByteArray) -> Unit) = withContext(Dispatchers.IO) { + return@withContext kanban.fetchRaw({ downloadFail(client, context) }, doOnLoadSuccess) + } + + private suspend fun downloadFail(client: Client, context: Context) = withContext(Dispatchers.Main) { + Toast.makeText(context, R.string.download_apk_fail, Toast.LENGTH_SHORT).show() + client.progress = null + } + + private suspend fun install(data: ByteArray, activity: Activity) = activity.apply{ + withContext(Dispatchers.IO) { + val f = File(externalCacheDir, "new.apk") + f.writeBytes(data) + val intent = Intent(Intent.ACTION_VIEW) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + val contentUri: Uri = FileProvider.getUriForFile(this@apply, "$packageName.fileprovider", f) + intent.setDataAndType(contentUri, "application/vnd.android.package-archive") + } else intent.setDataAndType(Uri.fromFile(f), "application/vnd.android.package-archive") + withContext(Dispatchers.Main) { + startActivity(intent) + } + } + } +} diff --git a/app/src/main/java/top/fumiama/copymanga/user/Member.kt b/app/src/main/java/top/fumiama/copymanga/user/Member.kt index c958b7a..28abaef 100644 --- a/app/src/main/java/top/fumiama/copymanga/user/Member.kt +++ b/app/src/main/java/top/fumiama/copymanga/user/Member.kt @@ -11,7 +11,7 @@ import top.fumiama.dmzj.copymanga.R class Member(private val pref: SharedPreferences, private val getString: (Int) -> String) { val hasLogin: Boolean get() = pref.getString("token", "")?.isNotEmpty()?:false - suspend fun login(username: String, pwd: String, salt: Int): LoginInfoStructure = withContext(Dispatchers.IO) { + suspend fun login(username: String, pwd: String, salt: Int): LoginInfoStructure = withContext(Dispatchers.IO) { try { CMApi.getLoginConnection(username, pwd, salt)?.apply { Gson().fromJson(inputStream.reader(), LoginInfoStructure::class.java)?.let { data -> diff --git a/app/src/main/res/drawable-anydpi/ic_circle.xml b/app/src/main/res/drawable-anydpi/ic_circle.xml new file mode 100644 index 0000000..385d7cf --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_circle.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-anydpi/ic_data.xml b/app/src/main/res/drawable-anydpi/ic_data.xml new file mode 100644 index 0000000..a354f86 --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_data.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-anydpi/ic_hot.xml b/app/src/main/res/drawable-anydpi/ic_hot.xml new file mode 100644 index 0000000..a46da1b --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_hot.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-anydpi/ic_image.xml b/app/src/main/res/drawable-anydpi/ic_image.xml new file mode 100644 index 0000000..5d37c4a --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_image.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-anydpi/ic_success.xml b/app/src/main/res/drawable-anydpi/ic_success.xml new file mode 100644 index 0000000..e929ff2 --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_success.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/card_book.xml b/app/src/main/res/layout/card_book.xml index e4018e6..3dbad67 100644 --- a/app/src/main/res/layout/card_book.xml +++ b/app/src/main/res/layout/card_book.xml @@ -78,7 +78,6 @@ android:layout_marginEnd="16dp" android:layout_marginBottom="4dp" android:gravity="center_horizontal" - android:text="获取标题失败" android:textAppearance="@style/TextAppearance.AppCompat.Body1" android:textColor="@android:color/white" android:textSize="12sp" diff --git a/app/src/main/res/layout/fragment_book.xml b/app/src/main/res/layout/fragment_book.xml index a772adb..c45f5c2 100644 --- a/app/src/main/res/layout/fragment_book.xml +++ b/app/src/main/res/layout/fragment_book.xml @@ -16,29 +16,30 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="@dimen/nav_header_vertical_spacing" - app:layout_constraintBottom_toTopOf="@id/fbov" + app:layout_constraintBottom_toTopOf="@id/fbvp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" - app:layout_scrollFlags="scroll|enterAlways" /> + app:layout_scrollFlags="scroll|exitUntilCollapsed" /> + + - - - - + app:layout_constraintTop_toBottomOf="@+id/fbiinf" + app:layout_behavior="@string/appbar_scrolling_view_behavior"/> + app:layout_constraintTop_toTopOf="parent" /> + + \ No newline at end of file diff --git a/app/src/main/res/layout/line_bookinfo_text.xml b/app/src/main/res/layout/line_bookinfo_text.xml index b6d0869..5826b69 100644 --- a/app/src/main/res/layout/line_bookinfo_text.xml +++ b/app/src/main/res/layout/line_bookinfo_text.xml @@ -20,7 +20,7 @@ android:layout_width="@dimen/icon_size_small" android:layout_height="@dimen/icon_size_small" android:layout_marginBottom="@dimen/nav_header_vertical_spacing" - android:background="@drawable/ic_list" + android:background="@drawable/ic_data" app:layout_constraintBottom_toTopOf="@+id/bitime" app:layout_constraintEnd_toStartOf="@+id/btsub" app:layout_constraintStart_toStartOf="parent" @@ -61,7 +61,7 @@ android:layout_width="@dimen/icon_size_small" android:layout_height="@dimen/icon_size_small" android:layout_marginBottom="@dimen/nav_header_vertical_spacing" - android:background="@drawable/ic_list" + android:background="@drawable/ic_image" app:layout_constraintBottom_toTopOf="@+id/bihit" app:layout_constraintEnd_toStartOf="@+id/bttag" app:layout_constraintStart_toStartOf="parent" @@ -82,7 +82,7 @@ android:layout_width="@dimen/icon_size_small" android:layout_height="@dimen/icon_size_small" android:layout_marginBottom="@dimen/nav_header_vertical_spacing" - android:background="@drawable/ic_list" + android:background="@drawable/ic_hot" app:layout_constraintBottom_toTopOf="@+id/bisub" app:layout_constraintEnd_toStartOf="@+id/bthit" app:layout_constraintStart_toStartOf="parent" @@ -103,7 +103,7 @@ android:layout_width="@dimen/icon_size_small" android:layout_height="@dimen/icon_size_small" android:layout_marginBottom="@dimen/nav_header_vertical_spacing" - android:background="@drawable/ic_author" + android:background="@drawable/ic_locate" app:layout_constraintBottom_toTopOf="@+id/bitag" app:layout_constraintEnd_toStartOf="@+id/btauth" app:layout_constraintStart_toStartOf="parent" diff --git a/app/src/main/res/layout/line_chapter.xml b/app/src/main/res/layout/line_chapter.xml index b020a48..60f3e8c 100644 --- a/app/src/main/res/layout/line_chapter.xml +++ b/app/src/main/res/layout/line_chapter.xml @@ -15,7 +15,7 @@ android:layout_marginStart="@dimen/nav_header_vertical_spacing" android:layout_marginTop="@dimen/nav_header_vertical_spacing" android:layout_marginBottom="@dimen/nav_header_vertical_spacing" - android:background="@drawable/ic_list" + android:background="@drawable/ic_circle" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" diff --git a/app/src/main/res/layout/page_nested_list.xml b/app/src/main/res/layout/page_nested_list.xml new file mode 100644 index 0000000..a307512 --- /dev/null +++ b/app/src/main/res/layout/page_nested_list.xml @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml index e4fb17c..56156d7 100644 --- a/app/src/main/res/navigation/mobile_navigation.xml +++ b/app/src/main/res/navigation/mobile_navigation.xml @@ -224,7 +224,7 @@ 主页 分类 排行 - ©2022–2023源文雨\n本应用为拷贝漫画的第三方客户端,数据均来源于网络,作者不对其中所呈现的任何内容负责。 + ©2022–2024源文雨\n本应用为拷贝漫画的第三方客户端,数据均来源于网络,作者不对其中所呈现的任何内容负责。 浏览历史 我的订阅 我的下载 @@ -29,6 +29,9 @@ illust: Hiten(490219) 请设定提示文字内容 清除设定的图片? + 选取图片失败 + 裁剪图片失败 + 下载更新失败 登录 注销 @@ -112,7 +115,9 @@ 热度 %1$d 状态 %1$s - 云端读到 %1$s + 区域 %1$s + 画幅 %1$s + 云读至%1$s 专题系列 漫画推荐 diff --git a/build.gradle b/build.gradle index 1af899f..5f5470d 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ buildscript { maven { url "https://jitpack.io" } } dependencies { - classpath 'com.android.tools.build:gradle:8.1.1' + classpath 'com.android.tools.build:gradle:8.2.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong @@ -27,6 +27,6 @@ allprojects { } } -task clean(type: Delete) { +tasks.register('clean', Delete) { delete rootProject.buildDir } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index bcbaca3..5563ca9 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-all.zip