Colour on icons: what each stands for, in the hub's colours (closes #25) d98e5a147428
A Tones object in the theme: the accent for repositories, folders and account details; purple for releases, projects and pending checks; the warning colour for private and internal; notifications by kind (broken builds red, fixed green, reviews purple); empty screens' icons in the accent.
- Author
- Andy McCall @andymccall <[email protected]>
- via
- agent
agent:claude@andymccall <[email protected]> · keyless, under your grant for changes,refs,seal · key ece019235b84
- When
- · 2026-10-28 16:37 UTC
- Signature
- ◈ sealed by agent:claude@andymccall
- Hash
d98e5a147428ce02147f8b87d97497550562a408f1c0aa8dc40dca143f993cae- Depends on
- 144cbf7bf2b5 57c0824300db 62429abe5869 840c75813f86 98dbd1220929 dce8ebd2482a dfbc3e972872 e0004d61958c e2df27a81e5d
- Depended on by
- b610bc6eeab7 821035db5a1c
- In bookmarks
- main
- In tags
- v0.1.1 v0.1.2 v0.1.3 v0.1.4 v0.1.5 v0.1.6 v0.1.7 v0.1.8 v0.1.9
- Edits
- 47 atoms, 1 tree operation, 13 files
Browse the tree at this change
added app/src/main/java/io/oxygenhub/android/ui/theme/Tones.kt +36 −0
| 1 | + | package io.oxygenhub.android.ui.theme |
|
| 2 | + | ||
| 3 | + | import androidx.compose.material3.MaterialTheme |
|
| 4 | + | import androidx.compose.runtime.Composable |
|
| 5 | + | import androidx.compose.ui.graphics.Color |
|
| 6 | + | ||
| 7 | + | /** |
|
| 8 | + | * What an icon stands for, in the hub's colours (#25), as its pages tint |
|
| 9 | + | * theirs: the accent for things you open (repositories, folders, account |
|
| 10 | + | * details), purple for releases, projects and pending things, the status |
|
| 11 | + | * colours for what passed, failed or is open. Each reads on both palettes. |
|
| 12 | + | */ |
|
| 13 | + | object Tones { |
|
| 14 | + | val repository: Color @Composable get() = MaterialTheme.colorScheme.primary |
|
| 15 | + | val folder: Color @Composable get() = MaterialTheme.colorScheme.primary |
|
| 16 | + | val info: Color @Composable get() = MaterialTheme.colorScheme.primary |
|
| 17 | + | val release: Color @Composable get() = MaterialTheme.colorScheme.tertiary |
|
| 18 | + | val project: Color @Composable get() = MaterialTheme.colorScheme.tertiary |
|
| 19 | + | val pending: Color @Composable get() = MaterialTheme.colorScheme.tertiary |
|
| 20 | + | val restricted: Color @Composable get() = LocalStatusColors.current.warn |
|
| 21 | + | val plain: Color @Composable get() = MaterialTheme.colorScheme.onSurfaceVariant |
|
| 22 | + | ||
| 23 | + | /** A notification's kind (the hub's `notify` kinds). */ |
|
| 24 | + | @Composable |
|
| 25 | + | fun of(kind: String): Color { |
|
| 26 | + | val s = LocalStatusColors.current |
|
| 27 | + | return when { |
|
| 28 | + | kind == "flow.failed" || kind == "backup" -> s.bad |
|
| 29 | + | kind == "flow.fixed" || kind == "backup.recovered" -> s.ok |
|
| 30 | + | kind.startsWith("proposal.review") -> MaterialTheme.colorScheme.tertiary |
|
| 31 | + | kind.endsWith(".comment") || kind == "mention" -> MaterialTheme.colorScheme.primary |
|
| 32 | + | kind.startsWith("proposal") || kind.startsWith("issue") -> s.ok |
|
| 33 | + | else -> MaterialTheme.colorScheme.primary |
|
| 34 | + | } |
|
| 35 | + | } |
|
| 36 | + | } |
modified CHANGELOG.md +1 −0
| … | 2 unchanged lines |
||
| 3 | 3 | ## Unreleased |
|
| 4 | 4 | ||
| 5 | 5 | - **Panels you can see (#24):** on a phone, cards and boxes were near-black on black. The app now uses OxygenHub's own colours by default (Account › Wallpaper colours turns Android's back on), every card is one panel with a 1 dp edge, as the website's have, on a tone a clear step above the background, and wallpaper colours in the dark get the same steps. A backdrop stays inside its band, and an image the app cannot show yet (a README's badge) no longer leaves a 180 dp blank. |
|
| 6 | + | - **Colour on icons (#25):** icons say what they are in the hub's colours, as its pages do: repositories, folders and account details in the accent, releases, projects and pending checks in purple, private and internal locks in their warning colour, notifications by kind (a broken build red, a fixed one green, a review purple), and empty screens' icons in the accent. |
|
| 6 | 7 | ||
| 7 | 8 | ## 0.1.0 (2026-10-28) |
|
| 8 | 9 | ||
| … | 25 unchanged lines |
modified app/src/main/java/io/oxygenhub/android/ui/account/AccountScreen.kt +5 −4
| … | 45 unchanged lines |
||
| 46 | 46 | import io.oxygenhub.android.ui.common.AvatarImage |
|
| 47 | 47 | import io.oxygenhub.android.ui.common.Panel |
|
| 48 | 48 | import io.oxygenhub.android.ui.theme.Appearance |
|
| 49 | + | import io.oxygenhub.android.ui.theme.Tones |
|
| 49 | 50 | import io.oxygenhub.android.ui.theme.rememberWallpaperColours |
|
| 50 | 51 | import io.oxygenhub.android.update.UpdateCard |
|
| 51 | 52 | import kotlinx.coroutines.launch |
|
| … | 23 unchanged lines |
||
| 75 | 76 | AppearanceCard() |
|
| 76 | 77 | Panel(Modifier.fillMaxWidth()) { |
|
| 77 | 78 | ListItem( |
|
| 78 | - | leadingContent = { Icon(Icons.Outlined.Dns, contentDescription = null) }, |
|
| 79 | + | leadingContent = { Icon(Icons.Outlined.Dns, contentDescription = null, tint = Tones.info) }, |
|
| 79 | 80 | headlineContent = { Text("Hub") }, |
|
| 80 | 81 | supportingContent = { Text(session.hub) }, |
|
| 81 | 82 | ) |
|
| 82 | 83 | ListItem( |
|
| 83 | - | leadingContent = { Icon(Icons.Outlined.Key, contentDescription = null) }, |
|
| 84 | + | leadingContent = { Icon(Icons.Outlined.Key, contentDescription = null, tint = Tones.info) }, |
|
| 84 | 85 | headlineContent = { Text("Allowed") }, |
|
| 85 | 86 | supportingContent = { Text(session.scopes.ifEmpty { listOf("(the hub did not say)") }.joinToString(", ")) }, |
|
| 86 | 87 | ) |
|
| 87 | 88 | ListItem( |
|
| 88 | - | leadingContent = { Icon(Icons.Outlined.Memory, contentDescription = null) }, |
|
| 89 | + | leadingContent = { Icon(Icons.Outlined.Memory, contentDescription = null, tint = Tones.info) }, |
|
| 89 | 90 | headlineContent = { Text("Native core") }, |
|
| 90 | 91 | supportingContent = { Text(core) }, |
|
| 91 | 92 | ) |
|
| … | 41 unchanged lines |
||
| 133 | 134 | val wallpaper = rememberWallpaperColours() |
|
| 134 | 135 | Panel(Modifier.fillMaxWidth()) { |
|
| 135 | 136 | ListItem( |
|
| 136 | - | leadingContent = { Icon(Icons.Outlined.Palette, contentDescription = null) }, |
|
| 137 | + | leadingContent = { Icon(Icons.Outlined.Palette, contentDescription = null, tint = Tones.info) }, |
|
| 137 | 138 | headlineContent = { Text("Wallpaper colours") }, |
|
| 138 | 139 | supportingContent = { Text(if (wallpaper) "The app takes its colours from your wallpaper." else "The app uses OxygenHub's own colours, as the website does.") }, |
|
| 139 | 140 | trailingContent = { Switch(checked = wallpaper, onCheckedChange = { Appearance.setWallpaperColours(context, it) }) }, |
|
| … | 3 unchanged lines |
modified app/src/main/java/io/oxygenhub/android/ui/code/CodeBrowser.kt +4 −3
| … | 40 unchanged lines |
||
| 41 | 41 | import io.oxygenhub.android.ui.common.LoadContent |
|
| 42 | 42 | import io.oxygenhub.android.ui.common.NoImages |
|
| 43 | 43 | import io.oxygenhub.android.ui.common.Panel |
|
| 44 | + | import io.oxygenhub.android.ui.theme.Tones |
|
| 44 | 45 | ||
| 45 | 46 | /** |
|
| 46 | 47 | * A repository's code (#3): where you are (the reference, then each folder |
|
| … | 18 unchanged lines |
||
| 65 | 66 | item { |
|
| 66 | 67 | ListItem( |
|
| 67 | 68 | modifier = Modifier.clickable { vm.up() }, |
|
| 68 | - | leadingContent = { Icon(Icons.Outlined.Folder, contentDescription = null) }, |
|
| 69 | + | leadingContent = { Icon(Icons.Outlined.Folder, contentDescription = null, tint = Tones.folder) }, |
|
| 69 | 70 | headlineContent = { Text("..") }, |
|
| 70 | 71 | ) |
|
| 71 | 72 | } |
|
| … | 77 unchanged lines |
||
| 149 | 150 | TextButton(onClick = { vm.open(parts.take(i + 1).joinToString("/")) }) { Text(part) } |
|
| 150 | 151 | } |
|
| 151 | 152 | TextButton(onClick = { onOpenHistory(ref) }) { |
|
| 152 | - | Icon(Icons.Outlined.History, contentDescription = null) |
|
| 153 | + | Icon(Icons.Outlined.History, contentDescription = null, tint = Tones.info) |
|
| 153 | 154 | Text(" History") |
|
| 154 | 155 | } |
|
| 155 | 156 | } |
|
| … | 7 unchanged lines |
||
| 163 | 164 | Icon( |
|
| 164 | 165 | if (e.isDir) Icons.Outlined.Folder else Icons.AutoMirrored.Outlined.InsertDriveFile, |
|
| 165 | 166 | contentDescription = if (e.isDir) "Folder" else "File", |
|
| 166 | - | tint = if (e.isDir) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurfaceVariant, |
|
| 167 | + | tint = if (e.isDir) Tones.folder else Tones.plain, |
|
| 167 | 168 | ) |
|
| 168 | 169 | }, |
|
| 169 | 170 | headlineContent = { Text(e.name) }, |
|
| … | 19 unchanged lines |
modified app/src/main/java/io/oxygenhub/android/ui/common/States.kt +2 −1
| … | 24 unchanged lines |
||
| 25 | 25 | import androidx.compose.ui.text.style.TextAlign |
|
| 26 | 26 | import androidx.compose.ui.unit.dp |
|
| 27 | 27 | import io.oxygenhub.android.ui.backdrop.Backdrop |
|
| 28 | + | import io.oxygenhub.android.ui.theme.Tones |
|
| 28 | 29 | import uniffi.rust_core.Backdrop as Scene |
|
| 29 | 30 | ||
| 30 | 31 | /** A spinner in the middle of the space. */ |
|
| … | 45 unchanged lines |
||
| 76 | 77 | horizontalAlignment = Alignment.CenterHorizontally, |
|
| 77 | 78 | verticalArrangement = Arrangement.Center, |
|
| 78 | 79 | ) { |
|
| 79 | - | Icon(icon, contentDescription = null, modifier = Modifier.size(48.dp), tint = MaterialTheme.colorScheme.onSurfaceVariant) |
|
| 80 | + | Icon(icon, contentDescription = null, modifier = Modifier.size(48.dp), tint = Tones.info.copy(alpha = 0.85f)) |
|
| 80 | 81 | Spacer(Modifier.height(16.dp)) |
|
| 81 | 82 | Text(title, style = MaterialTheme.typography.titleMedium, textAlign = TextAlign.Center) |
|
| 82 | 83 | Spacer(Modifier.height(8.dp)) |
|
| … | 30 unchanged lines |
modified app/src/main/java/io/oxygenhub/android/ui/dashboard/DashboardScreen.kt +2 −1
| … | 48 unchanged lines |
||
| 49 | 49 | import io.oxygenhub.android.ui.common.relativeTime |
|
| 50 | 50 | import io.oxygenhub.android.ui.repos.RepositoryRow |
|
| 51 | 51 | import io.oxygenhub.android.ui.theme.LocalStatusColors |
|
| 52 | + | import io.oxygenhub.android.ui.theme.Tones |
|
| 52 | 53 | ||
| 53 | 54 | @Composable |
|
| 54 | 55 | fun DashboardScreen( |
|
| … | 115 unchanged lines |
||
| 170 | 171 | ListItem( |
|
| 171 | 172 | colors = ListItemDefaults.colors(containerColor = Color.Transparent), |
|
| 172 | 173 | leadingContent = { |
|
| 173 | - | Icon(if ((inbox.valueOrNull?.unread ?: 0) > 0) Icons.Outlined.MarkEmailUnread else Icons.Outlined.Inbox, contentDescription = null) |
|
| 174 | + | Icon(if ((inbox.valueOrNull?.unread ?: 0) > 0) Icons.Outlined.MarkEmailUnread else Icons.Outlined.Inbox, contentDescription = null, tint = Tones.info) |
|
| 174 | 175 | }, |
|
| 175 | 176 | headlineContent = { |
|
| 176 | 177 | Text( |
|
| … | 42 unchanged lines |
modified app/src/main/java/io/oxygenhub/android/ui/inbox/InboxScreen.kt +4 −3
| … | 7 unchanged lines |
||
| 8 | 8 | import androidx.compose.foundation.lazy.items |
|
| 9 | 9 | import androidx.compose.foundation.shape.CircleShape |
|
| 10 | 10 | import androidx.compose.material.icons.Icons |
|
| 11 | + | import androidx.compose.material.icons.automirrored.outlined.CallMerge |
|
| 11 | 12 | import androidx.compose.material.icons.outlined.AlternateEmail |
|
| 13 | + | import androidx.compose.material.icons.outlined.Backup |
|
| 12 | 14 | import androidx.compose.material.icons.outlined.BugReport |
|
| 13 | - | import androidx.compose.material.icons.automirrored.outlined.CallMerge |
|
| 14 | - | import androidx.compose.material.icons.outlined.Backup |
|
| 15 | 15 | import androidx.compose.material.icons.outlined.ChatBubbleOutline |
|
| 16 | 16 | import androidx.compose.material.icons.outlined.DoneAll |
|
| 17 | 17 | import androidx.compose.material.icons.outlined.Inbox |
|
| … | 25 unchanged lines |
||
| 43 | 43 | import io.oxygenhub.android.ui.common.EmptyState |
|
| 44 | 44 | import io.oxygenhub.android.ui.common.LoadContent |
|
| 45 | 45 | import io.oxygenhub.android.ui.common.relativeTime |
|
| 46 | + | import io.oxygenhub.android.ui.theme.Tones |
|
| 46 | 47 | ||
| 47 | 48 | /** |
|
| 48 | 49 | * The inbox. A notification opens what it is about on its own screen in |
|
| … | 47 unchanged lines |
||
| 96 | 97 | colors = if (n.read) ListItemDefaults.colors() else ListItemDefaults.colors(containerColor = MaterialTheme.colorScheme.surfaceContainerHigh), |
|
| 97 | 98 | leadingContent = { |
|
| 98 | 99 | Box(contentAlignment = Alignment.TopEnd) { |
|
| 99 | - | Icon(iconFor(n.kind), contentDescription = null) |
|
| 100 | + | Icon(iconFor(n.kind), contentDescription = null, tint = Tones.of(n.kind)) |
|
| 100 | 101 | if (!n.read) { |
|
| 101 | 102 | Surface(Modifier.size(8.dp), shape = CircleShape, color = MaterialTheme.colorScheme.primary) {} |
|
| 102 | 103 | } |
|
| … | 46 unchanged lines |
modified app/src/main/java/io/oxygenhub/android/ui/issues/IssuesScreen.kt +3 −2
| … | 13 unchanged lines |
||
| 14 | 14 | import androidx.compose.foundation.rememberScrollState |
|
| 15 | 15 | import androidx.compose.foundation.shape.RoundedCornerShape |
|
| 16 | 16 | import androidx.compose.material.icons.Icons |
|
| 17 | + | import androidx.compose.material.icons.outlined.ChatBubbleOutline |
|
| 17 | 18 | import androidx.compose.material.icons.outlined.CheckCircle |
|
| 18 | - | import androidx.compose.material.icons.outlined.ChatBubbleOutline |
|
| 19 | 19 | import androidx.compose.material.icons.outlined.PushPin |
|
| 20 | 20 | import androidx.compose.material.icons.outlined.RadioButtonUnchecked |
|
| 21 | 21 | import androidx.compose.material.icons.outlined.TaskAlt |
|
| … | 22 unchanged lines |
||
| 44 | 44 | import io.oxygenhub.android.ui.common.LoadContent |
|
| 45 | 45 | import io.oxygenhub.android.ui.common.relativeTime |
|
| 46 | 46 | import io.oxygenhub.android.ui.theme.LocalStatusColors |
|
| 47 | + | import io.oxygenhub.android.ui.theme.Tones |
|
| 47 | 48 | ||
| 48 | 49 | /** |
|
| 49 | 50 | * A repository's issues with their filter, for the repository's tab; an |
|
| … | 54 unchanged lines |
||
| 104 | 105 | overlineContent = if (issue.pinned) { |
|
| 105 | 106 | { |
|
| 106 | 107 | Row(verticalAlignment = Alignment.CenterVertically) { |
|
| 107 | - | Icon(Icons.Outlined.PushPin, contentDescription = null, modifier = Modifier.padding(end = 4.dp)) |
|
| 108 | + | Icon(Icons.Outlined.PushPin, contentDescription = null, modifier = Modifier.padding(end = 4.dp), tint = Tones.info) |
|
| 108 | 109 | Text("Pinned") |
|
| 109 | 110 | } |
|
| 110 | 111 | } |
|
| … | 51 unchanged lines |
modified app/src/main/java/io/oxygenhub/android/ui/owners/Owner.kt +5 −4
| … | 33 unchanged lines |
||
| 34 | 34 | import io.oxygenhub.android.api.Visibility |
|
| 35 | 35 | import io.oxygenhub.android.ui.common.AppScreen |
|
| 36 | 36 | import io.oxygenhub.android.ui.common.AvatarImage |
|
| 37 | + | import io.oxygenhub.android.ui.common.Load |
|
| 37 | 38 | import io.oxygenhub.android.ui.common.LoadContent |
|
| 38 | - | import io.oxygenhub.android.ui.common.Load |
|
| 39 | 39 | import io.oxygenhub.android.ui.common.load |
|
| 40 | + | import io.oxygenhub.android.ui.common.relativeTime |
|
| 40 | 41 | import io.oxygenhub.android.ui.common.rememberAvatar |
|
| 41 | - | import io.oxygenhub.android.ui.common.relativeTime |
|
| 42 | + | import io.oxygenhub.android.ui.theme.Tones |
|
| 42 | 43 | import kotlinx.coroutines.Job |
|
| 43 | 44 | import kotlinx.coroutines.async |
|
| 44 | 45 | import kotlinx.coroutines.coroutineScope |
|
| … | 83 unchanged lines |
||
| 128 | 129 | items(page.projects, key = { "p${it.number}" }) { p -> |
|
| 129 | 130 | ListItem( |
|
| 130 | 131 | modifier = Modifier.clickable { onOpenProject(p) }, |
|
| 131 | - | leadingContent = { Icon(Icons.Outlined.ViewKanban, contentDescription = null) }, |
|
| 132 | + | leadingContent = { Icon(Icons.Outlined.ViewKanban, contentDescription = null, tint = Tones.project) }, |
|
| 132 | 133 | headlineContent = { Text(p.title.ifBlank { "Project ${p.number}" }) }, |
|
| 133 | 134 | supportingContent = if (p.description.isNotBlank()) { |
|
| 134 | 135 | { Text(p.description, maxLines = 2) } |
|
| … | 16 unchanged lines |
||
| 151 | 152 | ) |
|
| 152 | 153 | }, |
|
| 153 | 154 | trailingContent = if (r.visibility != Visibility.Public) { |
|
| 154 | - | { Icon(Icons.Outlined.Lock, contentDescription = "Not public") } |
|
| 155 | + | { Icon(Icons.Outlined.Lock, contentDescription = "Not public", tint = Tones.restricted) } |
|
| 155 | 156 | } else { |
|
| 156 | 157 | null |
|
| 157 | 158 | }, |
|
| … | 17 unchanged lines |
modified app/src/main/java/io/oxygenhub/android/ui/proposals/ProposalScreen.kt +2 −1
| … | 59 unchanged lines |
||
| 60 | 60 | import io.oxygenhub.android.ui.common.relativeTime |
|
| 61 | 61 | import io.oxygenhub.android.ui.issues.LabelChip |
|
| 62 | 62 | import io.oxygenhub.android.ui.theme.LocalStatusColors |
|
| 63 | + | import io.oxygenhub.android.ui.theme.Tones |
|
| 63 | 64 | ||
| 64 | 65 | /** |
|
| 65 | 66 | * One proposal: whether it may land and what stands in the way, in the |
|
| … | 216 unchanged lines |
||
| 282 | 283 | } |
|
| 283 | 284 | p.requestedReviewers.forEach { r -> |
|
| 284 | 285 | ListItem( |
|
| 285 | - | leadingContent = { Icon(Icons.Outlined.Schedule, null) }, |
|
| 286 | + | leadingContent = { Icon(Icons.Outlined.Schedule, null, tint = Tones.pending) }, |
|
| 286 | 287 | headlineContent = { Text(r) }, |
|
| 287 | 288 | supportingContent = { Text("asked to review") }, |
|
| 288 | 289 | ) |
|
| … | 62 unchanged lines |
modified app/src/main/java/io/oxygenhub/android/ui/releases/Releases.kt +2 −1
| … | 44 unchanged lines |
||
| 45 | 45 | import io.oxygenhub.android.ui.common.Panel |
|
| 46 | 46 | import io.oxygenhub.android.ui.common.load |
|
| 47 | 47 | import io.oxygenhub.android.ui.common.relativeTime |
|
| 48 | + | import io.oxygenhub.android.ui.theme.Tones |
|
| 48 | 49 | import kotlinx.coroutines.CancellationException |
|
| 49 | 50 | import kotlinx.coroutines.Job |
|
| 50 | 51 | import kotlinx.coroutines.flow.MutableStateFlow |
|
| … | 70 unchanged lines |
||
| 121 | 122 | r.assets.forEach { a -> |
|
| 122 | 123 | ListItem( |
|
| 123 | 124 | modifier = Modifier.clickable { if (a.url.isNotBlank()) uri.openUri(a.url) }, |
|
| 124 | - | leadingContent = { Icon(Icons.Outlined.Download, contentDescription = "Download") }, |
|
| 125 | + | leadingContent = { Icon(Icons.Outlined.Download, contentDescription = "Download", tint = Tones.release) }, |
|
| 125 | 126 | headlineContent = { Text(a.name) }, |
|
| 126 | 127 | supportingContent = { Text("${bytes(a.size)} · ${a.downloads} downloads") }, |
|
| 127 | 128 | ) |
|
| … | 53 unchanged lines |
modified app/src/main/java/io/oxygenhub/android/ui/repos/RepositoryRow.kt +4 −3
| … | 22 unchanged lines |
||
| 23 | 23 | import io.oxygenhub.android.api.Repository |
|
| 24 | 24 | import io.oxygenhub.android.api.Visibility |
|
| 25 | 25 | import io.oxygenhub.android.ui.common.relativeTime |
|
| 26 | + | import io.oxygenhub.android.ui.theme.Tones |
|
| 26 | 27 | ||
| 27 | 28 | @Composable |
|
| 28 | 29 | fun RepositoryRow(repo: Repository, onClick: () -> Unit, modifier: Modifier = Modifier, selected: Boolean = false) { |
|
| … | 5 unchanged lines |
||
| 34 | 35 | // Transparent: the row takes the colour of what holds it (a card, a pane). |
|
| 35 | 36 | ListItemDefaults.colors(containerColor = Color.Transparent) |
|
| 36 | 37 | }, |
|
| 37 | - | leadingContent = { Icon(Icons.Outlined.Book, contentDescription = null) }, |
|
| 38 | + | leadingContent = { Icon(Icons.Outlined.Book, contentDescription = null, tint = Tones.repository) }, |
|
| 38 | 39 | headlineContent = { Text(repo.slug, maxLines = 1, overflow = TextOverflow.Ellipsis) }, |
|
| 39 | 40 | supportingContent = if (repo.description.isNotBlank()) { |
|
| 40 | 41 | { Text(repo.description, maxLines = 2, overflow = TextOverflow.Ellipsis) } |
|
| … | 3 unchanged lines |
||
| 44 | 45 | trailingContent = { |
|
| 45 | 46 | Row(verticalAlignment = Alignment.CenterVertically) { |
|
| 46 | 47 | when (repo.visibility) { |
|
| 47 | - | Visibility.Private -> Icon(Icons.Outlined.Lock, contentDescription = "Private", modifier = Modifier.size(16.dp)) |
|
| 48 | - | Visibility.Internal -> Icon(Icons.Outlined.Domain, contentDescription = "Internal", modifier = Modifier.size(16.dp)) |
|
| 48 | + | Visibility.Private -> Icon(Icons.Outlined.Lock, contentDescription = "Private", modifier = Modifier.size(16.dp), tint = Tones.restricted) |
|
| 49 | + | Visibility.Internal -> Icon(Icons.Outlined.Domain, contentDescription = "Internal", modifier = Modifier.size(16.dp), tint = Tones.restricted) |
|
| 49 | 50 | Visibility.Public -> {} |
|
| 50 | 51 | } |
|
| 51 | 52 | if (repo.visibility != Visibility.Public) Spacer(Modifier.width(6.dp)) |
|
| … | 5 unchanged lines |
modified app/src/main/java/io/oxygenhub/android/update/AppUpdate.kt +2 −1
| … | 16 unchanged lines |
||
| 17 | 17 | import io.oxygenhub.android.api.HubApi |
|
| 18 | 18 | import io.oxygenhub.android.api.Release |
|
| 19 | 19 | import io.oxygenhub.android.ui.common.Panel |
|
| 20 | + | import io.oxygenhub.android.ui.theme.Tones |
|
| 20 | 21 | ||
| 21 | 22 | /** Where the app's own releases are (#7), built and signed by OxygenFlow. */ |
|
| 22 | 23 | const val APP_HUB = "https://oxygenhub.io" |
|
| … | 47 unchanged lines |
||
| 70 | 71 | val uri = LocalUriHandler.current |
|
| 71 | 72 | Panel(Modifier.fillMaxWidth()) { |
|
| 72 | 73 | ListItem( |
|
| 73 | - | leadingContent = { Icon(Icons.Outlined.SystemUpdate, contentDescription = null) }, |
|
| 74 | + | leadingContent = { Icon(Icons.Outlined.SystemUpdate, contentDescription = null, tint = Tones.info) }, |
|
| 74 | 75 | headlineContent = { Text(update?.let { "Version ${it.version} is out" } ?: "OxygenHub $installed") }, |
|
| 75 | 76 | supportingContent = { |
|
| 76 | 77 | Text(if (update != null) "You have $installed. Download it and open the file to update." else "Releases are at $APP_HUB/$APP_OWNER/$APP_REPO.") |
|
| … | 5 unchanged lines |