fix: 章节点击事件

This commit is contained in:
HapeLee committed 2026-06-10 00:42:00 +08:00
1 parent 1c3ea16043
commit 7b9a5dca16
7 files changed
+61 -44

No files matched your search

@@ -15,4 +15,5 @@ object LocalPreferencesKeys {
val MATCH_MODE = intPreferencesKey("match_mode") val MATCH_MODE = intPreferencesKey("match_mode")
val EXPLORE_LAYOUT_GRID_PORTRAIT = intPreferencesKey("explore_layout_grid_portrait") val EXPLORE_LAYOUT_GRID_PORTRAIT = intPreferencesKey("explore_layout_grid_portrait")
val EXPLORE_LAYOUT_GRID_LANDSCAPE = intPreferencesKey("explore_layout_grid_landscape") 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(), translateChapterUseCase = get(),
readSettingsRepository = get(), readSettingsRepository = get(),
readBookStyleConfigRepository = get(), readBookStyleConfigRepository = get(),
readAloudSettingsRepository = get() readAloudSettingsRepository = get(),
localPreferencesRepository = get()
) )
} }
viewModelOf(::ChangeCoverViewModel) viewModelOf(::ChangeCoverViewModel)
@@ -310,7 +310,7 @@ sealed interface ReadBookIntent {
data object OpenBookInfo : ReadBookIntent data object OpenBookInfo : ReadBookIntent
data object OpenChapterList : ReadBookIntent data object OpenChapterList : ReadBookIntent
data object OpenChapterUrl : ReadBookIntent data object OpenChapterUrl : ReadBookIntent
data class SetReadUrlInBrowser(val useBrowser: Boolean) : ReadBookIntent data object ToggleReadUrlInBrowser : ReadBookIntent
// Content edit // Content edit
data object LoadContentEdit : ReadBookIntent data object LoadContentEdit : ReadBookIntent
@@ -523,6 +523,7 @@ sealed interface ReadBookEffect {
val sourceOrigin: String?, val sourceOrigin: String?,
val sourceName: String?, val sourceName: String?,
val sourceType: Int?, val sourceType: Int?,
val html: String? = null,
) : ReadBookEffect ) : ReadBookEffect
// Menu actions that need Activity // Menu actions that need Activity
@@ -631,7 +632,6 @@ sealed interface ReadBookDialog {
data class SureSyncProgress(val progress: BookProgress) : ReadBookDialog data class SureSyncProgress(val progress: BookProgress) : ReadBookDialog
data object ConfirmSkipToChapter : ReadBookDialog data object ConfirmSkipToChapter : ReadBookDialog
data class ConfirmChapterPay(val chapterTitle: String) : ReadBookDialog data class ConfirmChapterPay(val chapterTitle: String) : ReadBookDialog
data object ConfirmReadUrlInBrowser : ReadBookDialog
} }
/** /**
@@ -849,7 +849,20 @@ private fun MenuTitleBar(
) { ) {
AppText( AppText(
text = state.chapterName, 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, style = labelStyle,
color = titleTextColor, color = titleTextColor,
maxLines = 1, maxLines = 1,
@@ -17,6 +17,8 @@ import io.legado.app.constant.ReadMenuBlurMode
import io.legado.app.constant.Status import io.legado.app.constant.Status
import io.legado.app.data.appDb import io.legado.app.data.appDb
import io.legado.app.data.entities.Book 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.BookChapter
import io.legado.app.data.entities.BookProgress import io.legado.app.data.entities.BookProgress
import io.legado.app.data.entities.Bookmark 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.isMobi
import io.legado.app.help.book.removeType import io.legado.app.help.book.removeType
import io.legado.app.help.book.simulatedTotalChapterNum import io.legado.app.help.book.simulatedTotalChapterNum
import io.legado.app.constant.AppPattern
import io.legado.app.help.config.AppConfig import io.legado.app.help.config.AppConfig
import io.legado.app.utils.EncoderUtils
import io.legado.app.utils.openUrl import io.legado.app.utils.openUrl
import io.legado.app.help.config.ReadBookConfig import io.legado.app.help.config.ReadBookConfig
import io.legado.app.help.coroutine.Coroutine 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.callbackFlow
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.onCompletion import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@@ -118,7 +119,8 @@ class ReadBookViewModel(
val translateChapterUseCase: io.legado.app.domain.usecase.TranslateChapterUseCase, val translateChapterUseCase: io.legado.app.domain.usecase.TranslateChapterUseCase,
private val readSettingsRepository: ReadSettingsRepository, private val readSettingsRepository: ReadSettingsRepository,
private val readBookStyleConfigRepository: ReadBookStyleConfigRepository, private val readBookStyleConfigRepository: ReadBookStyleConfigRepository,
private val readAloudSettingsRepository: ReadAloudSettingsRepository private val readAloudSettingsRepository: ReadAloudSettingsRepository,
private val localPreferencesRepository: LocalPreferencesRepository
) : BaseViewModel(application), ReadBook.CallBack { ) : BaseViewModel(application), ReadBook.CallBack {
// --- MVI State --- // --- MVI State ---
@@ -342,10 +344,7 @@ class ReadBookViewModel(
} }
} }
is ReadBookIntent.OpenChapterUrl -> openChapterUrl() is ReadBookIntent.OpenChapterUrl -> openChapterUrl()
is ReadBookIntent.SetReadUrlInBrowser -> { is ReadBookIntent.ToggleReadUrlInBrowser -> toggleReadUrlInBrowser()
AppConfig.readUrlInBrowser = intent.useBrowser
openChapterUrl()
}
is ReadBookIntent.LoadContentEdit -> loadContentEdit() is ReadBookIntent.LoadContentEdit -> loadContentEdit()
is ReadBookIntent.SaveContentEdit -> saveContentEdit(intent.content, intent.saveToSource) is ReadBookIntent.SaveContentEdit -> saveContentEdit(intent.content, intent.saveToSource)
is ReadBookIntent.ResetContentEdit -> resetContentEdit() is ReadBookIntent.ResetContentEdit -> resetContentEdit()
@@ -2967,47 +2966,46 @@ class ReadBookViewModel(
} }
private fun openChapterUrl() { private fun openChapterUrl() {
if (ReadBook.isLocalBook) return
val book = ReadBook.book ?: return val book = ReadBook.book ?: return
if (book.isLocal) return
val chapter = ReadBook.curTextChapter?.chapter val chapter = ReadBook.curTextChapter?.chapter
?: appDb.bookChapterDao.getChapter(book.bookUrl, ReadBook.durChapterIndex) ?: appDb.bookChapterDao.getChapter(book.bookUrl, ReadBook.durChapterIndex)
?: return ?: return
val rawUrl = chapter.getAbsoluteURL() val url = chapter.getAbsoluteURL()
if (rawUrl.isBlank()) return if (url.isBlank()) return
val url = resolveChapterUrl(rawUrl) viewModelScope.launch {
if (url.isBlank()) { val useBrowser = localPreferencesRepository
context.toastOnUi(R.string.cannot_open_url) .getPreference(LocalPreferencesKeys.READ_URL_IN_BROWSER, false)
return .first()
} if (useBrowser) {
if (AppConfig.readUrlInBrowser) { context.openUrl(url.substringBefore(",{"))
context.openUrl(url.substringBefore(",{")) } else {
} else { val bookSource = ReadBook.bookSource
_effects.tryEmit( _effects.tryEmit(
ReadBookEffect.OpenWebView( ReadBookEffect.OpenWebView(
title = chapter.title, title = chapter.title,
url = url, url = url,
sourceOrigin = ReadBook.bookSource?.bookSourceUrl, sourceOrigin = bookSource?.bookSourceUrl,
sourceName = ReadBook.bookSource?.bookSourceName, sourceName = bookSource?.bookSourceName,
sourceType = ReadBook.bookSource?.getSourceType(), sourceType = bookSource?.getSourceType(),
)
) )
) }
} }
} }
/** private fun toggleReadUrlInBrowser() {
* 解析章节URL,处理data:;base64,...格式 viewModelScope.launch {
* 从base64编码的JSON中提取真实URL val current = localPreferencesRepository
*/ .getPreference(LocalPreferencesKeys.READ_URL_IN_BROWSER, false)
private fun resolveChapterUrl(url: String): String { .first()
if (!url.startsWith("data:", ignoreCase = true)) return url val newValue = !current
val match = AppPattern.dataUriRegex.matchEntire(url) ?: return url localPreferencesRepository.updatePreference(
return try { LocalPreferencesKeys.READ_URL_IN_BROWSER, newValue
val decoded = EncoderUtils.base64Decode(match.groupValues[1]) )
val json = GSON.fromJsonObject<Map<String, Any>>(decoded).getOrNull() context.toastOnUi(
val realUrl = json?.get("url")?.toString() ?: "" if (newValue) R.string.open_by_browser else R.string.open_by_webview
realUrl.ifBlank { url } )
} catch (_: Exception) {
url
} }
} }
@@ -1074,6 +1074,8 @@
<string name="open_fun">打开方式</string> <string name="open_fun">打开方式</string>
<string name="use_browser_open">是否使用外部浏览器打开?</string> <string name="use_browser_open">是否使用外部浏览器打开?</string>
<string name="cannot_open_url">该URL无法直接打开</string> <string name="cannot_open_url">该URL无法直接打开</string>
<string name="open_by_browser">已切换为浏览器打开</string>
<string name="open_by_webview">已切换为WebView打开</string>
<string name="see">查看</string> <string name="see">查看</string>
<string name="open">打开</string> <string name="open">打开</string>
<string name="del_login_header">删除登录头</string> <string name="del_login_header">删除登录头</string>
+2
View File
@@ -1103,6 +1103,8 @@
<string name="open_fun">open function</string> <string name="open_fun">open function</string>
<string name="use_browser_open">Is it opened in an external browser?</string> <string name="use_browser_open">Is it opened in an external browser?</string>
<string name="cannot_open_url">This URL cannot be opened directly</string> <string name="cannot_open_url">This URL cannot be opened directly</string>
<string name="open_by_browser">Switched to browser opening</string>
<string name="open_by_webview">Switched to WebView opening</string>
<string name="see">see</string> <string name="see">see</string>
<string name="open">open</string> <string name="open">open</string>
<string name="del_login_header">del login header</string> <string name="del_login_header">del login header</string>