This commit is contained in:
Horis 2024-04-10 13:58:25 +08:00
parent bbe90f1c55
commit cc75fc9394
6 changed files with 98 additions and 52 deletions

View File

@ -4,6 +4,7 @@ package io.legado.app.constant
object IntentAction { object IntentAction {
const val start = "start" const val start = "start"
const val play = "play" const val play = "play"
const val playNew = "playNew"
const val stop = "stop" const val stop = "stop"
const val resume = "resume" const val resume = "resume"
const val pause = "pause" const val pause = "pause"

View File

@ -288,6 +288,14 @@ data class Book(
return appDb.bookSourceDao.getBookSource(origin) return appDb.bookSourceDao.getBookSource(origin)
} }
fun getChapter(index: Int): BookChapter? {
return appDb.bookChapterDao.getChapter(bookUrl, index)
}
fun getDurChapter(): BookChapter? {
return getChapter(durChapterIndex)
}
fun isLocalModified(): Boolean { fun isLocalModified(): Boolean {
return isLocal && LocalBook.getLastModified(this).getOrDefault(0L) > latestChapterTime return isLocal && LocalBook.getLastModified(this).getOrDefault(0L) > latestChapterTime
} }

View File

@ -97,10 +97,10 @@ data class ReplaceRule(
AppLog.put("正则语法错误或不支持:${ex.localizedMessage}", ex) AppLog.put("正则语法错误或不支持:${ex.localizedMessage}", ex)
return false return false
} }
} // Pattern.compile测试通过但是部分情况下会替换超时报错一般发生在修改表达式时漏删了
// Pattern.compile测试通过但是部分情况下会替换超时报错一般发生在修改表达式时漏删了 if (pattern.endsWith('|') && !pattern.endsWith("\\|")) {
if (pattern.endsWith('|') and !pattern.endsWith("\\|")) { return false
return false }
} }
return true return true
} }

View File

@ -27,9 +27,25 @@ object AudioPlay {
var inBookshelf = false var inBookshelf = false
var bookSource: BookSource? = null var bookSource: BookSource? = null
val loadingChapters = arrayListOf<Int>() val loadingChapters = arrayListOf<Int>()
var durChapterIndex = 0
fun headers(hasLoginHeader: Boolean): Map<String, String>? { fun upData(context: Context, book: Book) {
return bookSource?.getHeaderMap(hasLoginHeader) AudioPlay.book = book
upDurChapter(book)
if (durChapterIndex != book.durChapterIndex) {
durChapterIndex = book.durChapterIndex
playNew(context)
}
}
fun resetData(context: Context, book: Book) {
stop(context)
AudioPlay.book = book
titleData.postValue(book.name)
coverData.postValue(book.getDisplayCover())
bookSource = book.getBookSource()
durChapterIndex = book.durChapterIndex
upDurChapter(book)
} }
/** /**
@ -48,11 +64,27 @@ object AudioPlay {
} }
} }
/**
* 从头播放新章节
*/
fun playNew(context: Context) {
book?.let {
if (durChapter == null) {
upDurChapter(it)
}
durChapter?.let {
context.startService<AudioPlayService> {
action = IntentAction.playNew
}
}
}
}
/** /**
* 更新当前章节 * 更新当前章节
*/ */
fun upDurChapter(book: Book) { fun upDurChapter(book: Book) {
durChapter = appDb.bookChapterDao.getChapter(book.bookUrl, book.durChapterIndex) durChapter = book.getDurChapter()
postEvent(EventBus.AUDIO_SUB_TITLE, durChapter?.title ?: "") postEvent(EventBus.AUDIO_SUB_TITLE, durChapter?.title ?: "")
postEvent(EventBus.AUDIO_SIZE, durChapter?.end?.toInt() ?: 0) postEvent(EventBus.AUDIO_SIZE, durChapter?.end?.toInt() ?: 0)
postEvent(EventBus.AUDIO_PROGRESS, book.durChapterPos) postEvent(EventBus.AUDIO_PROGRESS, book.durChapterPos)
@ -105,9 +137,10 @@ object AudioPlay {
book?.let { book -> book?.let { book ->
book.durChapterIndex = index book.durChapterIndex = index
book.durChapterPos = 0 book.durChapterPos = 0
durChapterIndex = book.durChapterIndex
durChapter = null durChapter = null
saveRead() saveRead()
play(context) playNew(context)
} }
} }
} }
@ -118,6 +151,7 @@ object AudioPlay {
if (book.durChapterIndex > 0) { if (book.durChapterIndex > 0) {
book.durChapterIndex -= 1 book.durChapterIndex -= 1
book.durChapterPos = 0 book.durChapterPos = 0
durChapterIndex = book.durChapterIndex
durChapter = null durChapter = null
saveRead() saveRead()
play(context) play(context)
@ -133,6 +167,7 @@ object AudioPlay {
if (book.durChapterIndex + 1 < book.totalChapterNum) { if (book.durChapterIndex + 1 < book.totalChapterNum) {
book.durChapterIndex += 1 book.durChapterIndex += 1
book.durChapterPos = 0 book.durChapterPos = 0
durChapterIndex = book.durChapterIndex
durChapter = null durChapter = null
saveRead() saveRead()
play(context) play(context)

View File

@ -144,11 +144,20 @@ class AudioPlayService : BaseService(),
when (action) { when (action) {
IntentAction.play -> { IntentAction.play -> {
exoPlayer.stop() exoPlayer.stop()
upPlayProgressJob?.cancel()
pause = false pause = false
position = AudioPlay.book?.durChapterPos ?: 0 position = AudioPlay.book?.durChapterPos ?: 0
loadContent() loadContent()
} }
IntentAction.playNew -> {
exoPlayer.stop()
upPlayProgressJob?.cancel()
pause = false
position = 0
loadContent()
}
IntentAction.pause -> pause() IntentAction.pause -> pause()
IntentAction.resume -> resume() IntentAction.resume -> resume()
IntentAction.prev -> AudioPlay.prev(this) IntentAction.prev -> AudioPlay.prev(this)
@ -160,7 +169,7 @@ class AudioPlayService : BaseService(),
adjustProgress(intent.getIntExtra("position", position)) adjustProgress(intent.getIntExtra("position", position))
} }
else -> stopSelf() IntentAction.stop -> stopSelf()
} }
} }
return super.onStartCommand(intent, flags, startId) return super.onStartCommand(intent, flags, startId)
@ -204,7 +213,6 @@ class AudioPlayService : BaseService(),
source = AudioPlay.bookSource, source = AudioPlay.bookSource,
ruleData = AudioPlay.book, ruleData = AudioPlay.book,
chapter = AudioPlay.durChapter, chapter = AudioPlay.durChapter,
headerMapF = AudioPlay.headers(true),
) )
exoPlayer.setMediaItem(analyzeUrl.getMediaItem()) exoPlayer.setMediaItem(analyzeUrl.getMediaItem())
exoPlayer.playWhenReady = true exoPlayer.playWhenReady = true

