Compare commits

...

12 Commits

Author SHA1 Message Date
Horis
5685d442ff
Merge pull request #3898 from adhu2018/master
重构、修复和其他优化
2024-04-29 13:33:31 +08:00
Horis
94fb7564f1 优化 2024-04-28 16:41:45 +08:00
Horis
11eb304fae 优化 2024-04-28 16:39:48 +08:00
Horis
33e9286a8e 优化 2024-04-28 12:56:35 +08:00
Horis
e57ad3a09e 优化 2024-04-28 12:14:13 +08:00
adhu2018
29a6b49d67
refactor: 显示帮助信息相关 2024-04-28 01:04:51 +08:00
adhu2018
025dbcc3d4
refactor: 显示帮助信息相关 2024-04-28 01:04:40 +08:00
adhu2018
10d2764c61
other 2024-04-28 01:03:26 +08:00
adhu2018
5b86fb8dd8
fix: 综合排序 2024-04-28 01:01:58 +08:00
adhu2018
59d4bb6c8e
pref: 减少遍历次数 2024-04-28 01:01:18 +08:00
adhu2018
85575111da
other 2024-04-28 00:58:23 +08:00
Horis
f83a2bc357 优化 2024-04-27 22:28:44 +08:00
26 changed files with 160 additions and 131 deletions

View File

@ -11,7 +11,6 @@ import io.legado.app.constant.PageAnim
import io.legado.app.constant.PreferKey
import io.legado.app.help.DefaultData
import io.legado.app.help.coroutine.Coroutine
import io.legado.app.ui.book.read.page.provider.ChapterProvider
import io.legado.app.utils.BitmapUtils
import io.legado.app.utils.FileUtils
import io.legado.app.utils.GSON

View File

@ -133,7 +133,7 @@ public class QueryTTF {
}
private static class GlyfLayout {
public short numberOfContours; // 非负值为简单字型,负值为合字型
public short numberOfContours; // 非负值为简单字型,负值为合字型
public short xMin;
public short yMin;
public short xMax;

View File

@ -7,6 +7,7 @@ import android.net.wifi.WifiManager
import android.os.Build
import android.os.PowerManager
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import io.legado.app.R
import io.legado.app.base.BaseService
import io.legado.app.constant.AppConst
@ -15,7 +16,16 @@ import io.legado.app.constant.IntentAction
import io.legado.app.constant.NotificationId
import io.legado.app.constant.PreferKey
import io.legado.app.receiver.NetworkChangedListener
import io.legado.app.utils.*
import io.legado.app.utils.NetworkUtils
import io.legado.app.utils.getPrefBoolean
import io.legado.app.utils.getPrefInt
import io.legado.app.utils.postEvent
import io.legado.app.utils.printOnDebug
import io.legado.app.utils.sendToClip
import io.legado.app.utils.servicePendingIntent
import io.legado.app.utils.startService
import io.legado.app.utils.stopService
import io.legado.app.utils.toastOnUi
import io.legado.app.web.HttpServer
import io.legado.app.web.WebSocketServer
import splitties.init.appCtx
@ -33,6 +43,11 @@ class WebService : BaseService() {
context.startService<WebService>()
}
fun startForeground(context: Context) {
val intent = Intent(context, WebService::class.java)
ContextCompat.startForegroundService(context, intent)
}
fun stop(context: Context) {
context.stopService<WebService>()
}

View File

@ -1,10 +1,14 @@
package io.legado.app.service
import android.app.Dialog
import android.app.ForegroundServiceStartNotAllowedException
import android.content.Intent
import android.os.Build
import android.service.quicksettings.Tile
import android.service.quicksettings.TileService
import android.view.WindowManager.BadTokenException
import androidx.annotation.RequiresApi
import io.legado.app.R
import io.legado.app.constant.IntentAction
import io.legado.app.utils.printOnDebug
@ -22,6 +26,7 @@ class WebTileService : TileService() {
state = Tile.STATE_ACTIVE
updateTile()
}
IntentAction.stop -> qsTile?.run {
state = Tile.STATE_INACTIVE
updateTile()
@ -49,7 +54,24 @@ class WebTileService : TileService() {
if (WebService.isRun) {
WebService.stop(this)
} else {
WebService.start(this)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
val dialog = Dialog(this, R.style.AppTheme_Transparent)
dialog.setOnShowListener {
try {
WebService.startForeground(this)
} catch (e: ForegroundServiceStartNotAllowedException) {
e.printStackTrace()
}
dialog.dismiss()
}
try {
showDialog(dialog)
} catch (e: BadTokenException) {
e.printStackTrace()
}
} else {
WebService.start(this)
}
}
}

View File

@ -93,7 +93,6 @@ import io.legado.app.ui.replace.ReplaceRuleActivity
import io.legado.app.ui.replace.edit.ReplaceEditActivity
import io.legado.app.ui.widget.PopupAction
import io.legado.app.ui.widget.dialog.PhotoDialog
import io.legado.app.ui.widget.dialog.TextDialog
import io.legado.app.utils.ACache
import io.legado.app.utils.Debounce
import io.legado.app.utils.LogUtils
@ -114,6 +113,7 @@ import io.legado.app.utils.observeEvent
import io.legado.app.utils.observeEventSticky
import io.legado.app.utils.postEvent
import io.legado.app.utils.showDialogFragment
import io.legado.app.utils.showHelp
import io.legado.app.utils.startActivity
import io.legado.app.utils.sysScreenOffTime
import io.legado.app.utils.throttle
@ -553,7 +553,7 @@ class ReadBookActivity : BaseReadBookActivity(),
R.id.menu_effective_replaces -> showDialogFragment<EffectiveReplacesDialog>()
R.id.menu_help -> showReadMenuHelp()
R.id.menu_help -> showHelp()
}
return super.onCompatOptionsItemSelected(item)
}
@ -1022,11 +1022,6 @@ class ReadBookActivity : BaseReadBookActivity(),
}
}
override fun showReadMenuHelp() {
val text = String(assets.open("web/help/md/readMenuHelp.md").readBytes())
showDialogFragment(TextDialog(getString(R.string.help), text, TextDialog.Mode.MD))
}
/**
* 显示朗读菜单
*/
@ -1255,6 +1250,10 @@ class ReadBookActivity : BaseReadBookActivity(),
}
}
override fun showHelp() {
showHelp("readMenuHelp")
}
/**
* 长按图片
*/

