Merge branch 'gedoor:master' into master

pull/1744/head
Xwite 3 years ago committed by GitHub
commit 39db492f81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      app/build.gradle
  2. BIN
      app/cronetlib/cronet_api.jar
  3. BIN
      app/cronetlib/cronet_impl_common_java.jar
  4. BIN
      app/cronetlib/cronet_impl_native_java.jar
  5. 2
      app/src/main/assets/cronet.json
  6. 26
      app/src/main/assets/updateLog.md
  7. 2
      app/src/main/java/io/legado/app/App.kt
  8. 5
      app/src/main/java/io/legado/app/constant/EventBus.kt
  9. 2
      app/src/main/java/io/legado/app/help/config/AppConfig.kt
  10. 4
      app/src/main/java/io/legado/app/help/storage/AppWebDav.kt
  11. 14
      app/src/main/java/io/legado/app/model/AudioPlay.kt
  12. 66
      app/src/main/java/io/legado/app/model/localBook/LocalBook.kt
  13. 41
      app/src/main/java/io/legado/app/service/AudioPlayService.kt
  14. 4
      app/src/main/java/io/legado/app/service/BaseReadAloudService.kt
  15. 23
      app/src/main/java/io/legado/app/ui/book/audio/AudioPlayActivity.kt
  16. 40
      app/src/main/java/io/legado/app/ui/book/audio/ComposeView.kt
  17. 4
      app/src/main/java/io/legado/app/ui/book/local/ImportBookViewModel.kt
  18. 28
      app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt
  19. 2
      app/src/main/java/io/legado/app/ui/book/read/config/ReadAloudDialog.kt
  20. 35
      app/src/main/res/layout/activity_audio_play.xml
  21. 1
      app/src/main/res/values-es-rES/strings.xml
  22. 1
      app/src/main/res/values-ja-rJP/strings.xml
  23. 1
      app/src/main/res/values-pt-rBR/strings.xml
  24. 1
      app/src/main/res/values-zh-rHK/strings.xml
  25. 1
      app/src/main/res/values-zh-rTW/strings.xml
  26. 1
      app/src/main/res/values-zh/strings.xml
  27. 1
      app/src/main/res/values/strings.xml
  28. 2
      gradle.properties