View File

@ -2,6 +2,7 @@ package io.legado.app.ui.book.audio
import android.app.Application import android.app.Application
import android.content.Intent import android.content.Intent
import androidx.lifecycle.viewModelScope
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.BaseViewModel import io.legado.app.base.BaseViewModel
import io.legado.app.constant.BookType import io.legado.app.constant.BookType
@ -12,70 +13,63 @@ import io.legado.app.data.entities.BookChapter
import io.legado.app.data.entities.BookSource import io.legado.app.data.entities.BookSource
import io.legado.app.help.book.removeType import io.legado.app.help.book.removeType
import io.legado.app.model.AudioPlay import io.legado.app.model.AudioPlay
import io.legado.app.model.AudioPlay.durChapter
import io.legado.app.model.webBook.WebBook import io.legado.app.model.webBook.WebBook
import io.legado.app.utils.postEvent import io.legado.app.utils.postEvent
import io.legado.app.utils.toastOnUi import io.legado.app.utils.toastOnUi
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers.IO
class AudioPlayViewModel(application: Application) : BaseViewModel(application) { class AudioPlayViewModel(application: Application) : BaseViewModel(application) {
fun initData(intent: Intent) = AudioPlay.apply { fun initData(intent: Intent) = AudioPlay.apply {
execute { execute {
val bookUrl = intent.getStringExtra("bookUrl") val bookUrl = intent.getStringExtra("bookUrl") ?: return@execute
if (bookUrl != null && bookUrl != book?.bookUrl) { val book = appDb.bookDao.getBook(bookUrl) ?: return@execute
stop(context) inBookshelf = intent.getBooleanExtra("inBookshelf", true)
inBookshelf = intent.getBooleanExtra("inBookshelf", true) initBook(book)
book = appDb.bookDao.getBook(bookUrl) }.onFinally {
book?.let { book ->
titleData.postValue(book.name)
coverData.postValue(book.getDisplayCover())
durChapter = appDb.bookChapterDao.getChapter(book.bookUrl, book.durChapterIndex)
upDurChapter(book)
bookSource = appDb.bookSourceDao.getBookSource(book.origin)
if (durChapter == null) {
if (book.tocUrl.isEmpty()) {
loadBookInfo(book)
} else {
loadChapterList(book)
}
}
}
}
saveRead() saveRead()
} }
} }
private fun loadBookInfo(book: Book) { private fun initBook(book: Book) {
execute { val isSameBook = AudioPlay.book?.bookUrl == book.bookUrl
AudioPlay.bookSource?.let { if (isSameBook) {
WebBook.getBookInfo(this, it, book) AudioPlay.upData(context, book)
.onSuccess { } else {
loadChapterList(book) AudioPlay.resetData(context, book)
} }
if (durChapter == null) {
if (book.tocUrl.isEmpty()) {
loadBookInfo(book)
} else {
loadChapterList(book)
} }
} }
} }
private fun loadBookInfo(book: Book) {
val bookSource = AudioPlay.bookSource ?: return
WebBook.getBookInfo(viewModelScope, bookSource, book).onSuccess(IO) {
loadChapterList(book)
}
}
private fun loadChapterList(book: Book) { private fun loadChapterList(book: Book) {
execute { val bookSource = AudioPlay.bookSource ?: return
AudioPlay.bookSource?.let { WebBook.getChapterList(viewModelScope, bookSource, book).onSuccess(IO) { cList ->
WebBook.getChapterList(this, it, book) book.save()
.onSuccess(Dispatchers.IO) { cList -> appDb.bookChapterDao.insert(*cList.toTypedArray())
book.save() AudioPlay.upDurChapter(book)
appDb.bookChapterDao.insert(*cList.toTypedArray()) }.onError {
AudioPlay.upDurChapter(book) context.toastOnUi(R.string.error_load_toc)
}.onError {
context.toastOnUi(R.string.error_load_toc)
}
}
} }
} }
fun upSource() { fun upSource() {
execute { execute {
AudioPlay.book?.let { book -> val book = AudioPlay.book ?: return@execute
AudioPlay.bookSource = appDb.bookSourceDao.getBookSource(book.origin) AudioPlay.bookSource = book.getBookSource()
}
} }
} }