mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-12 19:41:10 +00:00
fix(ui): flip booleans with a switch instead of on/off menus
This commit is contained in:
3 files changed
+50
-11
No files matched your search
@@ -278,15 +278,13 @@ internal fun SetupPanel(
|
||||
FrameGenMenu(s, a, host)
|
||||
}
|
||||
}
|
||||
SettingsRow("Session logs", "${if (s.logsEnabled) "Enabled" else "Disabled"} · logs are saved after each session") {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) {
|
||||
SecondaryButton(if (s.logsEnabled) "Turn off" else "Turn on") { a.onLogs() }
|
||||
SecondaryButton("Share latest") { a.onShareLogs() }
|
||||
}
|
||||
}
|
||||
SettingsRow("Offline mode", s.offlineAccount?.let { if (s.offline) "Enabled for $it" else "Signed in as $it" } ?: "Sign in to Steam first") {
|
||||
SecondaryButton(if (s.offline) "Turn off" else "Turn on", enabled = s.offlineAccount != null) { a.onOffline() }
|
||||
}
|
||||
ToggleRow(host, "logs", "Session logs", "Saved after each session", s.logsEnabled) { a.onLogs() }
|
||||
ActionRow("Latest session logs", "Send them with a bug report", "Share logs", a.onShareLogs)
|
||||
ToggleRow(
|
||||
host, "offline", "Offline mode",
|
||||
s.offlineAccount?.let { "Signed in as $it" } ?: "Sign in to Steam first",
|
||||
s.offline, enabled = s.offlineAccount != null,
|
||||
) { a.onOffline() }
|
||||
}
|
||||
}
|
||||
3 -> {
|
||||
|
||||
@@ -420,7 +420,7 @@ fun SessionDrawer(open: Boolean, page: Int, controllerActive: Boolean, onPageCha
|
||||
}
|
||||
SettingsGroup("Support") {
|
||||
SettingsRow("Session logs", "Send this session's logs with a bug report") {
|
||||
DrawerOutlineButton("Send logs", modifier = focus.track(page, "share-logs")) {
|
||||
DrawerOutlineButton("Share logs", modifier = focus.track(page, "share-logs")) {
|
||||
host.open = null
|
||||
a.onShareLogs()
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.ui.focus.focusProperties
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.semantics.contentDescription
|
||||
import androidx.compose.ui.semantics.stateDescription
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
@@ -385,7 +387,46 @@ fun <T> ChoiceRow(
|
||||
|
||||
@Composable
|
||||
fun ToggleRow(host: MenuHost, key: String, label: String, hint: String?, checked: Boolean, enabled: Boolean = true, chipModifier: Modifier = Modifier, onChange: (Boolean) -> Unit) =
|
||||
ChoiceRow(host, key, label, hint, listOf(true to "On", false to "Off"), checked, enabled, chipModifier = chipModifier, onPick = onChange)
|
||||
SettingsRow(label, hint) {
|
||||
ToggleSwitch(checked, enabled, label, chipModifier) { host.open = null; onChange(it) }
|
||||
}
|
||||
|
||||
/** An on/off switch: one tap or one A press flips it, where a menu of On and Off took three. */
|
||||
@Composable
|
||||
fun ToggleSwitch(checked: Boolean, enabled: Boolean = true, label: String? = null, modifier: Modifier = Modifier, onChange: (Boolean) -> Unit) {
|
||||
val colors = MaterialTheme.colorScheme
|
||||
val pal = LocalPalette.current
|
||||
val src = remember { MutableInteractionSource() }
|
||||
val hot = src.collectIsFocusedAsState().value || src.collectIsHoveredAsState().value
|
||||
val track by animateColorAsState(if (checked) pal.signal else colors.surfaceVariant, Motion.tw(180), label = "switchTrack")
|
||||
val edge by animateColorAsState(if (hot) pal.signal else if (checked) pal.signal else pal.line2, Motion.tw(180), label = "switchEdge")
|
||||
val knob by animateFloatAsState(if (checked) 1f else 0f, Motion.sp(0.7f), label = "switchKnob")
|
||||
val flip = { onChange(!checked) }
|
||||
val shape = RoundedCornerShape(99.dp)
|
||||
// 48dp tall to touch; the visible track sits inside it.
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = modifier
|
||||
.heightIn(min = 48.dp).widthIn(min = 64.dp)
|
||||
.alpha(if (enabled) 1f else 0.5f)
|
||||
.hoverable(src)
|
||||
.clickable(interactionSource = src, indication = null, enabled = enabled, role = Role.Switch, onClick = flip)
|
||||
.controllerConfirm(enabled = enabled, onClick = flip)
|
||||
.semantics { stateDescription = if (checked) "On" else "Off"; if (label != null) contentDescription = label },
|
||||
) {
|
||||
Box(
|
||||
Modifier.size(width = 52.dp, height = 30.dp).clip(shape).background(track)
|
||||
.border(if (hot) 2.dp else 1.dp, if (hot && checked) colors.onBackground else edge, shape),
|
||||
) {
|
||||
Box(
|
||||
Modifier.padding(4.dp).size(22.dp)
|
||||
.graphicsLayer { translationX = knob * 22.dp.toPx() }
|
||||
.clip(CircleShape)
|
||||
.background(if (checked) pal.onSignal else colors.onSurfaceVariant),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MultiRow(
|
||||
|
||||
Reference in new issue
Block a user