Skip to content

Commit

Permalink
Add support for light theme
Browse files Browse the repository at this point in the history
  • Loading branch information
DRSchlaubi committed Nov 19, 2023
1 parent 7dfad24 commit 67c2877
Show file tree
Hide file tree
Showing 20 changed files with 133 additions and 53 deletions.
2 changes: 1 addition & 1 deletion app/android/src/main/java/UpdateActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ fun UpdateScreen(activity: Activity) {
) {
Text(
strings.appCrash,
color = ColorScheme.textColor,
color = ColorScheme.current.textColor,
style = MaterialTheme.typography.headlineMedium
)
val currentInfo = updateInfo
Expand Down
4 changes: 2 additions & 2 deletions app/android/src/main/java/UpdateAwareAppScope.kt
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,15 @@ fun UpdateAwareAppScope(activity: Activity, content: @Composable () -> Unit) {
modifier = Modifier
.padding(vertical = 7.dp)
.background(
MaterialTheme.colorScheme.primary,
MaterialTheme.ColorScheme.current.primary,
RoundedCornerShape(50.dp)
)
) {
@Composable
fun Info(text: String) {
Text(
text,
style = MaterialTheme.typography.headlineSmall.copy(color = ColorScheme.textColor),
style = MaterialTheme.typography.headlineSmall.copy(color = ColorScheme.current.textColor),
modifier = Modifier.padding(horizontal = 15.dp, vertical = 10.dp)
)
}
Expand Down
4 changes: 2 additions & 2 deletions app/desktop/src/commonMain/kotlin/AuthorizationScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ fun AuthorizationScreen(alreadyWaiting: Boolean, onAuth: () -> Unit) {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize().background(ColorScheme.container)
modifier = Modifier.fillMaxSize().background(ColorScheme.current.container)
) {
val strings = LocalStrings.current
Text(strings.pleaseSignIn, color = ColorScheme.textColor)
Text(strings.pleaseSignIn, color = ColorScheme.current.textColor)
if (waiting) {
CircularProgressIndicator()
} else {
Expand Down
4 changes: 2 additions & 2 deletions app/desktop/src/commonMain/kotlin/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ fun startApplication(forAuth: Boolean = false) = application {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize().background(ColorScheme.container)
modifier = Modifier.fillMaxSize().background(ColorScheme.current.container)
) {
Text(strings.needsUpdate, color = ColorScheme.textColor)
Text(strings.needsUpdate, color = ColorScheme.current.textColor)
Button({
launchUri(URI("https://github.com/DRSchlaubi/tonbrett/releases/latest"))
exitApplication()
Expand Down
2 changes: 1 addition & 1 deletion app/ios/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ plugins {

@OptIn(ExperimentalKotlinGradlePluginApi::class)
kotlin {
targetHierarchy.default()
applyDefaultHierarchyTemplate()
iosX64()
iosSimulatorArm64()
iosArm64()
Expand Down
1 change: 0 additions & 1 deletion app/ios/iosApp/ComposeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ struct ContentView: View {
var body: some View {
ComposeView(receivedToken: receivedToken, onAuth: signIn)
.ignoresSafeArea(.keyboard) // Compose has own keyboard handler
.preferredColorScheme(.dark) // there is no light theme YET or ever
}

func signIn(url: String) {
Expand Down
8 changes: 7 additions & 1 deletion app/shared/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ plugins {

@OptIn(ExperimentalKotlinGradlePluginApi::class)
kotlin {
targetHierarchy.default {
applyDefaultHierarchyTemplate {
common {
group("nonWeb") {
withNative()
Expand Down Expand Up @@ -81,6 +81,12 @@ kotlin {
}
}

named("desktopMain") {
dependencies {
implementation(libs.os.theme.detector)
}
}

androidMain {
dependencies {
implementation(libs.androidx.browser)
Expand Down
52 changes: 43 additions & 9 deletions app/shared/src/commonMain/kotlin/ColorScheme.kt
Original file line number Diff line number Diff line change
@@ -1,14 +1,48 @@
package dev.schlaubi.tonbrett.app

import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.graphics.Color

object ColorScheme {
val container = Color(17, 18, 20)
val secondaryContainer = Color(43, 45, 49)
val searchBarColor = Color(30, 31, 34)
val textColor = Color.White
val active = Color(87, 242, 135)
val disabled = Color.LightGray
val blurple = Color(88, 101, 242)
val error = Color(237, 66, 69)
// Currently no auto update, due to: https://github.com/JetBrains/compose-multiplatform/issues/1986
@Composable
expect fun isSystemInDarkMode(): Boolean

sealed interface ColorScheme {
val container: Color
val secondaryContainer: Color
val searchBarColor: Color
val textColor: Color
val active: Color
val disabled: Color
val blurple: Color
val error: Color

companion object {
val current: ColorScheme
@Composable
get() = if (isSystemInDarkMode()) DarkColorScheme else LightColorTheme
}
}

private object DarkColorScheme : ColorScheme {
override val container = Color(17, 18, 20)
override val secondaryContainer = Color(43, 45, 49)
override val searchBarColor = Color(30, 31, 34)
override val textColor = Color.White
override val active = Color(87, 242, 135)
override val disabled = Color.LightGray
override val blurple = Color(88, 101, 242)
override val error = Color(237, 66, 69)
}

private object LightColorTheme : ColorScheme {
override val container = Color(255, 255, 255)
override val secondaryContainer = Color(242, 243, 245)
override val searchBarColor = Color(227, 229, 232)
override val textColor = Color.Black
override val active = Color(87, 242, 135)
override val disabled = Color.DarkGray
override val blurple = Color(88, 101, 242)
override val error = Color(237, 66, 69)
}
12 changes: 7 additions & 5 deletions app/shared/src/commonMain/kotlin/TonbrettApp.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.schlaubi.tonbrett.app

import androidx.compose.foundation.background
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
Expand Down Expand Up @@ -53,6 +54,7 @@ fun TonbrettApp(sessionExpiredState: MutableState<Boolean> = remember { mutableS
var initialUser: User? by remember { mutableStateOf(null) }

val lyricist = rememberStrings(Locale.current.toLanguageTag())

suspend fun reportError(exception: Exception) {
if (exception is ReauthorizationRequiredException) {
sessionExpired = true
Expand Down Expand Up @@ -85,7 +87,7 @@ fun TonbrettApp(sessionExpiredState: MutableState<Boolean> = remember { mutableS
val user = initialUser
if (!crashed && !sessionExpired && user != null) {
Scaffold(
containerColor = ColorScheme.container,
containerColor = ColorScheme.current.container,
snackbarHost = { SnackbarHost(scaffoldState.snackbarHostState) }) { padding ->
Column(Modifier.padding(padding)) {
SoundList(::reportError, user.voiceState)
Expand All @@ -106,7 +108,7 @@ fun TonbrettApp(sessionExpiredState: MutableState<Boolean> = remember { mutableS
if (user == null && !sessionExpired) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.background(ColorScheme.container)
modifier = Modifier.background(ColorScheme.current.container)
.fillMaxSize()
) {
CircularProgressIndicator()
Expand All @@ -115,7 +117,7 @@ fun TonbrettApp(sessionExpiredState: MutableState<Boolean> = remember { mutableS
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.background(ColorScheme.container)
modifier = Modifier.background(ColorScheme.current.container)
.fillMaxSize()
) {
if (sessionExpired) {
Expand All @@ -124,15 +126,15 @@ fun TonbrettApp(sessionExpiredState: MutableState<Boolean> = remember { mutableS
Icon(Icons.Default.Refresh, LocalStrings.current.reAuthorize)
Text(
LocalStrings.current.reAuthorize,
color = ColorScheme.textColor
color = ColorScheme.current.textColor
)
}
}
} else if (crashed) {
CrashErrorScreen(LocalStrings.current.crashedExplainer) {
Button({ crashed = false }) {
Icon(Icons.Default.Refresh, LocalStrings.current.reload)
Text(LocalStrings.current.reload, color = ColorScheme.textColor)
Text(LocalStrings.current.reload, color = ColorScheme.current.textColor)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion app/shared/src/commonMain/kotlin/components/ErrorText.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ import dev.schlaubi.tonbrett.app.ColorScheme

@Composable
fun ErrorText(message: String) {
Text(message, color = ColorScheme.textColor, fontSize = 3.em, textAlign = TextAlign.Center)
Text(message, color = ColorScheme.current.textColor, fontSize = 3.em, textAlign = TextAlign.Center)
}
18 changes: 9 additions & 9 deletions app/shared/src/commonMain/kotlin/components/SearchBar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -102,21 +102,21 @@ fun SearchBar(updateSounds: SoundUpdater) {
DockedSearchBar(
value, ::updateSearch, { focusRequester.freeFocus() }, showSuggestions, ::showSuggestions,
modifier = Modifier.fillMaxWidth().padding(horizontal = 5.dp).focusRequester(focusRequester),
placeholder = { Text(strings.searchExplainer, color = ColorScheme.textColor.copy(alpha = .7f)) },
placeholder = { Text(strings.searchExplainer, color = ColorScheme.current.textColor.copy(alpha = .7f)) },
trailingIcon = {
TrailingIcon(value, {
updateSearch(it)
}, false)
},
colors = SearchBarDefaults.colors(
containerColor = ColorScheme.searchBarColor,
containerColor = ColorScheme.current.searchBarColor,
inputFieldColors = TextFieldDefaults.colors(
focusedContainerColor = ColorScheme.searchBarColor,
unfocusedContainerColor = ColorScheme.searchBarColor,
focusedPlaceholderColor = ColorScheme.secondaryContainer,
unfocusedPlaceholderColor = ColorScheme.secondaryContainer,
focusedTextColor = ColorScheme.textColor,
unfocusedTextColor = ColorScheme.textColor
focusedContainerColor = ColorScheme.current.searchBarColor,
unfocusedContainerColor = ColorScheme.current.searchBarColor,
focusedPlaceholderColor = ColorScheme.current.secondaryContainer,
unfocusedPlaceholderColor = ColorScheme.current.secondaryContainer,
focusedTextColor = ColorScheme.current.textColor,
unfocusedTextColor = ColorScheme.current.textColor
)
)
) {
Expand All @@ -138,7 +138,7 @@ fun SearchBar(updateSounds: SoundUpdater) {
val height = with(density) { constraints.maxHeight.toDp() }

if (height > 100.dp) {
Text(strings.typeForMoreSuggestions, color = ColorScheme.textColor)
Text(strings.typeForMoreSuggestions, color = ColorScheme.current.textColor)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ fun SearchSuggestions(
if (value.isNotBlank() && currentTags.isNotEmpty()) {
Text(
strings.searchByTag,
color = ColorScheme.textColor,
color = ColorScheme.current.textColor,
modifier = Modifier.padding(horizontal = 5.dp)
)
currentTags.forEach { tag ->
Expand All @@ -89,7 +89,7 @@ fun SearchSuggestions(
}
Text(
strings.searchOptions,
color = ColorScheme.textColor,
color = ColorScheme.current.textColor,
modifier = Modifier.padding(horizontal = 5.dp)
)
Column(Modifier.hoverable(interactionSource)) {
Expand Down Expand Up @@ -137,7 +137,7 @@ private fun SyntaxSuggestion(
updateSelected(index)
}
val text = buildAnnotatedString {
append(AnnotatedString("$name:", SpanStyle(color = ColorScheme.textColor)))
append(AnnotatedString("$name:", SpanStyle(color = ColorScheme.current.textColor)))
append(' ')
val color = if (value.isBlank()) Color.Gray else Color.LightGray
val text = value.ifBlank { placeholder }?.substringAfter(':')
Expand Down
14 changes: 7 additions & 7 deletions app/shared/src/commonMain/kotlin/components/SoundContainer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ fun SoundContainer(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 5.dp)
.background(ColorScheme.error)
.background(ColorScheme.current.error)
) {
Text(
lastDisabledReason!!,
Expand Down Expand Up @@ -130,12 +130,12 @@ fun SoundCard(
SoundToolTip(description, hovered && !playing) {
SoundCardContextMenuArea(id) {
ElevatedCard(
colors = CardDefaults.cardColors(containerColor = ColorScheme.secondaryContainer),
colors = CardDefaults.cardColors(containerColor = ColorScheme.current.secondaryContainer),
shape = corners,
modifier = Modifier.height(height = 64.dp)
.fillMaxWidth()
.conditional(playing) {
border(BorderStroke(2.dp, ColorScheme.active), corners)
border(BorderStroke(2.dp, ColorScheme.current.active), corners)
}
.hoverable(interactionSource)
.conditional(isMobile && !waiting && !disabled) {
Expand Down Expand Up @@ -169,10 +169,10 @@ fun SoundCard(
) {
require(emoji is Sound.Emoji.HasUrl?) { "This emoji is invalid: $emoji" }
OptionalWebImage(emoji?.url, modifier = Modifier.size(32.dp).padding(end = 5.dp))
Text(name, color = ColorScheme.textColor, fontSize = 16.sp, textAlign = TextAlign.Center)
Text(name, color = ColorScheme.current.textColor, fontSize = 16.sp, textAlign = TextAlign.Center)
}
if (playing && hovered && !disabled && !waiting) {
Box(Modifier.zIndex(1f).background(ColorScheme.secondaryContainer)) {
Box(Modifier.zIndex(1f).background(ColorScheme.current.secondaryContainer)) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
Expand All @@ -181,13 +181,13 @@ fun SoundCard(
IconButton({
play()
}) {
Icon(Icons.Default.Refresh, null, tint = ColorScheme.textColor)
Icon(Icons.Default.Refresh, null, tint = ColorScheme.current.textColor)
}
Divider(Modifier.width(1.dp).height(15.dp))
IconButton({
stop()
}) {
Icon(Icons.Default.Stop, null, tint = ColorScheme.textColor)
Icon(Icons.Default.Stop, null, tint = ColorScheme.current.textColor)
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions app/shared/src/commonMain/kotlin/util/SoundToolTip.kt
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ fun SoundToolTip(text: String?, isShown: Boolean, content: @Composable () -> Uni
SelectionContainer {
Text(
text,
color = whenPositionedOrTransparent(ColorScheme.textColor),
color = whenPositionedOrTransparent(ColorScheme.current.textColor),
textAlign = TextAlign.Center,
modifier = Modifier
.background(whenPositionedOrTransparent(Color.Black), RoundedCornerShape(7.dp))
.background(whenPositionedOrTransparent(ColorScheme.current.searchBarColor), RoundedCornerShape(7.dp))
.onSizeChanged {
height = it.height
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package dev.schlaubi.tonbrett.app

import androidx.compose.runtime.*
import com.jthemedetecor.OsThemeDetector
import org.jetbrains.skiko.SystemTheme
import org.jetbrains.skiko.currentSystemTheme

@Composable
actual fun isSystemInDarkMode(): Boolean {
var darkTheme by remember {
mutableStateOf(currentSystemTheme == SystemTheme.DARK)
}

DisposableEffect(Unit) {
val darkThemeListener = { isDarkTheme: Boolean ->
darkTheme = isDarkTheme
}

val detector = OsThemeDetector.getDetector().apply {
registerListener(darkThemeListener)
}

onDispose {
detector.removeListener(darkThemeListener)
}
}

return darkTheme
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ fun MobileTonbrettApp(receivedToken: String? = null, onAuth: (url: String) -> Un
} else {
strings.pleaseSignIn
}
Text(text, color = MaterialTheme.colorScheme.onSecondary)
Text(text, color = MaterialTheme.ColorScheme.current.onSecondary)
Button(::authorize) {
Icon(Icons.Default.OpenInBrowser, null)
Text(strings.signInWithDiscord)
Expand Down
7 changes: 7 additions & 0 deletions app/shared/src/nonDesktopMain/kotlin/ColorScheme.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package dev.schlaubi.tonbrett.app

import androidx.compose.runtime.Composable
import androidx.compose.foundation.isSystemInDarkTheme as composeIsSystemInDarkTheme1

@Composable
actual fun isSystemInDarkMode() = composeIsSystemInDarkTheme1()
Loading

0 comments on commit 67c2877

Please sign in to comment.