mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-12 03:21:08 +00:00
feat(session): explain paused sessions and offer stop
This commit is contained in:
1 parent
5ebafaabda
commit
5d5b45a012
3 files changed
+65
-14
No files matched your search
@@ -355,9 +355,12 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback {
|
||||
onComponentsRefresh = { refreshDrawerComponents() },
|
||||
onComponentSwap = { pid, comp, value -> swapDrawerComponent(pid, comp, value) },
|
||||
))
|
||||
if (SessionState.suspended) SessionPausedOverlay {
|
||||
SessionService.resume(this@SessionActivity)
|
||||
}
|
||||
if (SessionState.suspended) SessionPausedOverlay(
|
||||
title = pausedTitle(),
|
||||
onResume = { SessionService.resume(this@SessionActivity) },
|
||||
// As the drawer's Stop does; stopping resumes the paused processes first.
|
||||
onStop = { SessionService.stop(this@SessionActivity); finish() },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -475,6 +478,12 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback {
|
||||
if (SessionState.running) SessionState.mode
|
||||
else intent.getStringExtra(SessionService.EXTRA_MODE) ?: SessionService.MODE_STEAM
|
||||
|
||||
private fun pausedTitle(): String = when (SessionState.mode) {
|
||||
SessionService.MODE_DESKTOP -> "The desktop is paused"
|
||||
SessionService.MODE_RUN -> (com.droiddeck.launcher.frontend.Library.nameForProgram(SessionState.program) ?: "The program") + " is paused"
|
||||
else -> "Steam is paused"
|
||||
}
|
||||
|
||||
private fun loadingTitle(): String = when (loadingMode()) {
|
||||
SessionService.MODE_DESKTOP ->
|
||||
if (!SessionState.running && intent.getStringExtra(SessionService.EXTRA_STEAM_UI) != null) "Starting Steam on the desktop"
|
||||
|
||||
@@ -1733,6 +1733,7 @@ internal fun PrimaryButton(
|
||||
enabled: Boolean = true,
|
||||
main: Boolean = false,
|
||||
compact: Boolean = false,
|
||||
modifier: Modifier = Modifier,
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
val colors = MaterialTheme.colorScheme
|
||||
@@ -1751,7 +1752,7 @@ internal fun PrimaryButton(
|
||||
val lift by animateFloatAsState(if (hot) 14f else 6f, Motion.tw(300), label = "btnLift")
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = track
|
||||
modifier = modifier.then(track)
|
||||
.then(if (frontFocus != null) Modifier.focusRequester(frontFocus.primary).onFocusChanged { if (it.isFocused) frontFocus.last = FrontFocus.PRIMARY } else Modifier)
|
||||
.graphicsLayer { scaleX = scale; scaleY = scale; shadowElevation = if (enabled) lift.dp.toPx() else 0f; shape = Shape12; clip = false; ambientShadowColor = pal.signal; spotShadowColor = pal.signal }
|
||||
.clip(Shape12)
|
||||
@@ -1768,7 +1769,7 @@ internal fun PrimaryButton(
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun SecondaryButton(text: String, enabled: Boolean = true, compact: Boolean = false, onClick: () -> Unit) {
|
||||
internal fun SecondaryButton(text: String, enabled: Boolean = true, compact: Boolean = false, modifier: Modifier = Modifier, onClick: () -> Unit) {
|
||||
val colors = MaterialTheme.colorScheme
|
||||
val src = remember { MutableInteractionSource() }
|
||||
val hot = rememberHot(src) && enabled
|
||||
@@ -1778,7 +1779,7 @@ internal fun SecondaryButton(text: String, enabled: Boolean = true, compact: Boo
|
||||
val edge by animateColorAsState(if (hot) pal.signal else pal.line2, Motion.tw(250), label = "secEdge")
|
||||
val fill by animateColorAsState(if (hot) pal.signal.copy(alpha = 0.14f) else Color.White.copy(alpha = 0.03f), Motion.tw(250), label = "secFill")
|
||||
Box(
|
||||
modifier = Modifier.paneItem("btn:$text").downToFirstTile().graphicsLayer { scaleX = scale; scaleY = scale }.clip(Shape12).background(fill).border(1.dp, edge, Shape12)
|
||||
modifier = modifier.paneItem("btn:$text").downToFirstTile().graphicsLayer { scaleX = scale; scaleY = scale }.clip(Shape12).background(fill).border(1.dp, edge, Shape12)
|
||||
.alpha(if (enabled) 1f else 0.5f)
|
||||
.hoverable(src).clickable(interactionSource = src, indication = LocalIndication.current, enabled = enabled, onClick = onClick)
|
||||
.controllerConfirm(enabled = enabled, onClick = onClick)
|
||||
|
||||
@@ -5,6 +5,7 @@ import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.material.icons.filled.Pause
|
||||
import androidx.compose.material.icons.outlined.Menu
|
||||
import androidx.compose.material.icons.outlined.MoreHoriz
|
||||
import androidx.compose.material.icons.outlined.PowerSettingsNew
|
||||
@@ -291,10 +292,17 @@ private fun StageRow(label: String, state: StageMark, detail: String, percent: I
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A session paused in the background (the Manual background behaviour): what is paused, that it
|
||||
* picks up where it left off, and the two ways on - Resume first, for the pad.
|
||||
*/
|
||||
@Composable
|
||||
fun SessionPausedOverlay(onResume: () -> Unit) {
|
||||
fun SessionPausedOverlay(title: String = "Steam is paused", onResume: () -> Unit, onStop: (() -> Unit)? = null) {
|
||||
val colors = MaterialTheme.colorScheme
|
||||
val pal = LocalPalette.current
|
||||
val interactionSource = remember { MutableInteractionSource() }
|
||||
val resumeFocus = remember { FocusRequester() }
|
||||
var confirmStop by remember { mutableStateOf(false) }
|
||||
LaunchedEffect(Unit) {
|
||||
androidx.compose.runtime.withFrameNanos { }
|
||||
runCatching { resumeFocus.requestFocus() }
|
||||
@@ -302,22 +310,55 @@ fun SessionPausedOverlay(onResume: () -> Unit) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(Color(0xF20B0D10))
|
||||
.background(pal.background.copy(alpha = 0.94f))
|
||||
.clickable(interactionSource = interactionSource, indication = null) {},
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier.padding(32.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(10.dp),
|
||||
modifier = Modifier.widthIn(max = 440.dp).padding(32.dp),
|
||||
) {
|
||||
OutlinedButton(
|
||||
onClick = onResume,
|
||||
modifier = Modifier.focusRequester(resumeFocus).controllerConfirm(onClick = onResume),
|
||||
) {
|
||||
Text("Resume session")
|
||||
Box(contentAlignment = Alignment.Center, modifier = Modifier.padding(bottom = 6.dp).size(64.dp).border(2.dp, pal.line2, CircleShape)) {
|
||||
Icon(Icons.Filled.Pause, contentDescription = null, tint = colors.onBackground, modifier = Modifier.size(30.dp))
|
||||
}
|
||||
Text(title, fontSize = 28.sp, fontWeight = FontWeight.Bold, color = colors.onBackground, textAlign = TextAlign.Center)
|
||||
Text(
|
||||
"It stopped while DroidDeck was in the background and picks up where it left off.",
|
||||
fontSize = 15.sp, lineHeight = 21.sp, color = colors.onSurfaceVariant, textAlign = TextAlign.Center,
|
||||
)
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(10.dp), modifier = Modifier.padding(top = 14.dp)) {
|
||||
PrimaryButton("Resume", modifier = Modifier.focusRequester(resumeFocus).controllerConfirm(onClick = onResume), onClick = onResume)
|
||||
if (onStop != null) SecondaryButton("Stop session") { confirmStop = true }
|
||||
}
|
||||
}
|
||||
}
|
||||
if (confirmStop && onStop != null) {
|
||||
val cancelFocus = remember { FocusRequester() }
|
||||
val cancel = { confirmStop = false }
|
||||
val stop = { confirmStop = false; onStop() }
|
||||
LaunchedEffect(Unit) {
|
||||
androidx.compose.runtime.withFrameNanos { }
|
||||
runCatching { cancelFocus.requestFocus() }
|
||||
}
|
||||
// Opens on Cancel, as the menu's does: a stray A press never ends the session.
|
||||
AlertDialog(
|
||||
onDismissRequest = cancel,
|
||||
modifier = Modifier.controllerBack(onBack = cancel),
|
||||
title = { Text("Stop session?") },
|
||||
text = { Text("Everything running in this session closes.") },
|
||||
confirmButton = {
|
||||
TextButton(
|
||||
onClick = stop,
|
||||
modifier = Modifier.controllerConfirm(onClick = stop),
|
||||
colors = ButtonDefaults.textButtonColors(contentColor = colors.error),
|
||||
) { Text("Stop") }
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = cancel, modifier = Modifier.focusRequester(cancelFocus).controllerConfirm(onClick = cancel)) { Text("Cancel") }
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Everything the drawer shows and does. */
|
||||
|
||||
Reference in new issue
Block a user