@ -244,8 +244,9 @@ dependencies {
implementation('com.github.liuyueyi.quick-chinese-transfer:quick-transfer-core:0.2.3')
//
implementation('cn.hutool:hutool-crypto:5.7.22')
implementation('cn.hutool:hutool-crypto:5.8.0.M1')
//renderscriptToolkit
implementation('com.github.android:renderscript-intrinsics-replacement-toolkit:b6363490c3')
//com.github.AmrDeveloper:CodeView已集成到应用内

Binary file not shown.

@ -1 +1 @@
{"x86":"dad15d54e348efc1e692d72e72e9d52e","armeabi-v7a":"8745ce95fc4bc9063743a890d92bf411","x86_64":"35dd2701803d69aa66d8ac8f836e0123","arm64-v8a":"30165de860a5f288417d536d542401c3","version":"99.0.4844.88"}
{"x86":"ff4b324fca11309c5e93a45f65970540","armeabi-v7a":"65e8bb0095d5be314ada2f523718f477","x86_64":"3dac75809f86b8edd1399a642bd26f59","arm64-v8a":"ac515c2995b4fb831419313056b1d3f0","version":"100.0.4896.58"}

@ -11,6 +11,13 @@
* 正文出现缺字漏字、内容缺失、排版错乱等情况,有可能是净化规则或简繁转换出现问题。
* 漫画源看书显示乱码,**阅读与其他软件的源并不通用**,请导入阅读的支持的漫画源!
**2022/03/29**
* 更新cronet: 100.0.4896.58
* tts朗读不在指定为中文,跟随系统设置,因为有些人需要朗读英文,如果朗读不出来可以去tts设置里看看是不是中文
* 修复详情也封面背景模糊失效的bug
* 优化音频界面定时设定
**2022/03/25**
* 更新cronet: 99.0.4844.88
@ -557,22 +564,6 @@ fun getZipByteArrayContent(url: String, path: String): ByteArray?
* 样式属性可以搜索 [FleboxLayout子元素支持的属性介绍](https://www.jianshu.com/p/3c471953e36d)
* 样式属性可省略,有默认值
```json
[
{
"title": "xxx",
"url": "",
"style": {
"layout_flexGrow": 0,
"layout_flexShrink": 1,
"layout_alignSelf": "auto",
"layout_flexBasisPercent": -1,
"layout_wrapBefore": false
}
}
]
```
**2021/07/07**
1. 默认规则新增类似`jsonPath`的索引写法 by bushixuanqi
@ -770,9 +761,6 @@ chapter.html的关键字有{title}、{content}
* 增加三星 S Pen 支持 by [dacer](https://github.com/dacer)
* 订阅添加阅读下载,可以从多个渠道下载
* 修复一些BUG
**2020/12/30**
* 解决文件下载异常,在线语音可正常播放 by [Celeter](https://github.com/Celeter)
* 更新默认在线朗读库, 默认id小于0方便下次更新时删除旧数据, 有重复的自己删除
* 导入导出书单

@ -58,7 +58,7 @@ class App : MultiDexApplication() {
2 -> ChineseUtils.s2t("初始化")
}
//同步阅读记录
if (AppWebDav.isOk && AppConfig.syncBookProgress) {
if (AppWebDav.syncBookProgress) {
AppWebDav.downloadAllBookProgress()
}
}

@ -7,7 +7,8 @@ object EventBus {
const val BOOKSHELF_REFRESH = "bookshelfRefresh"
const val ALOUD_STATE = "aloud_state"
const val TTS_PROGRESS = "ttsStart"
const val TTS_DS = "ttsDs"
const val AUDIO_DS = "audioDs"
const val READ_ALOUD_DS = "readAloudDs"
const val BATTERY_CHANGED = "batteryChanged"
const val TIME_CHANGED = "timeChanged"
const val UP_CONFIG = "upConfig"
@ -17,13 +18,11 @@ object EventBus {
const val AUDIO_PROGRESS = "audioProgress"
const val AUDIO_SIZE = "audioSize"
const val AUDIO_SPEED = "audioSpeed"
const val AUDIO_ERROR = "audioError"
const val NOTIFY_MAIN = "notifyMain"
const val WEB_SERVICE = "webService"
const val UP_DOWNLOAD = "upDownload"
const val SAVE_CONTENT = "saveContent"
const val CHECK_SOURCE = "checkSource"
const val CHECK_SOURCE_MESSAGE = "checkSourceMessage"
const val CHECK_SOURCE_DONE = "checkSourceDone"
const val TIP_COLOR = "tipColor"
const val SOURCE_CHANGED = "sourceChanged"

@ -282,8 +282,6 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
val importKeepName get() = appCtx.getPrefBoolean(PreferKey.importKeepName)
val syncBookProgress get() = appCtx.getPrefBoolean(PreferKey.syncBookProgress, true)
var preDownloadNum
get() = appCtx.getPrefInt(PreferKey.preDownloadNum, 10)
set(value) {

@ -29,6 +29,8 @@ object AppWebDav {
private val bookProgressUrl = "${rootWebDavUrl}bookProgress/"
private val zipFilePath = "${appCtx.externalFiles.absolutePath}${File.separator}backup.zip"
val syncBookProgress get() = appCtx.getPrefBoolean(PreferKey.syncBookProgress, true)
var isOk = false
init {
@ -167,7 +169,7 @@ object AppWebDav {
fun uploadBookProgress(book: Book) {
if (!isOk) return
if (!AppConfig.syncBookProgress) return
if (!syncBookProgress) return
if (!NetworkUtils.isAvailable()) return
Coroutine.async {
val bookProgress = BookProgress(book)

@ -15,6 +15,7 @@ import io.legado.app.help.coroutine.Coroutine
import io.legado.app.service.AudioPlayService
import io.legado.app.utils.postEvent
import io.legado.app.utils.startService
import splitties.init.appCtx
object AudioPlay {
var titleData = MutableLiveData<String>()
@ -138,10 +139,17 @@ object AudioPlay {
}
}
fun addTimer(context: Context) {
val intent = Intent(context, AudioPlayService::class.java)
fun addTimer() {
val intent = Intent(appCtx, AudioPlayService::class.java)
intent.action = IntentAction.addTimer
context.startService(intent)
appCtx.startService(intent)
}
fun setTimer(minute: Int) {
val intent = Intent(appCtx, AudioPlayService::class.java)
intent.action = IntentAction.setTimer
intent.putExtra("minute", minute)
appCtx.startService(intent)
}
fun saveRead(book: Book) {

@ -16,12 +16,17 @@ import java.io.File
import java.io.FileInputStream
import java.io.FileNotFoundException
import java.io.InputStream
import java.util.regex.Matcher
import java.util.regex.Pattern
import javax.script.SimpleBindings
object LocalBook {
private val nameAuthorPatterns = arrayOf(
Pattern.compile("(.*?)《([^《》]+)》(.*)"),
Pattern.compile("(^)(.+) 作者:(.+)$"),
Pattern.compile("(^)(.+) by (.+)$")
)
@Throws(FileNotFoundException::class, SecurityException::class)
fun getBookInputStream(book: Book): InputStream {
val uri = Uri.parse(book.bookUrl)
@ -117,44 +122,37 @@ object LocalBook {
val tempFileName = fileName.substringBeforeLast(".")
var name: String
var author: String
//匹配(知轩藏书常用格式) 《书名》其它信息作者:作者名.txt
val m1 = Pattern
.compile("(.*?)《([^《》]+)》(.*)")
.matcher(tempFileName)
//匹配 书名 作者:作者名.txt
val m2 = Pattern
.compile("(^)(.+) 作者:(.+)$")
.matcher(tempFileName)
(m1.takeIf { m1.find() } ?: m2.takeIf { m2.find() }).run {
if (this is Matcher) {
//按默认格式将文件名分解成书名、作者名
for (pattern in nameAuthorPatterns) {
pattern.matcher(tempFileName).takeIf { it.find() }?.run {
name = group(2)!!
author = BookHelp.formatBookAuthor((group(1) ?: "") + (group(3) ?: ""))
} else if (!AppConfig.bookImportFileName.isNullOrBlank()) {
try {
//在脚本中定义如何分解文件名成书名、作者名
val jsonStr = AppConst.SCRIPT_ENGINE.eval(
//在用户脚本后添加捕获author、name的代码,只要脚本中author、name有值就会被捕获
AppConfig.bookImportFileName + "\nJSON.stringify({author:author,name:name})",
//将文件名注入到脚步的src变量中
SimpleBindings().also { it["src"] = tempFileName }
).toString()
val bookMess = GSON.fromJsonObject<HashMap<String, String>>(jsonStr)
.getOrThrow() ?: HashMap()
name = bookMess["name"] ?: tempFileName
author = bookMess["author"]?.takeIf { it.length != tempFileName.length } ?: ""
} catch (e: Exception) {
name = BookHelp.formatBookName(tempFileName)
author = BookHelp.formatBookAuthor(tempFileName.replace(name, ""))
.takeIf { it.length != tempFileName.length } ?: ""
}
} else {
val group1 = group(1) ?: ""
val group3 = group(3) ?: ""
author = BookHelp.formatBookAuthor(group1 + group3)
return Pair(name, author)
}
}
if (!AppConfig.bookImportFileName.isNullOrBlank()) {
try {
//在脚本中定义如何分解文件名成书名、作者名
val jsonStr = AppConst.SCRIPT_ENGINE.eval(
//在用户脚本后添加捕获author、name的代码,只要脚本中author、name有值就会被捕获
AppConfig.bookImportFileName + "\nJSON.stringify({author:author,name:name})",
//将文件名注入到脚步的src变量中
SimpleBindings().also { it["src"] = tempFileName }
).toString()
val bookMess = GSON.fromJsonObject<HashMap<String, String>>(jsonStr)
.getOrThrow() ?: HashMap()
name = bookMess["name"] ?: tempFileName
author = bookMess["author"]?.takeIf { it.length != tempFileName.length } ?: ""
} catch (e: Exception) {
name = BookHelp.formatBookName(tempFileName)
author = BookHelp.formatBookAuthor(tempFileName.replace(name, ""))
.takeIf { it.length != tempFileName.length } ?: ""
}
} else {
name = BookHelp.formatBookName(tempFileName)
author = BookHelp.formatBookAuthor(tempFileName.replace(name, ""))
.takeIf { it.length != tempFileName.length } ?: ""
}
return Pair(name, author)
}

@ -45,7 +45,7 @@ class AudioPlayService : BaseService(),
companion object {
var isRun = false
private set
var pause = false
var pause = true
private set
var timeMinute: Int = 0
private set
@ -59,11 +59,10 @@ class AudioPlayService : BaseService(),
private val exoPlayer: ExoPlayer by lazy {
ExoPlayer.Builder(this).build()
}
private var title: String = ""
private var subtitle: String = ""
private var mediaSessionCompat: MediaSessionCompat? = null
private var broadcastReceiver: BroadcastReceiver? = null
private var position = 0
private var audioFocusLossTransient = false
private var position = AudioPlay.book?.durChapterPos ?: 0
private var dsJob: Job? = null
private var upPlayProgressJob: Job? = null
private var playSpeed: Float = 1f
@ -76,18 +75,16 @@ class AudioPlayService : BaseService(),
initMediaSession()
initBroadcastReceiver()
upMediaSessionPlaybackState(PlaybackStateCompat.STATE_PLAYING)
doDs()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
intent?.action?.let { action ->
when (action) {
IntentAction.play -> {
AudioPlay.book?.let {
title = it.name
subtitle = AudioPlay.durChapter?.title ?: ""
position = it.durChapterPos
loadContent()
}
pause = false
position = AudioPlay.book?.durChapterPos ?: 0
loadContent()
}
IntentAction.pause -> pause(true)
IntentAction.resume -> resume()
@ -171,6 +168,10 @@ class AudioPlayService : BaseService(),
private fun resume() {
try {
pause = false
if (url.isEmpty()) {
loadContent()
return
}
if (!exoPlayer.isPlaying) {
exoPlayer.play()
}
@ -260,11 +261,11 @@ class AudioPlayService : BaseService(),
}
private fun addTimer() {
if (timeMinute == 60) {
if (timeMinute == 180) {
timeMinute = 0
} else {
timeMinute += 10
if (timeMinute > 60) timeMinute = 60
if (timeMinute > 180) timeMinute = 180
}
doDs()
}
@ -273,7 +274,7 @@ class AudioPlayService : BaseService(),
* 定时
*/
private fun doDs() {
postEvent(EventBus.TTS_DS, timeMinute)
postEvent(EventBus.AUDIO_DS, timeMinute)
upNotification()
dsJob?.cancel()
dsJob = launch {
@ -287,7 +288,7 @@ class AudioPlayService : BaseService(),
AudioPlay.stop(this@AudioPlayService)
}
}
postEvent(EventBus.TTS_DS, timeMinute)
postEvent(EventBus.AUDIO_DS, timeMinute)
upNotification()
}
}
@ -360,7 +361,6 @@ class AudioPlayService : BaseService(),
*/
private fun contentLoadFinish(chapter: BookChapter, content: String) {
if (chapter.index == AudioPlay.book?.durChapterIndex) {
subtitle = chapter.title
url = content
play()
}
@ -426,13 +426,18 @@ class AudioPlayService : BaseService(),
when (focusChange) {
AudioManager.AUDIOFOCUS_GAIN -> {
// 重新获得焦点, 可做恢复播放,恢复后台音量的操作
audioFocusLossTransient = false
if (!pause) resume()
}
AudioManager.AUDIOFOCUS_LOSS -> {
// 永久丢失焦点除非重新主动获取,这种情况是被其他播放器抢去了焦点, 为避免与其他播放器混音,可将音乐暂停
if (audioFocusLossTransient) {
pause(true)
}
}
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
// 暂时丢失焦点,这种情况是被其他应用申请了短暂的焦点,可压低后台音量
audioFocusLossTransient = true
if (!pause) pause(false)
}
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> {
@ -454,9 +459,9 @@ class AudioPlayService : BaseService(),
)
else -> getString(R.string.audio_play_t)
}
nTitle += ": $title"
var nSubtitle = subtitle
if (subtitle.isEmpty()) {
nTitle += ": ${AudioPlay.book?.name}"
var nSubtitle = AudioPlay.durChapter?.title
if (nSubtitle.isNullOrEmpty()) {
nSubtitle = getString(R.string.audio_play_s)
}
val builder = NotificationCompat

@ -206,7 +206,7 @@ abstract class BaseReadAloudService : BaseService(),
*/
@Synchronized
private fun doDs() {
postEvent(EventBus.TTS_DS, timeMinute)
postEvent(EventBus.READ_ALOUD_DS, timeMinute)
upNotification()
dsJob?.cancel()
dsJob = launch {
@ -220,7 +220,7 @@ abstract class BaseReadAloudService : BaseService(),
ReadAloud.stop(this@BaseReadAloudService)
}
}
postEvent(EventBus.TTS_DS, timeMinute)
postEvent(EventBus.READ_ALOUD_DS, timeMinute)
upNotification()
}
}

@ -1,5 +1,6 @@
package io.legado.app.ui.book.audio
import android.annotation.SuppressLint
import android.app.Activity
import android.icu.text.SimpleDateFormat
import android.os.Build
@ -8,6 +9,7 @@ import android.view.Menu
import android.view.MenuItem
import android.widget.SeekBar
import androidx.activity.viewModels
import androidx.compose.runtime.mutableStateOf
import io.legado.app.R
import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.EventBus
@ -25,6 +27,7 @@ import io.legado.app.ui.book.changesource.ChangeBookSourceDialog
import io.legado.app.ui.book.source.edit.BookSourceEditActivity
import io.legado.app.ui.book.toc.TocActivityResult
import io.legado.app.ui.login.SourceLoginActivity
import io.legado.app.ui.theme.AppTheme
import io.legado.app.ui.widget.seekbar.SeekBarChangeListener
import io.legado.app.utils.*
import io.legado.app.utils.viewbindingdelegate.viewBinding
@ -42,6 +45,7 @@ class AudioPlayActivity :
override val viewModel by viewModels<AudioPlayViewModel>()
private var menu: Menu? = null
private var adjustProgress = false
private val timerViewState = mutableStateOf(false)
private val progressTimeFormat by lazy {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
SimpleDateFormat("mm:ss", Locale.getDefault())
@ -153,7 +157,19 @@ class AudioPlayActivity :
AudioPlay.adjustSpeed(this@AudioPlayActivity, -0.1f)
}
binding.ivTimer.setOnClickListener {
AudioPlay.addTimer(this@AudioPlayActivity)
if (AudioPlayService.isRun) {
timerViewState.value = true
} else {
toastOnUi(R.string.cannot_timed_non_playback)
}
}
binding.composeView.setContent {
AppTheme {
TimerDialog(
state = timerViewState,
binding.ivTimer
)
}
}
}
@ -210,6 +226,7 @@ class AudioPlayActivity :
}
}
@SuppressLint("SetTextI18n")
override fun observeLiveBus() {
observeEvent<Boolean>(EventBus.MEDIA_BUTTON) {
if (it) {
@ -239,6 +256,10 @@ class AudioPlayActivity :
binding.tvSpeed.text = String.format("%.1fX", it)
binding.tvSpeed.visible()
}
observeEventSticky<Int>(EventBus.AUDIO_DS) {
binding.tvTimer.text = "${it}m"
binding.tvTimer.visible(it > 0)
}
}
}

@ -0,0 +1,40 @@
package io.legado.app.ui.book.audio
import android.view.View
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Card
import androidx.compose.material.Slider
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import io.legado.app.model.AudioPlay
import io.legado.app.service.AudioPlayService
@Composable
fun TimerDialog(state: MutableState<Boolean>, parent: View) {
val intOffset = IntArray(2)
parent.getLocationInWindow(intOffset)
if (state.value) {
val timeMinute = remember {
mutableStateOf(AudioPlayService.timeMinute)
}
Dialog(onDismissRequest = { state.value = false }) {
Card(Modifier.fillMaxWidth()) {
Slider(
modifier = Modifier.padding(horizontal = 16.dp),
value = timeMinute.value.toFloat(), onValueChange = {
timeMinute.value = it.toInt()
AudioPlay.setTimer(it.toInt())
},
valueRange = 0f..180f
)
}
}
}
}

@ -58,10 +58,10 @@ class ImportBookViewModel(application: Application) : BaseViewModel(application)
}.map { docList ->
when (sort) {
2 -> docList.sortedWith(
compareBy({ !it.isDir }, { it.lastModified }, { it.name })
compareBy({ !it.isDir }, { -it.lastModified }, { it.name })
)
1 -> docList.sortedWith(
compareBy({ !it.isDir }, { it.size }, { it.name })
compareBy({ !it.isDir }, { -it.size }, { it.name })
)
else -> docList.sortedWith(
compareBy({ !it.isDir }, { it.name })

@ -168,20 +168,24 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
book: Book,
alertSync: ((progress: BookProgress) -> Unit)? = null
) {
if (AppConfig.syncBookProgress)
execute {
execute {
if (AppWebDav.syncBookProgress) {
AppWebDav.getBookProgress(book)
}.onSuccess {
it?.let { progress ->
if (progress.durChapterIndex < book.durChapterIndex ||
(progress.durChapterIndex == book.durChapterIndex && progress.durChapterPos < book.durChapterPos)
) {
alertSync?.invoke(progress)
} else {
ReadBook.setProgress(progress)
}
}
?: throw NoStackTraceException("没有进度")
} else {
throw NoStackTraceException("进度同步未启用")
}
}.onSuccess { progress ->
if (progress.durChapterIndex < book.durChapterIndex ||
(progress.durChapterIndex == book.durChapterIndex
&& progress.durChapterPos < book.durChapterPos)
) {
alertSync?.invoke(progress)
} else {
ReadBook.setProgress(progress)
}
}
}
/**

@ -184,7 +184,7 @@ class ReadAloudDialog : BaseDialogFragment(R.layout.dialog_read_aloud) {
override fun observeLiveBus() {
observeEvent<Int>(EventBus.ALOUD_STATE) { upPlayState() }
observeEvent<Int>(EventBus.TTS_DS) { binding.seekTimer.progress = it }
observeEvent<Int>(EventBus.READ_ALOUD_DS) { binding.seekTimer.progress = it }
}
interface CallBack {

@ -2,10 +2,10 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background"
android:orientation="vertical"
tools:context=".ui.book.audio.AudioPlayActivity">
<ImageView
@ -28,15 +28,30 @@
app:layout_constraintTop_toTopOf="parent"
app:themeMode="dark" />
<TextView
android:id="@+id/tv_timer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:background="@drawable/shape_fillet_btn_press"
android:paddingLeft="6dp"
android:paddingRight="6dp"
android:textColor="@color/md_white_1000"
android:visibility="invisible"
app:drawableLeftCompat="@drawable/ic_timer_black_24dp"
app:drawableTint="@color/md_white_1000"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/title_bar" />
<TextView
android:id="@+id/tv_speed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:background="@drawable/shape_fillet_btn_press"
android:paddingLeft="6dp"
android:paddingRight="6dp"
android:textColor="@color/md_white_1000"
android:paddingStart="3dp"
android:paddingEnd="3dp"
android:visibility="invisible"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/title_bar" />
@ -58,12 +73,12 @@
android:id="@+id/tv_sub_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:paddingTop="6dp"
android:paddingEnd="16dp"
android:paddingBottom="6dp"
android:textColor="@color/md_white_1000"
android:gravity="center"
app:layout_constraintBottom_toTopOf="@+id/ll_player_progress" />
<LinearLayout
@ -106,10 +121,10 @@
android:id="@+id/ll_play_menu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="24dp"
android:paddingRight="24dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingLeft="24dp"
android:paddingRight="24dp"
app:layout_constraintBottom_toBottomOf="parent">
<ImageView
@ -208,4 +223,10 @@
</LinearLayout>
<androidx.compose.ui.platform.ComposeView
android:id="@+id/compose_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -964,5 +964,6 @@
<string name="scroll_to_dur_source">定位到当前书源</string>
<string name="sys_tts_config">系统tts设置</string>
<string name="sys_tts_config_summary">打开系统tts设置界面</string>
<string name="cannot_timed_non_playback">非播放状态无法定时</string>
<!-- string end -->
</resources>

@ -967,5 +967,6 @@
<string name="scroll_to_dur_source">定位到当前书源</string>
<string name="sys_tts_config">系统tts设置</string>
<string name="sys_tts_config_summary">打开系统tts设置界面</string>
<string name="cannot_timed_non_playback">非播放状态无法定时</string>
<!-- string end -->
</resources>

@ -967,5 +967,6 @@
<string name="scroll_to_dur_source">定位到当前书源</string>
<string name="sys_tts_config">系统tts设置</string>
<string name="sys_tts_config_summary">打开系统tts设置界面</string>
<string name="cannot_timed_non_playback">非播放状态无法定时</string>
<!-- string end -->
</resources>

@ -964,5 +964,6 @@
<string name="scroll_to_dur_source">定位到当前书源</string>
<string name="sys_tts_config">系统tts设置</string>
<string name="sys_tts_config_summary">打开系统tts设置界面</string>
<string name="cannot_timed_non_playback">非播放状态无法定时</string>
<!-- string end -->
</resources>

@ -966,5 +966,6 @@
<string name="scroll_to_dur_source">定位到目前書源</string>
<string name="sys_tts_config">系统tts设置</string>
<string name="sys_tts_config_summary">打开系统tts设置界面</string>
<string name="cannot_timed_non_playback">非播放状态无法定时</string>
<!-- string end -->
</resources>

@ -966,5 +966,6 @@
<string name="scroll_to_dur_source">定位到当前书源</string>
<string name="sys_tts_config">系统tts设置</string>
<string name="sys_tts_config_summary">打开系统tts设置界面</string>
<string name="cannot_timed_non_playback">非播放状态无法定时</string>
<!-- string end -->
</resources>

@ -967,5 +967,6 @@
<string name="scroll_to_dur_source">定位到当前书源</string>
<string name="sys_tts_config">系统tts设置</string>
<string name="sys_tts_config_summary">打开系统tts设置界面</string>
<string name="cannot_timed_non_playback">非播放状态无法定时</string>
<!-- string end -->
</resources>

@ -23,4 +23,4 @@ kotlin.code.style=official
android.enableResourceOptimizations=true
#https://chromiumdash.appspot.com/releases?platform=Android
CronetVersion=99.0.4844.88
CronetVersion=100.0.4896.58

Loading…
Cancel
Save