Merge remote-tracking branch 'origin/master'
This commit is contained in:
Vendored
+2
-2
@@ -250,8 +250,8 @@
|
|||||||
## 对外提供api
|
## 对外提供api
|
||||||
-keep class io.legado.app.api.ReturnData{*;}
|
-keep class io.legado.app.api.ReturnData{*;}
|
||||||
|
|
||||||
# Apache Commons Compress
|
# 繁简转换
|
||||||
-keep class org.apache.commons.compress.archivers.** {*;}
|
-keep class com.github.liuyueyi.quick.transfer.** {*;}
|
||||||
|
|
||||||
|
|
||||||
#-------------------Cronet------------------------------------
|
#-------------------Cronet------------------------------------
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import android.content.Context
|
|||||||
import android.content.pm.ActivityInfo
|
import android.content.pm.ActivityInfo
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import com.github.liuyueyi.quick.transfer.ChineseUtils
|
|
||||||
import com.github.liuyueyi.quick.transfer.constants.TransType
|
import com.github.liuyueyi.quick.transfer.constants.TransType
|
||||||
import com.jeremyliao.liveeventbus.LiveEventBus
|
import com.jeremyliao.liveeventbus.LiveEventBus
|
||||||
import io.legado.app.base.AppContextWrapper
|
import io.legado.app.base.AppContextWrapper
|
||||||
@@ -31,6 +30,7 @@ import io.legado.app.help.http.okHttpClient
|
|||||||
import io.legado.app.help.source.SourceHelp
|
import io.legado.app.help.source.SourceHelp
|
||||||
import io.legado.app.help.storage.Backup
|
import io.legado.app.help.storage.Backup
|
||||||
import io.legado.app.model.BookCover
|
import io.legado.app.model.BookCover
|
||||||
|
import io.legado.app.utils.ChineseUtils
|
||||||
import io.legado.app.utils.defaultSharedPreferences
|
import io.legado.app.utils.defaultSharedPreferences
|
||||||
import io.legado.app.utils.getPrefBoolean
|
import io.legado.app.utils.getPrefBoolean
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -73,7 +73,10 @@ class App : Application() {
|
|||||||
Backup.clearCache()
|
Backup.clearCache()
|
||||||
//初始化简繁转换引擎
|
//初始化简繁转换引擎
|
||||||
when (AppConfig.chineseConverterType) {
|
when (AppConfig.chineseConverterType) {
|
||||||
1 -> ChineseUtils.preLoad(true, TransType.TRADITIONAL_TO_SIMPLE)
|
1 -> launch {
|
||||||
|
ChineseUtils.fixT2sDict()
|
||||||
|
}
|
||||||
|
|
||||||
2 -> ChineseUtils.preLoad(true, TransType.SIMPLE_TO_TRADITIONAL)
|
2 -> ChineseUtils.preLoad(true, TransType.SIMPLE_TO_TRADITIONAL)
|
||||||
}
|
}
|
||||||
//调整排序序号
|
//调整排序序号
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import androidx.room.Entity
|
|||||||
import androidx.room.ForeignKey
|
import androidx.room.ForeignKey
|
||||||
import androidx.room.Ignore
|
import androidx.room.Ignore
|
||||||
import androidx.room.Index
|
import androidx.room.Index
|
||||||
import com.github.liuyueyi.quick.transfer.ChineseUtils
|
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.constant.AppLog
|
import io.legado.app.constant.AppLog
|
||||||
import io.legado.app.constant.AppPattern
|
import io.legado.app.constant.AppPattern
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ import android.annotation.SuppressLint
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.os.Looper
|
||||||
import android.webkit.WebSettings
|
import android.webkit.WebSettings
|
||||||
import io.legado.app.constant.AppConst
|
import io.legado.app.constant.AppConst
|
||||||
|
import io.legado.app.constant.AppLog
|
||||||
import io.legado.app.exception.NoStackTraceException
|
import io.legado.app.exception.NoStackTraceException
|
||||||
import io.legado.app.help.config.AppConfig
|
import io.legado.app.help.config.AppConfig
|
||||||
import io.legado.app.help.config.LocalConfig
|
import io.legado.app.help.config.LocalConfig
|
||||||
@@ -37,9 +39,26 @@ class CrashHandler(val context: Context) : Thread.UncaughtExceptionHandler {
|
|||||||
* uncaughtException 回调函数
|
* uncaughtException 回调函数
|
||||||
*/
|
*/
|
||||||
override fun uncaughtException(thread: Thread, ex: Throwable) {
|
override fun uncaughtException(thread: Thread, ex: Throwable) {
|
||||||
ReadAloud.stop(context)
|
if (shouldAbsorb(ex)) {
|
||||||
handleException(ex)
|
AppLog.put("发生未捕获的异常\n${ex.localizedMessage}", ex)
|
||||||
mDefaultHandler?.uncaughtException(thread, ex)
|
Looper.loop()
|
||||||
|
} else {
|
||||||
|
ReadAloud.stop(context)
|
||||||
|
handleException(ex)
|
||||||
|
mDefaultHandler?.uncaughtException(thread, ex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun shouldAbsorb(e: Throwable): Boolean {
|
||||||
|
return when {
|
||||||
|
e::class.simpleName == "CannotDeliverBroadcastException" -> true
|
||||||
|
e is SecurityException && e.message?.contains(
|
||||||
|
"nor current process has android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS",
|
||||||
|
true
|
||||||
|
) == true -> true
|
||||||
|
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -107,7 +126,8 @@ class CrashHandler(val context: Context) : Thread.UncaughtExceptionHandler {
|
|||||||
val time = format.format(Date())
|
val time = format.format(Date())
|
||||||
val fileName = "crash-$time-$timestamp.log"
|
val fileName = "crash-$time-$timestamp.log"
|
||||||
try {
|
try {
|
||||||
val backupPath = AppConfig.backupPath ?: throw NoStackTraceException("备份路径未配置")
|
val backupPath = AppConfig.backupPath
|
||||||
|
?: throw NoStackTraceException("备份路径未配置")
|
||||||
val uri = Uri.parse(backupPath)
|
val uri = Uri.parse(backupPath)
|
||||||
val fileDoc = FileDoc.fromUri(uri, true)
|
val fileDoc = FileDoc.fromUri(uri, true)
|
||||||
fileDoc.createFileIfNotExist(fileName, "crash")
|
fileDoc.createFileIfNotExist(fileName, "crash")
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import android.webkit.WebSettings
|
|||||||
import androidx.annotation.Keep
|
import androidx.annotation.Keep
|
||||||
import cn.hutool.core.codec.Base64
|
import cn.hutool.core.codec.Base64
|
||||||
import cn.hutool.core.util.HexUtil
|
import cn.hutool.core.util.HexUtil
|
||||||
import com.github.liuyueyi.quick.transfer.ChineseUtils
|
import io.legado.app.utils.ChineseUtils
|
||||||
import io.legado.app.constant.AppConst
|
import io.legado.app.constant.AppConst
|
||||||
import io.legado.app.constant.AppConst.dateFormat
|
import io.legado.app.constant.AppConst.dateFormat
|
||||||
import io.legado.app.constant.AppLog
|
import io.legado.app.constant.AppLog
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package io.legado.app.help.book
|
package io.legado.app.help.book
|
||||||
|
|
||||||
import com.github.liuyueyi.quick.transfer.ChineseUtils
|
|
||||||
import io.legado.app.constant.AppLog
|
import io.legado.app.constant.AppLog
|
||||||
import io.legado.app.constant.AppPattern.spaceRegex
|
import io.legado.app.constant.AppPattern.spaceRegex
|
||||||
import io.legado.app.data.appDb
|
import io.legado.app.data.appDb
|
||||||
@@ -10,6 +9,7 @@ import io.legado.app.data.entities.ReplaceRule
|
|||||||
import io.legado.app.exception.RegexTimeoutException
|
import io.legado.app.exception.RegexTimeoutException
|
||||||
import io.legado.app.help.config.AppConfig
|
import io.legado.app.help.config.AppConfig
|
||||||
import io.legado.app.help.config.ReadBookConfig
|
import io.legado.app.help.config.ReadBookConfig
|
||||||
|
import io.legado.app.utils.ChineseUtils
|
||||||
import io.legado.app.utils.escapeRegex
|
import io.legado.app.utils.escapeRegex
|
||||||
import io.legado.app.utils.replace
|
import io.legado.app.utils.replace
|
||||||
import io.legado.app.utils.stackTraceStr
|
import io.legado.app.utils.stackTraceStr
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import io.legado.app.utils.activityPendingIntent
|
|||||||
import io.legado.app.utils.cnCompare
|
import io.legado.app.utils.cnCompare
|
||||||
import io.legado.app.utils.createFolderIfNotExist
|
import io.legado.app.utils.createFolderIfNotExist
|
||||||
import io.legado.app.utils.isContentScheme
|
import io.legado.app.utils.isContentScheme
|
||||||
|
import io.legado.app.utils.outputStream
|
||||||
import io.legado.app.utils.postEvent
|
import io.legado.app.utils.postEvent
|
||||||
import io.legado.app.utils.readBytes
|
import io.legado.app.utils.readBytes
|
||||||
import io.legado.app.utils.readText
|
import io.legado.app.utils.readText
|
||||||
@@ -140,7 +141,7 @@ class ExportBookService : BaseService() {
|
|||||||
startForeground(NotificationId.ExportBookService, notification.build())
|
startForeground(NotificationId.ExportBookService, notification.build())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun upExportNotification() {
|
private fun upExportNotification(finish: Boolean = false) {
|
||||||
val notification = NotificationCompat.Builder(this, AppConst.channelIdDownload)
|
val notification = NotificationCompat.Builder(this, AppConst.channelIdDownload)
|
||||||
.setSmallIcon(R.drawable.ic_export)
|
.setSmallIcon(R.drawable.ic_export)
|
||||||
.setSubText(getString(R.string.export_book))
|
.setSubText(getString(R.string.export_book))
|
||||||
@@ -149,7 +150,7 @@ class ExportBookService : BaseService() {
|
|||||||
.setContentText(notificationContentText)
|
.setContentText(notificationContentText)
|
||||||
.setDeleteIntent(servicePendingIntent<ExportBookService>(IntentAction.stop))
|
.setDeleteIntent(servicePendingIntent<ExportBookService>(IntentAction.stop))
|
||||||
.setGroup(groupKey)
|
.setGroup(groupKey)
|
||||||
if (exportJob?.isActive == true) {
|
if (!finish) {
|
||||||
notification.setOngoing(true)
|
notification.setOngoing(true)
|
||||||
notification.addAction(
|
notification.addAction(
|
||||||
R.drawable.ic_stop_black_24dp,
|
R.drawable.ic_stop_black_24dp,
|
||||||
@@ -168,7 +169,7 @@ class ExportBookService : BaseService() {
|
|||||||
while (true) {
|
while (true) {
|
||||||
val (bookUrl, exportConfig) = waitExportBooks.entries.firstOrNull() ?: let {
|
val (bookUrl, exportConfig) = waitExportBooks.entries.firstOrNull() ?: let {
|
||||||
notificationContentText = "导出完成"
|
notificationContentText = "导出完成"
|
||||||
upExportNotification()
|
upExportNotification(true)
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
exportProgress[bookUrl] = 0
|
exportProgress[bookUrl] = 0
|
||||||
@@ -230,21 +231,24 @@ class ExportBookService : BaseService() {
|
|||||||
DocumentUtils.delete(doc, filename)
|
DocumentUtils.delete(doc, filename)
|
||||||
val bookDoc = DocumentUtils.createFileIfNotExist(doc, filename)
|
val bookDoc = DocumentUtils.createFileIfNotExist(doc, filename)
|
||||||
?: throw NoStackTraceException("创建文档失败,请尝试重新设置导出文件夹")
|
?: throw NoStackTraceException("创建文档失败,请尝试重新设置导出文件夹")
|
||||||
|
val charset = Charset.forName(AppConfig.exportCharset)
|
||||||
contentResolver.openOutputStream(bookDoc.uri, "wa")?.use { bookOs ->
|
contentResolver.openOutputStream(bookDoc.uri, "wa")?.use { bookOs ->
|
||||||
getAllContents(book) { text, srcList ->
|
BufferedOutputStream(bookOs, 64 * 1024).use { bos ->
|
||||||
bookOs.write(text.toByteArray(Charset.forName(AppConfig.exportCharset)))
|
getAllContents(book) { text, srcList ->
|
||||||
srcList?.forEach {
|
bos.write(text.toByteArray(charset))
|
||||||
val vFile = BookHelp.getImage(book, it.src)
|
srcList?.forEach {
|
||||||
if (vFile.exists()) {
|
val vFile = BookHelp.getImage(book, it.src)
|
||||||
DocumentUtils.createFileIfNotExist(
|
if (vFile.exists()) {
|
||||||
doc,
|
DocumentUtils.createFileIfNotExist(
|
||||||
"${it.index}-${MD5Utils.md5Encode16(it.src)}.jpg",
|
doc,
|
||||||
subDirs = arrayOf(
|
"${it.index}-${MD5Utils.md5Encode16(it.src)}.jpg",
|
||||||
"${book.name}_${book.author}",
|
subDirs = arrayOf(
|
||||||
"images",
|
"${book.name}_${book.author}",
|
||||||
it.chapterTitle
|
"images",
|
||||||
)
|
it.chapterTitle
|
||||||
)?.writeBytes(this, vFile.readBytes())
|
)
|
||||||
|
)?.writeBytes(this, vFile.readBytes())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -259,18 +263,22 @@ class ExportBookService : BaseService() {
|
|||||||
val filename = book.getExportFileName("txt")
|
val filename = book.getExportFileName("txt")
|
||||||
val bookPath = FileUtils.getPath(file, filename)
|
val bookPath = FileUtils.getPath(file, filename)
|
||||||
val bookFile = FileUtils.createFileWithReplace(bookPath)
|
val bookFile = FileUtils.createFileWithReplace(bookPath)
|
||||||
getAllContents(book) { text, srcList ->
|
val charset = Charset.forName(AppConfig.exportCharset)
|
||||||
bookFile.appendText(text, Charset.forName(AppConfig.exportCharset))
|
val bos = BufferedOutputStream(bookFile.outputStream(true), 64 * 1024)
|
||||||
srcList?.forEach {
|
bos.use {
|
||||||
val vFile = BookHelp.getImage(book, it.src)
|
getAllContents(book) { text, srcList ->
|
||||||
if (vFile.exists()) {
|
bos.write(text.toByteArray(charset))
|
||||||
FileUtils.createFileIfNotExist(
|
srcList?.forEach {
|
||||||
file,
|
val vFile = BookHelp.getImage(book, it.src)
|
||||||
"${book.name}_${book.author}",
|
if (vFile.exists()) {
|
||||||
"images",
|
FileUtils.createFileIfNotExist(
|
||||||
it.chapterTitle,
|
file,
|
||||||
"${it.index}-${MD5Utils.md5Encode16(it.src)}.jpg"
|
"${book.name}_${book.author}",
|
||||||
).writeBytes(vFile.readBytes())
|
"images",
|
||||||
|
it.chapterTitle,
|
||||||
|
"${it.index}-${MD5Utils.md5Encode16(it.src)}.jpg"
|
||||||
|
).writeBytes(vFile.readBytes())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -249,10 +249,11 @@ class BgTextConfigDialog : BaseDialogFragment(R.layout.dialog_read_bg_text) {
|
|||||||
val fontPath = ReadBookConfig.textFont
|
val fontPath = ReadBookConfig.textFont
|
||||||
if (fontPath.isNotEmpty()) {
|
if (fontPath.isNotEmpty()) {
|
||||||
val fontName = FileUtils.getName(fontPath)
|
val fontName = FileUtils.getName(fontPath)
|
||||||
val fontBytes = fontPath.parseToUri().readBytes(requireContext())
|
val fontInputStream =
|
||||||
fontBytes.let {
|
fontPath.parseToUri().inputStream(requireContext()).getOrNull()
|
||||||
|
fontInputStream?.use {
|
||||||
val fontExportFile = FileUtils.createFileIfNotExist(configDir, fontName)
|
val fontExportFile = FileUtils.createFileIfNotExist(configDir, fontName)
|
||||||
fontExportFile.writeBytes(it)
|
it.copyTo(fontExportFile.outputStream())
|
||||||
exportFiles.add(fontExportFile)
|
exportFiles.add(fontExportFile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -261,8 +262,10 @@ class BgTextConfigDialog : BaseDialogFragment(R.layout.dialog_read_bg_text) {
|
|||||||
val bgFile = File(ReadBookConfig.durConfig.bgStr)
|
val bgFile = File(ReadBookConfig.durConfig.bgStr)
|
||||||
if (bgFile.exists()) {
|
if (bgFile.exists()) {
|
||||||
val bgExportFile = File(FileUtils.getPath(configDir, bgName))
|
val bgExportFile = File(FileUtils.getPath(configDir, bgName))
|
||||||
bgFile.copyTo(bgExportFile)
|
if (!bgExportFile.exists()) {
|
||||||
exportFiles.add(bgExportFile)
|
bgFile.copyTo(bgExportFile)
|
||||||
|
exportFiles.add(bgExportFile)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ReadBookConfig.durConfig.bgTypeNight == 2) {
|
if (ReadBookConfig.durConfig.bgTypeNight == 2) {
|
||||||
@@ -270,8 +273,10 @@ class BgTextConfigDialog : BaseDialogFragment(R.layout.dialog_read_bg_text) {
|
|||||||
val bgFile = File(ReadBookConfig.durConfig.bgStrNight)
|
val bgFile = File(ReadBookConfig.durConfig.bgStrNight)
|
||||||
if (bgFile.exists()) {
|
if (bgFile.exists()) {
|
||||||
val bgExportFile = File(FileUtils.getPath(configDir, bgName))
|
val bgExportFile = File(FileUtils.getPath(configDir, bgName))
|
||||||
bgFile.copyTo(bgExportFile)
|
if (!bgExportFile.exists()) {
|
||||||
exportFiles.add(bgExportFile)
|
bgFile.copyTo(bgExportFile)
|
||||||
|
exportFiles.add(bgExportFile)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ReadBookConfig.durConfig.bgTypeEInk == 2) {
|
if (ReadBookConfig.durConfig.bgTypeEInk == 2) {
|
||||||
@@ -279,8 +284,10 @@ class BgTextConfigDialog : BaseDialogFragment(R.layout.dialog_read_bg_text) {
|
|||||||
val bgFile = File(ReadBookConfig.durConfig.bgStrEInk)
|
val bgFile = File(ReadBookConfig.durConfig.bgStrEInk)
|
||||||
if (bgFile.exists()) {
|
if (bgFile.exists()) {
|
||||||
val bgExportFile = File(FileUtils.getPath(configDir, bgName))
|
val bgExportFile = File(FileUtils.getPath(configDir, bgName))
|
||||||
bgFile.copyTo(bgExportFile)
|
if (!bgExportFile.exists()) {
|
||||||
exportFiles.add(bgExportFile)
|
bgFile.copyTo(bgExportFile)
|
||||||
|
exportFiles.add(bgExportFile)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val configZipPath = FileUtils.getPath(requireContext().externalCache, configFileName)
|
val configZipPath = FileUtils.getPath(requireContext().externalCache, configFileName)
|
||||||
@@ -288,14 +295,17 @@ class BgTextConfigDialog : BaseDialogFragment(R.layout.dialog_read_bg_text) {
|
|||||||
if (uri.isContentScheme()) {
|
if (uri.isContentScheme()) {
|
||||||
DocumentFile.fromTreeUri(requireContext(), uri)?.let { treeDoc ->
|
DocumentFile.fromTreeUri(requireContext(), uri)?.let { treeDoc ->
|
||||||
treeDoc.findFile(exportFileName)?.delete()
|
treeDoc.findFile(exportFileName)?.delete()
|
||||||
treeDoc.createFile("", exportFileName)
|
val out = treeDoc.createFile("", exportFileName)?.openOutputStream()
|
||||||
?.writeBytes(requireContext(), File(configZipPath).readBytes())
|
out?.use {
|
||||||
|
File(configZipPath).inputStream().use {
|
||||||
|
it.copyTo(out)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val exportPath = FileUtils.getPath(File(uri.path!!), exportFileName)
|
val exportPath = FileUtils.getPath(File(uri.path!!), exportFileName)
|
||||||
FileUtils.delete(exportPath)
|
FileUtils.delete(exportPath)
|
||||||
FileUtils.createFileIfNotExist(exportPath)
|
File(configZipPath).copyTo(FileUtils.createFileIfNotExist(exportPath))
|
||||||
.writeBytes(File(configZipPath).readBytes())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.onSuccess {
|
}.onSuccess {
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import androidx.core.view.get
|
import androidx.core.view.get
|
||||||
import com.github.liuyueyi.quick.transfer.ChineseUtils
|
|
||||||
import com.github.liuyueyi.quick.transfer.constants.TransType
|
import com.github.liuyueyi.quick.transfer.constants.TransType
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.base.BaseDialogFragment
|
import io.legado.app.base.BaseDialogFragment
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package io.legado.app.ui.book.searchContent
|
|||||||
|
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import com.github.liuyueyi.quick.transfer.ChineseUtils
|
|
||||||
import io.legado.app.base.BaseViewModel
|
import io.legado.app.base.BaseViewModel
|
||||||
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
|
||||||
@@ -10,13 +9,14 @@ import io.legado.app.data.entities.BookChapter
|
|||||||
import io.legado.app.help.book.BookHelp
|
import io.legado.app.help.book.BookHelp
|
||||||
import io.legado.app.help.book.ContentProcessor
|
import io.legado.app.help.book.ContentProcessor
|
||||||
import io.legado.app.help.config.AppConfig
|
import io.legado.app.help.config.AppConfig
|
||||||
|
import io.legado.app.utils.ChineseUtils
|
||||||
import kotlinx.coroutines.ensureActive
|
import kotlinx.coroutines.ensureActive
|
||||||
import kotlin.coroutines.coroutineContext
|
import kotlin.coroutines.coroutineContext
|
||||||
|
|
||||||
class SearchContentViewModel(application: Application) : BaseViewModel(application) {
|
class SearchContentViewModel(application: Application) : BaseViewModel(application) {
|
||||||
var bookUrl: String = ""
|
var bookUrl: String = ""
|
||||||
var book: Book? = null
|
var book: Book? = null
|
||||||
var contentProcessor: ContentProcessor? = null
|
private var contentProcessor: ContentProcessor? = null
|
||||||
var lastQuery: String = ""
|
var lastQuery: String = ""
|
||||||
var searchResultCounts = 0
|
var searchResultCounts = 0
|
||||||
val cacheChapterNames = hashSetOf<String>()
|
val cacheChapterNames = hashSetOf<String>()
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ class WebViewActivity : VMBaseActivity<ActivityWebViewBinding, WebViewModel>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
binding.root.longSnackbar("跳转其它应用", "确认") {
|
binding.root.longSnackbar(R.string.jump_to_another_app, R.string.confirm) {
|
||||||
openUrl(url)
|
openUrl(url)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package io.legado.app.utils
|
||||||
|
|
||||||
|
import com.github.liuyueyi.quick.transfer.ChineseUtils
|
||||||
|
import com.github.liuyueyi.quick.transfer.constants.TransType
|
||||||
|
import com.github.liuyueyi.quick.transfer.dictionary.DictionaryContainer
|
||||||
|
|
||||||
|
object ChineseUtils {
|
||||||
|
|
||||||
|
private var fixed = false
|
||||||
|
|
||||||
|
fun s2t(content: String): String {
|
||||||
|
return ChineseUtils.s2t(content)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun t2s(content: String): String {
|
||||||
|
if (!fixed) {
|
||||||
|
fixed = true
|
||||||
|
fixT2sDict()
|
||||||
|
}
|
||||||
|
return ChineseUtils.t2s(content)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun preLoad(async: Boolean, vararg transType: TransType) {
|
||||||
|
ChineseUtils.preLoad(async, *transType)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unLoad(vararg transType: TransType) {
|
||||||
|
ChineseUtils.unLoad(*transType)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fixT2sDict() {
|
||||||
|
val dict = DictionaryContainer.getInstance().getDictionary(TransType.TRADITIONAL_TO_SIMPLE)
|
||||||
|
dict.chars.run {
|
||||||
|
remove('劈')
|
||||||
|
remove('脊')
|
||||||
|
}
|
||||||
|
kotlin.runCatching {
|
||||||
|
dict.dict.run {
|
||||||
|
remove("支援")
|
||||||
|
remove("路易斯")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -212,7 +212,7 @@ fun FileDoc.createFileIfNotExist(
|
|||||||
vararg subDirs: String
|
vararg subDirs: String
|
||||||
): FileDoc {
|
): FileDoc {
|
||||||
return if (uri.isContentScheme()) {
|
return if (uri.isContentScheme()) {
|
||||||
val documentFile = DocumentFile.fromTreeUri(appCtx, uri)!!
|
val documentFile = asDocumentFile()!!
|
||||||
val tmp = DocumentUtils.createFileIfNotExist(documentFile, fileName, *subDirs)!!
|
val tmp = DocumentUtils.createFileIfNotExist(documentFile, fileName, *subDirs)!!
|
||||||
FileDoc.fromDocumentFile(tmp)
|
FileDoc.fromDocumentFile(tmp)
|
||||||
} else {
|
} else {
|
||||||
@@ -226,7 +226,7 @@ fun FileDoc.createFolderIfNotExist(
|
|||||||
vararg subDirs: String
|
vararg subDirs: String
|
||||||
): FileDoc {
|
): FileDoc {
|
||||||
return if (uri.isContentScheme()) {
|
return if (uri.isContentScheme()) {
|
||||||
val documentFile = DocumentFile.fromTreeUri(appCtx, uri)!!
|
val documentFile = asDocumentFile()!!
|
||||||
val tmp = DocumentUtils.createFolderIfNotExist(documentFile, *subDirs)!!
|
val tmp = DocumentUtils.createFolderIfNotExist(documentFile, *subDirs)!!
|
||||||
FileDoc.fromDocumentFile(tmp)
|
FileDoc.fromDocumentFile(tmp)
|
||||||
} else {
|
} else {
|
||||||
@@ -257,7 +257,7 @@ fun FileDoc.exists(
|
|||||||
vararg subDirs: String
|
vararg subDirs: String
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return if (uri.isContentScheme()) {
|
return if (uri.isContentScheme()) {
|
||||||
DocumentUtils.exists(DocumentFile.fromTreeUri(appCtx, uri)!!, fileName, *subDirs)
|
DocumentUtils.exists(asDocumentFile()!!, fileName, *subDirs)
|
||||||
} else {
|
} else {
|
||||||
val path = FileUtils.getPath(uri.path!!, *subDirs) + File.separator + fileName
|
val path = FileUtils.getPath(uri.path!!, *subDirs) + File.separator + fileName
|
||||||
FileUtils.exist(path)
|
FileUtils.exist(path)
|
||||||
@@ -266,7 +266,7 @@ fun FileDoc.exists(
|
|||||||
|
|
||||||
fun FileDoc.exists(): Boolean {
|
fun FileDoc.exists(): Boolean {
|
||||||
return if (uri.isContentScheme()) {
|
return if (uri.isContentScheme()) {
|
||||||
DocumentFile.fromTreeUri(appCtx, uri)!!.exists()
|
asDocumentFile()!!.exists()
|
||||||
} else {
|
} else {
|
||||||
FileUtils.exist(uri.path!!)
|
FileUtils.exist(uri.path!!)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package io.legado.app.utils
|
|||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
|
||||||
fun File.getFile(vararg subDirFiles: String): File {
|
fun File.getFile(vararg subDirFiles: String): File {
|
||||||
val path = FileUtils.getPath(this, *subDirFiles)
|
val path = FileUtils.getPath(this, *subDirFiles)
|
||||||
@@ -79,3 +80,7 @@ fun File.checkWrite(): Boolean {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun File.outputStream(append: Boolean = false): FileOutputStream {
|
||||||
|
return FileOutputStream(this, append)
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package io.legado.app.utils
|
||||||
|
|
||||||
|
import com.github.liuyueyi.quick.transfer.Trie
|
||||||
|
import com.github.liuyueyi.quick.transfer.TrieNode
|
||||||
|
import java.util.HashMap
|
||||||
|
|
||||||
|
fun <T> Trie<T>.getRoot(): TrieNode<T> {
|
||||||
|
val rootField = javaClass.getDeclaredField("root")
|
||||||
|
.apply { isAccessible = true }
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return rootField.get(this) as TrieNode<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> TrieNode<T>.getChildren(): HashMap<Char, TrieNode<T>> {
|
||||||
|
val childrenField = javaClass.getDeclaredField("children")
|
||||||
|
.apply { isAccessible = true }
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return childrenField.get(this) as HashMap<Char, TrieNode<T>>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> Trie<T>.remove(value: String) {
|
||||||
|
var node = getRoot()
|
||||||
|
val nodes = arrayListOf<TrieNode<T>>()
|
||||||
|
val chars = value.toCharArray()
|
||||||
|
for (c in chars) {
|
||||||
|
nodes.add(node)
|
||||||
|
node = node.getChildren()[c] ?: break
|
||||||
|
if (!node.isLeaf) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for ((ch, n) in chars.reversed().zip(nodes.reversed())) {
|
||||||
|
val children = n.getChildren()
|
||||||
|
children.remove(ch)
|
||||||
|
if (children.isNotEmpty()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user