View File

@ -150,7 +150,7 @@ class ReadMenu @JvmOverloads constructor(
}
callBack.upSystemUiVisibility()
if (!LocalConfig.readMenuHelpVersionIsLast) {
callBack.showReadMenuHelp()
callBack.showHelp()
}
}
@ -580,7 +580,7 @@ class ReadMenu @JvmOverloads constructor(
fun showReadAloudDialog()
fun upSystemUiVisibility()
fun onClickReadAloud()
fun showReadMenuHelp()
fun showHelp()
fun showLogin()
fun payAction()
fun disableSource()

View File

@ -17,8 +17,14 @@ import io.legado.app.ui.login.SourceLoginActivity
import io.legado.app.ui.widget.code.addJsPattern
import io.legado.app.ui.widget.code.addJsonPattern
import io.legado.app.ui.widget.code.addLegadoPattern
import io.legado.app.ui.widget.dialog.TextDialog
import io.legado.app.utils.*
import io.legado.app.utils.GSON
import io.legado.app.utils.applyTint
import io.legado.app.utils.sendToClip
import io.legado.app.utils.setLayout
import io.legado.app.utils.showDialogFragment
import io.legado.app.utils.showHelp
import io.legado.app.utils.startActivity
import io.legado.app.utils.toastOnUi
import io.legado.app.utils.viewbindingdelegate.viewBinding
class HttpTtsEditDialog() : BaseDialogFragment(R.layout.dialog_http_tts_edit, true),
@ -111,7 +117,7 @@ class HttpTtsEditDialog() : BaseDialogFragment(R.layout.dialog_http_tts_edit, tr
initView(it)
}
R.id.menu_log -> showDialogFragment<AppLogDialog>()
R.id.menu_help -> help()
R.id.menu_help -> showHelp("httpTTSHelp")
}
return true
}
@ -130,11 +136,4 @@ class HttpTtsEditDialog() : BaseDialogFragment(R.layout.dialog_http_tts_edit, tr
)
}
private fun help() {
val helpStr = String(
requireContext().assets.open("web/help/md/httpTTSHelp.md").readBytes()
)
showDialogFragment(TextDialog(getString(R.string.help), helpStr, TextDialog.Mode.MD))
}
}

