Merge pull request #1506 from lalala-12138/feature/text-select-menu-filter
Feature/text select menu filter
This commit is contained in:
@@ -132,6 +132,8 @@ object PreferKey {
|
|||||||
const val brightness = "brightness"
|
const val brightness = "brightness"
|
||||||
const val nightBrightness = "nightBrightness"
|
const val nightBrightness = "nightBrightness"
|
||||||
const val expandTextMenu = "expandTextMenu"
|
const val expandTextMenu = "expandTextMenu"
|
||||||
|
const val showSelectMenuIcon = "showSelectMenuIcon"
|
||||||
|
const val textSelectMenuFilter = "textSelectMenuFilter"
|
||||||
const val doublePageHorizontal = "doubleHorizontalPage"
|
const val doublePageHorizontal = "doubleHorizontalPage"
|
||||||
const val readUrlOpenInBrowser = "readUrlInBrowser"
|
const val readUrlOpenInBrowser = "readUrlInBrowser"
|
||||||
const val defaultBookTreeUri = "defaultBookTreeUri"
|
const val defaultBookTreeUri = "defaultBookTreeUri"
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ data class ReadPreferences(
|
|||||||
val optimizeRender: Boolean = false,
|
val optimizeRender: Boolean = false,
|
||||||
val disableReturnKey: Boolean = false,
|
val disableReturnKey: Boolean = false,
|
||||||
val expandTextMenu: Boolean = false,
|
val expandTextMenu: Boolean = false,
|
||||||
|
val showSelectMenuIcon: Boolean = true,
|
||||||
|
val textSelectMenuFilter: String = "",
|
||||||
val showReadTitleAddition: Boolean = true,
|
val showReadTitleAddition: Boolean = true,
|
||||||
val autoReadSpeed: Int = 10,
|
val autoReadSpeed: Int = 10,
|
||||||
val prevKeys: String = "",
|
val prevKeys: String = "",
|
||||||
@@ -230,6 +232,12 @@ class ReadSettingsRepository(
|
|||||||
suspend fun setExpandTextMenu(value: Boolean) =
|
suspend fun setExpandTextMenu(value: Boolean) =
|
||||||
settingsRepository.putBoolean(PreferKey.expandTextMenu, value)
|
settingsRepository.putBoolean(PreferKey.expandTextMenu, value)
|
||||||
|
|
||||||
|
suspend fun setShowSelectMenuIcon(value: Boolean) =
|
||||||
|
settingsRepository.putBoolean(PreferKey.showSelectMenuIcon, value)
|
||||||
|
|
||||||
|
suspend fun setTextSelectMenuFilter(value: String) =
|
||||||
|
settingsRepository.putString(PreferKey.textSelectMenuFilter, value)
|
||||||
|
|
||||||
suspend fun setShowReadTitleAddition(value: Boolean) =
|
suspend fun setShowReadTitleAddition(value: Boolean) =
|
||||||
settingsRepository.putBoolean(PreferKey.showReadTitleAddition, value)
|
settingsRepository.putBoolean(PreferKey.showReadTitleAddition, value)
|
||||||
|
|
||||||
@@ -420,6 +428,8 @@ class ReadSettingsRepository(
|
|||||||
optimizeRender = this[Keys.OptimizeRender] ?: false,
|
optimizeRender = this[Keys.OptimizeRender] ?: false,
|
||||||
disableReturnKey = this[Keys.DisableReturnKey] ?: false,
|
disableReturnKey = this[Keys.DisableReturnKey] ?: false,
|
||||||
expandTextMenu = this[Keys.ExpandTextMenu] ?: false,
|
expandTextMenu = this[Keys.ExpandTextMenu] ?: false,
|
||||||
|
showSelectMenuIcon = this[Keys.ShowSelectMenuIcon] ?: true,
|
||||||
|
textSelectMenuFilter = this[Keys.TextSelectMenuFilter] ?: "",
|
||||||
showReadTitleAddition = this[Keys.ShowReadTitleAddition] ?: true,
|
showReadTitleAddition = this[Keys.ShowReadTitleAddition] ?: true,
|
||||||
autoReadSpeed = this[Keys.AutoReadSpeed] ?: 10,
|
autoReadSpeed = this[Keys.AutoReadSpeed] ?: 10,
|
||||||
prevKeys = this[Keys.PrevKeys] ?: "",
|
prevKeys = this[Keys.PrevKeys] ?: "",
|
||||||
@@ -518,6 +528,8 @@ class ReadSettingsRepository(
|
|||||||
val OptimizeRender = booleanPreferencesKey(PreferKey.optimizeRender)
|
val OptimizeRender = booleanPreferencesKey(PreferKey.optimizeRender)
|
||||||
val DisableReturnKey = booleanPreferencesKey(PreferKey.disableReturnKey)
|
val DisableReturnKey = booleanPreferencesKey(PreferKey.disableReturnKey)
|
||||||
val ExpandTextMenu = booleanPreferencesKey(PreferKey.expandTextMenu)
|
val ExpandTextMenu = booleanPreferencesKey(PreferKey.expandTextMenu)
|
||||||
|
val ShowSelectMenuIcon = booleanPreferencesKey(PreferKey.showSelectMenuIcon)
|
||||||
|
val TextSelectMenuFilter = stringPreferencesKey(PreferKey.textSelectMenuFilter)
|
||||||
val ShowReadTitleAddition = booleanPreferencesKey(PreferKey.showReadTitleAddition)
|
val ShowReadTitleAddition = booleanPreferencesKey(PreferKey.showReadTitleAddition)
|
||||||
val AutoReadSpeed = intPreferencesKey(PreferKey.autoReadSpeed)
|
val AutoReadSpeed = intPreferencesKey(PreferKey.autoReadSpeed)
|
||||||
val PrevKeys = stringPreferencesKey(PreferKey.prevKeys)
|
val PrevKeys = stringPreferencesKey(PreferKey.prevKeys)
|
||||||
|
|||||||
@@ -684,6 +684,7 @@ sealed interface ReadBookSheet {
|
|||||||
data object AudioCacheCleanConfig : ReadBookSheet
|
data object AudioCacheCleanConfig : ReadBookSheet
|
||||||
data object ClickActionConfig : ReadBookSheet
|
data object ClickActionConfig : ReadBookSheet
|
||||||
data object PageKeyConfig : ReadBookSheet
|
data object PageKeyConfig : ReadBookSheet
|
||||||
|
data object TextSelectMenuFilterConfig : ReadBookSheet
|
||||||
data object InfoConfig : ReadBookSheet
|
data object InfoConfig : ReadBookSheet
|
||||||
data class Dict(val word: String) : ReadBookSheet
|
data class Dict(val word: String) : ReadBookSheet
|
||||||
data class Bookmark(
|
data class Bookmark(
|
||||||
@@ -1197,6 +1198,12 @@ sealed interface ConfigUpdate {
|
|||||||
data class ExpandTextMenu(val value: Boolean) : ConfigUpdate {
|
data class ExpandTextMenu(val value: Boolean) : ConfigUpdate {
|
||||||
override val actions = emptySet<ConfigUpdateAction>()
|
override val actions = emptySet<ConfigUpdateAction>()
|
||||||
}
|
}
|
||||||
|
data class ShowSelectMenuIcon(val value: Boolean) : ConfigUpdate {
|
||||||
|
override val actions = emptySet<ConfigUpdateAction>()
|
||||||
|
}
|
||||||
|
data class TextSelectMenuFilter(val value: String) : ConfigUpdate {
|
||||||
|
override val actions = emptySet<ConfigUpdateAction>()
|
||||||
|
}
|
||||||
data class ShowReadTitleAddition(val value: Boolean) : ConfigUpdate {
|
data class ShowReadTitleAddition(val value: Boolean) : ConfigUpdate {
|
||||||
override val actions = emptySet<ConfigUpdateAction>()
|
override val actions = emptySet<ConfigUpdateAction>()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import io.legado.app.ui.widget.components.FontSelectSheet
|
|||||||
import io.legado.app.ui.widget.components.alert.AppAlertDialog
|
import io.legado.app.ui.widget.components.alert.AppAlertDialog
|
||||||
import io.legado.app.ui.widget.components.changeSource.ChangeSourceSheet
|
import io.legado.app.ui.widget.components.changeSource.ChangeSourceSheet
|
||||||
import io.legado.app.ui.widget.components.log.AppLogSheet
|
import io.legado.app.ui.widget.components.log.AppLogSheet
|
||||||
|
import io.legado.app.ui.config.readConfig.TextSelectMenuFilterSheet
|
||||||
import io.legado.app.utils.toastOnUi
|
import io.legado.app.utils.toastOnUi
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
|
|
||||||
@@ -243,6 +244,10 @@ fun ReadBookScreen(
|
|||||||
onIntent(ReadBookIntent.DismissSheet)
|
onIntent(ReadBookIntent.DismissSheet)
|
||||||
onIntent(ReadBookIntent.ShowSheet(ReadBookSheet.PageKeyConfig))
|
onIntent(ReadBookIntent.ShowSheet(ReadBookSheet.PageKeyConfig))
|
||||||
},
|
},
|
||||||
|
onOpenTextSelectMenuFilterConfig = {
|
||||||
|
onIntent(ReadBookIntent.DismissSheet)
|
||||||
|
onIntent(ReadBookIntent.ShowSheet(ReadBookSheet.TextSelectMenuFilterConfig))
|
||||||
|
},
|
||||||
)
|
)
|
||||||
ReadAloudConfigSheet(
|
ReadAloudConfigSheet(
|
||||||
show = state.activeSheet is ReadBookSheet.ReadAloudConfig,
|
show = state.activeSheet is ReadBookSheet.ReadAloudConfig,
|
||||||
@@ -337,6 +342,16 @@ fun ReadBookScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is ReadBookSheet.TextSelectMenuFilterConfig -> {
|
||||||
|
TextSelectMenuFilterSheet(
|
||||||
|
show = true,
|
||||||
|
onDismissRequest = dismissSheet,
|
||||||
|
onFilterChanged = {
|
||||||
|
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.TextSelectMenuFilter(it)))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
is ReadBookSheet.PageAnim -> {
|
is ReadBookSheet.PageAnim -> {
|
||||||
PageAnimConfigSheet(
|
PageAnimConfigSheet(
|
||||||
onDismissRequest = dismissSheet,
|
onDismissRequest = dismissSheet,
|
||||||
|
|||||||
@@ -3479,6 +3479,18 @@ class ReadBookViewModel(
|
|||||||
readSettingsRepository.setExpandTextMenu(update.value)
|
readSettingsRepository.setExpandTextMenu(update.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
is ConfigUpdate.ShowSelectMenuIcon -> {
|
||||||
|
ReadConfig.showSelectMenuIcon = update.value
|
||||||
|
viewModelScope.launch {
|
||||||
|
readSettingsRepository.setShowSelectMenuIcon(update.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is ConfigUpdate.TextSelectMenuFilter -> {
|
||||||
|
ReadConfig.textSelectMenuFilter = update.value
|
||||||
|
viewModelScope.launch {
|
||||||
|
readSettingsRepository.setTextSelectMenuFilter(update.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
is ConfigUpdate.ShowReadTitleAddition -> {
|
is ConfigUpdate.ShowReadTitleAddition -> {
|
||||||
ReadConfig.showReadTitleAddition = update.value
|
ReadConfig.showReadTitleAddition = update.value
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import io.legado.app.constant.AppLog
|
|||||||
import io.legado.app.databinding.ItemTextBinding
|
import io.legado.app.databinding.ItemTextBinding
|
||||||
import io.legado.app.databinding.PopupActionMenuBinding
|
import io.legado.app.databinding.PopupActionMenuBinding
|
||||||
import io.legado.app.ui.config.readConfig.ReadConfig
|
import io.legado.app.ui.config.readConfig.ReadConfig
|
||||||
|
import io.legado.app.utils.dpToPx
|
||||||
import io.legado.app.utils.gone
|
import io.legado.app.utils.gone
|
||||||
import io.legado.app.utils.isAbsUrl
|
import io.legado.app.utils.isAbsUrl
|
||||||
import io.legado.app.utils.printOnDebug
|
import io.legado.app.utils.printOnDebug
|
||||||
@@ -44,9 +45,10 @@ class TextActionMenu(
|
|||||||
setHasStableIds(true)
|
setHasStableIds(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val menuItems: List<MenuItemImpl>
|
private var menuItems: List<MenuItemImpl> = emptyList()
|
||||||
private val visibleMenuItems = arrayListOf<MenuItemImpl>()
|
private val visibleMenuItems = arrayListOf<MenuItemImpl>()
|
||||||
private val moreMenuItems = arrayListOf<MenuItemImpl>()
|
private val moreMenuItems = arrayListOf<MenuItemImpl>()
|
||||||
|
private val myMenu = MenuBuilder(context)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@SuppressLint("InflateParams")
|
@SuppressLint("InflateParams")
|
||||||
@@ -57,13 +59,7 @@ class TextActionMenu(
|
|||||||
isFocusable = false
|
isFocusable = false
|
||||||
animationStyle = R.style.TextActionMenuAnimation
|
animationStyle = R.style.TextActionMenuAnimation
|
||||||
|
|
||||||
val myMenu = MenuBuilder(context)
|
|
||||||
val otherMenu = MenuBuilder(context)
|
|
||||||
SupportMenuInflater(context).inflate(R.menu.content_select_action, myMenu)
|
SupportMenuInflater(context).inflate(R.menu.content_select_action, myMenu)
|
||||||
onInitializeMenu(otherMenu)
|
|
||||||
menuItems = myMenu.visibleItems + otherMenu.visibleItems
|
|
||||||
visibleMenuItems.addAll(menuItems.subList(0, 6))
|
|
||||||
moreMenuItems.addAll(menuItems.subList(6, menuItems.size))
|
|
||||||
binding.recyclerView.adapter = adapter
|
binding.recyclerView.adapter = adapter
|
||||||
binding.recyclerViewMore.adapter = adapter
|
binding.recyclerViewMore.adapter = adapter
|
||||||
setOnDismissListener {
|
setOnDismissListener {
|
||||||
@@ -91,6 +87,18 @@ class TextActionMenu(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun upMenu() {
|
fun upMenu() {
|
||||||
|
val otherMenu = MenuBuilder(context)
|
||||||
|
onInitializeMenu(otherMenu)
|
||||||
|
menuItems = myMenu.visibleItems + otherMenu.visibleItems
|
||||||
|
visibleMenuItems.clear()
|
||||||
|
moreMenuItems.clear()
|
||||||
|
if (menuItems.size > 6) {
|
||||||
|
visibleMenuItems.addAll(menuItems.subList(0, 6))
|
||||||
|
moreMenuItems.addAll(menuItems.subList(6, menuItems.size))
|
||||||
|
} else {
|
||||||
|
visibleMenuItems.addAll(menuItems)
|
||||||
|
}
|
||||||
|
|
||||||
if (expandTextMenu()) {
|
if (expandTextMenu()) {
|
||||||
adapter.setItems(menuItems)
|
adapter.setItems(menuItems)
|
||||||
binding.ivMenuMore.gone()
|
binding.ivMenuMore.gone()
|
||||||
@@ -172,6 +180,15 @@ class TextActionMenu(
|
|||||||
) {
|
) {
|
||||||
with(binding) {
|
with(binding) {
|
||||||
textView.text = item.title
|
textView.text = item.title
|
||||||
|
val icon = item.icon
|
||||||
|
if (icon != null && ReadConfig.showSelectMenuIcon) {
|
||||||
|
val size = 18.dpToPx()
|
||||||
|
icon.setBounds(0, 0, size, size)
|
||||||
|
textView.setCompoundDrawables(icon, null, null, null)
|
||||||
|
textView.compoundDrawablePadding = 6.dpToPx()
|
||||||
|
} else {
|
||||||
|
textView.setCompoundDrawables(null, null, null, null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,11 +272,23 @@ class TextActionMenu(
|
|||||||
private fun onInitializeMenu(menu: Menu) {
|
private fun onInitializeMenu(menu: Menu) {
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
var menuItemOrder = 100
|
var menuItemOrder = 100
|
||||||
|
val pm = context.packageManager
|
||||||
|
val filterSet = ReadConfig.textSelectMenuFilter.split(",").filter { it.isNotEmpty() }.toSet()
|
||||||
for (resolveInfo in getSupportedActivities()) {
|
for (resolveInfo in getSupportedActivities()) {
|
||||||
menu.add(
|
val componentName = "${resolveInfo.activityInfo.packageName}/${resolveInfo.activityInfo.name}"
|
||||||
|
if (filterSet.contains(componentName)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val menuItem = menu.add(
|
||||||
Menu.NONE, Menu.NONE,
|
Menu.NONE, Menu.NONE,
|
||||||
menuItemOrder++, resolveInfo.loadLabel(context.packageManager)
|
menuItemOrder++, resolveInfo.loadLabel(pm)
|
||||||
).intent = createProcessTextIntentForResolveInfo(resolveInfo)
|
)
|
||||||
|
menuItem.intent = createProcessTextIntentForResolveInfo(resolveInfo)
|
||||||
|
if (ReadConfig.showSelectMenuIcon) {
|
||||||
|
menuItem.icon = kotlin.runCatching {
|
||||||
|
resolveInfo.loadIcon(pm)
|
||||||
|
}.getOrNull()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
context.toastOnUi("获取文字操作菜单出错:${it.localizedMessage}")
|
context.toastOnUi("获取文字操作菜单出错:${it.localizedMessage}")
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ fun MoreConfigSheet(
|
|||||||
onIntent: (ReadBookIntent) -> Unit,
|
onIntent: (ReadBookIntent) -> Unit,
|
||||||
onOpenClickRegionalConfig: () -> Unit,
|
onOpenClickRegionalConfig: () -> Unit,
|
||||||
onOpenPageKeyConfig: () -> Unit,
|
onOpenPageKeyConfig: () -> Unit,
|
||||||
|
onOpenTextSelectMenuFilterConfig: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val readSettingsRepository: ReadSettingsRepository = koinInject()
|
val readSettingsRepository: ReadSettingsRepository = koinInject()
|
||||||
val preferences by readSettingsRepository.preferences.collectAsStateWithLifecycle(
|
val preferences by readSettingsRepository.preferences.collectAsStateWithLifecycle(
|
||||||
@@ -137,13 +138,17 @@ fun MoreConfigSheet(
|
|||||||
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.ClickImgWay(it)))
|
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.ClickImgWay(it)))
|
||||||
},
|
},
|
||||||
onOpenClickRegionalConfig = onOpenClickRegionalConfig,
|
onOpenClickRegionalConfig = onOpenClickRegionalConfig,
|
||||||
|
onOpenPageKeyConfig = onOpenPageKeyConfig,
|
||||||
|
onOpenTextSelectMenuFilterConfig = onOpenTextSelectMenuFilterConfig,
|
||||||
onDisableReturnKeyChange = {
|
onDisableReturnKeyChange = {
|
||||||
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.DisableReturnKey(it)))
|
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.DisableReturnKey(it)))
|
||||||
},
|
},
|
||||||
onOpenPageKeyConfig = onOpenPageKeyConfig,
|
|
||||||
onExpandTextMenuChange = {
|
onExpandTextMenuChange = {
|
||||||
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.ExpandTextMenu(it)))
|
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.ExpandTextMenu(it)))
|
||||||
},
|
},
|
||||||
|
onShowSelectMenuIconChange = {
|
||||||
|
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.ShowSelectMenuIcon(it)))
|
||||||
|
},
|
||||||
onShowReadTitleAdditionChange = {
|
onShowReadTitleAdditionChange = {
|
||||||
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.ShowReadTitleAddition(it)))
|
onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.ShowReadTitleAddition(it)))
|
||||||
},
|
},
|
||||||
@@ -300,7 +305,9 @@ private fun OtherSettings(
|
|||||||
onOpenClickRegionalConfig: () -> Unit,
|
onOpenClickRegionalConfig: () -> Unit,
|
||||||
onDisableReturnKeyChange: (Boolean) -> Unit,
|
onDisableReturnKeyChange: (Boolean) -> Unit,
|
||||||
onOpenPageKeyConfig: () -> Unit,
|
onOpenPageKeyConfig: () -> Unit,
|
||||||
|
onOpenTextSelectMenuFilterConfig: () -> Unit,
|
||||||
onExpandTextMenuChange: (Boolean) -> Unit,
|
onExpandTextMenuChange: (Boolean) -> Unit,
|
||||||
|
onShowSelectMenuIconChange: (Boolean) -> Unit,
|
||||||
onShowReadTitleAdditionChange: (Boolean) -> Unit,
|
onShowReadTitleAdditionChange: (Boolean) -> Unit,
|
||||||
onShowMenuIconChange: (Boolean) -> Unit,
|
onShowMenuIconChange: (Boolean) -> Unit,
|
||||||
) {
|
) {
|
||||||
@@ -357,11 +364,20 @@ private fun OtherSettings(
|
|||||||
title = stringResource(R.string.custom_page_key),
|
title = stringResource(R.string.custom_page_key),
|
||||||
onClick = onOpenPageKeyConfig,
|
onClick = onOpenPageKeyConfig,
|
||||||
)
|
)
|
||||||
|
TinyClickableSettingItem(
|
||||||
|
title = stringResource(R.string.text_select_menu_filter),
|
||||||
|
onClick = onOpenTextSelectMenuFilterConfig,
|
||||||
|
)
|
||||||
TinySwitchSettingItem(
|
TinySwitchSettingItem(
|
||||||
title = stringResource(R.string.expand_text_menu),
|
title = stringResource(R.string.expand_text_menu),
|
||||||
checked = preferences.expandTextMenu,
|
checked = preferences.expandTextMenu,
|
||||||
onCheckedChange = onExpandTextMenuChange,
|
onCheckedChange = onExpandTextMenuChange,
|
||||||
)
|
)
|
||||||
|
TinySwitchSettingItem(
|
||||||
|
title = stringResource(R.string.show_select_menu_icon),
|
||||||
|
checked = preferences.showSelectMenuIcon,
|
||||||
|
onCheckedChange = onShowSelectMenuIconChange,
|
||||||
|
)
|
||||||
TinySwitchSettingItem(
|
TinySwitchSettingItem(
|
||||||
title = stringResource(R.string.show_read_title_addition),
|
title = stringResource(R.string.show_read_title_addition),
|
||||||
checked = preferences.showReadTitleAddition,
|
checked = preferences.showReadTitleAddition,
|
||||||
|
|||||||
@@ -84,6 +84,12 @@ object ReadConfig {
|
|||||||
var expandTextMenu
|
var expandTextMenu
|
||||||
get() = ReadMenuConfig.expandTextMenu
|
get() = ReadMenuConfig.expandTextMenu
|
||||||
set(value) { ReadMenuConfig.expandTextMenu = value }
|
set(value) { ReadMenuConfig.expandTextMenu = value }
|
||||||
|
var showSelectMenuIcon
|
||||||
|
get() = ReadMenuConfig.showSelectMenuIcon
|
||||||
|
set(value) { ReadMenuConfig.showSelectMenuIcon = value }
|
||||||
|
var textSelectMenuFilter
|
||||||
|
get() = ReadMenuConfig.textSelectMenuFilter
|
||||||
|
set(value) { ReadMenuConfig.textSelectMenuFilter = value }
|
||||||
var showReadTitleAddition
|
var showReadTitleAddition
|
||||||
get() = ReadMenuConfig.showReadTitleAddition
|
get() = ReadMenuConfig.showReadTitleAddition
|
||||||
set(value) { ReadMenuConfig.showReadTitleAddition = value }
|
set(value) { ReadMenuConfig.showReadTitleAddition = value }
|
||||||
@@ -264,6 +270,8 @@ object ReadConfig {
|
|||||||
readBarStyle = preferences.readBarStyle
|
readBarStyle = preferences.readBarStyle
|
||||||
progressBarBehavior = preferences.progressBarBehavior
|
progressBarBehavior = preferences.progressBarBehavior
|
||||||
expandTextMenu = preferences.expandTextMenu
|
expandTextMenu = preferences.expandTextMenu
|
||||||
|
showSelectMenuIcon = preferences.showSelectMenuIcon
|
||||||
|
textSelectMenuFilter = preferences.textSelectMenuFilter
|
||||||
showReadTitleAddition = preferences.showReadTitleAddition
|
showReadTitleAddition = preferences.showReadTitleAddition
|
||||||
showMenuIcon = preferences.showMenuIcon
|
showMenuIcon = preferences.showMenuIcon
|
||||||
clickActionTL = preferences.clickActionTL
|
clickActionTL = preferences.clickActionTL
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ data class ReadConfigUiState(
|
|||||||
val optimizeRender: Boolean = false,
|
val optimizeRender: Boolean = false,
|
||||||
val disableReturnKey: Boolean = false,
|
val disableReturnKey: Boolean = false,
|
||||||
val expandTextMenu: Boolean = false,
|
val expandTextMenu: Boolean = false,
|
||||||
|
val showSelectMenuIcon: Boolean = true,
|
||||||
|
val textSelectMenuFilter: String = "",
|
||||||
val showReadTitleAddition: Boolean = true,
|
val showReadTitleAddition: Boolean = true,
|
||||||
val autoReadSpeed: Int = 10,
|
val autoReadSpeed: Int = 10,
|
||||||
val prevKeys: String = "",
|
val prevKeys: String = "",
|
||||||
@@ -76,6 +78,8 @@ sealed interface ReadConfigIntent {
|
|||||||
data class OptimizeRenderChanged(val value: Boolean) : ReadConfigIntent
|
data class OptimizeRenderChanged(val value: Boolean) : ReadConfigIntent
|
||||||
data class DisableReturnKeyChanged(val value: Boolean) : ReadConfigIntent
|
data class DisableReturnKeyChanged(val value: Boolean) : ReadConfigIntent
|
||||||
data class ExpandTextMenuChanged(val value: Boolean) : ReadConfigIntent
|
data class ExpandTextMenuChanged(val value: Boolean) : ReadConfigIntent
|
||||||
|
data class ShowSelectMenuIconChanged(val value: Boolean) : ReadConfigIntent
|
||||||
|
data class TextSelectMenuFilterChanged(val value: String) : ReadConfigIntent
|
||||||
data class ShowReadTitleAdditionChanged(val value: Boolean) : ReadConfigIntent
|
data class ShowReadTitleAdditionChanged(val value: Boolean) : ReadConfigIntent
|
||||||
data class ShowMenuIconChanged(val value: Boolean) : ReadConfigIntent
|
data class ShowMenuIconChanged(val value: Boolean) : ReadConfigIntent
|
||||||
data class PageKeysChanged(val prevKeys: String, val nextKeys: String) : ReadConfigIntent
|
data class PageKeysChanged(val prevKeys: String, val nextKeys: String) : ReadConfigIntent
|
||||||
|
|||||||
@@ -369,6 +369,30 @@ fun ReadConfigScreen(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
SwitchSettingItem(
|
||||||
|
title = stringResource(R.string.show_select_menu_icon),
|
||||||
|
checked = state.showSelectMenuIcon,
|
||||||
|
onCheckedChange = {
|
||||||
|
viewModel.onIntent(ReadConfigIntent.ShowSelectMenuIconChanged(it))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var showSelectMenuFilterSheet by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
ClickableSettingItem(
|
||||||
|
title = stringResource(R.string.text_select_menu_filter),
|
||||||
|
description = stringResource(R.string.text_select_menu_filter_desc),
|
||||||
|
onClick = { showSelectMenuFilterSheet = true }
|
||||||
|
)
|
||||||
|
|
||||||
|
TextSelectMenuFilterSheet(
|
||||||
|
show = showSelectMenuFilterSheet,
|
||||||
|
onDismissRequest = { showSelectMenuFilterSheet = false },
|
||||||
|
onFilterChanged = {
|
||||||
|
viewModel.onIntent(ReadConfigIntent.TextSelectMenuFilterChanged(it))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
SwitchSettingItem(
|
SwitchSettingItem(
|
||||||
title = stringResource(R.string.show_read_title_addition),
|
title = stringResource(R.string.show_read_title_addition),
|
||||||
checked = state.showReadTitleAddition,
|
checked = state.showReadTitleAddition,
|
||||||
|
|||||||
@@ -197,6 +197,16 @@ class ReadConfigViewModel(
|
|||||||
readSettingsRepository.setExpandTextMenu(intent.value)
|
readSettingsRepository.setExpandTextMenu(intent.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is ReadConfigIntent.ShowSelectMenuIconChanged -> {
|
||||||
|
ReadConfig.showSelectMenuIcon = intent.value
|
||||||
|
readSettingsRepository.setShowSelectMenuIcon(intent.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
is ReadConfigIntent.TextSelectMenuFilterChanged -> {
|
||||||
|
ReadConfig.textSelectMenuFilter = intent.value
|
||||||
|
readSettingsRepository.setTextSelectMenuFilter(intent.value)
|
||||||
|
}
|
||||||
|
|
||||||
is ReadConfigIntent.ShowReadTitleAdditionChanged -> {
|
is ReadConfigIntent.ShowReadTitleAdditionChanged -> {
|
||||||
ReadConfig.showReadTitleAddition = intent.value
|
ReadConfig.showReadTitleAddition = intent.value
|
||||||
readSettingsRepository.setShowReadTitleAddition(intent.value)
|
readSettingsRepository.setShowReadTitleAddition(intent.value)
|
||||||
@@ -263,6 +273,8 @@ class ReadConfigViewModel(
|
|||||||
optimizeRender = optimizeRender,
|
optimizeRender = optimizeRender,
|
||||||
disableReturnKey = disableReturnKey,
|
disableReturnKey = disableReturnKey,
|
||||||
expandTextMenu = expandTextMenu,
|
expandTextMenu = expandTextMenu,
|
||||||
|
showSelectMenuIcon = showSelectMenuIcon,
|
||||||
|
textSelectMenuFilter = textSelectMenuFilter,
|
||||||
showReadTitleAddition = showReadTitleAddition,
|
showReadTitleAddition = showReadTitleAddition,
|
||||||
autoReadSpeed = autoReadSpeed,
|
autoReadSpeed = autoReadSpeed,
|
||||||
prevKeys = prevKeys,
|
prevKeys = prevKeys,
|
||||||
|
|||||||
@@ -40,6 +40,16 @@ object ReadMenuConfig {
|
|||||||
false
|
false
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var showSelectMenuIcon by prefDelegate(
|
||||||
|
PreferKey.showSelectMenuIcon,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
|
||||||
|
var textSelectMenuFilter by prefDelegate(
|
||||||
|
PreferKey.textSelectMenuFilter,
|
||||||
|
""
|
||||||
|
)
|
||||||
|
|
||||||
var showReadTitleAddition by prefDelegate(
|
var showReadTitleAddition by prefDelegate(
|
||||||
PreferKey.showReadTitleAddition,
|
PreferKey.showReadTitleAddition,
|
||||||
true
|
true
|
||||||
|
|||||||
@@ -0,0 +1,175 @@
|
|||||||
|
package io.legado.app.ui.config.readConfig
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Check
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import coil.compose.AsyncImage
|
||||||
|
import io.legado.app.R
|
||||||
|
import io.legado.app.ui.theme.LegadoTheme
|
||||||
|
import io.legado.app.ui.widget.components.AdaptiveSwitch
|
||||||
|
import io.legado.app.ui.widget.components.button.series.SmallPlainButton
|
||||||
|
import io.legado.app.ui.widget.components.card.NormalCard
|
||||||
|
import io.legado.app.ui.widget.components.modalBottomSheet.AppModalBottomSheet
|
||||||
|
import io.legado.app.ui.widget.components.text.AppText
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun TextSelectMenuFilterSheet(
|
||||||
|
show: Boolean,
|
||||||
|
onDismissRequest: () -> Unit,
|
||||||
|
onFilterChanged: (String) -> Unit
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val pm = context.packageManager
|
||||||
|
|
||||||
|
// 查询所有注册了 ACTION_PROCESS_TEXT 的第三方 Activity
|
||||||
|
var apps by remember { mutableStateOf<List<TextSelectMenuAppInfo>>(emptyList()) }
|
||||||
|
LaunchedEffect(show) {
|
||||||
|
if (show) {
|
||||||
|
val list = kotlinx.coroutines.withContext(kotlinx.coroutines.Dispatchers.IO) {
|
||||||
|
val intent = Intent().setAction(Intent.ACTION_PROCESS_TEXT).setType("text/plain")
|
||||||
|
pm.queryIntentActivities(intent, 0).map { resolveInfo ->
|
||||||
|
val title = resolveInfo.loadLabel(pm).toString()
|
||||||
|
val componentName = "${resolveInfo.activityInfo.packageName}/${resolveInfo.activityInfo.name}"
|
||||||
|
val icon = kotlin.runCatching { resolveInfo.loadIcon(pm) }.getOrNull()
|
||||||
|
TextSelectMenuAppInfo(title, componentName, icon)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
apps = list
|
||||||
|
} else {
|
||||||
|
apps = emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var pendingFilterString by remember(show) {
|
||||||
|
mutableStateOf(ReadConfig.textSelectMenuFilter)
|
||||||
|
}
|
||||||
|
|
||||||
|
val disabledSet = remember(pendingFilterString) {
|
||||||
|
pendingFilterString.split(",").filter { it.isNotEmpty() }.toSet()
|
||||||
|
}
|
||||||
|
|
||||||
|
AppModalBottomSheet(
|
||||||
|
show = show,
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
title = stringResource(R.string.text_select_menu_filter),
|
||||||
|
endAction = {
|
||||||
|
SmallPlainButton(
|
||||||
|
icon = Icons.Default.Check,
|
||||||
|
onClick = {
|
||||||
|
onFilterChanged(pendingFilterString)
|
||||||
|
onDismissRequest()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.fillMaxHeight(0.8f)
|
||||||
|
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||||
|
) {
|
||||||
|
if (apps.isEmpty()) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.weight(1f),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
AppText(text = stringResource(R.string.no_apps_found))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LazyColumn(
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
|
) {
|
||||||
|
items(apps) { app ->
|
||||||
|
val isEnabled = !disabledSet.contains(app.componentName)
|
||||||
|
NormalCard(
|
||||||
|
onClick = {
|
||||||
|
val nextSet = if (isEnabled) {
|
||||||
|
disabledSet + app.componentName
|
||||||
|
} else {
|
||||||
|
disabledSet - app.componentName
|
||||||
|
}
|
||||||
|
pendingFilterString = nextSet.joinToString(",")
|
||||||
|
},
|
||||||
|
cornerRadius = 12.dp,
|
||||||
|
containerColor = LegadoTheme.colorScheme.surfaceContainerHigh,
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 8.dp, vertical = 12.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(40.dp)
|
||||||
|
.padding(4.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
AsyncImage(
|
||||||
|
model = app.icon,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.fillMaxSize()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(horizontal = 8.dp)
|
||||||
|
) {
|
||||||
|
AppText(
|
||||||
|
text = app.title,
|
||||||
|
style = LegadoTheme.typography.titleMedium
|
||||||
|
)
|
||||||
|
}
|
||||||
|
AdaptiveSwitch(
|
||||||
|
checked = isEnabled,
|
||||||
|
onCheckedChange = { checked ->
|
||||||
|
val nextSet = if (checked) {
|
||||||
|
disabledSet - app.componentName
|
||||||
|
} else {
|
||||||
|
disabledSet + app.componentName
|
||||||
|
}
|
||||||
|
pendingFilterString = nextSet.joinToString(",")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class TextSelectMenuAppInfo(
|
||||||
|
val title: String,
|
||||||
|
val componentName: String,
|
||||||
|
val icon: android.graphics.drawable.Drawable?
|
||||||
|
)
|
||||||
@@ -1098,6 +1098,12 @@
|
|||||||
<string name="open_sys_dir_picker_error">打开系统文件夹选择器出错,将自动打开应用文件夹选择器</string>
|
<string name="open_sys_dir_picker_error">打开系统文件夹选择器出错,将自动打开应用文件夹选择器</string>
|
||||||
<string name="open_sys_doc_picker_error">打开系统文件选择器出错,将自动打开应用文件选择器</string>
|
<string name="open_sys_doc_picker_error">打开系统文件选择器出错,将自动打开应用文件选择器</string>
|
||||||
<string name="expand_text_menu">展开文本选择菜单</string>
|
<string name="expand_text_menu">展开文本选择菜单</string>
|
||||||
|
<string name="show_select_menu_icon">展示选择菜单图标</string>
|
||||||
|
<string name="text_select_menu_filter">选择菜单应用过滤</string>
|
||||||
|
<string name="text_select_menu_filter_desc">过滤文字选择操作菜单中显示的第三方应用</string>
|
||||||
|
<string name="show_all">全部显示</string>
|
||||||
|
<string name="hide_all">全不显示</string>
|
||||||
|
<string name="no_apps_found">未找到支持文字处理的第三方应用</string>
|
||||||
<string name="book_tree_uri_t">书籍保存位置</string>
|
<string name="book_tree_uri_t">书籍保存位置</string>
|
||||||
<string name="book_tree_uri_s">从其它应用打开的书籍保存位置</string>
|
<string name="book_tree_uri_s">从其它应用打开的书籍保存位置</string>
|
||||||
<string name="select_book_folder">选择保存书籍的文件夹</string>
|
<string name="select_book_folder">选择保存书籍的文件夹</string>
|
||||||
|
|||||||
@@ -1130,6 +1130,12 @@
|
|||||||
<string name="open_sys_dir_picker_error">Error opening system folder selector, automatically open application folder selector</string>
|
<string name="open_sys_dir_picker_error">Error opening system folder selector, automatically open application folder selector</string>
|
||||||
<string name="open_sys_doc_picker_error">Error opening system file selector, automatically open application file selector</string>
|
<string name="open_sys_doc_picker_error">Error opening system file selector, automatically open application file selector</string>
|
||||||
<string name="expand_text_menu">Expand Text Selection Menu</string>
|
<string name="expand_text_menu">Expand Text Selection Menu</string>
|
||||||
|
<string name="show_select_menu_icon">Show Text Selection Menu Icons</string>
|
||||||
|
<string name="text_select_menu_filter">Text Selection Menu Filter</string>
|
||||||
|
<string name="text_select_menu_filter_desc">Filter the third-party apps displayed in the selection menu</string>
|
||||||
|
<string name="show_all">Show All</string>
|
||||||
|
<string name="hide_all">Hide All</string>
|
||||||
|
<string name="no_apps_found">No third-party apps supporting text actions found</string>
|
||||||
<string name="book_tree_uri_t">Book Save Location</string>
|
<string name="book_tree_uri_t">Book Save Location</string>
|
||||||
<string name="book_tree_uri_s">Save location for books opened from other apps</string>
|
<string name="book_tree_uri_s">Save location for books opened from other apps</string>
|
||||||
<string name="select_book_folder">Select the folder where the books are saved</string>
|
<string name="select_book_folder">Select the folder where the books are saved</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user