mirror of
				https://github.com/oxen-io/session-android.git
				synced 2025-10-30 23:09:20 +00:00 
			
		
		
		
	Cleaning up the code for theming and decoupling the isClassic logic
This commit is contained in:
		| @@ -60,30 +60,6 @@ val Colors.disabled @Composable get() = onSurface.copy(alpha = ContentAlpha.disa | ||||
|  | ||||
| val blackAlpha40 = Color.Black.copy(alpha = 0.4f) | ||||
|  | ||||
| val LocalColors = staticCompositionLocalOf { sessionColors(isLight = false, isClassic = true) } | ||||
|  | ||||
| data class SessionColors( | ||||
|     val isLight: Boolean = false, | ||||
|     val primary: Color = Color.Unspecified, | ||||
|     val danger: Color = Color.Unspecified, | ||||
|     val disabled: Color = Color.Unspecified, | ||||
|     val background: Color = Color.Unspecified, | ||||
|     val backgroundSecondary: Color = Color.Unspecified, | ||||
|     val text: Color = Color.Unspecified, | ||||
|     val textSecondary: Color = Color.Unspecified, | ||||
|     val borders: Color = Color.Unspecified, | ||||
|     val textBubbleSent: Color = Color.Unspecified, | ||||
|     val backgroundBubbleReceived: Color = Color.Unspecified, | ||||
|     val textBubbleReceived: Color = Color.Unspecified, | ||||
| ) { | ||||
|     val backgroundLight get() = if (isLight) backgroundSecondary else Color.White | ||||
|     val onBackgroundLight get() = if (isLight) text else background | ||||
|     val button get() = if (isLight) text else primary | ||||
|     val divider get() = text.copy(alpha = TabRowDefaults.DividerOpacity) | ||||
|     val backgroundBubbleSent get() = primary | ||||
|     @Composable fun radioButtonColors() = RadioButtonDefaults.colors(selectedColor = primary, unselectedColor = text, disabledColor = disabled) | ||||
| } | ||||
|  | ||||
| val primaryGreen = Color(0xFF31F196) | ||||
| val primaryBlue = Color(0xFF57C9FA) | ||||
| val primaryPurple = Color(0xFFC993FF) | ||||
| @@ -97,77 +73,6 @@ val dangerLight = Color(0xFFE12D19) | ||||
| val disabledDark = Color(0xFFA1A2A1) | ||||
| val disabledLight = Color(0xFF6D6D6D) | ||||
|  | ||||
| fun sessionColors( | ||||
|     isLight: Boolean, | ||||
|     isClassic: Boolean, | ||||
|     primary: Color = if (isClassic) primaryGreen else primaryBlue | ||||
| ): SessionColors = if (isClassic) { | ||||
|     if (isLight) classicLight else classicDark | ||||
| } else { | ||||
|     if (isLight) oceanLight else oceanDark | ||||
| }.copy( | ||||
|     primary = primary | ||||
| ) | ||||
|  | ||||
| val classicDark = SessionColors( | ||||
|     isLight = false, | ||||
|     primary = primaryGreen, | ||||
|     danger = dangerDark, | ||||
|     disabled = disabledDark, | ||||
|     background = Color.Black, | ||||
|     backgroundSecondary = classicDark1, | ||||
|     text = Color.White, | ||||
|     textSecondary = classicDark5, | ||||
|     borders = classicDark3, | ||||
|     textBubbleSent = Color.Black, | ||||
|     backgroundBubbleReceived = classicDark2, | ||||
|     textBubbleReceived = Color.White, | ||||
| ) | ||||
|  | ||||
| val classicLight = SessionColors( | ||||
|     isLight = true, | ||||
|     primary = primaryGreen, | ||||
|     danger = dangerLight, | ||||
|     disabled = disabledLight, | ||||
|     background = Color.White, | ||||
|     backgroundSecondary = classicLight5, | ||||
|     text = Color.Black, | ||||
|     textSecondary = classicLight1, | ||||
|     borders = classicLight3, | ||||
|     textBubbleSent = Color.Black, | ||||
|     backgroundBubbleReceived = classicLight4, | ||||
|     textBubbleReceived = classicLight4, | ||||
| ) | ||||
|  | ||||
| val oceanDark = SessionColors( | ||||
|     isLight = false, | ||||
|     primary = primaryBlue, | ||||
|     danger = dangerDark, | ||||
|     disabled = disabledDark, | ||||
|     background = oceanDark2, | ||||
|     backgroundSecondary = oceanDark1, | ||||
|     text = Color.White, | ||||
|     textSecondary = oceanDark5, | ||||
|     borders = oceanDark4, | ||||
|     textBubbleSent = Color.Black, | ||||
|     backgroundBubbleReceived = oceanDark4, | ||||
|     textBubbleReceived = oceanDark4, | ||||
| ) | ||||
|  | ||||
| val oceanLight = SessionColors( | ||||
|     isLight = true, | ||||
|     primary = primaryBlue, | ||||
|     danger = dangerLight, | ||||
|     disabled = disabledLight, | ||||
|     background = oceanLight7, | ||||
|     backgroundSecondary = oceanLight6, | ||||
|     text = oceanLight1, | ||||
|     textSecondary = oceanLight2, | ||||
|     borders = oceanLight3, | ||||
|     textBubbleSent = oceanLight1, | ||||
|     backgroundBubbleReceived = oceanLight4, | ||||
|     textBubbleReceived = oceanLight4 | ||||
| ) | ||||
|  | ||||
| @Composable | ||||
| fun transparentButtonColors() = ButtonDefaults.buttonColors(backgroundColor = Color.Transparent) | ||||
| @@ -175,55 +80,6 @@ fun transparentButtonColors() = ButtonDefaults.buttonColors(backgroundColor = Co | ||||
| @Composable | ||||
| fun destructiveButtonColors() = ButtonDefaults.buttonColors(backgroundColor = Color.Transparent, contentColor = LocalColors.current.danger) | ||||
|  | ||||
| @Composable | ||||
| fun Colors(name: String, colors: List<Color>) { | ||||
|     Column { | ||||
|         colors.forEachIndexed { i, it -> | ||||
|             Box(Modifier.background(it)) { | ||||
|                 Text("$name: $i") | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @Preview | ||||
| @Composable | ||||
| fun PreviewThemeColors( | ||||
|     @PreviewParameter(SessionColorsParameterProvider::class) sessionColors: SessionColors | ||||
| ) { | ||||
|     PreviewTheme(sessionColors) { ThemeColors() } | ||||
| } | ||||
|  | ||||
| @Composable | ||||
| private fun ThemeColors() { | ||||
|     Column { | ||||
|         Box(Modifier.background(MaterialTheme.colors.primary)) { | ||||
|             Text("primary", style = MaterialTheme.typography.base) | ||||
|         } | ||||
|         Box(Modifier.background(MaterialTheme.colors.primaryVariant)) { | ||||
|             Text("primaryVariant", style = MaterialTheme.typography.base) | ||||
|         } | ||||
|         Box(Modifier.background(MaterialTheme.colors.secondary)) { | ||||
|             Text("secondary", style = MaterialTheme.typography.base) | ||||
|         } | ||||
|         Box(Modifier.background(MaterialTheme.colors.secondaryVariant)) { | ||||
|             Text("secondaryVariant", style = MaterialTheme.typography.base) | ||||
|         } | ||||
|         Box(Modifier.background(MaterialTheme.colors.surface)) { | ||||
|             Text("surface", style = MaterialTheme.typography.base) | ||||
|         } | ||||
|         Box(Modifier.background(MaterialTheme.colors.primarySurface)) { | ||||
|             Text("primarySurface", style = MaterialTheme.typography.base) | ||||
|         } | ||||
|         Box(Modifier.background(MaterialTheme.colors.background)) { | ||||
|             Text("background", style = MaterialTheme.typography.base) | ||||
|         } | ||||
|         Box(Modifier.background(MaterialTheme.colors.error)) { | ||||
|             Text("error", style = MaterialTheme.typography.base) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @Composable | ||||
| fun outlinedTextFieldColors( | ||||
|     isError: Boolean | ||||
| @@ -234,13 +90,3 @@ fun outlinedTextFieldColors( | ||||
|     unfocusedBorderColor = LocalColors.current.borders, | ||||
|     placeholderColor = if (isError) LocalColors.current.danger else LocalColors.current.textSecondary | ||||
| ) | ||||
|  | ||||
| fun TextSecurePreferences.Companion.getAccentColor(context: Context): Color = when (getAccentColorName(context)) { | ||||
|     BLUE_ACCENT -> primaryBlue | ||||
|     PURPLE_ACCENT -> primaryPurple | ||||
|     PINK_ACCENT -> primaryPink | ||||
|     RED_ACCENT -> primaryRed | ||||
|     ORANGE_ACCENT -> primaryOrange | ||||
|     YELLOW_ACCENT -> primaryYellow | ||||
|     else -> primaryGreen | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,6 @@ | ||||
| package org.thoughtcrime.securesms.ui | ||||
|  | ||||
| data class SessionColorSet( | ||||
|     val lightTheme: SessionColors, | ||||
|     val darkTheme: SessionColors | ||||
| ) | ||||
| @@ -0,0 +1,50 @@ | ||||
| package org.thoughtcrime.securesms.ui | ||||
|  | ||||
| import androidx.compose.material.Colors | ||||
| import androidx.compose.material.RadioButtonDefaults | ||||
| import androidx.compose.material.TabRowDefaults | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.ui.graphics.Color | ||||
|  | ||||
| data class SessionColors( | ||||
|     val isLight: Boolean = false, | ||||
|     val primary: Color = Color.Unspecified, | ||||
|     val danger: Color = Color.Unspecified, | ||||
|     val disabled: Color = Color.Unspecified, | ||||
|     val background: Color = Color.Unspecified, | ||||
|     val backgroundSecondary: Color = Color.Unspecified, | ||||
|     val text: Color = Color.Unspecified, | ||||
|     val textSecondary: Color = Color.Unspecified, | ||||
|     val borders: Color = Color.Unspecified, | ||||
|     val textBubbleSent: Color = Color.Unspecified, | ||||
|     val backgroundBubbleReceived: Color = Color.Unspecified, | ||||
|     val textBubbleReceived: Color = Color.Unspecified, | ||||
| ) { | ||||
|     // To delete and instead use figma terms and add them to the data class above ------ | ||||
|     val backgroundLight get() = if (isLight) backgroundSecondary else Color.White | ||||
|     val onBackgroundLight get() = if (isLight) text else background | ||||
|     val button get() = if (isLight) text else primary | ||||
|     val backgroundBubbleSent get() = primary | ||||
|     // -------------------------------------------------------------------------------- | ||||
|  | ||||
|     @Composable | ||||
|     fun radioButtonColors() = RadioButtonDefaults.colors(selectedColor = primary, unselectedColor = text, disabledColor = disabled) | ||||
|  | ||||
|     val divider get() = text.copy(alpha = TabRowDefaults.DividerOpacity) | ||||
|  | ||||
|     fun toMaterialColors() = Colors( | ||||
|         primary = background, | ||||
|         primaryVariant = backgroundSecondary, | ||||
|         secondary = background, | ||||
|         secondaryVariant = background, | ||||
|         background = background, | ||||
|         surface = background, | ||||
|         error = danger, | ||||
|         onPrimary = text, | ||||
|         onSecondary = text, | ||||
|         onBackground = text, | ||||
|         onSurface = text, | ||||
|         onError = text, | ||||
|         isLight = isLight | ||||
|     ) | ||||
| } | ||||
| @@ -4,6 +4,7 @@ import android.content.Context | ||||
| import androidx.compose.foundation.background | ||||
| import androidx.compose.foundation.isSystemInDarkTheme | ||||
| import androidx.compose.foundation.layout.Box | ||||
| import androidx.compose.foundation.layout.Column | ||||
| import androidx.compose.foundation.shape.RoundedCornerShape | ||||
| import androidx.compose.foundation.text.selection.LocalTextSelectionColors | ||||
| import androidx.compose.foundation.text.selection.TextSelectionColors | ||||
| @@ -11,12 +12,20 @@ import androidx.compose.material.Colors | ||||
| import androidx.compose.material.LocalContentColor | ||||
| import androidx.compose.material.MaterialTheme | ||||
| import androidx.compose.material.Shapes | ||||
| import androidx.compose.material.Text | ||||
| import androidx.compose.material.primarySurface | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.runtime.CompositionLocalProvider | ||||
| import androidx.compose.runtime.compositionLocalOf | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.graphics.Color | ||||
| import androidx.compose.ui.platform.LocalContext | ||||
| import androidx.compose.ui.tooling.preview.Preview | ||||
| import androidx.compose.ui.tooling.preview.PreviewParameter | ||||
| import androidx.compose.ui.tooling.preview.PreviewParameterProvider | ||||
| import network.loki.messenger.R | ||||
| import org.session.libsession.utilities.AppTextSecurePreferences | ||||
| import org.session.libsession.utilities.TextSecurePreferences | ||||
| import org.thoughtcrime.securesms.util.ThemeState | ||||
| import org.thoughtcrime.securesms.util.themeState | ||||
|  | ||||
| @@ -27,7 +36,7 @@ import org.thoughtcrime.securesms.util.themeState | ||||
| fun SessionMaterialTheme( | ||||
|     content: @Composable () -> Unit | ||||
| ) { | ||||
|     SessionMaterialTheme(LocalContext.current.sessionColors()) { content() } | ||||
|     SessionMaterialTheme(LocalContext.current.composeTheme()) { content() } | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -58,24 +67,104 @@ fun SessionMaterialTheme( | ||||
|     } | ||||
| } | ||||
|  | ||||
| private fun SessionColors.toMaterialColors() = Colors( | ||||
|     primary = background, | ||||
|     primaryVariant = backgroundSecondary, | ||||
|     secondary = background, | ||||
|     secondaryVariant = background, | ||||
|     background = background, | ||||
|     surface = background, | ||||
|     error = danger, | ||||
|     onPrimary = text, | ||||
|     onSecondary = text, | ||||
|     onBackground = text, | ||||
|     onSurface = text, | ||||
|     onError = text, | ||||
|     isLight = isLight | ||||
| // Compose theme holder | ||||
| val LocalColors = compositionLocalOf { classicDark } | ||||
|  | ||||
| // Our themes | ||||
| val classicDark = SessionColors( | ||||
|     isLight = false, | ||||
|     primary = primaryGreen, | ||||
|     danger = dangerDark, | ||||
|     disabled = disabledDark, | ||||
|     background = Color.Black, | ||||
|     backgroundSecondary = classicDark1, | ||||
|     text = Color.White, | ||||
|     textSecondary = classicDark5, | ||||
|     borders = classicDark3, | ||||
|     textBubbleSent = Color.Black, | ||||
|     backgroundBubbleReceived = classicDark2, | ||||
|     textBubbleReceived = Color.White, | ||||
| ) | ||||
|  | ||||
| @Composable private fun Context.sessionColors() = AppTextSecurePreferences(this).themeState().sessionColors() | ||||
| @Composable private fun ThemeState.sessionColors() = sessionColors(if (followSystem) !isSystemInDarkTheme() else isLight, isClassic, accent) | ||||
| val classicLight = SessionColors( | ||||
|     isLight = true, | ||||
|     primary = primaryGreen, | ||||
|     danger = dangerLight, | ||||
|     disabled = disabledLight, | ||||
|     background = Color.White, | ||||
|     backgroundSecondary = classicLight5, | ||||
|     text = Color.Black, | ||||
|     textSecondary = classicLight1, | ||||
|     borders = classicLight3, | ||||
|     textBubbleSent = Color.Black, | ||||
|     backgroundBubbleReceived = classicLight4, | ||||
|     textBubbleReceived = classicLight4, | ||||
| ) | ||||
|  | ||||
| val oceanDark = SessionColors( | ||||
|     isLight = false, | ||||
|     primary = primaryBlue, | ||||
|     danger = dangerDark, | ||||
|     disabled = disabledDark, | ||||
|     background = oceanDark2, | ||||
|     backgroundSecondary = oceanDark1, | ||||
|     text = Color.White, | ||||
|     textSecondary = oceanDark5, | ||||
|     borders = oceanDark4, | ||||
|     textBubbleSent = Color.Black, | ||||
|     backgroundBubbleReceived = oceanDark4, | ||||
|     textBubbleReceived = oceanDark4, | ||||
| ) | ||||
|  | ||||
| val oceanLight = SessionColors( | ||||
|     isLight = true, | ||||
|     primary = primaryBlue, | ||||
|     danger = dangerLight, | ||||
|     disabled = disabledLight, | ||||
|     background = oceanLight7, | ||||
|     backgroundSecondary = oceanLight6, | ||||
|     text = oceanLight1, | ||||
|     textSecondary = oceanLight2, | ||||
|     borders = oceanLight3, | ||||
|     textBubbleSent = oceanLight1, | ||||
|     backgroundBubbleReceived = oceanLight4, | ||||
|     textBubbleReceived = oceanLight4 | ||||
| ) | ||||
|  | ||||
| val classicTheme = SessionColorSet( | ||||
|     lightTheme = classicLight, | ||||
|     darkTheme = classicDark | ||||
| ) | ||||
|  | ||||
| val oceanTheme = SessionColorSet( | ||||
|     lightTheme = oceanLight, | ||||
|     darkTheme = oceanDark | ||||
| ) | ||||
|  | ||||
| @Composable private fun Context.composeTheme() = AppTextSecurePreferences(this).themeState().composeTheme() | ||||
| // We still need to match xml values for now but once we go full Compose all of this can go | ||||
| @Composable private fun ThemeState.composeTheme(): SessionColors { | ||||
|     // pick the theme based on xml value | ||||
|     val colorSet = when (theme) { | ||||
|         R.style.Ocean_Light, | ||||
|         R.style.Ocean_Dark -> oceanTheme | ||||
|  | ||||
|         else -> classicTheme | ||||
|     } | ||||
|  | ||||
|     // get the mode (light/dark/system) from settings | ||||
|     val colorMode = | ||||
|         when { | ||||
|             followSystem -> { // user decided to 'match system settings' | ||||
|                 if(isSystemInDarkTheme()) colorSet.darkTheme else colorSet.lightTheme | ||||
|             } | ||||
|             isLight -> colorSet.lightTheme | ||||
|             else -> colorSet.darkTheme | ||||
|         } | ||||
|  | ||||
|     // set the accent as per user choice | ||||
|     return colorMode.copy(primary = accent) | ||||
| } | ||||
|  | ||||
| val sessionShapes = Shapes( | ||||
|     small = RoundedCornerShape(50) | ||||
| @@ -98,9 +187,44 @@ fun PreviewTheme( | ||||
|  | ||||
| class SessionColorsParameterProvider : PreviewParameterProvider<SessionColors> { | ||||
|     override val values = sequenceOf( | ||||
|         sessionColors(isLight = false, isClassic = true), | ||||
|         sessionColors(isLight = true, isClassic = true), | ||||
|         sessionColors(isLight = false, isClassic = false), | ||||
|         sessionColors(isLight = true, isClassic = false), | ||||
|         classicDark, classicLight, oceanDark, oceanLight | ||||
|     ) | ||||
| } | ||||
|  | ||||
| @Preview | ||||
| @Composable | ||||
| fun PreviewThemeColors( | ||||
|     @PreviewParameter(SessionColorsParameterProvider::class) sessionColors: SessionColors | ||||
| ) { | ||||
|     PreviewTheme(sessionColors) { ThemeColors() } | ||||
| } | ||||
|  | ||||
| @Composable | ||||
| private fun ThemeColors() { | ||||
|     Column { | ||||
|         Box(Modifier.background(MaterialTheme.colors.primary)) { | ||||
|             Text("primary", style = MaterialTheme.typography.base) | ||||
|         } | ||||
|         Box(Modifier.background(MaterialTheme.colors.primaryVariant)) { | ||||
|             Text("primaryVariant", style = MaterialTheme.typography.base) | ||||
|         } | ||||
|         Box(Modifier.background(MaterialTheme.colors.secondary)) { | ||||
|             Text("secondary", style = MaterialTheme.typography.base) | ||||
|         } | ||||
|         Box(Modifier.background(MaterialTheme.colors.secondaryVariant)) { | ||||
|             Text("secondaryVariant", style = MaterialTheme.typography.base) | ||||
|         } | ||||
|         Box(Modifier.background(MaterialTheme.colors.surface)) { | ||||
|             Text("surface", style = MaterialTheme.typography.base) | ||||
|         } | ||||
|         Box(Modifier.background(MaterialTheme.colors.primarySurface)) { | ||||
|             Text("primarySurface", style = MaterialTheme.typography.base) | ||||
|         } | ||||
|         Box(Modifier.background(MaterialTheme.colors.background)) { | ||||
|             Text("background", style = MaterialTheme.typography.base) | ||||
|         } | ||||
|         Box(Modifier.background(MaterialTheme.colors.error)) { | ||||
|             Text("error", style = MaterialTheme.typography.base) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 ThomasSession
					ThomasSession