Polish shared Settings screen: nav icons, profile avatar, drop restart button

Adds Material icons to each Settings hub nav row (Account, General,
Appearance, Playback, Catalogs, Add-ons, Downloads, Developer) and shows
the active profile's avatar next to the display name at the top of the hub.
Removes the "Restart app" action end-to-end (action, store handling,
FluxaAppHost plumbing) since it was a no-op in both native and shared code.
This commit is contained in:
KhooLy 2026-07-14 01:33:22 +03:00
parent c983e6702f
commit 339e525d34
6 changed files with 60 additions and 18 deletions

View file

@ -121,6 +121,7 @@ class AndroidSettingsDataSource(
return SettingsUiState(
account = SettingsAccountUiModel(
displayName = profile.profileName?.takeIf { it.isNotBlank() } ?: profile.email,
avatarUrl = profile.avatarUrl,
isGuest = profile.isGuest,
hasTrakt = !profile.traktAccessToken.isNullOrBlank(),
hasMal = !profile.malAccessToken.isNullOrBlank(),

View file

@ -82,7 +82,6 @@ fun FluxaAppHost(
onConnectSimklRequested: () -> Unit = {},
onConnectAnilistRequested: () -> Unit = {},
onCheckForUpdateRequested: () -> Unit = {},
onRestartRequested: () -> Unit = {},
onDownloadOpened: (String) -> Unit = {},
onSettingsBackRequested: () -> Unit = {},
modifier: Modifier = Modifier
@ -121,7 +120,6 @@ fun FluxaAppHost(
onConnectSimklRequested = onConnectSimklRequested,
onConnectAnilistRequested = onConnectAnilistRequested,
onCheckForUpdateRequested = onCheckForUpdateRequested,
onRestartRequested = onRestartRequested,
onDownloadOpened = onDownloadOpened,
onSettingsBackRequested = onSettingsBackRequested,
modifier = modifier
@ -163,7 +161,6 @@ fun FluxaAppHost(
onConnectSimklRequested: () -> Unit = {},
onConnectAnilistRequested: () -> Unit = {},
onCheckForUpdateRequested: () -> Unit = {},
onRestartRequested: () -> Unit = {},
onDownloadOpened: (String) -> Unit = {},
onSettingsBackRequested: () -> Unit = {},
modifier: Modifier = Modifier
@ -349,7 +346,6 @@ fun FluxaAppHost(
SettingsAction.ConnectSimklRequested -> onConnectSimklRequested()
SettingsAction.ConnectAnilistRequested -> onConnectAnilistRequested()
SettingsAction.CheckForUpdateRequested -> onCheckForUpdateRequested()
SettingsAction.RestartRequested -> onRestartRequested()
is SettingsAction.DownloadOpened -> onDownloadOpened(action.id)
else -> scope.launch { settingsStore?.dispatch(action) }
}

View file

@ -9,6 +9,7 @@ enum class SettingsCategory {
data class SettingsAccountUiModel(
val displayName: String = "",
val avatarUrl: String? = null,
val isGuest: Boolean = true,
val hasTrakt: Boolean = false,
val hasMal: Boolean = false,
@ -210,7 +211,6 @@ sealed interface SettingsAction {
data object DisconnectSyncRequested : SettingsAction
data object SwitchProfilesRequested : SettingsAction
data object CheckForUpdateRequested : SettingsAction
data object RestartRequested : SettingsAction
data class DownloadOpened(val id: String) : SettingsAction
data class DownloadCancelled(val id: String) : SettingsAction
}

View file

@ -293,13 +293,32 @@ fun SettingsInfoRow(label: String, value: String) {
}
@Composable
fun SettingsNavRow(label: String, onClick: () -> Unit) {
fun SettingsNavRow(label: String, icon: androidx.compose.ui.graphics.vector.ImageVector? = null, onClick: () -> Unit) {
Row(
modifier = Modifier.fillMaxWidth().clickable(onClick = onClick).padding(vertical = 14.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(label, color = Color.White, fontWeight = FontWeight.Medium)
Row(verticalAlignment = Alignment.CenterVertically) {
if (icon != null) {
Box(
modifier = Modifier
.size(32.dp)
.clip(RoundedCornerShape(9.dp))
.background(Color.White.copy(alpha = 0.08f)),
contentAlignment = Alignment.Center
) {
androidx.compose.material3.Icon(
imageVector = icon,
contentDescription = null,
tint = Color.White.copy(alpha = 0.85f),
modifier = Modifier.size(18.dp)
)
}
Spacer(Modifier.width(14.dp))
}
Text(label, color = Color.White, fontWeight = FontWeight.Medium)
}
Text("", color = Color.White.copy(alpha = 0.4f), fontSize = 18.sp)
}
}

View file

@ -16,6 +16,15 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AccountCircle
import androidx.compose.material.icons.filled.Code
import androidx.compose.material.icons.filled.Download
import androidx.compose.material.icons.filled.Extension
import androidx.compose.material.icons.filled.MenuBook
import androidx.compose.material.icons.filled.Palette
import androidx.compose.material.icons.filled.PlayCircle
import androidx.compose.material.icons.filled.Tune
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
@ -112,18 +121,37 @@ private fun SettingsHubContent(
onSwitchProfiles: () -> Unit,
onAction: (SettingsAction) -> Unit
) {
Text(state.account.displayName, color = Color.White, fontWeight = FontWeight.Bold, fontSize = 18.sp, modifier = Modifier.padding(vertical = 8.dp))
SettingsNavRow(AppStrings.t(lang, "auto.account")) { onNavigate(SettingsCategory.Account) }
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(vertical = 8.dp)) {
Box(
modifier = Modifier.size(44.dp).clip(CircleShape).background(Color.White.copy(alpha = 0.1f)),
contentAlignment = Alignment.Center
) {
if (!state.account.avatarUrl.isNullOrBlank()) {
com.fluxa.app.shared.image.FluxaRemoteImage(
imageUrl = state.account.avatarUrl,
cacheKey = "settings-avatar:${state.account.avatarUrl}",
contentDescription = null,
modifier = Modifier.fillMaxSize().clip(CircleShape),
contentScale = androidx.compose.ui.layout.ContentScale.Crop
)
} else {
com.fluxa.app.shared.feature.profile.ProfileDefaultAvatar(modifier = Modifier.size(26.dp))
}
}
Spacer(Modifier.width(12.dp))
Text(state.account.displayName, color = Color.White, fontWeight = FontWeight.Bold, fontSize = 18.sp)
}
SettingsNavRow(AppStrings.t(lang, "auto.account"), icon = Icons.Filled.AccountCircle) { onNavigate(SettingsCategory.Account) }
SettingsSectionHeader(AppStrings.t(lang, "settings.section_preferences"))
SettingsNavRow(AppStrings.t(lang, "auto.general")) { onNavigate(SettingsCategory.General) }
SettingsNavRow(AppStrings.t(lang, "auto.appearance")) { onNavigate(SettingsCategory.Appearance) }
SettingsNavRow(AppStrings.t(lang, "auto.playback")) { onNavigate(SettingsCategory.Playback) }
SettingsNavRow(AppStrings.t(lang, "auto.general"), icon = Icons.Filled.Tune) { onNavigate(SettingsCategory.General) }
SettingsNavRow(AppStrings.t(lang, "auto.appearance"), icon = Icons.Filled.Palette) { onNavigate(SettingsCategory.Appearance) }
SettingsNavRow(AppStrings.t(lang, "auto.playback"), icon = Icons.Filled.PlayCircle) { onNavigate(SettingsCategory.Playback) }
SettingsSectionHeader(AppStrings.t(lang, "settings.section_content"))
SettingsNavRow(AppStrings.t(lang, "auto.catalogs")) { onNavigate(SettingsCategory.Content) }
SettingsNavRow(AppStrings.t(lang, "auto.add_ons")) { onNavigate(SettingsCategory.Addons) }
SettingsNavRow(AppStrings.t(lang, "auto.downloads")) { onNavigate(SettingsCategory.Downloads) }
SettingsNavRow(AppStrings.t(lang, "auto.catalogs"), icon = Icons.Filled.MenuBook) { onNavigate(SettingsCategory.Content) }
SettingsNavRow(AppStrings.t(lang, "auto.add_ons"), icon = Icons.Filled.Extension) { onNavigate(SettingsCategory.Addons) }
SettingsNavRow(AppStrings.t(lang, "auto.downloads"), icon = Icons.Filled.Download) { onNavigate(SettingsCategory.Downloads) }
SettingsSectionHeader(AppStrings.t(lang, "settings.section_system"))
SettingsToggleRow(
@ -133,8 +161,7 @@ private fun SettingsHubContent(
onValueChanged = { onAction(SettingsAction.SystemChanged(state.system.copy(automaticUpdates = it))) }
)
SettingsActionRow(AppStrings.t(lang, "settings.check_for_updates")) { onAction(SettingsAction.CheckForUpdateRequested) }
SettingsNavRow(AppStrings.t(lang, "settings.developer")) { onNavigate(SettingsCategory.Developer) }
SettingsActionRow(AppStrings.t(lang, "auto.restart"), destructive = true) { onAction(SettingsAction.RestartRequested) }
SettingsNavRow(AppStrings.t(lang, "settings.developer"), icon = Icons.Filled.Code) { onNavigate(SettingsCategory.Developer) }
Spacer(Modifier.height(12.dp))
Text(state.system.appVersionLabel, color = Color.White.copy(alpha = 0.35f), fontSize = 11.sp)

View file

@ -43,7 +43,6 @@ class SettingsStore(
SettingsAction.DisconnectSyncRequested -> dataSource.disconnectSync()
SettingsAction.SwitchProfilesRequested -> Unit
SettingsAction.CheckForUpdateRequested -> Unit
SettingsAction.RestartRequested -> Unit
is SettingsAction.DownloadOpened -> Unit
is SettingsAction.DownloadCancelled -> dataSource.cancelDownload(action.id)
}