fix: 修复 justInitData 在 initData 完成前被设置
This commit is contained in:
@@ -6,12 +6,14 @@ import android.content.Intent
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.provider.OpenableColumns
|
import android.provider.OpenableColumns
|
||||||
import android.speech.tts.TextToSpeech
|
import android.speech.tts.TextToSpeech
|
||||||
|
import android.util.Base64
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import io.legado.app.BuildConfig
|
import io.legado.app.BuildConfig
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.constant.AppConst
|
import io.legado.app.constant.AppConst
|
||||||
import io.legado.app.base.BaseViewModel
|
import io.legado.app.base.BaseViewModel
|
||||||
import io.legado.app.constant.AppLog
|
import io.legado.app.constant.AppLog
|
||||||
|
import io.legado.app.constant.AppPattern
|
||||||
import io.legado.app.constant.BookType
|
import io.legado.app.constant.BookType
|
||||||
import io.legado.app.constant.EventBus
|
import io.legado.app.constant.EventBus
|
||||||
import io.legado.app.constant.PreferKey
|
import io.legado.app.constant.PreferKey
|
||||||
@@ -70,6 +72,9 @@ import io.legado.app.ui.book.searchContent.SearchResult
|
|||||||
import io.legado.app.ui.config.otherConfig.OtherConfig
|
import io.legado.app.ui.config.otherConfig.OtherConfig
|
||||||
import io.legado.app.ui.config.readConfig.ReadConfig
|
import io.legado.app.ui.config.readConfig.ReadConfig
|
||||||
import io.legado.app.ui.config.themeConfig.ThemeConfig
|
import io.legado.app.ui.config.themeConfig.ThemeConfig
|
||||||
|
import io.legado.app.ui.widget.components.importComponents.BaseImportUiState
|
||||||
|
import io.legado.app.ui.widget.components.importComponents.ImportItemWrapper
|
||||||
|
import io.legado.app.ui.widget.components.importComponents.ImportStatus
|
||||||
import io.legado.app.utils.GSON
|
import io.legado.app.utils.GSON
|
||||||
import io.legado.app.utils.ImageSaveUtils
|
import io.legado.app.utils.ImageSaveUtils
|
||||||
import io.legado.app.utils.NetworkUtils
|
import io.legado.app.utils.NetworkUtils
|
||||||
@@ -77,12 +82,14 @@ import io.legado.app.utils.StringUtils
|
|||||||
import io.legado.app.utils.fromJsonObject
|
import io.legado.app.utils.fromJsonObject
|
||||||
import io.legado.app.utils.hexString
|
import io.legado.app.utils.hexString
|
||||||
import io.legado.app.utils.isAbsUrl
|
import io.legado.app.utils.isAbsUrl
|
||||||
|
import io.legado.app.utils.isDataUrl
|
||||||
import io.legado.app.utils.isJsonArray
|
import io.legado.app.utils.isJsonArray
|
||||||
import io.legado.app.utils.isJsonObject
|
import io.legado.app.utils.isJsonObject
|
||||||
import io.legado.app.utils.isTrue
|
import io.legado.app.utils.isTrue
|
||||||
import io.legado.app.utils.mapParallelSafe
|
import io.legado.app.utils.mapParallelSafe
|
||||||
import io.legado.app.utils.openUrl
|
import io.legado.app.utils.openUrl
|
||||||
import io.legado.app.utils.postEvent
|
import io.legado.app.utils.postEvent
|
||||||
|
import io.legado.app.utils.sendToClip
|
||||||
import io.legado.app.utils.toStringArray
|
import io.legado.app.utils.toStringArray
|
||||||
import io.legado.app.utils.toastOnUi
|
import io.legado.app.utils.toastOnUi
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
@@ -111,6 +118,7 @@ import kotlinx.coroutines.flow.update
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
|
import java.net.URLEncoder
|
||||||
import kotlin.coroutines.coroutineContext
|
import kotlin.coroutines.coroutineContext
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -181,8 +189,8 @@ class ReadBookViewModel(
|
|||||||
fun onIntent(intent: ReadBookIntent) {
|
fun onIntent(intent: ReadBookIntent) {
|
||||||
when (intent) {
|
when (intent) {
|
||||||
is ReadBookIntent.InitData -> {
|
is ReadBookIntent.InitData -> {
|
||||||
justInitData = true
|
|
||||||
initData(intent.intent)
|
initData(intent.intent)
|
||||||
|
justInitData = true
|
||||||
}
|
}
|
||||||
is ReadBookIntent.InitReadBookConfig -> initReadBookConfig(intent.intent)
|
is ReadBookIntent.InitReadBookConfig -> initReadBookConfig(intent.intent)
|
||||||
is ReadBookIntent.NextPage -> ReadBook.moveToNextPage()
|
is ReadBookIntent.NextPage -> ReadBook.moveToNextPage()
|
||||||
@@ -685,13 +693,7 @@ class ReadBookViewModel(
|
|||||||
|
|
||||||
is ReadBookIntent.TtsProgress -> _effects.tryEmit(ReadBookEffect.UpTtsAloudSpan(intent.chapterStart))
|
is ReadBookIntent.TtsProgress -> _effects.tryEmit(ReadBookEffect.UpTtsAloudSpan(intent.chapterStart))
|
||||||
is ReadBookIntent.ReadAloudAction -> {
|
is ReadBookIntent.ReadAloudAction -> {
|
||||||
_uiState.update {
|
openReadMenuRoute(ReadBookMenuRoute.ReadAloud)
|
||||||
it.copy(
|
|
||||||
speakEngineName = computeSpeakEngineName(),
|
|
||||||
activeSheet = ReadBookSheet.ReadAloudConfig,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
loadTtsEngineItems()
|
|
||||||
}
|
}
|
||||||
is ReadBookIntent.ConfirmAddCurrentBookToBookshelf -> addCurrentBookToBookshelfAndFinish()
|
is ReadBookIntent.ConfirmAddCurrentBookToBookshelf -> addCurrentBookToBookshelfAndFinish()
|
||||||
is ReadBookIntent.ExitWithoutAddingCurrentBookToBookshelf -> removeCurrentNotShelfBookAndFinish()
|
is ReadBookIntent.ExitWithoutAddingCurrentBookToBookshelf -> removeCurrentNotShelfBookAndFinish()
|
||||||
@@ -839,9 +841,23 @@ class ReadBookViewModel(
|
|||||||
_effects.tryEmit(ReadBookEffect.OpenHttpTtsExportPicker)
|
_effects.tryEmit(ReadBookEffect.OpenHttpTtsExportPicker)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is ReadBookIntent.ExportAllHttpTtsAsUrl -> {
|
||||||
|
execute {
|
||||||
|
val json = exportHttpTtsJson()
|
||||||
|
val dataUrl = "data:application/json;base64," + Base64.encodeToString(
|
||||||
|
json.toByteArray(Charsets.UTF_8),
|
||||||
|
Base64.NO_WRAP
|
||||||
|
)
|
||||||
|
"legado://import/httpTTS?src=" + URLEncoder.encode(dataUrl, "UTF-8")
|
||||||
|
}.onSuccess { url ->
|
||||||
|
context.sendToClip(url)
|
||||||
|
_effects.tryEmit(ReadBookEffect.ShowToast(context.getString(R.string.copy_url)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
is ReadBookIntent.ExportHttpTtsToFile -> {
|
is ReadBookIntent.ExportHttpTtsToFile -> {
|
||||||
execute {
|
execute {
|
||||||
val json = GSON.toJson(appDb.httpTTSDao.all)
|
val json = exportHttpTtsJson()
|
||||||
context.contentResolver.openOutputStream(intent.uri)?.use { os ->
|
context.contentResolver.openOutputStream(intent.uri)?.use { os ->
|
||||||
os.write(json.toByteArray())
|
os.write(json.toByteArray())
|
||||||
}
|
}
|
||||||
@@ -864,6 +880,22 @@ class ReadBookViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReadBookIntent.CancelHttpTtsImport -> cancelHttpTtsImport()
|
||||||
|
|
||||||
|
is ReadBookIntent.ToggleHttpTtsImportSelection -> {
|
||||||
|
toggleHttpTtsImportSelection(intent.index)
|
||||||
|
}
|
||||||
|
|
||||||
|
is ReadBookIntent.ToggleHttpTtsImportAll -> {
|
||||||
|
toggleHttpTtsImportAll(intent.isSelected)
|
||||||
|
}
|
||||||
|
|
||||||
|
is ReadBookIntent.UpdateHttpTtsImportItem -> {
|
||||||
|
updateHttpTtsImportItem(intent.index, intent.httpTTS)
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadBookIntent.SaveImportedHttpTts -> saveImportedHttpTts()
|
||||||
|
|
||||||
is ReadBookIntent.SetReadAloudIgnoreAudioFocus -> {
|
is ReadBookIntent.SetReadAloudIgnoreAudioFocus -> {
|
||||||
viewModelScope.launch { readAloudSettingsRepository.setIgnoreAudioFocus(intent.value) }
|
viewModelScope.launch { readAloudSettingsRepository.setIgnoreAudioFocus(intent.value) }
|
||||||
}
|
}
|
||||||
@@ -1030,7 +1062,9 @@ class ReadBookViewModel(
|
|||||||
// Text action menu
|
// Text action menu
|
||||||
is ReadBookIntent.TextActionAloud -> {
|
is ReadBookIntent.TextActionAloud -> {
|
||||||
when (ReadConfig.contentSelectSpeakMod) {
|
when (ReadConfig.contentSelectSpeakMod) {
|
||||||
1 -> _effects.tryEmit(ReadBookEffect.TextActionAloudSelect)
|
1 -> intent.selectStartPos?.let {
|
||||||
|
_effects.tryEmit(ReadBookEffect.TextActionAloudSelect(it.copy()))
|
||||||
|
} ?: _effects.tryEmit(ReadBookEffect.TextActionSpeak(intent.text))
|
||||||
else -> _effects.tryEmit(ReadBookEffect.TextActionSpeak(intent.text))
|
else -> _effects.tryEmit(ReadBookEffect.TextActionSpeak(intent.text))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1094,7 +1128,7 @@ class ReadBookViewModel(
|
|||||||
is ReadBookIntent.OnResume -> handleOnResume()
|
is ReadBookIntent.OnResume -> handleOnResume()
|
||||||
is ReadBookIntent.OnPause -> handleOnPause()
|
is ReadBookIntent.OnPause -> handleOnPause()
|
||||||
is ReadBookIntent.OnDispose -> handleOnDispose()
|
is ReadBookIntent.OnDispose -> handleOnDispose()
|
||||||
is ReadBookIntent.CloseReadBook -> closeReadBook()
|
is ReadBookIntent.CloseReadBook -> closeReadBook(intent.keepReadAloud)
|
||||||
is ReadBookIntent.OpenBooksDirPicker -> requestBooksDirPicker(reloadChapterList = false)
|
is ReadBookIntent.OpenBooksDirPicker -> requestBooksDirPicker(reloadChapterList = false)
|
||||||
is ReadBookIntent.BooksDirSelected -> onBooksDirSelected(intent.uri)
|
is ReadBookIntent.BooksDirSelected -> onBooksDirSelected(intent.uri)
|
||||||
}
|
}
|
||||||
@@ -1157,10 +1191,6 @@ class ReadBookViewModel(
|
|||||||
private fun handleOnDispose() {
|
private fun handleOnDispose() {
|
||||||
backupJob?.cancel()
|
backupJob?.cancel()
|
||||||
ReadBook.cancelPreDownloadTask()
|
ReadBook.cancelPreDownloadTask()
|
||||||
if (BaseReadAloudService.isRun) {
|
|
||||||
ReadAloud.stop(context)
|
|
||||||
_uiState.update { it.copy(isReadAloudRunning = false, isReadAloudPaused = false) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showSpeakEngineConfig() {
|
private fun showSpeakEngineConfig() {
|
||||||
@@ -1203,26 +1233,63 @@ class ReadBookViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun importHttpTtsSource(text: String) {
|
private fun importHttpTtsSource(text: String) {
|
||||||
|
_uiState.update {
|
||||||
|
it.copy(httpTtsImportState = BaseImportUiState.Loading)
|
||||||
|
}
|
||||||
execute {
|
execute {
|
||||||
importHttpTtsSourceAwait(text.trim()).also { list ->
|
val list = importHttpTtsSourceAwait(text.trim())
|
||||||
if (list.isNotEmpty()) {
|
val items = list.map { httpTTS ->
|
||||||
appDb.httpTTSDao.insert(*list.toTypedArray())
|
val old = appDb.httpTTSDao.get(httpTTS.id)
|
||||||
|
val status = when {
|
||||||
|
old == null -> ImportStatus.New
|
||||||
|
httpTTS.lastUpdateTime > old.lastUpdateTime -> ImportStatus.Update
|
||||||
|
else -> ImportStatus.Existing
|
||||||
}
|
}
|
||||||
|
ImportItemWrapper(
|
||||||
|
data = httpTTS,
|
||||||
|
oldData = old,
|
||||||
|
status = status,
|
||||||
|
isSelected = status != ImportStatus.Existing,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}.onSuccess { list ->
|
if (items.isEmpty()) {
|
||||||
if (list.isNotEmpty()) {
|
throw NoStackTraceException(context.getString(R.string.wrong_format))
|
||||||
loadTtsEngineItems()
|
}
|
||||||
_effects.tryEmit(ReadBookEffect.ShowToast(context.getString(R.string.success)))
|
BaseImportUiState.Success(
|
||||||
|
source = text,
|
||||||
|
items = items,
|
||||||
|
)
|
||||||
|
}.onSuccess { importState ->
|
||||||
|
_uiState.update {
|
||||||
|
it.copy(httpTtsImportState = importState)
|
||||||
}
|
}
|
||||||
}.onError {
|
}.onError {
|
||||||
AppLog.put("导入朗读引擎失败\n${it.localizedMessage}", it, true)
|
AppLog.put("导入朗读引擎失败\n${it.localizedMessage}", it, true)
|
||||||
|
_uiState.update { state ->
|
||||||
|
state.copy(
|
||||||
|
httpTtsImportState = BaseImportUiState.Error(
|
||||||
|
it.localizedMessage ?: context.getString(R.string.wrong_format)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun importHttpTtsSourceAwait(text: String): List<HttpTTS> {
|
private suspend fun importHttpTtsSourceAwait(text: String): List<HttpTTS> {
|
||||||
return when {
|
return when {
|
||||||
|
text.isHttpTtsImportUri() -> {
|
||||||
|
val src = Uri.parse(text).getQueryParameter("src")
|
||||||
|
?: throw NoStackTraceException(context.getString(R.string.wrong_format))
|
||||||
|
importHttpTtsSourceAwait(src)
|
||||||
|
}
|
||||||
text.isJsonObject() -> listOf(HttpTTS.fromJson(text).getOrThrow())
|
text.isJsonObject() -> listOf(HttpTTS.fromJson(text).getOrThrow())
|
||||||
text.isJsonArray() -> HttpTTS.fromJsonArray(text).getOrThrow()
|
text.isJsonArray() -> HttpTTS.fromJsonArray(text).getOrThrow()
|
||||||
|
text.isDataUrl() -> {
|
||||||
|
val data = AppPattern.dataUriRegex.find(text)?.groupValues?.getOrNull(1)
|
||||||
|
?: throw NoStackTraceException(context.getString(R.string.wrong_format))
|
||||||
|
val body = Base64.decode(data, Base64.DEFAULT).toString(Charsets.UTF_8)
|
||||||
|
importHttpTtsSourceAwait(body)
|
||||||
|
}
|
||||||
text.isAbsUrl() -> {
|
text.isAbsUrl() -> {
|
||||||
val body = okHttpClient.newCallResponseBody {
|
val body = okHttpClient.newCallResponseBody {
|
||||||
if (text.endsWith("#requestWithoutUA")) {
|
if (text.endsWith("#requestWithoutUA")) {
|
||||||
@@ -1238,6 +1305,91 @@ class ReadBookViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun cancelHttpTtsImport() {
|
||||||
|
_uiState.update {
|
||||||
|
it.copy(
|
||||||
|
httpTtsImportState = BaseImportUiState.Idle,
|
||||||
|
activeSheet = ReadBookSheet.SpeakEngineConfig,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun toggleHttpTtsImportSelection(index: Int) {
|
||||||
|
val importState = _uiState.value.httpTtsImportState
|
||||||
|
as? BaseImportUiState.Success<HttpTTS> ?: return
|
||||||
|
if (index !in importState.items.indices) return
|
||||||
|
val items = importState.items.toMutableList()
|
||||||
|
val item = items[index]
|
||||||
|
items[index] = item.copy(isSelected = !item.isSelected)
|
||||||
|
_uiState.update {
|
||||||
|
it.copy(httpTtsImportState = importState.copy(items = items))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun toggleHttpTtsImportAll(isSelected: Boolean) {
|
||||||
|
val importState = _uiState.value.httpTtsImportState
|
||||||
|
as? BaseImportUiState.Success<HttpTTS> ?: return
|
||||||
|
_uiState.update {
|
||||||
|
it.copy(
|
||||||
|
httpTtsImportState = importState.copy(
|
||||||
|
items = importState.items.map { item ->
|
||||||
|
item.copy(isSelected = isSelected)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateHttpTtsImportItem(index: Int, httpTTS: HttpTTS) {
|
||||||
|
val importState = _uiState.value.httpTtsImportState
|
||||||
|
as? BaseImportUiState.Success<HttpTTS> ?: return
|
||||||
|
if (index !in importState.items.indices) return
|
||||||
|
val items = importState.items.toMutableList()
|
||||||
|
items[index] = items[index].copy(data = httpTTS)
|
||||||
|
_uiState.update {
|
||||||
|
it.copy(
|
||||||
|
httpTtsImportState = importState.copy(
|
||||||
|
items = items,
|
||||||
|
version = importState.version + 1,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveImportedHttpTts() {
|
||||||
|
val importState = _uiState.value.httpTtsImportState
|
||||||
|
as? BaseImportUiState.Success<HttpTTS> ?: return
|
||||||
|
val selected = importState.items
|
||||||
|
.filter { it.isSelected }
|
||||||
|
.map { it.data }
|
||||||
|
if (selected.isEmpty()) return
|
||||||
|
execute {
|
||||||
|
appDb.httpTTSDao.insert(*selected.toTypedArray())
|
||||||
|
}.onSuccess {
|
||||||
|
loadTtsEngineItems()
|
||||||
|
_uiState.update {
|
||||||
|
it.copy(
|
||||||
|
httpTtsImportState = BaseImportUiState.Idle,
|
||||||
|
activeSheet = ReadBookSheet.SpeakEngineConfig,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_effects.tryEmit(ReadBookEffect.ShowToast(context.getString(R.string.success)))
|
||||||
|
}.onError {
|
||||||
|
AppLog.put("保存朗读引擎失败\n${it.localizedMessage}", it, true)
|
||||||
|
_uiState.update { state ->
|
||||||
|
state.copy(
|
||||||
|
httpTtsImportState = BaseImportUiState.Error(
|
||||||
|
it.localizedMessage ?: context.getString(R.string.wrong_format)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun exportHttpTtsJson(): String {
|
||||||
|
return GSON.toJson(appDb.httpTTSDao.all)
|
||||||
|
}
|
||||||
|
|
||||||
private fun computeSpeakEngineName(): String {
|
private fun computeSpeakEngineName(): String {
|
||||||
val ttsEngine = ReadAloud.ttsEngine
|
val ttsEngine = ReadAloud.ttsEngine
|
||||||
?: return context.getString(R.string.system_tts)
|
?: return context.getString(R.string.system_tts)
|
||||||
@@ -1578,9 +1730,6 @@ class ReadBookViewModel(
|
|||||||
|
|
||||||
private fun setReadAloudTtsTimer(value: Int) {
|
private fun setReadAloudTtsTimer(value: Int) {
|
||||||
val timer = value.coerceIn(0, 180)
|
val timer = value.coerceIn(0, 180)
|
||||||
viewModelScope.launch {
|
|
||||||
readAloudSettingsRepository.setTtsTimer(timer)
|
|
||||||
}
|
|
||||||
ReadAloud.setTimer(context, timer)
|
ReadAloud.setTimer(context, timer)
|
||||||
_uiState.update { it.copy(readAloudTtsTimer = timer) }
|
_uiState.update { it.copy(readAloudTtsTimer = timer) }
|
||||||
}
|
}
|
||||||
@@ -1858,6 +2007,10 @@ class ReadBookViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun markJustInitData() {
|
||||||
|
justInitData = true
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun initBook(book: Book) {
|
private suspend fun initBook(book: Book) {
|
||||||
val isSameBook = ReadBook.book?.bookUrl == book.bookUrl
|
val isSameBook = ReadBook.book?.bookUrl == book.bookUrl
|
||||||
if (isSameBook) {
|
if (isSameBook) {
|
||||||
@@ -2159,7 +2312,10 @@ class ReadBookViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun closeReadBook() {
|
private var closeReadBookKeepReadAloud = false
|
||||||
|
|
||||||
|
private fun closeReadBook(keepReadAloud: Boolean = false) {
|
||||||
|
closeReadBookKeepReadAloud = keepReadAloud
|
||||||
val book = ReadBook.book
|
val book = ReadBook.book
|
||||||
if (!ReadBook.inBookshelf && book != null && OtherConfig.showAddToShelfAlert) {
|
if (!ReadBook.inBookshelf && book != null && OtherConfig.showAddToShelfAlert) {
|
||||||
_uiState.update {
|
_uiState.update {
|
||||||
@@ -2168,10 +2324,19 @@ class ReadBookViewModel(
|
|||||||
} else if (!ReadBook.inBookshelf) {
|
} else if (!ReadBook.inBookshelf) {
|
||||||
removeCurrentNotShelfBookAndFinish()
|
removeCurrentNotShelfBookAndFinish()
|
||||||
} else {
|
} else {
|
||||||
|
stopReadAloudForClose()
|
||||||
_effects.tryEmit(ReadBookEffect.Finish)
|
_effects.tryEmit(ReadBookEffect.Finish)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun stopReadAloudForClose() {
|
||||||
|
if (closeReadBookKeepReadAloud || !BaseReadAloudService.isRun) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ReadAloud.stop(context)
|
||||||
|
_uiState.update { it.copy(isReadAloudRunning = false, isReadAloudPaused = false) }
|
||||||
|
}
|
||||||
|
|
||||||
private fun addCurrentBookToBookshelfAndFinish() {
|
private fun addCurrentBookToBookshelfAndFinish() {
|
||||||
val book = ReadBook.book ?: return removeCurrentNotShelfBookAndFinish()
|
val book = ReadBook.book ?: return removeCurrentNotShelfBookAndFinish()
|
||||||
execute {
|
execute {
|
||||||
@@ -2187,6 +2352,7 @@ class ReadBookViewModel(
|
|||||||
ReadBook.inBookshelf = true
|
ReadBook.inBookshelf = true
|
||||||
}.onSuccess {
|
}.onSuccess {
|
||||||
_uiState.update { it.copy(activeDialog = null) }
|
_uiState.update { it.copy(activeDialog = null) }
|
||||||
|
stopReadAloudForClose()
|
||||||
_effects.tryEmit(ReadBookEffect.Finish)
|
_effects.tryEmit(ReadBookEffect.Finish)
|
||||||
}.onError {
|
}.onError {
|
||||||
AppLog.put("添加书籍到书架失败", it)
|
AppLog.put("添加书籍到书架失败", it)
|
||||||
@@ -2197,6 +2363,7 @@ class ReadBookViewModel(
|
|||||||
private fun removeCurrentNotShelfBookAndFinish() {
|
private fun removeCurrentNotShelfBookAndFinish() {
|
||||||
_uiState.update { it.copy(activeDialog = null) }
|
_uiState.update { it.copy(activeDialog = null) }
|
||||||
removeFromBookshelf {
|
removeFromBookshelf {
|
||||||
|
stopReadAloudForClose()
|
||||||
_effects.tryEmit(ReadBookEffect.Finish)
|
_effects.tryEmit(ReadBookEffect.Finish)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3786,3 +3953,10 @@ private data class SearchTextPoint(
|
|||||||
private fun Int.coerceSearchResultIndex(resultSize: Int): Int {
|
private fun Int.coerceSearchResultIndex(resultSize: Int): Int {
|
||||||
return if (resultSize <= 0) 0 else coerceIn(0, resultSize - 1)
|
return if (resultSize <= 0) 0 else coerceIn(0, resultSize - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun String.isHttpTtsImportUri(): Boolean {
|
||||||
|
val uri = runCatching { Uri.parse(this) }.getOrNull() ?: return false
|
||||||
|
return uri.scheme in setOf("legado", "yuedu")
|
||||||
|
&& uri.host == "import"
|
||||||
|
&& uri.path.equals("/httpTTS", ignoreCase = true)
|
||||||
|
}
|
||||||
|
|||||||
@@ -351,13 +351,15 @@ fun MainActivity.mainEntryProvider(
|
|||||||
effectsReady.await()
|
effectsReady.await()
|
||||||
collectorReady[0] = true
|
collectorReady[0] = true
|
||||||
readBookViewModel.initReadBookConfig(readIntent)
|
readBookViewModel.initReadBookConfig(readIntent)
|
||||||
readBookViewModel.initData(readIntent)
|
readBookViewModel.initData(readIntent) {
|
||||||
|
readBookViewModel.markJustInitData()
|
||||||
controller.onRouteInitialized()
|
controller.onRouteInitialized()
|
||||||
if (lifecycleOwner.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
|
if (lifecycleOwner.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
|
||||||
resumeReader()
|
resumeReader()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
entry<MainRouteSearchContent> { route ->
|
entry<MainRouteSearchContent> { route ->
|
||||||
val viewModel = koinViewModel<SearchContentViewModel>(
|
val viewModel = koinViewModel<SearchContentViewModel>(
|
||||||
|
|||||||
Reference in New Issue
Block a user