neiam
/gitgud
Git Gud
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
1
Log in to mark this repository.
Android: wall mode, so a tablet opens onto the CI wall
b2aad05 · gmorell · 2026-11-03 19:29
Message
{commit_body(@commit)}
Files changed
modified
android/README.md
+1
−1
@@ -16,7 +16,7 @@ B612-mono shell, so they feel like one product family.
| 16 | 16 | | **Issues** | List by state, read with server-rendered markdown, comment, quote-reply, close and reopen | |
| 17 | 17 | | **Pull requests** | List by state (`merged` is its own state), read description + reviews + discussion + line comments, comment, approve / request changes, merge — with the repo's merge blockers spelled out | |
| 18 | 18 | | **Wiki** | Page index and rendered pages (read-only) | |
| 19 | −| **Live CI wall** | Every job running right now, a card each, tiled to fill a tablet or TV the way the web's `/users/ci/live` does: up to six across, then the newest columns stack. Each card has its repo, job, clock, step bar and the tail of its log. Yours or one organization's; oldest or newest first (the chips, or R). Keeps the screen on. A TV lists the app on its home screen and opens straight onto the wall; elsewhere it's in the repo list's menu, or long-press the launcher icon | | |
| 19 | +| **Live CI wall** | Every job running right now, a card each, tiled to fill a tablet or TV the way the web's `/users/ci/live` does: up to six across, then the newest columns stack. Each card has its repo, job, clock, step bar and the tail of its log. Yours or one organization's; oldest or newest first (the chips, or R). Keeps the screen on. A TV lists the app on its home screen and opens straight onto the wall; elsewhere it's in the repo list's menu, or long-press the launcher icon. Tick **Wall mode** in that menu and a tablet opens onto the wall too; Back from there goes on to the repos | | |
| 20 | 20 | | **Home-screen widget** | The Plasma widget's strip on a phone: the logo and one status circle per watched repository, or one per organization folded into a single circle. Stretch it taller and the recent runs list underneath — tap a circle to filter them, the logo for every run, a run to open it. Polls every 15 minutes, every 30 s while a run is in flight | |
| 21 | 21 | |
| 22 | 22 | The summary and description F-Droid shows come from |
modified
android/app/src/main/java/org/neiam/gitgud/app/MainActivity.kt
+16
−4
@@ -62,7 +62,8 @@ class MainActivity : ComponentActivity() {
| 62 | 62 | val initialPair = parseIntent(intent) |
| 63 | 63 | link = parseLink(intent) |
| 64 | 64 | // Opened from a TV's home screen: a TV is there to be the wall. |
| 65 | − val startOnWall = intent?.hasCategory(Intent.CATEGORY_LEANBACK_LAUNCHER) == true | |
| 65 | + val fromTv = intent?.hasCategory(Intent.CATEGORY_LEANBACK_LAUNCHER) == true | |
| 66 | + val startOnWall = fromTv || prefs.wallOnLaunch | |
| 66 | 67 | |
| 67 | 68 | setContent { |
| 68 | 69 | // Nothing stored means follow the OS, the same default as the |
@@ -84,6 +85,7 @@ class MainActivity : ComponentActivity() {
| 84 | 85 | initialPair = initialPair, |
| 85 | 86 | link = link, |
| 86 | 87 | startOnWall = startOnWall, |
| 88 | + fromTv = fromTv, | |
| 87 | 89 | currentTheme = theme, |
| 88 | 90 | currentThemeKey = themeKey, |
| 89 | 91 | onPickTheme = { picked -> |
@@ -152,6 +154,7 @@ fun GitGudApp(
| 152 | 154 | initialPair: PairPayload?, |
| 153 | 155 | link: DeepLink? = null, |
| 154 | 156 | startOnWall: Boolean = false, |
| 157 | + fromTv: Boolean = false, | |
| 155 | 158 | currentTheme: AppTheme, |
| 156 | 159 | currentThemeKey: String, |
| 157 | 160 | onPickTheme: (String) -> Unit, |
@@ -197,6 +200,8 @@ fun GitGudApp(
| 197 | 200 | onPickTheme = onPickTheme, |
| 198 | 201 | onOpenRepo = { owner, name -> nav.navigate("repo/$owner/$name") }, |
| 199 | 202 | onOpenWall = { nav.navigate("wall") }, |
| 203 | + wallOnLaunch = prefs.wallOnLaunch, | |
| 204 | + onWallOnLaunch = { prefs.wallOnLaunch = it }, | |
| 200 | 205 | onUnpair = { |
| 201 | 206 | tokens.clear() |
| 202 | 207 | nav.navigate("pair") { popUpTo(0) } |
@@ -208,9 +213,16 @@ fun GitGudApp(
| 208 | 213 | CiWallScreen( |
| 209 | 214 | tokens = tokens, |
| 210 | 215 | prefs = prefs, |
| 211 | − // The wall is a TV's first screen: Back from there leaves | |
| 212 | − // the app rather than finding nothing to pop. | |
| 213 | − onBack = { if (!nav.popBackStack()) activity?.finish() }, | |
| 216 | + // When the wall is the first screen, Back leaves the app on | |
| 217 | + // a TV (as its other apps do), and goes on to the repo list | |
| 218 | + // on a tablet in wall mode, so the rest is still reachable. | |
| 219 | + onBack = { | |
| 220 | + when { | |
| 221 | + nav.popBackStack() -> Unit | |
| 222 | + fromTv -> activity?.finish() | |
| 223 | + else -> nav.navigate("repos") { popUpTo("wall") { inclusive = true } } | |
| 224 | + } | |
| 225 | + }, | |
| 214 | 226 | ) |
| 215 | 227 | } |
| 216 | 228 |
modified
android/app/src/main/java/org/neiam/gitgud/app/data/PrefsStore.kt
+9
−0
@@ -52,6 +52,14 @@ class PrefsStore(context: Context) {
| 52 | 52 | get() = prefs.getBoolean(KEY_WALL_NEWEST, false) |
| 53 | 53 | set(value) = prefs.edit().putBoolean(KEY_WALL_NEWEST, value).apply() |
| 54 | 54 | |
| 55 | + /** | |
| 56 | + * Wall mode: the app opens onto the CI wall rather than the repo | |
| 57 | + * list — for a tablet mounted on a wall. A TV always does. | |
| 58 | + */ | |
| 59 | + var wallOnLaunch: Boolean | |
| 60 | + get() = prefs.getBoolean(KEY_WALL_ON_LAUNCH, false) | |
| 61 | + set(value) = prefs.edit().putBoolean(KEY_WALL_ON_LAUNCH, value).apply() | |
| 62 | + | |
| 55 | 63 | private fun put(key: String, value: String?) { |
| 56 | 64 | prefs.edit().also { e -> |
| 57 | 65 | if (value == null) e.remove(key) else e.putString(key, value) |
@@ -63,5 +71,6 @@ class PrefsStore(context: Context) {
| 63 | 71 | private const val KEY_REPO_SORT = "repo_sort" |
| 64 | 72 | private const val KEY_WALL_SCOPE = "wall_scope" |
| 65 | 73 | private const val KEY_WALL_NEWEST = "wall_newest_first" |
| 74 | + private const val KEY_WALL_ON_LAUNCH = "wall_on_launch" | |
| 66 | 75 | } |
| 67 | 76 | } |
modified
android/app/src/main/java/org/neiam/gitgud/app/ui/RepoListScreen.kt
+14
−0
@@ -25,6 +25,7 @@ import androidx.compose.material.icons.filled.Refresh
| 25 | 25 | import androidx.compose.material.icons.automirrored.filled.Sort |
| 26 | 26 | import androidx.compose.material3.AlertDialog |
| 27 | 27 | import androidx.compose.material3.Card |
| 28 | +import androidx.compose.material3.Checkbox | |
| 28 | 29 | import androidx.compose.material3.DropdownMenu |
| 29 | 30 | import androidx.compose.material3.DropdownMenuItem |
| 30 | 31 | import androidx.compose.material3.ExperimentalMaterial3Api |
@@ -84,6 +85,8 @@ fun RepoListScreen(
| 84 | 85 | onPickTheme: (String) -> Unit, |
| 85 | 86 | onOpenRepo: (owner: String, name: String) -> Unit, |
| 86 | 87 | onOpenWall: () -> Unit, |
| 88 | + wallOnLaunch: Boolean, | |
| 89 | + onWallOnLaunch: (Boolean) -> Unit, | |
| 87 | 90 | onUnpair: () -> Unit, |
| 88 | 91 | ) { |
| 89 | 92 | val scope = rememberCoroutineScope() |
@@ -94,6 +97,7 @@ fun RepoListScreen(
| 94 | 97 | var sortPickerOpen by remember { mutableStateOf(false) } |
| 95 | 98 | var sort by remember { mutableStateOf(RepoSort.byKey(prefs.repoSortKey)) } |
| 96 | 99 | var reloadKey by remember { mutableStateOf(0) } |
| 100 | + var wallMode by remember { mutableStateOf(wallOnLaunch) } | |
| 97 | 101 | |
| 98 | 102 | LaunchedEffect(reloadKey) { |
| 99 | 103 | val creds = tokens.load() |
@@ -128,6 +132,16 @@ fun RepoListScreen(
| 128 | 132 | onOpenWall() |
| 129 | 133 | }, |
| 130 | 134 | ) |
| 135 | + DropdownMenuItem( | |
| 136 | + text = { Text("Wall mode: open on the wall") }, | |
| 137 | + trailingIcon = { | |
| 138 | + Checkbox(checked = wallMode, onCheckedChange = null) | |
| 139 | + }, | |
| 140 | + onClick = { | |
| 141 | + wallMode = !wallMode | |
| 142 | + onWallOnLaunch(wallMode) | |
| 143 | + }, | |
| 144 | + ) | |
| 131 | 145 | DropdownMenuItem( |
| 132 | 146 | text = { Text("Sort: ${sort.label}") }, |
| 133 | 147 | leadingIcon = { Icon(Icons.AutoMirrored.Filled.Sort, contentDescription = null) }, |
Parents: 78cc6fd