View File

@ -1,18 +1,15 @@
package io.legado.app.ui.book.read.page
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Picture
import android.graphics.Rect
import android.os.Build
import android.os.SystemClock
import androidx.core.graphics.withClip
import io.legado.app.help.config.AppConfig
import io.legado.app.help.config.ReadBookConfig
import io.legado.app.lib.theme.ThemeStore
import io.legado.app.ui.book.read.page.entities.PageDirection
import io.legado.app.utils.screenshot
import io.legado.app.utils.canvasrecorder.CanvasRecorderFactory
import io.legado.app.utils.canvasrecorder.recordIfNeeded
/**
* 自动翻页
@ -24,13 +21,10 @@ class AutoPager(private val readView: ReadView) {
private var scrollOffsetRemain = 0.0
private var scrollOffset = 0
private var lastTimeMillis = 0L
private var bitmap: Bitmap? = null
private var picture: Picture? = null
private var pictureIsDirty = true
private val atLeastApi23 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
private val rect = Rect()
private var canvasRecorder = CanvasRecorderFactory.create()
private val paint by lazy { Paint() }
fun start() {
isRunning = true
paint.color = ThemeStore.accentColor
@ -48,7 +42,7 @@ class AutoPager(private val readView: ReadView) {
readView.curPage.upSelectAble(AppConfig.textSelectAble)
readView.invalidate()
reset()
picture = null
canvasRecorder.recycle()
}
fun pause() {
@ -71,9 +65,12 @@ class AutoPager(private val readView: ReadView) {
progress = 0
scrollOffsetRemain = 0.0
scrollOffset = 0
bitmap?.recycle()
bitmap = null
pictureIsDirty = true
canvasRecorder.invalidate()
}
fun upRecorder() {
canvasRecorder.recycle()
canvasRecorder = CanvasRecorderFactory.create()
}
fun onDraw(canvas: Canvas) {
@ -86,24 +83,12 @@ class AutoPager(private val readView: ReadView) {
} else {
val bottom = progress
val width = readView.width
if (atLeastApi23) {
if (picture == null) {
picture = Picture()
}
if (pictureIsDirty) {
pictureIsDirty = false
readView.nextPage.screenshot(picture!!)
}
canvas.withClip(0, 0, width, bottom) {
drawPicture(picture!!)
}
} else {
if (bitmap == null) {
bitmap = readView.nextPage.screenshot()
}
rect.set(0, 0, width, bottom)
canvas.drawBitmap(bitmap!!, rect, rect, null)
canvasRecorder.recordIfNeeded(readView.nextPage)
canvas.withClip(0, 0, width, bottom) {
canvasRecorder.draw(this)
}
canvas.drawRect(
0f,
bottom.toFloat() - 1,

View File

@ -514,6 +514,7 @@ class ReadView(context: Context, attrs: AttributeSet) :
(pageDelegate as? ScrollPageDelegate)?.noAnim = AppConfig.noAnimScrollPage
if (upRecorder) {
(pageDelegate as? HorizontalPageDelegate)?.upRecorder()
autoPager.upRecorder()
}
pageDelegate?.setViewSize(width, height)
if (isScroll) {

View File

@ -20,6 +20,7 @@ import io.legado.app.ui.widget.dialog.TextDialog
import io.legado.app.utils.launch
import io.legado.app.utils.setEdgeEffectColor
import io.legado.app.utils.showDialogFragment
import io.legado.app.utils.showHelp
import io.legado.app.utils.toastOnUi
import io.legado.app.utils.viewbindingdelegate.viewBinding
import kotlinx.coroutines.launch
@ -184,14 +185,9 @@ class BookSourceDebugActivity : VMBaseActivity<ActivitySourceDebugBinding, BookS
R.id.menu_book_src -> showDialogFragment(TextDialog("html", viewModel.bookSrc))
R.id.menu_toc_src -> showDialogFragment(TextDialog("html", viewModel.tocSrc))
R.id.menu_content_src -> showDialogFragment(TextDialog("html", viewModel.contentSrc))
R.id.menu_help -> showHelp()
R.id.menu_help -> showHelp("debugHelp")
}
return super.onCompatOptionsItemSelected(item)
}
private fun showHelp() {
val text = String(assets.open("web/help/md/debugHelp.md").readBytes())
showDialogFragment(TextDialog(getString(R.string.help), text, TextDialog.Mode.MD))
}
}

View File

@ -43,7 +43,6 @@ import io.legado.app.ui.config.CheckSourceConfig
import io.legado.app.ui.file.HandleFileContract
import io.legado.app.ui.qrcode.QrCodeResult
import io.legado.app.ui.widget.SelectActionBar
import io.legado.app.ui.widget.dialog.TextDialog
import io.legado.app.ui.widget.recycler.DragSelectTouchHelper
import io.legado.app.ui.widget.recycler.ItemTouchCallback
import io.legado.app.ui.widget.recycler.VerticalDivider
@ -59,6 +58,7 @@ import io.legado.app.utils.sendToClip
import io.legado.app.utils.setEdgeEffectColor
import io.legado.app.utils.share
import io.legado.app.utils.showDialogFragment
import io.legado.app.utils.showHelp
import io.legado.app.utils.splitNotBlank
import io.legado.app.utils.startActivity
import io.legado.app.utils.toastOnUi
@ -134,7 +134,7 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
initSelectActionBar()
resumeCheckSource()
if (!LocalConfig.bookSourcesHelpVersionIsLast) {
showHelp()
showHelp("SourceMBookHelp")
}
}
@ -248,7 +248,7 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
searchView.setQuery(getString(R.string.disabled_explore), true)
}
R.id.menu_help -> showHelp()
R.id.menu_help -> showHelp("SourceMBookHelp")
}
if (item.groupId == R.id.source_group) {
searchView.setQuery("group:${item.title}", true)
@ -370,11 +370,6 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
}
}
private fun showHelp() {
val text = String(assets.open("web/help/md/SourceMBookHelp.md").readBytes())
showDialogFragment(TextDialog(getString(R.string.help), text, TextDialog.Mode.MD))
}
private fun initLiveDataGroup() {
lifecycleScope.launch {
appDb.bookSourceDao.flowGroups().conflate().collect {

View File

@ -22,7 +22,6 @@ import io.legado.app.ui.association.ImportTxtTocRuleDialog
import io.legado.app.ui.file.HandleFileContract
import io.legado.app.ui.qrcode.QrCodeResult
import io.legado.app.ui.widget.SelectActionBar
import io.legado.app.ui.widget.dialog.TextDialog
import io.legado.app.ui.widget.recycler.DragSelectTouchHelper
import io.legado.app.ui.widget.recycler.ItemTouchCallback
import io.legado.app.ui.widget.recycler.VerticalDivider
@ -34,6 +33,7 @@ import io.legado.app.utils.readText
import io.legado.app.utils.sendToClip
import io.legado.app.utils.setEdgeEffectColor
import io.legado.app.utils.showDialogFragment
import io.legado.app.utils.showHelp
import io.legado.app.utils.splitNotBlank
import io.legado.app.utils.toastOnUi
import io.legado.app.utils.viewbindingdelegate.viewBinding
@ -140,7 +140,7 @@ class TxtTocRuleActivity : VMBaseActivity<ActivityTxtTocRuleBinding, TxtTocRuleV
R.id.menu_import_onLine -> showImportDialog()
R.id.menu_import_qr -> qrCodeResult.launch()
R.id.menu_import_default -> viewModel.importDefault()
R.id.menu_help -> showTxtTocRuleHelp()
R.id.menu_help -> showHelp("txtTocRuleHelp")
}
return super.onCompatOptionsItemSelected(item)
@ -244,11 +244,6 @@ class TxtTocRuleActivity : VMBaseActivity<ActivityTxtTocRuleBinding, TxtTocRuleV
}
}
private fun showTxtTocRuleHelp() {
val text = String(assets.open("web/help/md/txtTocRuleHelp.md").readBytes())
showDialogFragment(TextDialog(getString(R.string.help), text, TextDialog.Mode.MD))
}
override fun onMenuItemClick(item: MenuItem): Boolean {
when (item.itemId) {
R.id.menu_enable_selection -> viewModel.enableSelection(*adapter.selection.toTypedArray())

View File

@ -88,7 +88,7 @@ class TxtTocRuleAdapter(context: Context, private val callBack: CallBack) :
bundle.keySet().map {
when (it) {
"selected" -> cbSource.isChecked = selected.contains(item)
"upNmae" -> cbSource.text = item.name
"upName" -> cbSource.text = item.name
"upExample" -> titleExample.text = item.example
"enabled" -> swtEnabled.isChecked = item.enable
}

View File

@ -29,7 +29,6 @@ import io.legado.app.lib.theme.primaryColor
import io.legado.app.ui.association.ImportTxtTocRuleDialog
import io.legado.app.ui.file.HandleFileContract
import io.legado.app.ui.qrcode.QrCodeResult
import io.legado.app.ui.widget.dialog.TextDialog
import io.legado.app.ui.widget.recycler.ItemTouchCallback
import io.legado.app.ui.widget.recycler.VerticalDivider
import io.legado.app.utils.ACache
@ -38,6 +37,7 @@ import io.legado.app.utils.launch
import io.legado.app.utils.readText
import io.legado.app.utils.setLayout
import io.legado.app.utils.showDialogFragment
import io.legado.app.utils.showHelp
import io.legado.app.utils.splitNotBlank
import io.legado.app.utils.toastOnUi
import io.legado.app.utils.viewbindingdelegate.viewBinding
@ -152,7 +152,7 @@ class TxtTocRuleDialog() : BaseDialogFragment(R.layout.dialog_toc_regex),
R.id.menu_import_onLine -> showImportDialog()
R.id.menu_import_qr -> qrCodeResult.launch()
R.id.menu_import_default -> viewModel.importDefault()
R.id.menu_help -> showTxtTocRuleHelp()
R.id.menu_help -> showHelp("txtTocRuleHelp")
}
return false
}
@ -197,11 +197,6 @@ class TxtTocRuleDialog() : BaseDialogFragment(R.layout.dialog_toc_regex),
}
}
private fun showTxtTocRuleHelp() {
val text = String(requireContext().assets.open("web/help/md/txtTocRuleHelp.md").readBytes())
showDialogFragment(TextDialog(getString(R.string.help), text, TextDialog.Mode.MD))
}
inner class TocRegexAdapter(context: Context) :
RecyclerAdapter<TxtTocRule, ItemTocRegexBinding>(context),
ItemTouchCallback.Callback {
@ -264,7 +259,7 @@ class TxtTocRuleDialog() : BaseDialogFragment(R.layout.dialog_toc_regex),
} else {
bundle.keySet().map {
when (it) {
"upNmae" -> rbRegexName.text = item.name
"upName" -> rbRegexName.text = item.name
"upExample" -> titleExample.text = item.example
"enabled" -> swtEnabled.isChecked = item.enable
"upSelect" -> rbRegexName.isChecked = item.name == selectedName

View File

@ -35,9 +35,17 @@ import io.legado.app.lib.prefs.fragment.PreferenceFragment
import io.legado.app.lib.theme.primaryColor
import io.legado.app.ui.about.AppLogDialog
import io.legado.app.ui.file.HandleFileContract
import io.legado.app.ui.widget.dialog.TextDialog
import io.legado.app.ui.widget.dialog.WaitDialog
import io.legado.app.utils.*
import io.legado.app.utils.applyTint
import io.legado.app.utils.checkWrite
import io.legado.app.utils.getPrefString
import io.legado.app.utils.isContentScheme
import io.legado.app.utils.launch
import io.legado.app.utils.setEdgeEffectColor
import io.legado.app.utils.showDialogFragment
import io.legado.app.utils.showHelp
import io.legado.app.utils.toEditable
import io.legado.app.utils.toastOnUi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.Job
@ -150,7 +158,7 @@ class BackupConfigFragment : PreferenceFragment(),
listView.setEdgeEffectColor(primaryColor)
activity?.addMenuProvider(this, viewLifecycleOwner)
if (!LocalConfig.backupHelpVersionIsLast) {
showHelp()
showHelp("webDavHelp")
}
}
@ -162,7 +170,7 @@ class BackupConfigFragment : PreferenceFragment(),
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
when (menuItem.itemId) {
R.id.menu_help -> {
showHelp()
showHelp("webDavHelp")
return true
}
@ -171,11 +179,6 @@ class BackupConfigFragment : PreferenceFragment(),
return false
}
private fun showHelp() {
val text = String(requireContext().assets.open("web/help/md/webDavHelp.md").readBytes())
showDialogFragment(TextDialog(getString(R.string.help), text, TextDialog.Mode.MD))
}
override fun onDestroy() {
super.onDestroy()
preferenceManager.sharedPreferences?.unregisterOnSharedPreferenceChangeListener(this)

View File

@ -23,7 +23,6 @@ import io.legado.app.ui.association.ImportDictRuleDialog
import io.legado.app.ui.file.HandleFileContract
import io.legado.app.ui.qrcode.QrCodeResult
import io.legado.app.ui.widget.SelectActionBar
import io.legado.app.ui.widget.dialog.TextDialog
import io.legado.app.ui.widget.recycler.DragSelectTouchHelper
import io.legado.app.ui.widget.recycler.ItemTouchCallback
import io.legado.app.ui.widget.recycler.VerticalDivider
@ -35,6 +34,7 @@ import io.legado.app.utils.readText
import io.legado.app.utils.sendToClip
import io.legado.app.utils.setEdgeEffectColor
import io.legado.app.utils.showDialogFragment
import io.legado.app.utils.showHelp
import io.legado.app.utils.splitNotBlank
import io.legado.app.utils.toastOnUi
import io.legado.app.utils.viewbindingdelegate.viewBinding
@ -143,7 +143,7 @@ class DictRuleActivity : VMBaseActivity<ActivityDictRuleBinding, DictRuleViewMod
R.id.menu_import_onLine -> showImportDialog()
R.id.menu_import_qr -> qrCodeResult.launch()
R.id.menu_import_default -> viewModel.importDefault()
R.id.menu_help -> showDictRuleHelp()
R.id.menu_help -> showHelp("dictRuleHelp")
}
return super.onCompatOptionsItemSelected(item)
}
@ -235,9 +235,4 @@ class DictRuleActivity : VMBaseActivity<ActivityDictRuleBinding, DictRuleViewMod
cancelButton()
}
}
private fun showDictRuleHelp() {
val text = String(assets.open("web/help/md/dictRuleHelp.md").readBytes())
showDialogFragment(TextDialog(getString(R.string.help), text, TextDialog.Mode.MD))
}
}

View File

@ -6,7 +6,6 @@ import android.view.View
import androidx.core.view.isGone
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.GridLayoutManager
@ -29,6 +28,7 @@ import io.legado.app.ui.book.info.BookInfoActivity
import io.legado.app.ui.book.read.ReadBookActivity
import io.legado.app.ui.main.MainViewModel
import io.legado.app.utils.cnCompare
import io.legado.app.utils.flowWithLifecycleFirst
import io.legado.app.utils.observeEvent
import io.legado.app.utils.setEdgeEffectColor
import io.legado.app.utils.startActivity
@ -175,7 +175,7 @@ class BooksFragment() : BaseFragment(R.layout.fragment_books),
else -> list.sortedByDescending { it.durChapterTime }
}
}.flowWithLifecycle(viewLifecycleOwner.lifecycle, Lifecycle.State.RESUMED).catch {
}.flowWithLifecycleFirst(viewLifecycleOwner.lifecycle, Lifecycle.State.RESUMED).catch {
AppLog.put("书架更新出错", it)
}.conflate().flowOn(Dispatchers.Default).collect { list ->
binding.tvEmptyMsg.isGone = list.isNotEmpty()

View File

@ -148,6 +148,11 @@ class BookshelfFragment2() : BaseBookshelfFragment(R.layout.fragment_bookshelf2)
3 -> list.sortedBy {
it.order
}
4 -> list.sortedByDescending {
max(it.latestChapterTime, it.durChapterTime)
}
else -> list.sortedByDescending {
it.durChapterTime
}

View File

@ -29,7 +29,6 @@ import io.legado.app.ui.dict.rule.DictRuleActivity
import io.legado.app.ui.file.FileManageActivity
import io.legado.app.ui.main.MainFragmentInterface
import io.legado.app.ui.replace.ReplaceRuleActivity
import io.legado.app.ui.widget.dialog.TextDialog
import io.legado.app.utils.LogUtils
import io.legado.app.utils.getPrefBoolean
import io.legado.app.utils.observeEventSticky
@ -37,7 +36,7 @@ import io.legado.app.utils.openUrl
import io.legado.app.utils.putPrefBoolean
import io.legado.app.utils.sendToClip
import io.legado.app.utils.setEdgeEffectColor
import io.legado.app.utils.showDialogFragment
import io.legado.app.utils.showHelp
import io.legado.app.utils.startActivity
import io.legado.app.utils.viewbindingdelegate.viewBinding
@ -68,10 +67,7 @@ class MyFragment() : BaseFragment(R.layout.fragment_my_config), MainFragmentInte
override fun onCompatOptionsItemSelected(item: MenuItem) {
when (item.itemId) {
R.id.menu_help -> {
val text = String(requireContext().assets.open("web/help/md/appHelp.md").readBytes())
showDialogFragment(TextDialog(getString(R.string.help), text, TextDialog.Mode.MD))
}
R.id.menu_help -> showHelp("appHelp")
}
}

View File

@ -33,7 +33,6 @@ import io.legado.app.ui.file.HandleFileContract
import io.legado.app.ui.qrcode.QrCodeResult
import io.legado.app.ui.replace.edit.ReplaceEditActivity
import io.legado.app.ui.widget.SelectActionBar
import io.legado.app.ui.widget.dialog.TextDialog
import io.legado.app.ui.widget.recycler.DragSelectTouchHelper
import io.legado.app.ui.widget.recycler.ItemTouchCallback
import io.legado.app.ui.widget.recycler.VerticalDivider
@ -47,6 +46,7 @@ import io.legado.app.utils.readText
import io.legado.app.utils.sendToClip
import io.legado.app.utils.setEdgeEffectColor
import io.legado.app.utils.showDialogFragment
import io.legado.app.utils.showHelp
import io.legado.app.utils.splitNotBlank
import io.legado.app.utils.toastOnUi
import io.legado.app.utils.viewbindingdelegate.viewBinding
@ -255,7 +255,7 @@ class ReplaceRuleActivity : VMBaseActivity<ActivityReplaceRuleBinding, ReplaceRu
allowExtensions = arrayOf("txt", "json")
}
R.id.menu_import_qr -> qrCodeResult.launch()
R.id.menu_help -> showHelp()
R.id.menu_help -> showHelp("replaceRuleHelp")
R.id.menu_group_null -> {
searchView.setQuery(getString(R.string.no_group), true)
}
@ -324,11 +324,6 @@ class ReplaceRuleActivity : VMBaseActivity<ActivityReplaceRuleBinding, ReplaceRu
}
}
private fun showHelp() {
val text = String(assets.open("web/help/md/replaceRuleHelp.md").readBytes())
showDialogFragment(TextDialog(getString(R.string.help), text, TextDialog.Mode.MD))
}
override fun onQueryTextChange(newText: String?): Boolean {
observeReplaceRuleData(newText)
return false

View File

@ -28,7 +28,6 @@ import io.legado.app.ui.file.HandleFileContract
import io.legado.app.ui.qrcode.QrCodeResult
import io.legado.app.ui.rss.source.edit.RssSourceEditActivity
import io.legado.app.ui.widget.SelectActionBar
import io.legado.app.ui.widget.dialog.TextDialog
import io.legado.app.ui.widget.recycler.DragSelectTouchHelper
import io.legado.app.ui.widget.recycler.ItemTouchCallback
import io.legado.app.ui.widget.recycler.VerticalDivider
@ -44,6 +43,7 @@ import io.legado.app.utils.sendToClip
import io.legado.app.utils.setEdgeEffectColor
import io.legado.app.utils.share
import io.legado.app.utils.showDialogFragment
import io.legado.app.utils.showHelp
import io.legado.app.utils.splitNotBlank
import io.legado.app.utils.startActivity
import io.legado.app.utils.toastOnUi
@ -163,7 +163,7 @@ class RssSourceActivity : VMBaseActivity<ActivityRssSourceBinding, RssSourceView
R.id.menu_group_null -> {
searchView.setQuery(getString(R.string.no_group), true)
}
R.id.menu_help -> showHelp()
R.id.menu_help -> showHelp("SourceMRssHelp")
else -> if (item.groupId == R.id.source_group) {
searchView.setQuery("group:${item.title}", true)
}
@ -354,11 +354,6 @@ class RssSourceActivity : VMBaseActivity<ActivityRssSourceBinding, RssSourceView
}
}
private fun showHelp() {
val text = String(assets.open("web/help/md/SourceMRssHelp.md").readBytes())
showDialogFragment(TextDialog(getString(R.string.help), text, TextDialog.Mode.MD))
}
override fun upCountView() {
binding.selectActionBar.upCountView(
adapter.selection.size,

View File

@ -203,8 +203,10 @@ val Activity.navigationBarGravity: Int
return gravity ?: Gravity.BOTTOM
}
/**
* 显示目录help下的帮助文档
*/
fun AppCompatActivity.showHelp(fileName: String) {
//显示目录help下的帮助文档
val mdText = String(assets.open("web/help/md/${fileName}.md").readBytes())
showDialogFragment(TextDialog(getString(R.string.help), mdText, TextDialog.Mode.MD))
}

