refactor: simplify SettingsScreen and PluginScreen by removing unused pluginManager references and enhancing DefaultAbilityPluginSelector

This commit is contained in:
Kingkor Roy Tirtho 2026-07-15 23:26:15 +06:00
parent 1ef1eff3cb
commit a590fa59f9
4 changed files with 301 additions and 307 deletions

View File

@ -85,7 +85,7 @@ val navigationModule = module {
LibraryScreen()
}
navigation<Routes.Settings> {
SettingsScreen(pluginManager = get(), settingsViewModel = koinViewModel())
SettingsScreen(settingsViewModel = koinViewModel())
}
navigation<Routes.Plugins> {
PluginScreen(pluginManager = get())

View File

@ -17,10 +17,12 @@
package dev.krtirtho.spotube.modules.plugin
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
@ -29,6 +31,10 @@ import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
@ -46,13 +52,23 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import compose.icons.FeatherIcons
import compose.icons.feathericons.Activity
import compose.icons.feathericons.AlignLeft
import compose.icons.feathericons.Check
import compose.icons.feathericons.ExternalLink
import compose.icons.feathericons.FileText
import compose.icons.feathericons.Music
import compose.icons.feathericons.Package
import dev.krtirtho.spotube.PlatformType
import dev.krtirtho.spotube.core.ui.component.AdaptiveDropdownBottomSheet
import dev.krtirtho.spotube.core.ui.component.AdaptiveMenuItem
import dev.krtirtho.spotube.core.ui.component.ApplicationMainBar
import dev.krtirtho.spotube.core.ui.component.HeaderDisplayMode
import dev.krtirtho.spotube.core.webview.WebViewController
import dev.krtirtho.spotube.getPlatform
import dev.krtirtho.spotube.modules.plugin.components.InstallSection
@ -65,6 +81,7 @@ import io.github.vinceglb.filekit.readBytes
import kotlinx.coroutines.launch
import org.jetbrains.compose.resources.stringResource
import org.koin.compose.koinInject
import kotlinx.coroutines.flow.StateFlow
import spotube.composeapp.generated.resources.Res
import spotube.composeapp.generated.resources.plugin_empty_subtitle
import spotube.composeapp.generated.resources.plugin_empty_title
@ -75,6 +92,18 @@ import spotube.composeapp.generated.resources.plugin_installed_count
import spotube.composeapp.generated.resources.plugin_installed_plural
import spotube.composeapp.generated.resources.plugin_installed_singular
import spotube.composeapp.generated.resources.plugin_screen_title
import spotube.composeapp.generated.resources.settings_plugins_action_change
import spotube.composeapp.generated.resources.settings_plugins_action_select
import spotube.composeapp.generated.resources.settings_plugins_ability_audio
import spotube.composeapp.generated.resources.settings_plugins_ability_lyrics
import spotube.composeapp.generated.resources.settings_plugins_ability_metadata
import spotube.composeapp.generated.resources.settings_plugins_ability_scrobble
import spotube.composeapp.generated.resources.settings_plugins_clear
import spotube.composeapp.generated.resources.settings_plugins_default_ability_title
import spotube.composeapp.generated.resources.settings_plugins_manage_title
import spotube.composeapp.generated.resources.settings_plugins_no_plugins
import spotube.composeapp.generated.resources.settings_plugins_no_selection
import spotube.composeapp.generated.resources.settings_plugins_plugin_content_description
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@ -189,6 +218,26 @@ fun PluginScreen(
)
}
// ── Default ability plugin selectors ─────────────────
items(PluginAbility.entries.size) { index ->
val ability = PluginAbility.entries[index]
val selectedPlugin = state.selectedPlugins[ability]
DefaultAbilityPluginSelector(
ability = ability,
selectedPlugin = selectedPlugin,
state = when (ability) {
PluginAbility.METADATA -> pluginManager.metadataPlugins
PluginAbility.AUDIO -> pluginManager.audioPlugins
PluginAbility.LYRICS -> pluginManager.lyricsPlugins
PluginAbility.SCROBBLE -> pluginManager.scrobblePlugins
},
onSelected = { plugin ->
pluginManager.setSelectedPlugin(ability, plugin)
},
onManagePlugins = { }
)
}
if (state.plugins.isEmpty()) {
item {
Box(
@ -314,3 +363,253 @@ fun PluginScreen(
}
}
@Composable
fun DefaultAbilityPluginSelector(
ability: PluginAbility,
state: StateFlow<List<PluginEntry>>,
selectedPlugin: PluginEntry? = null,
onSelected: (PluginEntry?) -> Unit = { },
onManagePlugins: () -> Unit = { }
) {
val plugins by state.collectAsStateWithLifecycle()
val noPluginsText = stringResource(Res.string.settings_plugins_no_plugins)
val clearText = stringResource(Res.string.settings_plugins_clear)
val manageText = stringResource(Res.string.settings_plugins_manage_title)
val menuItems = buildList {
if (plugins.isNotEmpty()) {
plugins.forEach { plugin ->
val isSelected = selectedPlugin?.name == plugin.name
add(
AdaptiveMenuItem(
label = plugin.name,
onClick = { onSelected(plugin) },
selected = isSelected,
)
)
}
if (selectedPlugin != null) {
add(
AdaptiveMenuItem(
icon = FeatherIcons.AlignLeft,
label = clearText,
onClick = { onSelected(null) },
dividerBefore = true,
)
)
}
} else {
add(
AdaptiveMenuItem(
label = noPluginsText,
onClick = { },
enabled = false,
)
)
}
add(
AdaptiveMenuItem(
icon = FeatherIcons.ExternalLink,
label = manageText,
onClick = onManagePlugins,
dividerBefore = true,
)
)
}
Column(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp, vertical = 4.dp)
) {
Card(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(12.dp),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f)
),
border = BorderStroke(
width = 1.dp,
color = if (selectedPlugin != null) {
MaterialTheme.colorScheme.primary.copy(alpha = 0.3f)
} else {
MaterialTheme.colorScheme.outlineVariant
}
)
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp)
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Row(
modifier = Modifier.weight(1f),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(12.dp)
) {
Surface(
modifier = Modifier.clip(RoundedCornerShape(8.dp)),
color = when (ability) {
PluginAbility.METADATA -> Color(0xFF4CAF50).copy(alpha = 0.1f)
PluginAbility.AUDIO -> Color(0xFF2196F3).copy(alpha = 0.1f)
PluginAbility.LYRICS -> Color(0xFFFFC107).copy(alpha = 0.1f)
PluginAbility.SCROBBLE -> Color(0xFF9C27B0).copy(alpha = 0.1f)
}
) {
Icon(
imageVector = when (ability) {
PluginAbility.METADATA -> FeatherIcons.FileText
PluginAbility.AUDIO -> FeatherIcons.Music
PluginAbility.LYRICS -> FeatherIcons.AlignLeft
PluginAbility.SCROBBLE -> FeatherIcons.Activity
},
contentDescription = stringResource(
Res.string.settings_plugins_plugin_content_description,
ability.displayLabel()
),
modifier = Modifier.padding(8.dp),
tint = when (ability) {
PluginAbility.METADATA -> Color(0xFF4CAF50)
PluginAbility.AUDIO -> Color(0xFF2196F3)
PluginAbility.LYRICS -> Color(0xFFFFC107)
PluginAbility.SCROBBLE -> Color(0xFF9C27B0)
}
)
}
Column(modifier = Modifier.weight(1f)) {
Text(
stringResource(
Res.string.settings_plugins_default_ability_title,
ability.displayLabel()
),
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.onSurface
)
if (selectedPlugin != null) {
Text(
selectedPlugin.name,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.padding(top = 4.dp)
)
} else {
Text(
stringResource(Res.string.settings_plugins_no_selection),
style = MaterialTheme.typography.bodySmall,
color = Color.Gray,
modifier = Modifier.padding(top = 4.dp)
)
}
}
}
AdaptiveDropdownBottomSheet(
items = menuItems,
headerDisplayMode = HeaderDisplayMode.OnlyInBottomSheet,
header = {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
Surface(
modifier = Modifier.clip(RoundedCornerShape(8.dp)),
color = when (ability) {
PluginAbility.METADATA -> Color(0xFF4CAF50).copy(alpha = 0.1f)
PluginAbility.AUDIO -> Color(0xFF2196F3).copy(alpha = 0.1f)
PluginAbility.LYRICS -> Color(0xFFFFC107).copy(alpha = 0.1f)
PluginAbility.SCROBBLE -> Color(0xFF9C27B0).copy(alpha = 0.1f)
}
) {
Icon(
imageVector = when (ability) {
PluginAbility.METADATA -> FeatherIcons.FileText
PluginAbility.AUDIO -> FeatherIcons.Music
PluginAbility.LYRICS -> FeatherIcons.AlignLeft
PluginAbility.SCROBBLE -> FeatherIcons.Activity
},
contentDescription = null,
modifier = Modifier.padding(8.dp),
tint = when (ability) {
PluginAbility.METADATA -> Color(0xFF4CAF50)
PluginAbility.AUDIO -> Color(0xFF2196F3)
PluginAbility.LYRICS -> Color(0xFFFFC107)
PluginAbility.SCROBBLE -> Color(0xFF9C27B0)
}
)
}
Column(modifier = Modifier.weight(1f)) {
Text(
stringResource(
Res.string.settings_plugins_default_ability_title,
ability.displayLabel()
),
style = MaterialTheme.typography.titleMedium,
)
selectedPlugin?.let {
Text(
it.name,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.primary,
)
}
}
}
},
trigger = { onClick ->
Button(
onClick = onClick,
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.1f),
contentColor = MaterialTheme.colorScheme.primary
),
modifier = Modifier.clip(RoundedCornerShape(8.dp))
) {
Row(
horizontalArrangement = Arrangement.spacedBy(6.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = FeatherIcons.Check,
contentDescription = null,
modifier = Modifier.padding(0.dp),
tint = MaterialTheme.colorScheme.primary
)
Text(
if (selectedPlugin != null) {
stringResource(Res.string.settings_plugins_action_change)
} else {
stringResource(Res.string.settings_plugins_action_select)
},
style = MaterialTheme.typography.labelSmall
)
}
}
},
)
}
}
}
}
}
@Composable
private fun PluginAbility.displayLabel(): String {
return when (this) {
PluginAbility.METADATA -> stringResource(Res.string.settings_plugins_ability_metadata)
PluginAbility.AUDIO -> stringResource(Res.string.settings_plugins_ability_audio)
PluginAbility.LYRICS -> stringResource(Res.string.settings_plugins_ability_lyrics)
PluginAbility.SCROBBLE -> stringResource(Res.string.settings_plugins_ability_scrobble)
}
}

