mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 15:50:16 +02:00
Fixing Settings sticky header text overlapping with menu items (#928)
## Description - Adding a background for the Settings stickyHeader. This helps with visibility and prevents overlap with the menu items when scrolling. ### Related issues In the Settings screen, the header can overlap the text of the menu items when scrolling down. This is a minor UI bug only and does not affect functionality at all, but the fix seemed easy and harmless so I figured I'd give it a go. ### Testing Tested manually on TCL model 50S434 running Android TV. Tested manually using AVD emulation on Television (1080p) and Television (4K) preset devices. Reproduced the problem on all 3 devices and confirmed that my fix works across all. ## Screenshots Before: <img width="1920" height="1080" alt="before-settings-fix" src="https://github.com/user-attachments/assets/15f9916d-2583-4dc4-8302-cb1f3a395b1a" /> After: <img width="1920" height="1080" alt="after-settings-fix" src="https://github.com/user-attachments/assets/3f8781aa-7063-4eb4-bf4a-95ff34b9b1a1" /> ## AI or LLM usage None --------- Co-authored-by: Ray <154766448+damontecres@users.noreply.github.com>
This commit is contained in:
parent
7939fffd48
commit
55b148971e
1 changed files with 290 additions and 286 deletions
|
|
@ -11,8 +11,10 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.interaction.collectIsFocusedAsState
|
import androidx.compose.foundation.interaction.collectIsFocusedAsState
|
||||||
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.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
|
@ -166,308 +168,310 @@ fun PreferencesContent(
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
focusRequester.tryRequestFocus()
|
focusRequester.tryRequestFocus()
|
||||||
}
|
}
|
||||||
LazyColumn(
|
Column(
|
||||||
state = state,
|
|
||||||
horizontalAlignment = Alignment.Start,
|
|
||||||
verticalArrangement = Arrangement.spacedBy(0.dp),
|
|
||||||
contentPadding = PaddingValues(16.dp),
|
|
||||||
modifier = Modifier.background(MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp)),
|
modifier = Modifier.background(MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp)),
|
||||||
) {
|
) {
|
||||||
stickyHeader {
|
Text(
|
||||||
Text(
|
text = stringResource(screenTitle),
|
||||||
text = stringResource(screenTitle),
|
style = MaterialTheme.typography.headlineSmall,
|
||||||
style = MaterialTheme.typography.headlineSmall,
|
color = MaterialTheme.colorScheme.onSurface,
|
||||||
color = MaterialTheme.colorScheme.onSurface,
|
textAlign = TextAlign.Center,
|
||||||
textAlign = TextAlign.Center,
|
modifier =
|
||||||
modifier =
|
Modifier
|
||||||
Modifier
|
.fillMaxWidth()
|
||||||
.fillMaxWidth()
|
.padding(vertical = 8.dp),
|
||||||
.padding(vertical = 8.dp),
|
)
|
||||||
)
|
LazyColumn(
|
||||||
}
|
state = state,
|
||||||
if (UpdateChecker.ACTIVE &&
|
horizontalAlignment = Alignment.Start,
|
||||||
preferenceScreenOption == PreferenceScreenOption.BASIC &&
|
verticalArrangement = Arrangement.spacedBy(0.dp),
|
||||||
preferences.autoCheckForUpdates &&
|
contentPadding = PaddingValues(16.dp),
|
||||||
updateAvailable
|
modifier = Modifier.fillMaxSize(),
|
||||||
) {
|
) {
|
||||||
item {
|
if (UpdateChecker.ACTIVE &&
|
||||||
val updateFocusRequester = remember { FocusRequester() }
|
preferenceScreenOption == PreferenceScreenOption.BASIC &&
|
||||||
LaunchedEffect(Unit) {
|
preferences.autoCheckForUpdates &&
|
||||||
if (focusedIndex.first == 0 && focusedIndex.second == 0) {
|
updateAvailable
|
||||||
// Only re-focus if the user hasn't moved
|
) {
|
||||||
updateFocusRequester.tryRequestFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ClickPreference(
|
|
||||||
title = stringResource(R.string.install_update),
|
|
||||||
onClick = {
|
|
||||||
if (movementSounds) playOnClickSound(context)
|
|
||||||
viewModel.navigationManager.navigateTo(Destination.UpdateApp)
|
|
||||||
},
|
|
||||||
summary = release?.version?.toString(),
|
|
||||||
modifier =
|
|
||||||
Modifier
|
|
||||||
.focusRequester(updateFocusRequester)
|
|
||||||
.playSoundOnFocus(movementSounds),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prefList.forEachIndexed { groupIndex, group ->
|
|
||||||
item {
|
|
||||||
Text(
|
|
||||||
text = stringResource(group.title),
|
|
||||||
style = MaterialTheme.typography.titleMedium,
|
|
||||||
color = MaterialTheme.colorScheme.onSurface,
|
|
||||||
textAlign = TextAlign.Start,
|
|
||||||
modifier =
|
|
||||||
Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(top = 8.dp, bottom = 4.dp),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
val groupPreferences =
|
|
||||||
group.preferences +
|
|
||||||
group.conditionalPreferences
|
|
||||||
.filter { it.condition.invoke(preferences) }
|
|
||||||
.map { it.preferences }
|
|
||||||
.flatten()
|
|
||||||
groupPreferences.forEachIndexed { prefIndex, pref ->
|
|
||||||
pref as AppPreference<AppPreferences, Any>
|
|
||||||
item {
|
item {
|
||||||
val interactionSource = remember { MutableInteractionSource() }
|
val updateFocusRequester = remember { FocusRequester() }
|
||||||
val focused = interactionSource.collectIsFocusedAsState().value
|
LaunchedEffect(Unit) {
|
||||||
LaunchedEffect(focused) {
|
if (focusedIndex.first == 0 && focusedIndex.second == 0) {
|
||||||
if (focused) {
|
// Only re-focus if the user hasn't moved
|
||||||
focusedIndex = Pair(groupIndex, prefIndex)
|
updateFocusRequester.tryRequestFocus()
|
||||||
if (movementSounds) playOnClickSound(context)
|
|
||||||
onFocus.invoke(groupIndex, prefIndex)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
when (pref) {
|
ClickPreference(
|
||||||
AppPreference.InstalledVersion -> {
|
title = stringResource(R.string.install_update),
|
||||||
var clickCount by remember { mutableIntStateOf(0) }
|
onClick = {
|
||||||
ClickPreference(
|
if (movementSounds) playOnClickSound(context)
|
||||||
title = stringResource(R.string.installed_version),
|
viewModel.navigationManager.navigateTo(Destination.UpdateApp)
|
||||||
onClick = {
|
},
|
||||||
if (movementSounds) playOnClickSound(context)
|
summary = release?.version?.toString(),
|
||||||
if (clickCount++ >= 2) {
|
modifier =
|
||||||
clickCount = 0
|
Modifier
|
||||||
viewModel.navigationManager.navigateTo(Destination.Debug)
|
.focusRequester(updateFocusRequester)
|
||||||
}
|
.playSoundOnFocus(movementSounds),
|
||||||
},
|
)
|
||||||
summary = installedVersion.toString(),
|
}
|
||||||
interactionSource = interactionSource,
|
}
|
||||||
modifier =
|
prefList.forEachIndexed { groupIndex, group ->
|
||||||
Modifier
|
item {
|
||||||
.ifElse(
|
Text(
|
||||||
groupIndex == focusedIndex.first && prefIndex == focusedIndex.second,
|
text = stringResource(group.title),
|
||||||
Modifier.focusRequester(focusRequester),
|
style = MaterialTheme.typography.titleMedium,
|
||||||
),
|
color = MaterialTheme.colorScheme.onSurface,
|
||||||
)
|
textAlign = TextAlign.Start,
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 8.dp, bottom = 4.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val groupPreferences =
|
||||||
|
group.preferences +
|
||||||
|
group.conditionalPreferences
|
||||||
|
.filter { it.condition.invoke(preferences) }
|
||||||
|
.map { it.preferences }
|
||||||
|
.flatten()
|
||||||
|
groupPreferences.forEachIndexed { prefIndex, pref ->
|
||||||
|
pref as AppPreference<AppPreferences, Any>
|
||||||
|
item {
|
||||||
|
val interactionSource = remember { MutableInteractionSource() }
|
||||||
|
val focused = interactionSource.collectIsFocusedAsState().value
|
||||||
|
LaunchedEffect(focused) {
|
||||||
|
if (focused) {
|
||||||
|
focusedIndex = Pair(groupIndex, prefIndex)
|
||||||
|
if (movementSounds) playOnClickSound(context)
|
||||||
|
onFocus.invoke(groupIndex, prefIndex)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
when (pref) {
|
||||||
AppPreference.Update -> {
|
AppPreference.InstalledVersion -> {
|
||||||
ClickPreference(
|
var clickCount by remember { mutableIntStateOf(0) }
|
||||||
title =
|
ClickPreference(
|
||||||
if (release != null && updateAvailable) {
|
title = stringResource(R.string.installed_version),
|
||||||
stringResource(R.string.install_update)
|
onClick = {
|
||||||
} else if (!preferences.autoCheckForUpdates && release == null) {
|
if (movementSounds) playOnClickSound(context)
|
||||||
stringResource(R.string.check_for_updates)
|
if (clickCount++ >= 2) {
|
||||||
} else {
|
clickCount = 0
|
||||||
stringResource(R.string.no_update_available)
|
viewModel.navigationManager.navigateTo(Destination.Debug)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onClick = {
|
summary = installedVersion.toString(),
|
||||||
if (movementSounds) playOnClickSound(context)
|
interactionSource = interactionSource,
|
||||||
if (release != null && updateAvailable) {
|
modifier =
|
||||||
release?.let {
|
Modifier
|
||||||
viewModel.navigationManager.navigateTo(Destination.UpdateApp)
|
.ifElse(
|
||||||
|
groupIndex == focusedIndex.first && prefIndex == focusedIndex.second,
|
||||||
|
Modifier.focusRequester(focusRequester),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
AppPreference.Update -> {
|
||||||
|
ClickPreference(
|
||||||
|
title =
|
||||||
|
if (release != null && updateAvailable) {
|
||||||
|
stringResource(R.string.install_update)
|
||||||
|
} else if (!preferences.autoCheckForUpdates && release == null) {
|
||||||
|
stringResource(R.string.check_for_updates)
|
||||||
|
} else {
|
||||||
|
stringResource(R.string.no_update_available)
|
||||||
|
},
|
||||||
|
onClick = {
|
||||||
|
if (movementSounds) playOnClickSound(context)
|
||||||
|
if (release != null && updateAvailable) {
|
||||||
|
release?.let {
|
||||||
|
viewModel.navigationManager.navigateTo(Destination.UpdateApp)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
updateVM.init(preferences.updateUrl)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
updateVM.init(preferences.updateUrl)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onLongClick = {
|
|
||||||
if (movementSounds) playOnClickSound(context)
|
|
||||||
viewModel.navigationManager.navigateTo(Destination.UpdateApp)
|
|
||||||
},
|
|
||||||
summary =
|
|
||||||
if (updateAvailable) {
|
|
||||||
release?.version?.toString()
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
},
|
},
|
||||||
interactionSource = interactionSource,
|
onLongClick = {
|
||||||
modifier =
|
if (movementSounds) playOnClickSound(context)
|
||||||
Modifier
|
viewModel.navigationManager.navigateTo(Destination.UpdateApp)
|
||||||
.ifElse(
|
|
||||||
groupIndex == focusedIndex.first && prefIndex == focusedIndex.second,
|
|
||||||
Modifier.focusRequester(focusRequester),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
AppPreference.ClearImageCache -> {
|
|
||||||
val summary =
|
|
||||||
remember(cacheUsage) {
|
|
||||||
cacheUsage.let {
|
|
||||||
val diskMB = it.imageDiskUsed / AppPreference.MEGA_BIT
|
|
||||||
val memoryUsedMB =
|
|
||||||
it.imageMemoryUsed / AppPreference.MEGA_BIT
|
|
||||||
val memoryMaxMB =
|
|
||||||
it.imageMemoryMax / AppPreference.MEGA_BIT
|
|
||||||
"Disk: ${diskMB}mb, Memory: ${memoryUsedMB}mb/${memoryMaxMB}mb"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ClickPreference(
|
|
||||||
title = stringResource(pref.title),
|
|
||||||
onClick = {
|
|
||||||
SingletonImageLoader.get(context).let {
|
|
||||||
it.memoryCache?.clear()
|
|
||||||
it.diskCache?.clear()
|
|
||||||
updateCache = true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
modifier = Modifier,
|
|
||||||
summary = summary,
|
|
||||||
onLongClick = {},
|
|
||||||
interactionSource = interactionSource,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
AppPreference.UserPinnedNavDrawerItems -> {
|
|
||||||
NavDrawerPreference(
|
|
||||||
title = stringResource(pref.title),
|
|
||||||
summary = pref.summary(context, null),
|
|
||||||
modifier = Modifier,
|
|
||||||
interactionSource = interactionSource,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
AppPreference.SendAppLogs -> {
|
|
||||||
ClickPreference(
|
|
||||||
title = stringResource(pref.title),
|
|
||||||
onClick = {
|
|
||||||
viewModel.sendAppLogs()
|
|
||||||
},
|
|
||||||
modifier = Modifier,
|
|
||||||
summary = pref.summary(context, null),
|
|
||||||
onLongClick = {},
|
|
||||||
interactionSource = interactionSource,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
SubtitleSettings.Reset -> {
|
|
||||||
ClickPreference(
|
|
||||||
title = stringResource(pref.title),
|
|
||||||
onClick = {
|
|
||||||
viewModel.resetSubtitleSettings()
|
|
||||||
},
|
|
||||||
modifier = Modifier,
|
|
||||||
summary = pref.summary(context, null),
|
|
||||||
onLongClick = {},
|
|
||||||
interactionSource = interactionSource,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
AppPreference.RequireProfilePin -> {
|
|
||||||
SwitchPreference(
|
|
||||||
title = stringResource(pref.title),
|
|
||||||
value = currentUser?.pin.isNotNullOrBlank(),
|
|
||||||
onClick = {
|
|
||||||
showPinFlow = true
|
|
||||||
},
|
|
||||||
summaryOn = stringResource(R.string.enabled),
|
|
||||||
summaryOff = null,
|
|
||||||
modifier = Modifier,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
AppPreference.SeerrIntegration -> {
|
|
||||||
ClickPreference(
|
|
||||||
title = stringResource(pref.title),
|
|
||||||
onClick = {
|
|
||||||
seerrDialogMode =
|
|
||||||
when (val conn = seerrConnection) {
|
|
||||||
is SeerrConnectionStatus.Error -> {
|
|
||||||
SeerrDialogMode.Error(conn.serverUrl, conn.ex)
|
|
||||||
}
|
|
||||||
|
|
||||||
SeerrConnectionStatus.NotConfigured -> {
|
|
||||||
SeerrDialogMode.Add
|
|
||||||
}
|
|
||||||
|
|
||||||
is SeerrConnectionStatus.Success -> {
|
|
||||||
SeerrDialogMode.Remove(
|
|
||||||
conn.current.server.url,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
modifier = Modifier,
|
|
||||||
summary =
|
|
||||||
when (seerrConnection) {
|
|
||||||
is SeerrConnectionStatus.Error -> stringResource(R.string.voice_error_server)
|
|
||||||
SeerrConnectionStatus.NotConfigured -> stringResource(R.string.add_server)
|
|
||||||
is SeerrConnectionStatus.Success -> stringResource(R.string.enabled)
|
|
||||||
},
|
},
|
||||||
onLongClick = {},
|
summary =
|
||||||
interactionSource = interactionSource,
|
if (updateAvailable) {
|
||||||
)
|
release?.version?.toString()
|
||||||
}
|
} else {
|
||||||
|
null
|
||||||
|
},
|
||||||
|
interactionSource = interactionSource,
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.ifElse(
|
||||||
|
groupIndex == focusedIndex.first && prefIndex == focusedIndex.second,
|
||||||
|
Modifier.focusRequester(focusRequester),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
AppPreference.QuickConnect -> {
|
AppPreference.ClearImageCache -> {
|
||||||
ClickPreference(
|
val summary =
|
||||||
title = stringResource(pref.title),
|
remember(cacheUsage) {
|
||||||
onClick = {
|
cacheUsage.let {
|
||||||
if (currentUser != null) {
|
val diskMB = it.imageDiskUsed / AppPreference.MEGA_BIT
|
||||||
viewModel.resetQuickConnectStatus()
|
val memoryUsedMB =
|
||||||
showQuickConnectDialog = true
|
it.imageMemoryUsed / AppPreference.MEGA_BIT
|
||||||
}
|
val memoryMaxMB =
|
||||||
},
|
it.imageMemoryMax / AppPreference.MEGA_BIT
|
||||||
modifier = Modifier,
|
"Disk: ${diskMB}mb, Memory: ${memoryUsedMB}mb/${memoryMaxMB}mb"
|
||||||
summary = pref.summary(context, null),
|
|
||||||
onLongClick = {},
|
|
||||||
interactionSource = interactionSource,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
val value = pref.getter.invoke(preferences)
|
|
||||||
ComposablePreference(
|
|
||||||
preference = pref,
|
|
||||||
value = value,
|
|
||||||
onNavigate = viewModel.navigationManager::navigateTo,
|
|
||||||
onValueChange = { newValue ->
|
|
||||||
val validation = pref.validate(newValue)
|
|
||||||
when (validation) {
|
|
||||||
is PreferenceValidation.Invalid -> {
|
|
||||||
// TODO?
|
|
||||||
Toast
|
|
||||||
.makeText(
|
|
||||||
context,
|
|
||||||
validation.message,
|
|
||||||
Toast.LENGTH_SHORT,
|
|
||||||
).show()
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
ClickPreference(
|
||||||
|
title = stringResource(pref.title),
|
||||||
|
onClick = {
|
||||||
|
SingletonImageLoader.get(context).let {
|
||||||
|
it.memoryCache?.clear()
|
||||||
|
it.diskCache?.clear()
|
||||||
|
updateCache = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifier = Modifier,
|
||||||
|
summary = summary,
|
||||||
|
onLongClick = {},
|
||||||
|
interactionSource = interactionSource,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
PreferenceValidation.Valid -> {
|
AppPreference.UserPinnedNavDrawerItems -> {
|
||||||
scope.launch(ExceptionHandler()) {
|
NavDrawerPreference(
|
||||||
preferences =
|
title = stringResource(pref.title),
|
||||||
viewModel.preferenceDataStore.updateData { prefs ->
|
summary = pref.summary(context, null),
|
||||||
pref.setter(prefs, newValue)
|
modifier = Modifier,
|
||||||
}
|
interactionSource = interactionSource,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
AppPreference.SendAppLogs -> {
|
||||||
|
ClickPreference(
|
||||||
|
title = stringResource(pref.title),
|
||||||
|
onClick = {
|
||||||
|
viewModel.sendAppLogs()
|
||||||
|
},
|
||||||
|
modifier = Modifier,
|
||||||
|
summary = pref.summary(context, null),
|
||||||
|
onLongClick = {},
|
||||||
|
interactionSource = interactionSource,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
SubtitleSettings.Reset -> {
|
||||||
|
ClickPreference(
|
||||||
|
title = stringResource(pref.title),
|
||||||
|
onClick = {
|
||||||
|
viewModel.resetSubtitleSettings()
|
||||||
|
},
|
||||||
|
modifier = Modifier,
|
||||||
|
summary = pref.summary(context, null),
|
||||||
|
onLongClick = {},
|
||||||
|
interactionSource = interactionSource,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
AppPreference.RequireProfilePin -> {
|
||||||
|
SwitchPreference(
|
||||||
|
title = stringResource(pref.title),
|
||||||
|
value = currentUser?.pin.isNotNullOrBlank(),
|
||||||
|
onClick = {
|
||||||
|
showPinFlow = true
|
||||||
|
},
|
||||||
|
summaryOn = stringResource(R.string.enabled),
|
||||||
|
summaryOff = null,
|
||||||
|
modifier = Modifier,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
AppPreference.SeerrIntegration -> {
|
||||||
|
ClickPreference(
|
||||||
|
title = stringResource(pref.title),
|
||||||
|
onClick = {
|
||||||
|
seerrDialogMode =
|
||||||
|
when (val conn = seerrConnection) {
|
||||||
|
is SeerrConnectionStatus.Error -> {
|
||||||
|
SeerrDialogMode.Error(conn.serverUrl, conn.ex)
|
||||||
|
}
|
||||||
|
|
||||||
|
SeerrConnectionStatus.NotConfigured -> {
|
||||||
|
SeerrDialogMode.Add
|
||||||
|
}
|
||||||
|
|
||||||
|
is SeerrConnectionStatus.Success -> {
|
||||||
|
SeerrDialogMode.Remove(
|
||||||
|
conn.current.server.url,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifier = Modifier,
|
||||||
|
summary =
|
||||||
|
when (seerrConnection) {
|
||||||
|
is SeerrConnectionStatus.Error -> stringResource(R.string.voice_error_server)
|
||||||
|
SeerrConnectionStatus.NotConfigured -> stringResource(R.string.add_server)
|
||||||
|
is SeerrConnectionStatus.Success -> stringResource(R.string.enabled)
|
||||||
|
},
|
||||||
|
onLongClick = {},
|
||||||
|
interactionSource = interactionSource,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
AppPreference.QuickConnect -> {
|
||||||
|
ClickPreference(
|
||||||
|
title = stringResource(pref.title),
|
||||||
|
onClick = {
|
||||||
|
if (currentUser != null) {
|
||||||
|
viewModel.resetQuickConnectStatus()
|
||||||
|
showQuickConnectDialog = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifier = Modifier,
|
||||||
|
summary = pref.summary(context, null),
|
||||||
|
onLongClick = {},
|
||||||
|
interactionSource = interactionSource,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
val value = pref.getter.invoke(preferences)
|
||||||
|
ComposablePreference(
|
||||||
|
preference = pref,
|
||||||
|
value = value,
|
||||||
|
onNavigate = viewModel.navigationManager::navigateTo,
|
||||||
|
onValueChange = { newValue ->
|
||||||
|
val validation = pref.validate(newValue)
|
||||||
|
when (validation) {
|
||||||
|
is PreferenceValidation.Invalid -> {
|
||||||
|
// TODO?
|
||||||
|
Toast
|
||||||
|
.makeText(
|
||||||
|
context,
|
||||||
|
validation.message,
|
||||||
|
Toast.LENGTH_SHORT,
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
PreferenceValidation.Valid -> {
|
||||||
|
scope.launch(ExceptionHandler()) {
|
||||||
|
preferences =
|
||||||
|
viewModel.preferenceDataStore.updateData { prefs ->
|
||||||
|
pref.setter(prefs, newValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
interactionSource = interactionSource,
|
||||||
interactionSource = interactionSource,
|
modifier =
|
||||||
modifier =
|
Modifier
|
||||||
Modifier
|
.ifElse(
|
||||||
.ifElse(
|
groupIndex == focusedIndex.first && prefIndex == focusedIndex.second,
|
||||||
groupIndex == focusedIndex.first && prefIndex == focusedIndex.second,
|
Modifier.focusRequester(focusRequester),
|
||||||
Modifier.focusRequester(focusRequester),
|
),
|
||||||
),
|
)
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue