fix: 章节点击事件

This commit is contained in:
HapeLee
2026-06-10 00:42:00 +08:00
parent 1c3ea16043
commit 7b9a5dca16
7 changed files with 61 additions and 44 deletions
@@ -15,4 +15,5 @@ object LocalPreferencesKeys {
val MATCH_MODE = intPreferencesKey("match_mode")
val EXPLORE_LAYOUT_GRID_PORTRAIT = intPreferencesKey("explore_layout_grid_portrait")
val EXPLORE_LAYOUT_GRID_LANDSCAPE = intPreferencesKey("explore_layout_grid_landscape")
val READ_URL_IN_BROWSER = booleanPreferencesKey("read_url_in_browser")
}
@@ -268,7 +268,8 @@ val appModule = module {
translateChapterUseCase = get(),
readSettingsRepository = get(),
readBookStyleConfigRepository = get(),
readAloudSettingsRepository = get()
readAloudSettingsRepository = get(),
localPreferencesRepository = get()
)
}
viewModelOf(::ChangeCoverViewModel)
@@ -310,7 +310,7 @@ sealed interface ReadBookIntent {
data object OpenBookInfo : ReadBookIntent
data object OpenChapterList : ReadBookIntent
data object OpenChapterUrl : ReadBookIntent
data class SetReadUrlInBrowser(val useBrowser: Boolean) : ReadBookIntent
data object ToggleReadUrlInBrowser : ReadBookIntent
// Content edit
data object LoadContentEdit : ReadBookIntent
@@ -523,6 +523,7 @@ sealed interface ReadBookEffect {
val sourceOrigin: String?,
val sourceName: String?,
val sourceType: Int?,
val html: String? = null,
) : ReadBookEffect
// Menu actions that need Activity
@@ -631,7 +632,6 @@ sealed interface ReadBookDialog {
data class SureSyncProgress(val progress: BookProgress) : ReadBookDialog
data object ConfirmSkipToChapter : ReadBookDialog
data class ConfirmChapterPay(val chapterTitle: String) : ReadBookDialog
data object ConfirmReadUrlInBrowser : ReadBookDialog
}
/**
@@ -849,7 +849,20 @@ private fun MenuTitleBar(
) {
AppText(
text = state.chapterName,
modifier = Modifier.weight(1f),
modifier = Modifier
.weight(1f)
.then(
if (!state.isLocalBook) {
Modifier.combinedClickable(
onClick = { onIntent(ReadBookIntent.OpenChapterUrl) },
onLongClick = {
onIntent(ReadBookIntent.ToggleReadUrlInBrowser)
},
)
} else {
Modifier
}
),
style = labelStyle,
color = titleTextColor,
maxLines = 1,
@@ -17,6 +17,8 @@ import io.legado.app.constant.ReadMenuBlurMode
import io.legado.app.constant.Status
import io.legado.app.data.appDb
import io.legado.app.data.entities.Book
import io.legado.app.data.local.preferences.LocalPreferencesKeys
import io.legado.app.data.local.preferences.LocalPreferencesRepository
import io.legado.app.data.entities.BookChapter
import io.legado.app.data.entities.BookProgress
import io.legado.app.data.entities.Bookmark
@@ -39,9 +41,7 @@ import io.legado.app.help.book.isLocalTxt
import io.legado.app.help.book.isMobi
import io.legado.app.help.book.removeType
import io.legado.app.help.book.simulatedTotalChapterNum
import io.legado.app.constant.AppPattern
import io.legado.app.help.config.AppConfig
import io.legado.app.utils.EncoderUtils
import io.legado.app.utils.openUrl
import io.legado.app.help.config.ReadBookConfig
import io.legado.app.help.coroutine.Coroutine
@@ -93,6 +93,7 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onEach
@@ -118,7 +119,8 @@ class ReadBookViewModel(
val translateChapterUseCase: io.legado.app.domain.usecase.TranslateChapterUseCase,
private val readSettingsRepository: ReadSettingsRepository,
private val readBookStyleConfigRepository: ReadBookStyleConfigRepository,
private val readAloudSettingsRepository: ReadAloudSettingsRepository
private val readAloudSettingsRepository: ReadAloudSettingsRepository,
private val localPreferencesRepository: LocalPreferencesRepository
) : BaseViewModel(application), ReadBook.CallBack {
// --- MVI State ---
@@ -342,10 +344,7 @@ class ReadBookViewModel(
}
}
is ReadBookIntent.OpenChapterUrl -> openChapterUrl()
is ReadBookIntent.SetReadUrlInBrowser -> {
AppConfig.readUrlInBrowser = intent.useBrowser
openChapterUrl()
}
is ReadBookIntent.ToggleReadUrlInBrowser -> toggleReadUrlInBrowser()
is ReadBookIntent.LoadContentEdit -> loadContentEdit()
is ReadBookIntent.SaveContentEdit -> saveContentEdit(intent.content, intent.saveToSource)
is ReadBookIntent.ResetContentEdit -> resetContentEdit()
@@ -2967,47 +2966,46 @@ class ReadBookViewModel(
}
private fun openChapterUrl() {
if (ReadBook.isLocalBook) return
val book = ReadBook.book ?: return
if (book.isLocal) return
val chapter = ReadBook.curTextChapter?.chapter
?: appDb.bookChapterDao.getChapter(book.bookUrl, ReadBook.durChapterIndex)
?: return
val rawUrl = chapter.getAbsoluteURL()
if (rawUrl.isBlank()) return
val url = resolveChapterUrl(rawUrl)
if (url.isBlank()) {
context.toastOnUi(R.string.cannot_open_url)
return
}
if (AppConfig.readUrlInBrowser) {
context.openUrl(url.substringBefore(",{"))
} else {
_effects.tryEmit(
ReadBookEffect.OpenWebView(
title = chapter.title,
url = url,
sourceOrigin = ReadBook.bookSource?.bookSourceUrl,
sourceName = ReadBook.bookSource?.bookSourceName,
sourceType = ReadBook.bookSource?.getSourceType(),
val url = chapter.getAbsoluteURL()
if (url.isBlank()) return
viewModelScope.launch {
val useBrowser = localPreferencesRepository
.getPreference(LocalPreferencesKeys.READ_URL_IN_BROWSER, false)
.first()
if (useBrowser) {
context.openUrl(url.substringBefore(",{"))
} else {
val bookSource = ReadBook.bookSource
_effects.tryEmit(
ReadBookEffect.OpenWebView(
title = chapter.title,
url = url,
sourceOrigin = bookSource?.bookSourceUrl,
sourceName = bookSource?.bookSourceName,
sourceType = bookSource?.getSourceType(),
)
)
)
}
}
}
/**
* 解析章节URL,处理data:;base64,...格式
* 从base64编码的JSON中提取真实URL
*/
private fun resolveChapterUrl(url: String): String {
if (!url.startsWith("data:", ignoreCase = true)) return url
val match = AppPattern.dataUriRegex.matchEntire(url) ?: return url
return try {
val decoded = EncoderUtils.base64Decode(match.groupValues[1])
val json = GSON.fromJsonObject<Map<String, Any>>(decoded).getOrNull()
val realUrl = json?.get("url")?.toString() ?: ""
realUrl.ifBlank { url }
} catch (_: Exception) {
url
private fun toggleReadUrlInBrowser() {
viewModelScope.launch {
val current = localPreferencesRepository
.getPreference(LocalPreferencesKeys.READ_URL_IN_BROWSER, false)
.first()
val newValue = !current
localPreferencesRepository.updatePreference(
LocalPreferencesKeys.READ_URL_IN_BROWSER, newValue
)
context.toastOnUi(
if (newValue) R.string.open_by_browser else R.string.open_by_webview
)
}
}