View File

@ -37,7 +37,6 @@ import dev.krtirtho.spotube.PlatformType
import dev.krtirtho.spotube.getPlatform
import dev.krtirtho.spotube.core.navigation.NavigationCommands
import dev.krtirtho.spotube.core.ui.component.ApplicationMainBar
import dev.krtirtho.spotube.modules.plugin.PluginManager
import spotube.composeapp.generated.resources.*
import dev.krtirtho.spotube.modules.settings.sections.appearanceSection
import dev.krtirtho.spotube.modules.settings.sections.cacheSection
@ -54,9 +53,8 @@ import org.koin.compose.koinInject
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SettingsScreen(pluginManager: PluginManager, settingsViewModel: SettingsViewModel) {
fun SettingsScreen(settingsViewModel: SettingsViewModel) {
val navigatorCommands = koinInject<NavigationCommands>()
val pluginState by pluginManager.state.collectAsStateWithLifecycle()
val settingsState by settingsViewModel.settingsState.collectAsStateWithLifecycle()
val platformType = remember { getPlatform().type }
val isDesktopPlatform = platformType == PlatformType.Windows ||
@ -90,8 +88,6 @@ fun SettingsScreen(pluginManager: PluginManager, settingsViewModel: SettingsView
contentPadding = contentPadding,
) {
pluginsSection(
pluginManager = pluginManager,
pluginState = pluginState,
navigatorCommands = navigatorCommands,
)
if (settingsState != null) {

View File

@ -17,299 +17,29 @@
package dev.krtirtho.spotube.modules.settings.sections
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
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.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import compose.icons.FeatherIcons
import compose.icons.feathericons.Activity
import compose.icons.feathericons.AlignLeft
import compose.icons.feathericons.Check
import compose.icons.feathericons.ChevronRight
import compose.icons.feathericons.ExternalLink
import compose.icons.feathericons.FileText
import compose.icons.feathericons.Music
import compose.icons.feathericons.Package
import dev.krtirtho.spotube.core.navigation.NavigationCommands
import dev.krtirtho.spotube.core.navigation.Routes
import dev.krtirtho.spotube.core.ui.component.AdaptiveDropdownBottomSheet
import dev.krtirtho.spotube.core.ui.component.AdaptiveMenuItem
import dev.krtirtho.spotube.core.ui.component.HeaderDisplayMode
import spotube.composeapp.generated.resources.*
import dev.krtirtho.spotube.modules.plugin.PluginAbility
import dev.krtirtho.spotube.modules.plugin.PluginEntry
import dev.krtirtho.spotube.modules.plugin.PluginManager
import dev.krtirtho.spotube.modules.plugin.PluginManagerStates
import dev.krtirtho.spotube.modules.settings.components.SettingCardItem
import kotlinx.coroutines.flow.StateFlow
import org.jetbrains.compose.resources.stringResource
@Composable
fun DefaultAbilityPluginSelector(
ability: PluginAbility,
state: StateFlow<List<PluginEntry>>,
selectedPlugin: PluginEntry? = null,
onSelected: (PluginEntry?) -> Unit = { },
onManagePlugins: () -> Unit = { }
) {
val plugins by state.collectAsStateWithLifecycle()
val noPluginsText = stringResource(Res.string.settings_plugins_no_plugins)
val clearText = stringResource(Res.string.settings_plugins_clear)
val manageText = stringResource(Res.string.settings_plugins_manage_title)
val menuItems = buildList {
if (plugins.isNotEmpty()) {
plugins.forEach { plugin ->
val isSelected = selectedPlugin?.name == plugin.name
add(
AdaptiveMenuItem(
label = plugin.name,
onClick = { onSelected(plugin) },
selected = isSelected,
)
)
}
if (selectedPlugin != null) {
add(
AdaptiveMenuItem(
icon = FeatherIcons.AlignLeft,
label = clearText,
onClick = { onSelected(null) },
dividerBefore = true,
)
)
}
} else {
add(
AdaptiveMenuItem(
label = noPluginsText,
onClick = { },
enabled = false,
)
)
}
add(
AdaptiveMenuItem(
icon = FeatherIcons.ExternalLink,
label = manageText,
onClick = onManagePlugins,
dividerBefore = true,
)
)
}
Column(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp, vertical = 4.dp)
) {
Card(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(12.dp),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f)
),
border = BorderStroke(
width = 1.dp,
color = if (selectedPlugin != null) {
MaterialTheme.colorScheme.primary.copy(alpha = 0.3f)
} else {
MaterialTheme.colorScheme.outlineVariant
}
)
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp)
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Row(
modifier = Modifier.weight(1f),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(12.dp)
) {
Surface(
modifier = Modifier.clip(RoundedCornerShape(8.dp)),
color = when (ability) {
PluginAbility.METADATA -> Color(0xFF4CAF50).copy(alpha = 0.1f)
PluginAbility.AUDIO -> Color(0xFF2196F3).copy(alpha = 0.1f)
PluginAbility.LYRICS -> Color(0xFFFFC107).copy(alpha = 0.1f)
PluginAbility.SCROBBLE -> Color(0xFF9C27B0).copy(alpha = 0.1f)
}
) {
Icon(
imageVector = when (ability) {
PluginAbility.METADATA -> FeatherIcons.FileText
PluginAbility.AUDIO -> FeatherIcons.Music
PluginAbility.LYRICS -> FeatherIcons.AlignLeft
PluginAbility.SCROBBLE -> FeatherIcons.Activity
},
contentDescription = stringResource(
Res.string.settings_plugins_plugin_content_description,
ability.displayLabel()
),
modifier = Modifier.padding(8.dp),
tint = when (ability) {
PluginAbility.METADATA -> Color(0xFF4CAF50)
PluginAbility.AUDIO -> Color(0xFF2196F3)
PluginAbility.LYRICS -> Color(0xFFFFC107)
PluginAbility.SCROBBLE -> Color(0xFF9C27B0)
}
)
}
Column(modifier = Modifier.weight(1f)) {
Text(
stringResource(
Res.string.settings_plugins_default_ability_title,
ability.displayLabel()
),
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.onSurface
)
if (selectedPlugin != null) {
Text(
selectedPlugin.name,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.padding(top = 4.dp)
)
} else {
Text(
stringResource(Res.string.settings_plugins_no_selection),
style = MaterialTheme.typography.bodySmall,
color = Color.Gray,
modifier = Modifier.padding(top = 4.dp)
)
}
}
}
AdaptiveDropdownBottomSheet(
items = menuItems,
headerDisplayMode = HeaderDisplayMode.OnlyInBottomSheet,
header = {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
Surface(
modifier = Modifier.clip(RoundedCornerShape(8.dp)),
color = when (ability) {
PluginAbility.METADATA -> Color(0xFF4CAF50).copy(alpha = 0.1f)
PluginAbility.AUDIO -> Color(0xFF2196F3).copy(alpha = 0.1f)
PluginAbility.LYRICS -> Color(0xFFFFC107).copy(alpha = 0.1f)
PluginAbility.SCROBBLE -> Color(0xFF9C27B0).copy(alpha = 0.1f)
}
) {
Icon(
imageVector = when (ability) {
PluginAbility.METADATA -> FeatherIcons.FileText
PluginAbility.AUDIO -> FeatherIcons.Music
PluginAbility.LYRICS -> FeatherIcons.AlignLeft
PluginAbility.SCROBBLE -> FeatherIcons.Activity
},
contentDescription = null,
modifier = Modifier.padding(8.dp),
tint = when (ability) {
PluginAbility.METADATA -> Color(0xFF4CAF50)
PluginAbility.AUDIO -> Color(0xFF2196F3)
PluginAbility.LYRICS -> Color(0xFFFFC107)
PluginAbility.SCROBBLE -> Color(0xFF9C27B0)
}
)
}
Column(modifier = Modifier.weight(1f)) {
Text(
stringResource(
Res.string.settings_plugins_default_ability_title,
ability.displayLabel()
),
style = MaterialTheme.typography.titleMedium,
)
selectedPlugin?.let {
Text(
it.name,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.primary,
)
}
}
}
},
trigger = { onClick ->
Button(
onClick = onClick,
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.primary.copy(alpha = 0.1f),
contentColor = MaterialTheme.colorScheme.primary
),
modifier = Modifier.clip(RoundedCornerShape(8.dp))
) {
Row(
horizontalArrangement = Arrangement.spacedBy(6.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = FeatherIcons.Check,
contentDescription = null,
modifier = Modifier.padding(0.dp),
tint = MaterialTheme.colorScheme.primary
)
Text(
if (selectedPlugin != null) {
stringResource(Res.string.settings_plugins_action_change)
} else {
stringResource(Res.string.settings_plugins_action_select)
},
style = MaterialTheme.typography.labelSmall
)
}
}
},
)
}
}
}
}
}
internal fun LazyListScope.pluginsSection(
pluginManager: PluginManager,
pluginState: PluginManagerStates,
navigatorCommands: NavigationCommands
) {
item {
@ -351,35 +81,4 @@ internal fun LazyListScope.pluginsSection(
}
)
}
items(PluginAbility.entries.size) { index ->
val ability = PluginAbility.entries[index]
val selectedPlugin =
(pluginState as? PluginManagerStates.Data)?.selectedPlugins?.get(ability)
DefaultAbilityPluginSelector(
ability = ability,
selectedPlugin = selectedPlugin,
state = when (ability) {
PluginAbility.METADATA -> pluginManager.metadataPlugins
PluginAbility.AUDIO -> pluginManager.audioPlugins
PluginAbility.LYRICS -> pluginManager.lyricsPlugins
PluginAbility.SCROBBLE -> pluginManager.scrobblePlugins
},
onSelected = { plugin ->
pluginManager.setSelectedPlugin(ability, plugin)
},
onManagePlugins = {
navigatorCommands.navigateTo(Routes.Plugins)
}
)
}
}
@Composable
private fun PluginAbility.displayLabel(): String {
return when (this) {
PluginAbility.METADATA -> stringResource(Res.string.settings_plugins_ability_metadata)
PluginAbility.AUDIO -> stringResource(Res.string.settings_plugins_ability_audio)
PluginAbility.LYRICS -> stringResource(Res.string.settings_plugins_ability_lyrics)
PluginAbility.SCROBBLE -> stringResource(Res.string.settings_plugins_ability_scrobble)
}
}