View File

@ -32,14 +32,16 @@ object ChineseUtils {
fun fixT2sDict() {
val dict = DictionaryContainer.getInstance().getDictionary(TransType.TRADITIONAL_TO_SIMPLE)
dict.run {
remove("", "", "")
remove("支援", "沈默", "類比", "模擬", "划槳", "列根", "先進", "雪梨", "雪糕")
remove("零錢", "零钱", "離線", "碟片", "模組", "桌球", "案頭", "機車", "電漿")
remove("鳳梨", "魔戒", "載入")
remove("路易斯", "非同步", "出租车", "周杰倫", "马铃薯", "馬鈴薯", "機械人", "電單車")
remove("電扶梯", "音效卡", "飆車族", "點陣圖", "個入球", "顆進球")
remove("魔獸紀元", "高空彈跳", "铁达尼号")
remove("魔鬼終結者", "純文字檔案")
remove(
"", "", "",
"支援", "沈默", "類比", "模擬", "划槳", "列根", "先進", "雪梨", "雪糕",
"零錢", "零钱", "離線", "碟片", "模組", "桌球", "案頭", "機車", "電漿",
"鳳梨", "魔戒", "載入",
"路易斯", "非同步", "出租车", "周杰倫", "马铃薯", "馬鈴薯", "機械人", "電單車",
"電扶梯", "音效卡", "飆車族", "點陣圖", "個入球", "顆進球",
"魔獸紀元", "高空彈跳", "铁达尼号",
"魔鬼終結者", "純文字檔案"
)
}
}

View File

@ -1,13 +1,17 @@
package io.legado.app.utils
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.async
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.buffer
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.channelFlow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flatMapMerge
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
@ -185,3 +189,18 @@ inline fun <T> Flow<T>.onEachAsyncIndexed(
}.onEach { semaphore.release() }
}.buffer(0)
}
fun <T> Flow<T>.flowWithLifecycleFirst(
lifecycle: Lifecycle,
minActiveState: Lifecycle.State = Lifecycle.State.STARTED
): Flow<T> = callbackFlow {
if (!lifecycle.currentState.isAtLeast(minActiveState)) {
send(first())
}
lifecycle.repeatOnLifecycle(minActiveState) {
this@flowWithLifecycleFirst.collect {
send(it)
}
}
close()
}

