[新增] 由Compose重写的“我的”界面
This commit is contained in:
8 files changed
+408
-127
No files matched your search
@@ -4,6 +4,7 @@ package io.legado.app.constant
|
|||||||
object PreferKey {
|
object PreferKey {
|
||||||
const val language = "language"
|
const val language = "language"
|
||||||
const val fontScale = "fontScale"
|
const val fontScale = "fontScale"
|
||||||
|
const val appTheme = "app_theme"
|
||||||
const val themeMode = "themeMode"
|
const val themeMode = "themeMode"
|
||||||
const val userAgent = "userAgent"
|
const val userAgent = "userAgent"
|
||||||
const val showUnread = "showUnread"
|
const val showUnread = "showUnread"
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ import androidx.compose.ui.graphics.toArgb
|
|||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.text.buildAnnotatedString
|
import androidx.compose.ui.text.buildAnnotatedString
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import io.legado.app.ui.widget.components.AnimatedText
|
||||||
import io.legado.app.ui.widget.components.AnimatedTextLine
|
import io.legado.app.ui.widget.components.AnimatedTextLine
|
||||||
import io.legado.app.ui.widget.components.EmptyMessageView
|
import io.legado.app.ui.widget.components.EmptyMessageView
|
||||||
import io.legado.app.ui.widget.components.SearchBarSection
|
import io.legado.app.ui.widget.components.SearchBarSection
|
||||||
@@ -121,7 +122,7 @@ fun SearchContentScreen(
|
|||||||
} else {
|
} else {
|
||||||
"搜索内容"
|
"搜索内容"
|
||||||
}
|
}
|
||||||
AnimatedTextLine(
|
AnimatedText(
|
||||||
text = title
|
text = title
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -537,7 +537,7 @@ open class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
|
|||||||
idBookshelf4 -> BookshelfFragment4(position)
|
idBookshelf4 -> BookshelfFragment4(position)
|
||||||
idExplore -> ExploreFragment(position)
|
idExplore -> ExploreFragment(position)
|
||||||
idRss -> RssFragment(position)
|
idRss -> RssFragment(position)
|
||||||
else -> MyFragment(position)
|
else -> MyFragment.newInstance(position)
|
||||||
}
|
}
|
||||||
|
|
||||||
fragmentMap[getFragmentId(position)] = fragment
|
fragmentMap[getFragmentId(position)] = fragment
|
||||||
|
|||||||
@@ -1,13 +1,20 @@
|
|||||||
package io.legado.app.ui.main.my
|
package io.legado.app.ui.main.my
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.compose.ui.platform.ComposeView
|
||||||
|
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
|
import io.legado.app.ui.theme.AppTheme
|
||||||
import io.legado.app.base.BaseFragment
|
import io.legado.app.base.BaseFragment
|
||||||
import io.legado.app.constant.EventBus
|
import io.legado.app.constant.EventBus
|
||||||
import io.legado.app.constant.PreferKey
|
import io.legado.app.constant.PreferKey
|
||||||
@@ -26,6 +33,7 @@ import io.legado.app.ui.config.ConfigTag
|
|||||||
import io.legado.app.ui.dict.rule.DictRuleActivity
|
import io.legado.app.ui.dict.rule.DictRuleActivity
|
||||||
import io.legado.app.ui.file.FileManageActivity
|
import io.legado.app.ui.file.FileManageActivity
|
||||||
import io.legado.app.ui.main.MainFragmentInterface
|
import io.legado.app.ui.main.MainFragmentInterface
|
||||||
|
import io.legado.app.ui.main.explore.ExploreFragment
|
||||||
import io.legado.app.ui.replace.ReplaceRuleActivity
|
import io.legado.app.ui.replace.ReplaceRuleActivity
|
||||||
import io.legado.app.utils.LogUtils
|
import io.legado.app.utils.LogUtils
|
||||||
import io.legado.app.utils.getPrefBoolean
|
import io.legado.app.utils.getPrefBoolean
|
||||||
@@ -36,136 +44,80 @@ import io.legado.app.utils.sendToClip
|
|||||||
import io.legado.app.utils.showHelp
|
import io.legado.app.utils.showHelp
|
||||||
import io.legado.app.utils.startActivity
|
import io.legado.app.utils.startActivity
|
||||||
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
import io.legado.app.utils.viewbindingdelegate.viewBinding
|
||||||
|
import org.koin.androidx.compose.koinViewModel
|
||||||
|
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||||
|
|
||||||
class MyFragment() : BaseFragment(R.layout.fragment_my_config), MainFragmentInterface {
|
class MyFragment : Fragment(), MainFragmentInterface {
|
||||||
|
|
||||||
constructor(position: Int) : this() {
|
companion object {
|
||||||
val bundle = Bundle()
|
private const val ARG_POSITION = "position"
|
||||||
bundle.putInt("position", position)
|
|
||||||
arguments = bundle
|
|
||||||
}
|
|
||||||
|
|
||||||
override val position: Int? get() = arguments?.getInt("position")
|
fun newInstance(position: Int): MyFragment {
|
||||||
|
return MyFragment().apply {
|
||||||
private val binding by viewBinding(FragmentMyConfigBinding::bind)
|
arguments = Bundle().apply {
|
||||||
|
putInt(ARG_POSITION, position)
|
||||||
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
|
}
|
||||||
setSupportToolbar(binding.topBar)
|
}
|
||||||
val fragmentTag = "prefFragment"
|
|
||||||
var preferenceFragment = childFragmentManager.findFragmentByTag(fragmentTag)
|
|
||||||
if (preferenceFragment == null) preferenceFragment = MyPreferenceFragment()
|
|
||||||
childFragmentManager.beginTransaction()
|
|
||||||
.replace(R.id.pre_fragment, preferenceFragment, fragmentTag).commit()
|
|
||||||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.S)
|
|
||||||
binding.titleBar.fitsSystemWindows = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCompatCreateOptionsMenu(menu: Menu) {
|
|
||||||
menuInflater.inflate(R.menu.main_my, menu)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCompatOptionsItemSelected(item: MenuItem) {
|
|
||||||
when (item.itemId) {
|
|
||||||
R.id.menu_help -> showHelp("appHelp")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
override val position: Int by lazy {
|
||||||
* 配置
|
arguments?.getInt(ARG_POSITION) ?: 0
|
||||||
*/
|
}
|
||||||
class MyPreferenceFragment : PreferenceFragment(),
|
|
||||||
SharedPreferences.OnSharedPreferenceChangeListener {
|
|
||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
private val viewModel: MyViewModel by viewModel()
|
||||||
putPrefBoolean(PreferKey.webService, WebService.isRun)
|
|
||||||
addPreferencesFromResource(R.xml.pref_main)
|
override fun onCreateView(
|
||||||
findPreference<SwitchPreference>("webService")?.onLongClick {
|
inflater: LayoutInflater,
|
||||||
if (!WebService.isRun) {
|
container: ViewGroup?,
|
||||||
return@onLongClick false
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
|
||||||
|
return ComposeView(requireContext()).apply {
|
||||||
|
|
||||||
|
setViewCompositionStrategy(
|
||||||
|
ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed
|
||||||
|
)
|
||||||
|
|
||||||
|
setContent {
|
||||||
|
AppTheme{
|
||||||
|
MyScreen(
|
||||||
|
viewModel = viewModel,
|
||||||
|
onNavigate = { event ->
|
||||||
|
handleEvent(event)
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
context?.selector(arrayListOf("复制地址", "浏览器打开")) { _, i ->
|
}
|
||||||
when (i) {
|
}
|
||||||
0 -> context?.sendToClip(it.summary.toString())
|
}
|
||||||
1 -> context?.openUrl(it.summary.toString())
|
|
||||||
|
private fun handleEvent(event: PrefClickEvent) {
|
||||||
|
when (event) {
|
||||||
|
|
||||||
|
is PrefClickEvent.StartActivity -> {
|
||||||
|
startActivity(
|
||||||
|
Intent(requireContext(), event.destination).apply {
|
||||||
|
event.configTag?.let {
|
||||||
|
putExtra("configTag", it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
true
|
|
||||||
}
|
|
||||||
observeEventSticky<String>(EventBus.WEB_SERVICE) {
|
|
||||||
findPreference<SwitchPreference>(PreferKey.webService)?.let {
|
|
||||||
it.isChecked = WebService.isRun
|
|
||||||
it.summary = if (WebService.isRun) {
|
|
||||||
WebService.hostAddress
|
|
||||||
} else {
|
|
||||||
getString(R.string.web_service_desc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is PrefClickEvent.OpenUrl ->
|
||||||
|
requireContext().openUrl(event.url)
|
||||||
|
|
||||||
|
is PrefClickEvent.CopyUrl ->
|
||||||
|
requireContext().sendToClip(event.url)
|
||||||
|
|
||||||
|
is PrefClickEvent.ShowMd ->
|
||||||
|
showHelp(event.title)
|
||||||
|
|
||||||
|
PrefClickEvent.ExitApp ->
|
||||||
|
requireActivity().finish()
|
||||||
|
|
||||||
|
else -> Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
//listView.setEdgeEffectColor(primaryColor)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
preferenceManager.sharedPreferences?.registerOnSharedPreferenceChangeListener(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPause() {
|
|
||||||
preferenceManager.sharedPreferences?.unregisterOnSharedPreferenceChangeListener(this)
|
|
||||||
super.onPause()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSharedPreferenceChanged(
|
|
||||||
sharedPreferences: SharedPreferences?,
|
|
||||||
key: String?
|
|
||||||
) {
|
|
||||||
when (key) {
|
|
||||||
PreferKey.webService -> {
|
|
||||||
if (requireContext().getPrefBoolean("webService")) {
|
|
||||||
WebService.start(requireContext())
|
|
||||||
} else {
|
|
||||||
WebService.stop(requireContext())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
"recordLog" -> LogUtils.upLevel()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPreferenceTreeClick(preference: Preference): Boolean {
|
|
||||||
when (preference.key) {
|
|
||||||
"bookSourceManage" -> startActivity<BookSourceActivity>()
|
|
||||||
"replaceManage" -> startActivity<ReplaceRuleActivity>()
|
|
||||||
"dictRuleManage" -> startActivity<DictRuleActivity>()
|
|
||||||
"txtTocRuleManage" -> startActivity<TxtTocRuleActivity>()
|
|
||||||
"bookmark" -> startActivity<AllBookmarkActivity>()
|
|
||||||
"setting" -> startActivity<ConfigActivity> {
|
|
||||||
putExtra("configTag", ConfigTag.OTHER_CONFIG)
|
|
||||||
}
|
|
||||||
|
|
||||||
"web_dav_setting" -> startActivity<ConfigActivity> {
|
|
||||||
putExtra("configTag", ConfigTag.BACKUP_CONFIG)
|
|
||||||
}
|
|
||||||
|
|
||||||
"theme_setting" -> startActivity<ConfigActivity> {
|
|
||||||
putExtra("configTag", ConfigTag.THEME_CONFIG)
|
|
||||||
}
|
|
||||||
|
|
||||||
"read_setting" -> startActivity<ConfigActivity> {
|
|
||||||
putExtra("configTag", ConfigTag.READ_CONFIG)
|
|
||||||
}
|
|
||||||
|
|
||||||
"fileManage" -> startActivity<FileManageActivity>()
|
|
||||||
"readRecord" -> startActivity<ReadRecordActivity>()
|
|
||||||
"about" -> startActivity<AboutActivity>()
|
|
||||||
"exit" -> activity?.finish()
|
|
||||||
}
|
|
||||||
return super.onPreferenceTreeClick(preference)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,255 @@
|
|||||||
|
package io.legado.app.ui.main.my
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.only
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.systemBars
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.automirrored.filled.ExitToApp
|
||||||
|
import androidx.compose.material.icons.automirrored.filled.HelpOutline
|
||||||
|
import androidx.compose.material.icons.automirrored.filled.LibraryBooks
|
||||||
|
import androidx.compose.material.icons.automirrored.filled.MenuBook
|
||||||
|
import androidx.compose.material.icons.automirrored.filled.Rule
|
||||||
|
import androidx.compose.material.icons.filled.Backup
|
||||||
|
import androidx.compose.material.icons.filled.FindReplace
|
||||||
|
import androidx.compose.material.icons.filled.Info
|
||||||
|
import androidx.compose.material.icons.filled.Palette
|
||||||
|
import androidx.compose.material.icons.filled.Rule
|
||||||
|
import androidx.compose.material.icons.filled.Source
|
||||||
|
import androidx.compose.material.icons.filled.Translate
|
||||||
|
import androidx.compose.material.icons.filled.Web
|
||||||
|
import androidx.compose.material3.DropdownMenu
|
||||||
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.MediumTopAppBar
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.Switch
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TopAppBar
|
||||||
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import io.legado.app.R
|
||||||
|
import io.legado.app.ui.about.AboutActivity
|
||||||
|
import io.legado.app.ui.book.source.manage.BookSourceActivity
|
||||||
|
import io.legado.app.ui.book.toc.rule.TxtTocRuleActivity
|
||||||
|
import io.legado.app.ui.config.ConfigActivity
|
||||||
|
import io.legado.app.ui.config.ConfigTag
|
||||||
|
import io.legado.app.ui.dict.rule.DictRuleActivity
|
||||||
|
import io.legado.app.ui.replace.ReplaceRuleActivity
|
||||||
|
import io.legado.app.ui.widget.components.SettingItem
|
||||||
|
import io.legado.app.ui.widget.components.SplicedColumnGroup
|
||||||
|
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun MyScreen(
|
||||||
|
viewModel: MyViewModel,
|
||||||
|
onNavigate: (PrefClickEvent) -> Unit
|
||||||
|
) {
|
||||||
|
|
||||||
|
val uiState by viewModel.uiState.collectAsState()
|
||||||
|
var showMenu by remember { mutableStateOf(false) }
|
||||||
|
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||||
|
contentWindowInsets = WindowInsets.systemBars
|
||||||
|
.only(WindowInsetsSides.Horizontal + WindowInsetsSides.Top),
|
||||||
|
topBar = {
|
||||||
|
MediumTopAppBar(
|
||||||
|
title = {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.my)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
actions = {
|
||||||
|
IconButton(
|
||||||
|
onClick = { onNavigate(PrefClickEvent.ShowMd("appHelp", "xxx")) }
|
||||||
|
) {Icon(
|
||||||
|
Icons.AutoMirrored.Filled.HelpOutline, null)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scrollBehavior = scrollBehavior
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { padding ->
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(padding)
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
) {
|
||||||
|
SplicedColumnGroup(
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
|
title = ""
|
||||||
|
) {
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.book_source_manage),
|
||||||
|
description = stringResource(R.string.book_source_manage_desc),
|
||||||
|
imageVector = Icons.Default.Source,
|
||||||
|
onClick = {
|
||||||
|
onNavigate(
|
||||||
|
PrefClickEvent.StartActivity(BookSourceActivity::class.java)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.web_service),
|
||||||
|
description = if (uiState.isWebServiceRun)
|
||||||
|
uiState.webServiceAddress
|
||||||
|
else
|
||||||
|
stringResource(R.string.web_service_desc),
|
||||||
|
imageVector = Icons.Default.Web,
|
||||||
|
trailingContent = {
|
||||||
|
Switch(
|
||||||
|
checked = uiState.isWebServiceRun,
|
||||||
|
onCheckedChange = {
|
||||||
|
viewModel.onEvent(PrefClickEvent.ToggleWebService)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onClick = {
|
||||||
|
viewModel.onEvent(PrefClickEvent.ToggleWebService)
|
||||||
|
},
|
||||||
|
onLongClick = {
|
||||||
|
if (uiState.isWebServiceRun) {
|
||||||
|
showMenu = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
DropdownMenu(
|
||||||
|
expanded = showMenu,
|
||||||
|
onDismissRequest = { showMenu = false }
|
||||||
|
) {
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text("复制地址") },
|
||||||
|
onClick = {
|
||||||
|
onNavigate(PrefClickEvent.CopyUrl(uiState.webServiceAddress))
|
||||||
|
showMenu = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text("浏览器打开") },
|
||||||
|
onClick = {
|
||||||
|
onNavigate(PrefClickEvent.OpenUrl(uiState.webServiceAddress))
|
||||||
|
showMenu = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SplicedColumnGroup(
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
|
title = stringResource(R.string.setting)) {
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.backup_restore),
|
||||||
|
description = stringResource(R.string.web_dav_set_import_old),
|
||||||
|
imageVector = Icons.Default.Backup,
|
||||||
|
onClick = {
|
||||||
|
onNavigate(
|
||||||
|
PrefClickEvent.StartActivity(
|
||||||
|
ConfigActivity::class.java,
|
||||||
|
ConfigTag.BACKUP_CONFIG
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.theme_setting),
|
||||||
|
description = stringResource(R.string.theme_setting_s),
|
||||||
|
imageVector = Icons.Default.Palette,
|
||||||
|
onClick = {
|
||||||
|
onNavigate(
|
||||||
|
PrefClickEvent.StartActivity(
|
||||||
|
ConfigActivity::class.java,
|
||||||
|
ConfigTag.THEME_CONFIG
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.read),
|
||||||
|
description = stringResource(R.string.global_read_setting),
|
||||||
|
imageVector = Icons.AutoMirrored.Filled.LibraryBooks,
|
||||||
|
onClick = {
|
||||||
|
onNavigate(
|
||||||
|
PrefClickEvent.StartActivity(
|
||||||
|
ConfigActivity::class.java,
|
||||||
|
ConfigTag.READ_CONFIG
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
SplicedColumnGroup(
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
|
title = "规则"
|
||||||
|
) {
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.replace_purify),
|
||||||
|
imageVector = Icons.Default.FindReplace,
|
||||||
|
onClick = {
|
||||||
|
onNavigate(
|
||||||
|
PrefClickEvent.StartActivity(ReplaceRuleActivity::class.java)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.txt_toc_rule),
|
||||||
|
imageVector = Icons.AutoMirrored.Filled.Rule,
|
||||||
|
onClick = {
|
||||||
|
onNavigate(
|
||||||
|
PrefClickEvent.StartActivity(TxtTocRuleActivity::class.java)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.dict_rule),
|
||||||
|
imageVector = Icons.Default.Translate,
|
||||||
|
onClick = {
|
||||||
|
onNavigate(
|
||||||
|
PrefClickEvent.StartActivity(DictRuleActivity::class.java)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
SplicedColumnGroup(
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
|
title = stringResource(R.string.other)) {
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.about),
|
||||||
|
imageVector = Icons.Default.Info,
|
||||||
|
onClick = {
|
||||||
|
onNavigate(PrefClickEvent.StartActivity(AboutActivity::class.java))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
SettingItem(
|
||||||
|
title = stringResource(R.string.exit),
|
||||||
|
imageVector = Icons.AutoMirrored.Filled.ExitToApp,
|
||||||
|
onClick = {
|
||||||
|
onNavigate(PrefClickEvent.ExitApp)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package io.legado.app.ui.main.my
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import androidx.lifecycle.AndroidViewModel
|
||||||
|
import io.legado.app.service.WebService
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
|
||||||
|
data class MyUiState(
|
||||||
|
val isWebServiceRun: Boolean = false,
|
||||||
|
val webServiceAddress: String = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
sealed class PrefClickEvent {
|
||||||
|
data class OpenUrl(val url: String) : PrefClickEvent()
|
||||||
|
data class CopyUrl(val url: String) : PrefClickEvent()
|
||||||
|
data class ShowMd(val title: String, val path: String) : PrefClickEvent()
|
||||||
|
data class StartActivity(val destination: Class<*>, val configTag: String? = null) : PrefClickEvent()
|
||||||
|
object ShowWebServiceMenu : PrefClickEvent()
|
||||||
|
object ToggleWebService : PrefClickEvent()
|
||||||
|
object ExitApp : PrefClickEvent()
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyViewModel(
|
||||||
|
application: Application
|
||||||
|
) : AndroidViewModel(application) {
|
||||||
|
|
||||||
|
private val _uiState = MutableStateFlow(
|
||||||
|
MyUiState(
|
||||||
|
isWebServiceRun = WebService.isRun,
|
||||||
|
webServiceAddress = if (WebService.isRun) {
|
||||||
|
WebService.hostAddress
|
||||||
|
} else ""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val uiState: StateFlow<MyUiState> = _uiState.asStateFlow()
|
||||||
|
|
||||||
|
fun onEvent(event: PrefClickEvent) {
|
||||||
|
when (event) {
|
||||||
|
|
||||||
|
PrefClickEvent.ToggleWebService -> {
|
||||||
|
val newRun = !_uiState.value.isWebServiceRun
|
||||||
|
if (newRun) {
|
||||||
|
WebService.start(getApplication())
|
||||||
|
} else {
|
||||||
|
WebService.stop(getApplication())
|
||||||
|
}
|
||||||
|
updateWebServiceState()
|
||||||
|
}
|
||||||
|
|
||||||
|
PrefClickEvent.ShowWebServiceMenu -> {
|
||||||
|
// UI 自己处理 showMenu
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateWebServiceState() {
|
||||||
|
_uiState.value = MyUiState(
|
||||||
|
isWebServiceRun = WebService.isRun,
|
||||||
|
webServiceAddress = if (WebService.isRun) {
|
||||||
|
WebService.hostAddress
|
||||||
|
} else ""
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package io.legado.app.ui.widget.components
|
|||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.combinedClickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
@@ -31,7 +32,6 @@ import androidx.compose.ui.text.font.FontWeight
|
|||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.legado.app.base.AppTypography
|
|
||||||
|
|
||||||
@Preview(showBackground = true)
|
@Preview(showBackground = true)
|
||||||
@Composable
|
@Composable
|
||||||
@@ -101,12 +101,16 @@ fun SettingItem(
|
|||||||
description: String? = null,
|
description: String? = null,
|
||||||
option: String? = null,
|
option: String? = null,
|
||||||
trailingContent: @Composable (() -> Unit)? = null,
|
trailingContent: @Composable (() -> Unit)? = null,
|
||||||
onClick: () -> Unit
|
onClick: () -> Unit,
|
||||||
|
onLongClick: (() -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
ListItem(
|
ListItem(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.clip(RoundedCornerShape(4.dp))
|
.clip(RoundedCornerShape(4.dp))
|
||||||
.clickable(onClick = onClick),
|
.combinedClickable(
|
||||||
|
onClick = onClick,
|
||||||
|
onLongClick = onLongClick
|
||||||
|
),
|
||||||
leadingContent = {
|
leadingContent = {
|
||||||
when {
|
when {
|
||||||
painter != null -> {
|
painter != null -> {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ fun SplicedColumnGroup(
|
|||||||
text = title,
|
text = title,
|
||||||
style = MaterialTheme.typography.labelLarge,
|
style = MaterialTheme.typography.labelLarge,
|
||||||
color = MaterialTheme.colorScheme.primary,
|
color = MaterialTheme.colorScheme.primary,
|
||||||
modifier = Modifier.padding(start = 16.dp, bottom = 8.dp)
|
modifier = Modifier.padding(start = 12.dp, bottom = 8.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user