mirror of
https://github.com/twinksoftware/Gearslip.git
synced 2026-11-10 16:02:25 +01:00
usage notes changes, audio changes, video quality increase.
This commit is contained in:
1 parent
55320c4d98
commit
c212c2e2d1
4 files changed
+83
-35
No files matched your search
@@ -60,6 +60,8 @@ fun GearslipApp(onDisconnect: () -> Unit, onRequestCallScreening: () -> Unit) {
|
||||
},
|
||||
)
|
||||
}
|
||||
// Home's usage notes row opens Settings at that section rather than at the top.
|
||||
var settingsAtUsageNotes by rememberSaveable { mutableStateOf(false) }
|
||||
BackHandler(enabled = screen != Screen.HOME) {
|
||||
screen = if (screen == Screen.RECOMMENDED_APPS) Screen.SETTINGS else Screen.HOME
|
||||
}
|
||||
@@ -95,18 +97,20 @@ fun GearslipApp(onDisconnect: () -> Unit, onRequestCallScreening: () -> Unit) {
|
||||
when (screen) {
|
||||
Screen.HOME -> HomeScreen(
|
||||
onOpenLogs = { screen = Screen.LOGS },
|
||||
onOpenSettings = { screen = Screen.SETTINGS },
|
||||
onOpenSettings = { settingsAtUsageNotes = false; screen = Screen.SETTINGS },
|
||||
onOpenCarPreview = { screen = Screen.CAR_PREVIEW },
|
||||
onOpenHelp = { screen = Screen.HELP },
|
||||
onOpenUsageNotes = { settingsAtUsageNotes = true; screen = Screen.SETTINGS },
|
||||
onDisconnect = onDisconnect,
|
||||
)
|
||||
Screen.WHATS_NEW -> WhatsNewScreen(onBack = { screen = Screen.SETTINGS })
|
||||
Screen.LOGS -> LogsScreen(onBack = { screen = Screen.HOME })
|
||||
Screen.SETTINGS -> SettingsScreen(
|
||||
onBack = { screen = Screen.HOME },
|
||||
onOpenRecommendedApps = { screen = Screen.RECOMMENDED_APPS },
|
||||
onOpenWhatsNew = { screen = Screen.WHATS_NEW },
|
||||
onOpenRecommendedApps = { settingsAtUsageNotes = false; screen = Screen.RECOMMENDED_APPS },
|
||||
onOpenWhatsNew = { settingsAtUsageNotes = false; screen = Screen.WHATS_NEW },
|
||||
onReplayTutorial = { screen = Screen.SETUP_GUIDE },
|
||||
atUsageNotes = settingsAtUsageNotes,
|
||||
)
|
||||
Screen.RECOMMENDED_APPS -> RecommendedAppsScreen(onBack = { screen = Screen.SETTINGS })
|
||||
Screen.CAR_PREVIEW -> CarPreviewScreen(onBack = { screen = Screen.HOME })
|
||||
|
||||
@@ -48,6 +48,7 @@ fun HomeScreen(
|
||||
onOpenSettings: () -> Unit,
|
||||
onOpenCarPreview: () -> Unit,
|
||||
onOpenHelp: () -> Unit,
|
||||
onOpenUsageNotes: () -> Unit,
|
||||
onDisconnect: () -> Unit,
|
||||
) {
|
||||
val status by SessionStatus.state.collectAsStateWithLifecycle()
|
||||
@@ -92,7 +93,6 @@ fun HomeScreen(
|
||||
StatusCard(status)
|
||||
Spacer(Modifier.height(16.dp))
|
||||
UpdateCard()
|
||||
UsageNotesHomeCard()
|
||||
}
|
||||
|
||||
// Sits at the bottom, where a thumb reaches it.
|
||||
@@ -106,6 +106,9 @@ fun HomeScreen(
|
||||
Spacer(Modifier.height(16.dp))
|
||||
}
|
||||
|
||||
UsageNotesHomeCard(onOpen = onOpenUsageNotes)
|
||||
Spacer(Modifier.height(16.dp))
|
||||
|
||||
Surface(color = MaterialTheme.colorScheme.surfaceContainerHigh, shape = MaterialTheme.shapes.extraLarge) {
|
||||
Column {
|
||||
if (!live) {
|
||||
|
||||
@@ -57,6 +57,9 @@ import app.seb3thehacker.gearslip.BuildConfig
|
||||
import app.seb3thehacker.gearslip.CertProvider
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.snapshotFlow
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@@ -66,7 +69,16 @@ fun SettingsScreen(
|
||||
onOpenRecommendedApps: () -> Unit,
|
||||
onOpenWhatsNew: () -> Unit,
|
||||
onReplayTutorial: () -> Unit,
|
||||
atUsageNotes: Boolean = false,
|
||||
) {
|
||||
val scroll = rememberScrollState()
|
||||
// Opened from Home's usage notes row: usage notes is the last section, so start at the end.
|
||||
if (atUsageNotes) {
|
||||
LaunchedEffect(Unit) {
|
||||
snapshotFlow { scroll.maxValue }.first { it > 0 && it < Int.MAX_VALUE }
|
||||
scroll.scrollTo(scroll.maxValue)
|
||||
}
|
||||
}
|
||||
Scaffold(
|
||||
containerColor = MaterialTheme.colorScheme.background,
|
||||
topBar = {
|
||||
@@ -85,7 +97,7 @@ fun SettingsScreen(
|
||||
.fillMaxSize()
|
||||
.padding(padding)
|
||||
.padding(horizontal = 24.dp)
|
||||
.verticalScroll(rememberScrollState()),
|
||||
.verticalScroll(scroll),
|
||||
verticalArrangement = Arrangement.spacedBy(24.dp),
|
||||
) {
|
||||
Spacer(Modifier.height(0.dp))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package app.seb3thehacker.gearslip.ui
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import android.content.Context
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
@@ -9,6 +10,8 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.selection.toggleable
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
|
||||
import androidx.compose.material.icons.filled.Check
|
||||
import androidx.compose.material.icons.filled.Info
|
||||
import androidx.compose.material.icons.filled.KeyboardArrowDown
|
||||
import androidx.compose.material.icons.filled.KeyboardArrowUp
|
||||
@@ -83,11 +86,7 @@ internal fun ColumnScope.UsageStatsRows() {
|
||||
SettingsRow(
|
||||
"Send usage notes",
|
||||
Modifier.toggleable(on, role = Role.Switch) { on = it; save() },
|
||||
subtitle = when {
|
||||
BuildConfig.DEBUG -> "Dev build: nothing is ever sent"
|
||||
BuildConfig.STATS_URL.isBlank() -> "This build has no stats server, so it sends nothing"
|
||||
else -> null
|
||||
},
|
||||
subtitle = buildNote(),
|
||||
icon = Icons.Filled.Send,
|
||||
trailing = { Switch(checked = on, onCheckedChange = null) },
|
||||
)
|
||||
@@ -126,14 +125,7 @@ internal fun ColumnScope.UsageStatsRows() {
|
||||
)
|
||||
AnimatedVisibility(noteOpen) {
|
||||
// Rebuilt from the saved choices each time one changes, so it always matches.
|
||||
val note = remember(choices) {
|
||||
val preview = UsageStats.preview(context, everything = true)
|
||||
// Until the first drive the list is empty, so show what one entry looks like.
|
||||
val example = if (preview.optJSONArray("sessions")?.length() == 0) {
|
||||
"\n\nExample, not sent: one drive adds this to \"sessions\"\n" + UsageStats.exampleSession.toString(2)
|
||||
} else ""
|
||||
preview.toString(2) + example
|
||||
}
|
||||
val note = remember(choices) { notePreview(context) }
|
||||
Surface(
|
||||
color = MaterialTheme.colorScheme.surfaceContainerLowest,
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
@@ -164,23 +156,60 @@ private fun Choice(label: String, checked: Boolean, onChange: (Boolean) -> Unit)
|
||||
}
|
||||
}
|
||||
|
||||
/** Usage notes on Home, always: the switch, and once it's on, what to share. */
|
||||
/** The note as it would go out now, with an example drive until a real one is in it. */
|
||||
private fun notePreview(context: Context): String {
|
||||
val preview = UsageStats.preview(context, everything = true)
|
||||
// Until the first drive the list is empty, so show what one entry looks like.
|
||||
val example = if (preview.optJSONArray("sessions")?.length() == 0) {
|
||||
"\n\nExample, not sent: one drive adds this to \"sessions\"\n" + UsageStats.exampleSession.toString(2)
|
||||
} else ""
|
||||
return preview.toString(2) + example
|
||||
}
|
||||
|
||||
/** Why this build sends nothing, when it doesn't; null for a normal release. */
|
||||
private fun buildNote(): String? = when {
|
||||
BuildConfig.DEBUG -> "Dev build: nothing is ever sent"
|
||||
BuildConfig.STATS_URL.isBlank() -> "This build has no stats server, so it sends nothing"
|
||||
else -> null
|
||||
}
|
||||
|
||||
/**
|
||||
* Usage notes on Home, one row with one action either way. While they're off, the row is the
|
||||
* switch, so opting in is a single tap. Once they're on, it shrinks to a quiet line that opens
|
||||
* Settings at its usage notes section, so a driver already sharing isn't pitched again.
|
||||
*/
|
||||
@Composable
|
||||
internal fun UsageNotesHomeCard(modifier: Modifier = Modifier) {
|
||||
Column(modifier) {
|
||||
Text(
|
||||
USAGE_STATS_TITLE,
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier.padding(start = 16.dp, bottom = 4.dp),
|
||||
)
|
||||
Text(
|
||||
"Share a short note after each drive, so the next driver knows whether Gearslip works " +
|
||||
"in their car. No name, account, or location.",
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.padding(start = 16.dp, end = 16.dp, bottom = 12.dp),
|
||||
)
|
||||
SettingsCard { UsageStatsRows() }
|
||||
internal fun UsageNotesHomeCard(onOpen: () -> Unit, modifier: Modifier = Modifier) {
|
||||
val context = LocalContext.current
|
||||
var on by remember { mutableStateOf(UsageStats.enabled(context)) }
|
||||
|
||||
SettingsCard(modifier) {
|
||||
if (on) {
|
||||
SettingsRow(
|
||||
"Sharing usage notes",
|
||||
Modifier.clickable(onClick = onOpen),
|
||||
subtitle = buildNote(),
|
||||
icon = Icons.Filled.Check,
|
||||
trailing = {
|
||||
Icon(
|
||||
Icons.AutoMirrored.Filled.KeyboardArrowRight,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
},
|
||||
)
|
||||
} else {
|
||||
SettingsRow(
|
||||
USAGE_STATS_TITLE,
|
||||
Modifier.toggleable(false, role = Role.Switch) {
|
||||
UsageStats.set(context, true, UsageStats.choices(context))
|
||||
on = true
|
||||
},
|
||||
subtitle = buildNote() ?: ("A short note after each drive tells the next driver " +
|
||||
"whether their car works. No name, account, or location"),
|
||||
icon = Icons.Filled.Send,
|
||||
trailing = { Switch(checked = false, onCheckedChange = null) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user