Просмотр исходного кода

Merge pull request #1724 from a328929/fix/manga-shelf-confirmation-1716

fix: 恢复漫画退出时的加入书架确认
Kudomaga 4 месяцев назад
Родитель
Сommit
c0acb2f187

+ 1 - 0
app/build.gradle.kts

@@ -173,6 +173,7 @@ dependencies {
     "baselineProfile"(project(":baselineprofile"))
     coreLibraryDesugaring(libs.desugar)
     testImplementation(libs.junit)
+    testImplementation(libs.robolectric)
     androidTestImplementation(libs.bundles.androidTest)
     implementation(libs.kotlin.stdlib)
     implementation(libs.kotlinx.collections.immutable)

+ 2 - 2
app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageScreen.kt

@@ -295,7 +295,7 @@ private fun BookshelfManageScreen(
         }
         val bookUrl = pendingExportBookUrl ?: return@rememberLauncherForActivityResult
         val book = booksByUrl[bookUrl] ?: return@rememberLauncherForActivityResult
-        if (state.exportConfig.enableCustomExport) {
+        if (state.exportConfig.isCustomEpubExportEnabled) {
             customExportPath = dirPath
             customExportBook = book
             customExportAllChapter = false
@@ -336,7 +336,7 @@ private fun BookshelfManageScreen(
         val path = ACache.get().getAsString(exportBookPathKey)
         if (path.isNullOrEmpty() || !FileDoc.fromDir(path).checkWrite()) {
             selectExportFolder(book.bookUrl)
-        } else if (state.exportConfig.enableCustomExport) {
+        } else if (state.exportConfig.isCustomEpubExportEnabled) {
             customExportPath = path
             customExportBook = book
             customExportAllChapter = false

+ 4 - 1
app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageScreenViewModel.kt

@@ -60,7 +60,10 @@ data class BookshelfManageScreenExportConfig(
     val exportCharset: String = "UTF-8",
     val bookExportFileName: String? = null,
     val episodeExportFileName: String = ""
-)
+) {
+    val isCustomEpubExportEnabled: Boolean
+        get() = enableCustomExport && exportType == 1
+}
 
 data class BookshelfManageScreenUiState(
     val groupId: Long = -1,

+ 55 - 5
app/src/main/java/io/legado/app/ui/book/manga/ReadMangaActivity.kt

@@ -76,6 +76,7 @@ import io.legado.app.ui.book.source.edit.BookSourceEditActivity
 import io.legado.app.ui.book.toc.TocActivityResult
 import io.legado.app.ui.browser.WebViewActivity
 import io.legado.app.ui.config.readConfig.ReadConfig
+import io.legado.app.ui.config.otherConfig.OtherConfig
 import io.legado.app.ui.config.readMangaConfig.ReadMangaConfig
 import io.legado.app.ui.login.SourceLoginActivity
 import io.legado.app.ui.widget.number.NumberPickerDialog
@@ -140,6 +141,8 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
     }
 
     private var justInitData: Boolean = false
+    private var isExitActionRunning = false
+    private var isRestoredFromSavedState = false
     private var syncDialog: AlertDialog? = null
     private val handler by lazy { buildMainHandler() }
     private val eyeProtectionScheduler by lazy {
@@ -199,6 +202,7 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
     }
 
     override fun onCreate(savedInstanceState: Bundle?) {
+        isRestoredFromSavedState = savedInstanceState != null
         setEnterSharedElementCallback(MaterialContainerTransformSharedElementCallback())
         setExitSharedElementCallback(MaterialContainerTransformSharedElementCallback())
         val transform = MaterialContainerTransform().apply {
@@ -235,15 +239,61 @@ class ReadMangaActivity : VMBaseActivity<ActivityMangaBinding, ReadMangaViewMode
             GSON.fromJsonObject<MangaFooterConfig>(ReadMangaConfig.mangaFooterConfig).getOrNull()
                 ?: MangaFooterConfig()
 
-        onBackPressedDispatcher.addCallback(this){
-            if (savedInstanceState != null || !ReadManga.inBookshelf) {
-                finish()
-            } else {
-                supportFinishAfterTransition()
+        onBackPressedDispatcher.addCallback(this) {
+            requestReaderExit()
+        }
+    }
+
+    private fun requestReaderExit() {
+        if (isExitActionRunning) return
+        val book = ReadManga.book
+        if (book == null || ReadManga.inBookshelf) {
+            finishReader()
+            return
+        }
+        if (!OtherConfig.showAddToShelfAlert) {
+            discardCurrentNotShelfBook()
+            return
+        }
+        alert(title = getString(R.string.add_to_bookshelf)) {
+            setCancelable(false)
+            setMessage(getString(R.string.check_add_bookshelf, book.name))
+            okButton {
+                addCurrentBookToBookshelf()
+            }
+            noButton {
+                discardCurrentNotShelfBook()
             }
         }
     }
 
+    private fun addCurrentBookToBookshelf() {
+        isExitActionRunning = true
+        viewModel.addCurrentBookToBookshelf(
+            success = {
+                setResult(RESULT_OK)
+                finishReader()
+            },
+            onFailure = { isExitActionRunning = false }
+        )
+    }
+
+    private fun discardCurrentNotShelfBook() {
+        isExitActionRunning = true
+        viewModel.removeCurrentNotShelfBook(
+            success = ::finishReader,
+            onFailure = { isExitActionRunning = false }
+        )
+    }
+
+    private fun finishReader() {
+        if (ReadManga.inBookshelf && !isRestoredFromSavedState) {
+            supportFinishAfterTransition()
+        } else {
+            finish()
+        }
+    }
+
     override fun observeLiveBus() {
         observeEvent<MangaFooterConfig>(EventBus.UP_MANGA_CONFIG) {
             mMangaFooterConfig = it

+ 41 - 9
app/src/main/java/io/legado/app/ui/book/manga/ReadMangaViewModel.kt

@@ -313,12 +313,23 @@ class ReadMangaViewModel(
         }
     }
 
-    fun removeFromBookshelf(success: (() -> Unit)?) {
+    fun removeCurrentNotShelfBook(
+        success: () -> Unit,
+        onFailure: () -> Unit = {},
+    ) {
         val book = ReadManga.book
+        val bookUrl = book?.bookUrl
         Coroutine.async {
             book?.delete()
         }.onSuccess {
-            success?.invoke()
+            if (ReadManga.book?.bookUrl == bookUrl) {
+                ReadManga.book = null
+            }
+            success()
+        }.onError {
+            AppLog.put("移除临时漫画书籍失败", it)
+            context.toastOnUi("移除临时漫画书籍失败")
+            onFailure()
         }
     }
 
@@ -393,15 +404,27 @@ class ReadMangaViewModel(
         }
     }
 
-    fun addToBookshelf(book: Book, toc: List<BookChapter>, success: (() -> Unit)? = null) {
+    fun addCurrentBookToBookshelf(
+        success: () -> Unit,
+        onFailure: () -> Unit = {},
+    ) {
+        val book = ReadManga.book ?: return onFailure()
         execute {
-            book.removeType(BookType.notShelf)
-            if (book.order == 0) {
-                book.order = appDb.bookDao.minOrder - 1
-            }
+            val toc = appDb.bookChapterDao.getChapterList(book.bookUrl)
+            persistOnBookshelf(book, toc)
+            ReadManga.inBookshelf = true
+        }.onSuccess {
+            success()
+        }.onError {
+            AppLog.put("添加书籍到书架失败", it)
+            context.toastOnUi("添加书籍失败")
+            onFailure()
+        }
+    }
 
-            appDb.bookDao.insert(book)
-            appDb.bookChapterDao.insert(*toc.toTypedArray())
+    fun addToBookshelf(book: Book, toc: List<BookChapter>, success: (() -> Unit)? = null) {
+        execute {
+            persistOnBookshelf(book, toc)
         }.onSuccess {
             success?.invoke()
         }.onError {
@@ -409,4 +432,13 @@ class ReadMangaViewModel(
             context.toastOnUi("添加书籍失败")
         }
     }
+
+    private suspend fun persistOnBookshelf(book: Book, toc: List<BookChapter>) {
+        book.removeType(BookType.notShelf)
+        if (book.order == 0) {
+            book.order = appDb.bookDao.minOrder - 1
+        }
+        appDb.bookDao.insert(book)
+        appDb.bookChapterDao.insert(*toc.toTypedArray())
+    }
 }

+ 30 - 0
app/src/test/java/io/legado/app/ui/book/manage/BookshelfManageScreenExportConfigTest.kt

@@ -0,0 +1,30 @@
+package io.legado.app.ui.book.manage
+
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+class BookshelfManageScreenExportConfigTest {
+
+    @Test
+    fun customExport_requiresEpubFormat() {
+        assertFalse(
+            BookshelfManageScreenExportConfig(
+                enableCustomExport = true,
+                exportType = 0
+            ).isCustomEpubExportEnabled
+        )
+        assertTrue(
+            BookshelfManageScreenExportConfig(
+                enableCustomExport = true,
+                exportType = 1
+            ).isCustomEpubExportEnabled
+        )
+        assertFalse(
+            BookshelfManageScreenExportConfig(
+                enableCustomExport = false,
+                exportType = 1
+            ).isCustomEpubExportEnabled
+        )
+    }
+}

+ 2 - 0
gradle/libs.versions.toml

@@ -61,6 +61,7 @@ preference = "1.2.1"
 protobufJavalite = "4.26.1"
 quickChineseTransfer = "0.2.17"
 room = "2.8.4"
+robolectric = "4.16.1"
 splitties = "3.0.0"
 rhino = "1.8.1"
 desugar = "2.1.5"
@@ -187,6 +188,7 @@ room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
 room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" }
 room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
 room-testing = { module = "androidx.room:room-testing", version.ref = "room" }
+robolectric = { module = "org.robolectric:robolectric", version.ref = "robolectric" }
 
 glide-glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" }
 glide-okhttp= { module = "com.github.bumptech.glide:okhttp3-integration", version.ref ="glide" }