Merge branch 'master' into master

pull/1592/head
Xwite 3 years ago committed by GitHub
commit 9faa327d99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      app/src/main/assets/updateLog.md
  2. 2
      app/src/main/java/io/legado/app/constant/PreferKey.kt
  3. 7
      app/src/main/java/io/legado/app/data/entities/BookChapter.kt
  4. 2
      app/src/main/java/io/legado/app/help/AppConfig.kt
  5. 12
      app/src/main/java/io/legado/app/help/storage/AppWebDav.kt
  6. 7
      app/src/main/java/io/legado/app/service/HttpReadAloudService.kt
  7. 24
      app/src/main/java/io/legado/app/service/TTSReadAloudService.kt
  8. 7
      app/src/main/java/io/legado/app/ui/config/BackupConfigFragment.kt
  9. 108
      app/src/main/java/io/legado/app/ui/widget/code/CodeView.kt
  10. 8
      app/src/main/java/io/legado/app/utils/ToastUtils.kt
  11. 3
      app/src/main/res/values-es-rES/strings.xml
  12. 3
      app/src/main/res/values-ja-rJP/strings.xml
  13. 3
      app/src/main/res/values-pt-rBR/strings.xml
  14. 3
      app/src/main/res/values-zh-rHK/strings.xml
  15. 3
      app/src/main/res/values-zh-rTW/strings.xml
  16. 3
      app/src/main/res/values-zh/strings.xml
  17. 3
      app/src/main/res/values/strings.xml
  18. 8
      app/src/main/res/xml/pref_config_backup.xml
  19. 2
      build.gradle

@ -16,6 +16,7 @@
* 校验失效分组具体到搜索发现目录正文
* txt文件初次解析目录不选择禁用的正则
* txt单章字数超102400均分txt,添加开关
* 修复tts被回收后无法继续朗读的bug,重新初始化tts
**2022/02/03**

