EARHORNMUSIC UPnP · Android TV · Phones · Android Auto · GNU/Linux
Release 0.5.0

SettingsScreen.kt

Each line, with the release that last changed it.

0.5.01package dev.stave.ui.settings
2
3import androidx.activity.compose.BackHandler
4import androidx.compose.foundation.background
5import androidx.compose.foundation.clickable
6import androidx.compose.foundation.interaction.MutableInteractionSource
7import androidx.compose.foundation.layout.Arrangement
8import androidx.compose.foundation.layout.Box
9import androidx.compose.foundation.layout.Column
10import androidx.compose.foundation.layout.Row
11import androidx.compose.foundation.layout.Spacer
12import androidx.compose.foundation.layout.fillMaxSize
13import androidx.compose.foundation.layout.fillMaxWidth
14import androidx.compose.foundation.layout.height
15import androidx.compose.foundation.layout.padding
16import androidx.compose.foundation.layout.size
17import androidx.compose.foundation.lazy.LazyColumn
18import androidx.compose.runtime.Composable
19import androidx.compose.runtime.remember
20import androidx.compose.ui.Alignment
21import androidx.compose.ui.Modifier
22import androidx.compose.ui.unit.dp
23import androidx.tv.material3.MaterialTheme
24import androidx.tv.material3.Text
25import dev.stave.ui.components.staveFocusable
26import dev.stave.ui.theme.AccentAmber
27import dev.stave.ui.theme.OnMuted
28import dev.stave.ui.theme.OnPrimary
29import dev.stave.ui.theme.OnQuiet
30import dev.stave.ui.theme.SurfaceRaised
31import dev.stave.ui.theme.adaptiveScreenPaddingHorizontal
32import dev.stave.ui.theme.adaptiveScreenPaddingVertical
33import dev.stave.ui.theme.withInterDigits
34
35@Composable
36fun SettingsScreen(
37 onBack: () -> Unit,
38 onOpenAbout: () -> Unit,
39 onOpenGuide: () -> Unit,
40 onChooseServer: () -> Unit,
41 onOpenPlayback: () -> Unit,
42 onExit: () -> Unit,
43) {
44 BackHandler(onBack = onBack)
45
46 Column(
47 Modifier
48 .fillMaxSize()
49 .padding(horizontal = adaptiveScreenPaddingHorizontal(), vertical = adaptiveScreenPaddingVertical())
50 ) {
51 // Brand header
52 Row(
53 verticalAlignment = Alignment.CenterVertically,
54 horizontalArrangement = Arrangement.spacedBy(16.dp),
55 ) {
56 coil3.compose.AsyncImage(
57 model = dev.stave.R.drawable.earhorn_gramophone_glow,
58 contentDescription = null,
59 modifier = Modifier.size(48.dp),
60 )
61 Column {
62 Text("Settings", style = MaterialTheme.typography.displaySmall, color = OnPrimary)
63 Text("Earhorn Music Player", style = MaterialTheme.typography.bodySmall, color = OnMuted)
64 }
65 }
66 Spacer(Modifier.height(32.dp))
67
68 LazyColumn(verticalArrangement = Arrangement.spacedBy(8.dp)) {
69 item {
70 NavCard(
71 title = "Settings",
72 subtitle = "Mesh networking, output device, sound, lyrics, privacy, metadata, and display",
73 onClick = onOpenPlayback,
74 )
75 }
76 item {
77 NavCard(
78 title = "Server",
79 subtitle = "Rescan the network and pick a different UPnP/DLNA library",
80 onClick = onChooseServer,
81 )
82 }
83 item {
84 NavCard(
85 title = "User guide",
86 subtitle = "How clicks, long-presses, and the queue work",
87 onClick = onOpenGuide,
88 )
89 }
90 item {
91 NavCard(
92 title = "About",
93 subtitle = "Version, credits, and licenses",
94 onClick = onOpenAbout,
95 )
96 }
97 item { Spacer(Modifier.height(16.dp)) }
98 item {
99 NavCard(
100 title = "Exit Earhorn",
101 subtitle = "Close the app completely",
102 onClick = onExit,
103 accent = false,
104 )
105 }
106 }
107 }
108}
109
110@Composable
111private fun NavCard(
112 title: String,
113 subtitle: String,
114 onClick: () -> Unit,
115 accent: Boolean = true,
116) {
117 val interaction = remember { MutableInteractionSource() }
118 Box(
119 Modifier
120 .fillMaxWidth()
121 .background(SurfaceRaised)
122 .staveFocusable(interaction)
123 .clickable(interaction, indication = null) { onClick() }
124 .padding(horizontal = 24.dp, vertical = 18.dp)
125 ) {
126 Row(verticalAlignment = Alignment.CenterVertically) {
127 Column(Modifier.weight(1f)) {
128 Text(
129 withInterDigits(title),
130 style = MaterialTheme.typography.titleMedium,
131 color = if (accent) OnPrimary else OnMuted,
132 )
133 Spacer(Modifier.height(4.dp))
134 Text(
135 withInterDigits(subtitle),
136 style = MaterialTheme.typography.bodySmall,
137 color = OnMuted,
138 )
139 }
140 Text(
141 "\u25b8",
142 style = MaterialTheme.typography.titleLarge,
143 color = if (accent) AccentAmber else OnQuiet,
144 )
145 }
146 }
147}