View File

@ -12,6 +12,8 @@ import androidx.annotation.DrawableRes
import androidx.core.content.edit
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import io.legado.app.R
import io.legado.app.ui.widget.dialog.TextDialog
inline fun <reified T : DialogFragment> Fragment.showDialogFragment(
arguments: Bundle.() -> Unit = {}
@ -76,4 +78,9 @@ inline fun <reified T : Activity> Fragment.startActivity(
configIntent: Intent.() -> Unit = {}
) {
startActivity(Intent(requireContext(), T::class.java).apply(configIntent))
}
fun Fragment.showHelp(fileName: String) {
val mdText = String(requireContext().assets.open("web/help/md/${fileName}.md").readBytes())
showDialogFragment(TextDialog(getString(R.string.help), mdText, TextDialog.Mode.MD))
}

View File

@ -1,6 +1,7 @@
package io.legado.app.utils.canvasrecorder
import android.graphics.Canvas
import android.view.View
import androidx.core.graphics.withSave
inline fun CanvasRecorder.recordIfNeeded(
@ -13,6 +14,14 @@ inline fun CanvasRecorder.recordIfNeeded(
return true
}
fun CanvasRecorder.recordIfNeeded(view: View): Boolean {
if (!needRecord()) return false
record(view.width, view.height) {
view.draw(this)
}
return true
}
inline fun CanvasRecorder.record(width: Int, height: Int, block: Canvas.() -> Unit) {
try {
val canvas = beginRecording(width, height)