代码优化

This commit is contained in:
HapeLee committed 2026-05-15 17:03:41 +08:00
1 parent 584ada1819
commit f411b7136e
8 files changed
+97 -91

No files matched your search

+2 -1
View File
@@ -81,7 +81,8 @@
"Bash(dir /s /b \"D:\\\\AndroidPrj\\\\legado-with-MD3\")", "Bash(dir /s /b \"D:\\\\AndroidPrj\\\\legado-with-MD3\")",
"Bash(findstr /i \"miuix.*\\\\.kt\")", "Bash(findstr /i \"miuix.*\\\\.kt\")",
"Bash(findstr /v \"\\\\\\\\build\\\\\\\\\")", "Bash(findstr /v \"\\\\\\\\build\\\\\\\\\")",
"Bash(dir /s /b \"D:\\\\AndroidPrj\\\\legado-with-MD3\\\\.gradle\\\\*miuix*\")" "Bash(dir /s /b \"D:\\\\AndroidPrj\\\\legado-with-MD3\\\\.gradle\\\\*miuix*\")",
"Skill(legado-compose-review)"
] ]
} }
} }
@@ -2,6 +2,7 @@ package io.legado.app.ui.main
import androidx.annotation.StringRes import androidx.annotation.StringRes
import io.legado.app.R import io.legado.app.R
import io.legado.app.ui.config.themeConfig.ThemeConfig
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
sealed class MainDestination( sealed class MainDestination(
@@ -32,3 +33,11 @@ sealed class MainDestination(
val mainDestinations = persistentListOf<MainDestination>(Bookshelf, Explore, Rss, My) val mainDestinations = persistentListOf<MainDestination>(Bookshelf, Explore, Rss, My)
} }
} }
val MainDestination.customIconPath: String
get() = when (this) {
MainDestination.Bookshelf -> ThemeConfig.navIconBookshelf
MainDestination.Explore -> ThemeConfig.navIconExplore
MainDestination.Rss -> ThemeConfig.navIconRss
MainDestination.My -> ThemeConfig.navIconMy
}
@@ -1,7 +1,6 @@
package io.legado.app.ui.main package io.legado.app.ui.main
import android.content.Intent import android.content.Intent
import android.net.Uri
import android.os.Build import android.os.Build
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
@@ -24,7 +23,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.pager.rememberPagerState
@@ -52,24 +50,22 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.graphics.Color import androidx.core.net.toUri
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import coil.compose.AsyncImage
import com.kyant.backdrop.backdrops.layerBackdrop import com.kyant.backdrop.backdrops.layerBackdrop
import com.kyant.backdrop.backdrops.rememberLayerBackdrop import com.kyant.backdrop.backdrops.rememberLayerBackdrop
import dev.chrisbanes.haze.HazeState import dev.chrisbanes.haze.HazeState
import dev.chrisbanes.haze.hazeSource import dev.chrisbanes.haze.hazeSource
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.painter.BitmapPainter
import io.legado.app.R import io.legado.app.R
import io.legado.app.ui.config.themeConfig.ThemeConfig import io.legado.app.ui.config.themeConfig.ThemeConfig
import io.legado.app.ui.main.bookshelf.BookshelfScreen import io.legado.app.ui.main.bookshelf.BookshelfScreen
@@ -78,7 +74,6 @@ import io.legado.app.ui.main.explore.ExploreScreen
import io.legado.app.ui.main.my.MyScreen import io.legado.app.ui.main.my.MyScreen
import io.legado.app.ui.main.my.PrefClickEvent import io.legado.app.ui.main.my.PrefClickEvent
import io.legado.app.ui.main.rss.RssScreen import io.legado.app.ui.main.rss.RssScreen
import io.legado.app.ui.theme.regularHazeEffect
import io.legado.app.ui.widget.components.AppNavigationBar import io.legado.app.ui.widget.components.AppNavigationBar
import io.legado.app.ui.widget.components.AppNavigationBarItem import io.legado.app.ui.widget.components.AppNavigationBarItem
import io.legado.app.ui.widget.components.AppScaffold import io.legado.app.ui.widget.components.AppScaffold
@@ -95,6 +90,7 @@ import io.legado.app.utils.sendToClip
import io.legado.app.utils.showDialogFragment import io.legado.app.utils.showDialogFragment
import io.legado.app.utils.startActivityForBook import io.legado.app.utils.startActivityForBook
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.koin.androidx.compose.koinViewModel import org.koin.androidx.compose.koinViewModel
@@ -124,20 +120,21 @@ fun MainScreen(
val context = LocalContext.current val context = LocalContext.current
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
val mainUiState by viewModel.uiState.collectAsStateWithLifecycle() val mainUiState by viewModel.uiState.collectAsStateWithLifecycle()
val defaultHelpTitle = stringResource(R.string.help)
LaunchedEffect(viewModel, context) { LaunchedEffect(viewModel, context) {
viewModel.effects.collect { effect -> viewModel.effects.collectLatest { effect ->
when (effect) { when (effect) {
is MainEffect.OpenUrl -> { is MainEffect.OpenUrl -> {
context.startActivity( context.startActivity(
Intent(Intent.ACTION_VIEW, Uri.parse(effect.url)) Intent(Intent.ACTION_VIEW, effect.url.toUri())
) )
} }
is MainEffect.CopyUrl -> context.sendToClip(effect.url) is MainEffect.CopyUrl -> context.sendToClip(effect.url)
is MainEffect.ShowMarkdown -> { is MainEffect.ShowMarkdown -> {
val activity = context as? AppCompatActivity ?: return@collect val activity = context as? AppCompatActivity ?: return@collectLatest
val title = effect.title.ifBlank { context.getString(R.string.help) } val title = effect.title.ifBlank { defaultHelpTitle }
val mdText = withContext(Dispatchers.IO) { val mdText = withContext(Dispatchers.IO) {
context.assets context.assets
.open("web/help/md/${effect.path}.md") .open("web/help/md/${effect.path}.md")
@@ -288,12 +285,7 @@ fun MainScreen(
} }
}, },
label = if (labelVisibilityMode != "unlabeled") { label = if (labelVisibilityMode != "unlabeled") {
val hasCustomIcon = when (destination) { val hasCustomIcon = destination.customIconPath.isNotEmpty()
MainDestination.Bookshelf -> ThemeConfig.navIconBookshelf.isNotEmpty()
MainDestination.Explore -> ThemeConfig.navIconExplore.isNotEmpty()
MainDestination.Rss -> ThemeConfig.navIconRss.isNotEmpty()
MainDestination.My -> ThemeConfig.navIconMy.isNotEmpty()
}
if (hasCustomIcon) null else {{ AppText(stringResource(destination.labelId)) }} if (hasCustomIcon) null else {{ AppText(stringResource(destination.labelId)) }}
} else null } else null
) )
@@ -308,12 +300,7 @@ fun MainScreen(
AppNavigationBar() { AppNavigationBar() {
destinations.forEachIndexed { index, destination -> destinations.forEachIndexed { index, destination ->
val selected = pagerState.targetPage == index val selected = pagerState.targetPage == index
val customIconPath = when (destination) { val customIconPath = destination.customIconPath
MainDestination.Bookshelf -> ThemeConfig.navIconBookshelf
MainDestination.Explore -> ThemeConfig.navIconExplore
MainDestination.Rss -> ThemeConfig.navIconRss
MainDestination.My -> ThemeConfig.navIconMy
}
AppNavigationBarItem( AppNavigationBarItem(
modifier = Modifier.semantics(mergeDescendants = true) { modifier = Modifier.semantics(mergeDescendants = true) {
contentDescription = "nav_${destination.route}" contentDescription = "nav_${destination.route}"
@@ -442,22 +429,12 @@ fun MainScreen(
tabsCount = destinations.size, tabsCount = destinations.size,
isBlurEnabled = useLiquidGlass, isBlurEnabled = useLiquidGlass,
hasCustomIcons = destinations.any { dest -> hasCustomIcons = destinations.any { dest ->
when (dest) { dest.customIconPath.isNotEmpty()
MainDestination.Bookshelf -> ThemeConfig.navIconBookshelf.isNotEmpty()
MainDestination.Explore -> ThemeConfig.navIconExplore.isNotEmpty()
MainDestination.Rss -> ThemeConfig.navIconRss.isNotEmpty()
MainDestination.My -> ThemeConfig.navIconMy.isNotEmpty()
}
} }
) { ) {
destinations.forEachIndexed { index, destination -> destinations.forEachIndexed { index, destination ->
val selected = pagerState.targetPage == index val selected = pagerState.targetPage == index
val hasCustomIcon = when (destination) { val hasCustomIcon = destination.customIconPath.isNotEmpty()
MainDestination.Bookshelf -> ThemeConfig.navIconBookshelf.isNotEmpty()
MainDestination.Explore -> ThemeConfig.navIconExplore.isNotEmpty()
MainDestination.Rss -> ThemeConfig.navIconRss.isNotEmpty()
MainDestination.My -> ThemeConfig.navIconMy.isNotEmpty()
}
FloatingBottomBarItem( FloatingBottomBarItem(
onClick = { onClick = {
coroutineScope.launch { coroutineScope.launch {
@@ -536,31 +513,13 @@ private fun NavigationIcon(
selected: Boolean, selected: Boolean,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
val customIconPath = when (destination) { val customIconPath = destination.customIconPath
MainDestination.Bookshelf -> ThemeConfig.navIconBookshelf
MainDestination.Explore -> ThemeConfig.navIconExplore
MainDestination.Rss -> ThemeConfig.navIconRss
MainDestination.My -> ThemeConfig.navIconMy
}
if (customIconPath.isNotEmpty()) { if (customIconPath.isNotEmpty()) {
val context = LocalContext.current AsyncImage(
val bitmap = remember(customIconPath) { model = customIconPath,
kotlin.runCatching { contentDescription = null,
android.graphics.BitmapFactory.decodeFile(customIconPath) modifier = modifier.size(40.dp)
}.getOrNull() )
}
if (bitmap != null) {
Image(
painter = remember(bitmap) {
BitmapPainter(bitmap.asImageBitmap())
},
contentDescription = null,
modifier = modifier.size(40.dp)
)
} else {
val icon = AppIcons.mainDestination(destination, selected)
AppIcon(icon, contentDescription = null, modifier = modifier)
}
} else { } else {
val icon = AppIcons.mainDestination(destination, selected) val icon = AppIcons.mainDestination(destination, selected)
AppIcon(icon, contentDescription = null, modifier = modifier) AppIcon(icon, contentDescription = null, modifier = modifier)
@@ -2,9 +2,10 @@ package io.legado.app.ui.main
import android.app.Application import android.app.Application
import android.content.SharedPreferences import android.content.SharedPreferences
import androidx.compose.runtime.Stable
import io.legado.app.base.BaseViewModel import io.legado.app.base.BaseViewModel
import io.legado.app.constant.PreferKey
import io.legado.app.constant.EventBus import io.legado.app.constant.EventBus
import io.legado.app.constant.PreferKey
import io.legado.app.domain.usecase.AppStartupMaintenanceUseCase import io.legado.app.domain.usecase.AppStartupMaintenanceUseCase
import io.legado.app.domain.usecase.WebDavBackupUseCase import io.legado.app.domain.usecase.WebDavBackupUseCase
import io.legado.app.ui.config.themeConfig.ThemeConfig import io.legado.app.ui.config.themeConfig.ThemeConfig
@@ -13,13 +14,13 @@ import io.legado.app.utils.defaultSharedPreferences
import io.legado.app.utils.eventBus.FlowEventBus import io.legado.app.utils.eventBus.FlowEventBus
import io.legado.app.utils.getPrefBoolean import io.legado.app.utils.getPrefBoolean
import io.legado.app.utils.getPrefString import io.legado.app.utils.getPrefString
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
class MainViewModel( class MainViewModel(
application: Application, application: Application,
@@ -133,6 +134,7 @@ sealed interface MainEffect {
data object NavigateToReadRecord : MainEffect data object NavigateToReadRecord : MainEffect
} }
@Stable
data class MainUiState( data class MainUiState(
val destinations: ImmutableList<MainDestination> = MainDestination.mainDestinations, val destinations: ImmutableList<MainDestination> = MainDestination.mainDestinations,
val defaultHomePage: String = "bookshelf", val defaultHomePage: String = "bookshelf",
@@ -1,6 +1,7 @@
package io.legado.app.ui.main.my package io.legado.app.ui.main.my
import android.app.Application import android.app.Application
import androidx.compose.runtime.Stable
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import io.legado.app.base.BaseViewModel import io.legado.app.base.BaseViewModel
import io.legado.app.constant.EventBus import io.legado.app.constant.EventBus
@@ -12,6 +13,7 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@Stable
data class MyUiState( data class MyUiState(
val isWebServiceRun: Boolean = false, val isWebServiceRun: Boolean = false,
val webServiceAddress: String = "" val webServiceAddress: String = ""
@@ -5,7 +5,6 @@ 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
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
@@ -18,27 +17,22 @@ import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Login import androidx.compose.material.icons.automirrored.filled.Login
import androidx.compose.material.icons.automirrored.outlined.Label
import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Edit import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.Group
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material.icons.filled.Star import androidx.compose.material.icons.filled.Star
import androidx.compose.material.icons.filled.Subscriptions import androidx.compose.material.icons.filled.Subscriptions
import androidx.compose.material.icons.filled.VerticalAlignTop import androidx.compose.material.icons.filled.VerticalAlignTop
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.setValue
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
@@ -59,7 +53,6 @@ import io.legado.app.ui.theme.LegadoTheme
import io.legado.app.ui.theme.adaptiveContentPadding import io.legado.app.ui.theme.adaptiveContentPadding
import io.legado.app.ui.widget.components.SourceIcon import io.legado.app.ui.widget.components.SourceIcon
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.topbar.TopBarActionButton
import io.legado.app.ui.widget.components.divider.PillDivider import io.legado.app.ui.widget.components.divider.PillDivider
import io.legado.app.ui.widget.components.divider.PillHeaderDivider import io.legado.app.ui.widget.components.divider.PillHeaderDivider
import io.legado.app.ui.widget.components.list.ListScaffold import io.legado.app.ui.widget.components.list.ListScaffold
@@ -67,6 +60,7 @@ import io.legado.app.ui.widget.components.menuItem.MenuItemIcon
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
import io.legado.app.ui.widget.components.text.AppText import io.legado.app.ui.widget.components.text.AppText
import io.legado.app.ui.widget.components.topbar.TopBarActionButton
import io.legado.app.utils.openUrl import io.legado.app.utils.openUrl
import io.legado.app.utils.startActivity import io.legado.app.utils.startActivity
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
@@ -103,23 +97,35 @@ fun RssScreen(
is RssEffect.OpenExternalUrl -> { is RssEffect.OpenExternalUrl -> {
currentContext.openUrl(effect.url) currentContext.openUrl(effect.url)
} }
is RssEffect.OpenSourceEdit -> {
currentContext.startActivity<RssSourceEditActivity> {
putExtra("sourceUrl", effect.sourceUrl)
}
}
is RssEffect.Login -> {
currentContext.startActivity<SourceLoginActivity> {
putExtra("type", "rssSource")
putExtra("key", effect.sourceUrl)
}
}
RssEffect.OpenRuleSub -> {
currentContext.startActivity<RuleSubActivity>()
}
RssEffect.OpenFavorites -> {
currentContext.startActivity<RssFavoritesActivity>()
}
RssEffect.OpenSourceManage -> {
currentContext.startActivity<RssSourceActivity>()
}
} }
} }
} }
val edit: (RssSource) -> Unit = { rssSource ->
context.startActivity<RssSourceEditActivity> {
putExtra("sourceUrl", rssSource.sourceUrl)
}
}
val login: (RssSource) -> Unit = { rssSource ->
context.startActivity<SourceLoginActivity> {
putExtra("type", "rssSource")
putExtra("key", rssSource.sourceUrl)
}
}
ListScaffold( ListScaffold(
title = stringResource(R.string.rss), title = stringResource(R.string.rss),
state = uiState, state = uiState,
@@ -130,12 +136,12 @@ fun RssScreen(
searchPlaceholder = stringResource(R.string.search_rss_source), searchPlaceholder = stringResource(R.string.search_rss_source),
topBarActions = { topBarActions = {
TopBarActionButton( TopBarActionButton(
onClick = { context.startActivity<RuleSubActivity>() }, onClick = { viewModel.openRuleSub() },
imageVector = Icons.Default.Subscriptions, imageVector = Icons.Default.Subscriptions,
contentDescription = stringResource(R.string.rule_subscription) contentDescription = stringResource(R.string.rule_subscription)
) )
TopBarActionButton( TopBarActionButton(
onClick = { context.startActivity<RssFavoritesActivity>() }, onClick = { viewModel.openFavorites() },
imageVector = Icons.Default.Star, imageVector = Icons.Default.Star,
contentDescription = stringResource(R.string.favorite) contentDescription = stringResource(R.string.favorite)
) )
@@ -143,7 +149,7 @@ fun RssScreen(
dropDownMenuContent = { dismiss -> dropDownMenuContent = { dismiss ->
RoundDropdownMenuItem( RoundDropdownMenuItem(
onClick = { onClick = {
context.startActivity<RssSourceActivity>() viewModel.openSourceManage()
dismiss() dismiss()
}, },
text = stringResource(R.string.rss_feed_management), text = stringResource(R.string.rss_feed_management),
@@ -183,10 +189,10 @@ fun RssScreen(
source = source, source = source,
onClick = { viewModel.openSource(source) }, onClick = { viewModel.openSource(source) },
onTop = { viewModel.topSource(source) }, onTop = { viewModel.topSource(source) },
onEdit = { edit(source) }, onEdit = { viewModel.openSourceEdit(source) },
onDelete = { sourceToDeleteUrl = source.sourceUrl }, onDelete = { sourceToDeleteUrl = source.sourceUrl },
onDisable = { viewModel.disable(source) }, onDisable = { viewModel.disable(source) },
onLogin = { login(source) } onLogin = { viewModel.login(source) }
) )
} }
} }
@@ -1,5 +1,6 @@
package io.legado.app.ui.main.rss package io.legado.app.ui.main.rss
import androidx.compose.runtime.Stable
import io.legado.app.data.entities.RssSource import io.legado.app.data.entities.RssSource
import io.legado.app.ui.widget.components.list.ListUiState import io.legado.app.ui.widget.components.list.ListUiState
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
@@ -7,6 +8,7 @@ import kotlinx.collections.immutable.ImmutableSet
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentSetOf import kotlinx.collections.immutable.persistentSetOf
@Stable
data class RssUiState( data class RssUiState(
override val items: ImmutableList<RssSource> = persistentListOf(), override val items: ImmutableList<RssSource> = persistentListOf(),
override val selectedIds: ImmutableSet<String> = persistentSetOf(), override val selectedIds: ImmutableSet<String> = persistentSetOf(),
@@ -116,6 +116,26 @@ class RssViewModel(
} }
} }
fun openSourceEdit(rssSource: RssSource) {
_effects.tryEmit(RssEffect.OpenSourceEdit(rssSource.sourceUrl))
}
fun login(rssSource: RssSource) {
_effects.tryEmit(RssEffect.Login(rssSource.sourceUrl))
}
fun openRuleSub() {
_effects.tryEmit(RssEffect.OpenRuleSub)
}
fun openFavorites() {
_effects.tryEmit(RssEffect.OpenFavorites)
}
fun openSourceManage() {
_effects.tryEmit(RssEffect.OpenSourceManage)
}
fun openSource(rssSource: RssSource) { fun openSource(rssSource: RssSource) {
if (!rssSource.singleUrl) { if (!rssSource.singleUrl) {
_effects.tryEmit(RssEffect.OpenSort(rssSource.sourceUrl, null, null)) _effects.tryEmit(RssEffect.OpenSort(rssSource.sourceUrl, null, null))
@@ -186,4 +206,9 @@ sealed interface RssEffect {
) : RssEffect ) : RssEffect
data class OpenExternalUrl(val url: String) : RssEffect data class OpenExternalUrl(val url: String) : RssEffect
data class OpenSourceEdit(val sourceUrl: String) : RssEffect
data class Login(val sourceUrl: String) : RssEffect
data object OpenRuleSub : RssEffect
data object OpenFavorites : RssEffect
data object OpenSourceManage : RssEffect
} }