@ -49,7 +49,7 @@ object PreferKey {
const val webDavUrl = "web_dav_url"
const val webDavAccount = "web_dav_account"
const val webDavPassword = "web_dav_password"
const val webDavCreateDir = "webDavCreateDir"
const val webDavDir = "webDavDir"
const val exportToWebDav = "webDavCacheBackup"
const val exportNoChapterName = "exportNoChapterName"
const val exportType = "exportType"

@ -80,7 +80,6 @@ data class BookChapter(
chineseConvert: Boolean = true,
): String {
var displayTitle = title.replace(AppPattern.rnRegex, "")
val mDisplayTitle = displayTitle
if (chineseConvert) {
when (AppConfig.chineseConverterType) {
1 -> displayTitle = ChineseUtils.t2s(displayTitle)
@ -91,18 +90,20 @@ data class BookChapter(
replaceRules.forEach { item ->
if (item.pattern.isNotEmpty()) {
try {
displayTitle = if (item.isRegex) {
val mDisplayTitle = if (item.isRegex) {
displayTitle.replace(item.pattern.toRegex(), item.replacement)
} else {
displayTitle.replace(item.pattern, item.replacement)
}
if (mDisplayTitle.isNotBlank()) {
displayTitle = mDisplayTitle
}
} catch (e: Exception) {
appCtx.toastOnUi("${item.name}替换出错")
}
}
}
}
if (displayTitle.isBlank()) displayTitle = mDisplayTitle
return when {
!isVip -> displayTitle
isPay -> appCtx.getString(R.string.payed_title, displayTitle)

@ -271,6 +271,8 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
val replaceEnableDefault get() = appCtx.getPrefBoolean(PreferKey.replaceEnableDefault, true)
val webDavDir get() = appCtx.getPrefString(PreferKey.webDavDir, "legado")
val recordLog get() = appCtx.getPrefBoolean(PreferKey.recordLog)
val doublePageHorizontal: Boolean

@ -29,13 +29,13 @@ object AppWebDav {
private val rootWebDavUrl: String
get() {
var url = appCtx.getPrefString(PreferKey.webDavUrl)?.trim()
if (url.isNullOrEmpty()) {
url = defaultWebDavUrl
}
val configUrl = appCtx.getPrefString(PreferKey.webDavUrl)?.trim()
var url = if (configUrl.isNullOrEmpty()) defaultWebDavUrl else configUrl
if (!url.endsWith("/")) url = "${url}/"
if (appCtx.getPrefBoolean(PreferKey.webDavCreateDir, true)) {
url = "${url}legado/"
AppConfig.webDavDir?.trim()?.let {
if (it.isNotEmpty()) {
url = "${url}${it}/"
}
}
return url
}

@ -68,9 +68,10 @@ class HttpReadAloudService : BaseReadAloudService(),
ReadBook.readAloud()
} else {
super.play()
ReadAloud.httpTTS?.let {
kotlin.runCatching {
val tts = ReadAloud.httpTTS ?: throw NoStackTraceException("httpTts is null")
val fileName =
md5SpeakFileName(it.url, AppConfig.ttsSpeechRate.toString(), contentList[nowSpeak])
md5SpeakFileName(tts.url, AppConfig.ttsSpeechRate.toString(), contentList[nowSpeak])
if (nowSpeak == 0) {
downloadAudio()
} else {
@ -81,6 +82,8 @@ class HttpReadAloudService : BaseReadAloudService(),
downloadAudio()
}
}
}.onFailure {
toastOnUi("朗读出错:${it.localizedMessage}")
}
}
}

@ -11,6 +11,7 @@ import io.legado.app.constant.EventBus
import io.legado.app.help.AppConfig
import io.legado.app.help.MediaHelp
import io.legado.app.lib.dialogs.SelectItem
import io.legado.app.model.NoStackTraceException
import io.legado.app.model.ReadBook
import io.legado.app.utils.*
import java.util.*
@ -73,16 +74,25 @@ class TTSReadAloudService : BaseReadAloudService(), TextToSpeech.OnInitListener
ReadBook.readAloud()
} else {
super.play()
execute {
kotlin.runCatching {
MediaHelp.playSilentSound(this@TTSReadAloudService)
}.onFinally {
textToSpeech?.let {
it.speak("", TextToSpeech.QUEUE_FLUSH, null, null)
for (i in nowSpeak until contentList.size) {
val text = contentList[i].replace(AppPattern.notReadAloudRegex, "")
it.speak(text, TextToSpeech.QUEUE_ADD, null, AppConst.APP_TAG + i)
val tts = textToSpeech ?: throw NoStackTraceException("tts is null")
var result = tts.speak("", TextToSpeech.QUEUE_FLUSH, null, null)
if (result == TextToSpeech.ERROR) {
clearTTS()
initTts()
return
}
for (i in nowSpeak until contentList.size) {
val text = contentList[i].replace(AppPattern.notReadAloudRegex, "")
result = tts.speak(text, TextToSpeech.QUEUE_ADD, null, AppConst.APP_TAG + i)
if (result == TextToSpeech.ERROR) {
AppLog.put("tts朗读出错:$text")
}
}
}.onFailure {
AppLog.put("tts朗读出错", it)
toastOnUi(it.localizedMessage)
}
}
}

@ -121,6 +121,7 @@ class BackupConfigFragment : BasePreferenceFragment(),
upPreferenceSummary(PreferKey.webDavUrl, getPrefString(PreferKey.webDavUrl))
upPreferenceSummary(PreferKey.webDavAccount, getPrefString(PreferKey.webDavAccount))
upPreferenceSummary(PreferKey.webDavPassword, getPrefString(PreferKey.webDavPassword))
upPreferenceSummary(PreferKey.webDavDir, AppConfig.webDavDir)
upPreferenceSummary(PreferKey.backupPath, getPrefString(PreferKey.backupPath))
findPreference<io.legado.app.ui.widget.prefs.Preference>("web_dav_restore")
?.onLongClick { restoreDir.launch(); true }
@ -168,6 +169,7 @@ class BackupConfigFragment : BasePreferenceFragment(),
PreferKey.backupPath -> {
upPreferenceSummary(key, getPrefString(key))
}
PreferKey.webDavDir -> upPreferenceSummary(key, AppConfig.webDavDir)
}
}
@ -192,6 +194,11 @@ class BackupConfigFragment : BasePreferenceFragment(),
} else {
preference.summary = "*".repeat(value.toString().length)
}
PreferKey.webDavDir -> if (value.isNullOrBlank()) {
preference.summary = "null"
} else {
preference.summary = value
}
else -> {
if (preference is ListPreference) {
val index = preference.findIndexOfValue(value)

@ -20,7 +20,9 @@ import java.util.regex.Pattern
import kotlin.math.roundToInt
@Suppress("unused")
class CodeView : AppCompatMultiAutoCompleteTextView {
class CodeView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
AppCompatMultiAutoCompleteTextView(context, attrs) {
private var tabWidth = 0
private var tabWidthInCharacters = 0
private var mUpdateDelayTime = 500
@ -35,23 +37,53 @@ class CodeView : AppCompatMultiAutoCompleteTextView {
private val mSyntaxPatternMap: MutableMap<Pattern, Int> = HashMap()
private var mIndentCharacterList = mutableListOf('{', '+', '-', '*', '/', '=')
constructor(context: Context?) : super(context!!) {
initEditorView()
private val mUpdateRunnable = Runnable {
val source = text
highlightWithoutChange(source)
}
constructor(context: Context?, attrs: AttributeSet?) : super(
context!!, attrs
) {
initEditorView()
}
private val mEditorTextWatcher: TextWatcher = object : TextWatcher {
private var start = 0
private var count = 0
override fun beforeTextChanged(
charSequence: CharSequence,
start: Int,
before: Int,
count: Int
) {
this.start = start
this.count = count
}
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
context!!, attrs, defStyleAttr
) {
initEditorView()
override fun onTextChanged(
charSequence: CharSequence,
start: Int,
before: Int,
count: Int
) {
if (!modified) return
if (highlightWhileTextChanging) {
if (mSyntaxPatternMap.isNotEmpty()) {
convertTabs(editableText, start, count)
mUpdateHandler.postDelayed(mUpdateRunnable, mUpdateDelayTime.toLong())
}
}
if (mRemoveErrorsWhenTextChanged) removeAllErrorLines()
}
override fun afterTextChanged(editable: Editable) {
if (!highlightWhileTextChanging) {
if (!modified) return
cancelHighlighterRender()
if (mSyntaxPatternMap.isNotEmpty()) {
convertTabs(editableText, start, count)
mUpdateHandler.postDelayed(mUpdateRunnable, mUpdateDelayTime.toLong())
}
}
}
}
private fun initEditorView() {
init {
if (mAutoCompleteTokenizer == null) {
mAutoCompleteTokenizer = KeywordTokenizer()
}
@ -169,7 +201,10 @@ class CodeView : AppCompatMultiAutoCompleteTextView {
}
private fun highlight(editable: Editable): Editable {
if (editable.isEmpty() || editable.length > 1024) return editable
// if (editable.isEmpty() || editable.length > 1024) return editable
if (editable.length !in 1..1024) {
return editable
}
try {
clearSpans(editable)
highlightErrorLines(editable)
@ -345,51 +380,6 @@ class CodeView : AppCompatMultiAutoCompleteTextView {
super.showDropDown()
}
private val mUpdateRunnable = Runnable {
val source = text
highlightWithoutChange(source)
}
private val mEditorTextWatcher: TextWatcher = object : TextWatcher {
private var start = 0
private var count = 0
override fun beforeTextChanged(
charSequence: CharSequence,
start: Int,
before: Int,
count: Int
) {
this.start = start
this.count = count
}
override fun onTextChanged(
charSequence: CharSequence,
start: Int,
before: Int,
count: Int
) {
if (!modified) return
if (highlightWhileTextChanging) {
if (mSyntaxPatternMap.isNotEmpty()) {
convertTabs(editableText, start, count)
mUpdateHandler.postDelayed(mUpdateRunnable, mUpdateDelayTime.toLong())
}
}
if (mRemoveErrorsWhenTextChanged) removeAllErrorLines()
}
override fun afterTextChanged(editable: Editable) {
if (!highlightWhileTextChanging) {
if (!modified) return
cancelHighlighterRender()
if (mSyntaxPatternMap.isNotEmpty()) {
convertTabs(editableText, start, count)
mUpdateHandler.postDelayed(mUpdateRunnable, mUpdateDelayTime.toLong())
}
}
}
}
private inner class TabWidthSpan : ReplacementSpan() {
override fun getSize(
paint: Paint,

@ -26,9 +26,9 @@ fun Context.toastOnUi(message: CharSequence?) {
runOnUI {
kotlin.runCatching {
if (toast == null) {
toast = Toast.makeText(this, message, Toast.LENGTH_SHORT)
toast = Toast.makeText(this, message.toString(), Toast.LENGTH_SHORT)
} else {
toast?.setText(message)
toast?.setText(message.toString())
toast?.duration = Toast.LENGTH_SHORT
}
toast?.show()
@ -54,9 +54,9 @@ fun Context.longToastOnUi(message: CharSequence?) {
runOnUI {
kotlin.runCatching {
if (toast == null) {
toast = Toast.makeText(this, message, Toast.LENGTH_LONG)
toast = Toast.makeText(this, message.toString(), Toast.LENGTH_LONG)
} else {
toast?.setText(message)
toast?.setText(message.toString())
toast?.duration = Toast.LENGTH_LONG
}
toast?.show()

@ -9,8 +9,6 @@
<string name="menu_backup">Inicio</string>
<string name="menu_restore">Restaurar</string>
<string name="menu_import_old">Importar datos de Legado</string>
<string name="mkdirs">Crear carpeta</string>
<string name="mkdirs_description">Crea una carpeta de respaldo bajo el nombre de Legado.</string>
<string name="webdav_cache_backup">Respaldo de caché de libros sin conexión</string>
<string name="webdav_cache_backup_s">Exporta localmente lo respalda para su exportación</string>
<string name="backup_path">Respaldar para</string>
@ -929,5 +927,6 @@
<string name="less_than">小于</string>
<string name="check_source_config_summary">校验超时: %1$s秒\n校验项目:%2$s</string>
<string name="record_debug_log">记录调试日志</string>
<string name="sub_dir">子文件夹</string>
<!-- string end -->
</resources>

@ -9,8 +9,6 @@
<string name="menu_backup">Home</string>
<string name="menu_restore">Restore</string>
<string name="menu_import_old">Import Legado data</string>
<string name="mkdirs">Create a subfolder</string>
<string name="mkdirs_description">Create a folder named Legado as the backup folder.</string>
<string name="webdav_cache_backup">Offline cache book backup</string>
<string name="webdav_cache_backup_s">Export to local and back up to the exports directory under the legado folder</string>
<string name="backup_path">Backup to</string>
@ -932,5 +930,6 @@
<string name="less_than">小于</string>
<string name="check_source_config_summary">校验超时: %1$s秒\n校验项目:%2$s</string>
<string name="record_debug_log">记录调试日志</string>
<string name="sub_dir">子文件夹</string>
<!-- string end -->
</resources>

@ -9,8 +9,6 @@
<string name="menu_backup">Início</string>
<string name="menu_restore">Restaurar</string>
<string name="menu_import_old">Importar dados ao Legado</string>
<string name="mkdirs">Criar uma subpasta</string>
<string name="mkdirs_description">Criar uma pasta de Backup com o nome Legado.</string>
<string name="webdav_cache_backup">Backup do cache dos livros para leitura off-line</string>
<string name="webdav_cache_backup_s">Exportar localmente e fazer Backup à pasta de exportação</string>
<string name="backup_path">Backup para</string>
@ -930,5 +928,6 @@
<string name="less_than">小于</string>
<string name="check_source_config_summary">校验超时: %1$s秒\n校验项目:%2$s</string>
<string name="record_debug_log">记录调试日志</string>
<string name="sub_dir">子文件夹</string>
<!-- string end -->
</resources>

@ -8,8 +8,6 @@
<string name="menu_backup">Home</string>
<string name="menu_restore">還原</string>
<string name="menu_import_old">導入閲讀數據</string>
<string name="mkdirs">創建子文件夾</string>
<string name="mkdirs_description">創建 legado 文件夾作爲備份路徑</string>
<string name="webdav_cache_backup">離線緩存書籍備份</string>
<string name="webdav_cache_backup_s">導出本地同時備份到legado文件夾下exports目錄</string>
<string name="backup_path">備份路徑</string>
@ -929,5 +927,6 @@
<string name="less_than">小于</string>
<string name="check_source_config_summary">校验超时: %1$s秒\n校验项目:%2$s</string>
<string name="record_debug_log">记录调试日志</string>
<string name="sub_dir">子文件夹</string>
<!-- string end -->
</resources>

@ -8,8 +8,6 @@
<string name="menu_backup">備份</string>
<string name="menu_restore">復原</string>
<string name="menu_import_old">匯入閱讀資料</string>
<string name="mkdirs">建立子資料夾</string>
<string name="mkdirs_description">建立legado資料夾作為備份資料夾</string>
<string name="webdav_cache_backup">離線快取書籍備份</string>
<string name="webdav_cache_backup_s">匯出本機同時備份到legado資料夾下exports目錄</string>
<string name="backup_path">備份路徑</string>
@ -931,5 +929,6 @@
<string name="less_than">小于</string>
<string name="check_source_config_summary">校验超时: %1$s秒\n校验项目:%2$s</string>
<string name="record_debug_log">记录调试日志</string>
<string name="sub_dir">子文件夹</string>
<!-- string end -->
</resources>

@ -8,8 +8,6 @@
<string name="menu_backup">Home</string>
<string name="menu_restore">恢复</string>
<string name="menu_import_old">导入阅读数据</string>
<string name="mkdirs">创建子文件夹</string>
<string name="mkdirs_description">创建legado文件夹作为备份文件夹</string>
<string name="webdav_cache_backup">离线缓存书籍备份</string>
<string name="webdav_cache_backup_s">导出本地同时备份到legado文件夹下exports目录</string>
<string name="backup_path">备份路径</string>
@ -931,5 +929,6 @@
<string name="less_than">小于</string>
<string name="check_source_config_summary">校验超时: %1$s秒\n校验项目:%2$s</string>
<string name="record_debug_log">记录调试日志</string>
<string name="sub_dir">子文件夹</string>
<!-- string end -->
</resources>

@ -9,8 +9,6 @@
<string name="menu_backup">Home</string>
<string name="menu_restore">Restore</string>
<string name="menu_import_old">Import Legado data</string>
<string name="mkdirs">Create a subfolder</string>
<string name="mkdirs_description">Create a folder named Legado as the backup folder.</string>
<string name="webdav_cache_backup">Offline cache book backup</string>
<string name="webdav_cache_backup_s">Export to local and back up to the exports directory under the legado folder</string>
<string name="backup_path">Backup to</string>
@ -932,5 +930,6 @@
<string name="less_than">小于</string>
<string name="check_source_config_summary">校验超时: %1$s秒\n校验项目:%2$s</string>
<string name="record_debug_log">记录调试日志</string>
<string name="sub_dir">Sub dir</string>
<!-- string end -->
</resources>

@ -27,11 +27,9 @@
android:summary="@string/web_dav_pw_s"
app:iconSpaceReserved="false" />
<io.legado.app.ui.widget.prefs.SwitchPreference
android:key="webDavCreateDir"
android:defaultValue="true"
android:title="@string/mkdirs"
android:summary="@string/mkdirs_description"
<io.legado.app.ui.widget.prefs.EditTextPreference
android:key="webDavDir"
android:title="@string/sub_dir"
app:allowDividerAbove="false"
app:allowDividerBelow="false"
app:iconSpaceReserved="false" />

@ -13,7 +13,7 @@ buildscript {
//maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.0'
classpath 'com.android.tools.build:gradle:7.1.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'de.timfreiheit.resourceplaceholders:placeholders:0.4'
classpath 'de.undercouch:gradle-download-task:4.1.2'

Loading…
Cancel
Save