diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/LandingActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/LandingActivity.kt index 07e3a3faf2..7059095748 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/LandingActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/LandingActivity.kt @@ -48,6 +48,7 @@ import org.thoughtcrime.securesms.onboarding.pickname.startPickDisplayNameActivi import org.thoughtcrime.securesms.service.KeyCachingService import org.thoughtcrime.securesms.showOpenUrlDialog import org.thoughtcrime.securesms.ui.AppTheme +import org.thoughtcrime.securesms.ui.LocalColors import org.thoughtcrime.securesms.ui.LocalDimensions import org.thoughtcrime.securesms.ui.PreviewTheme import org.thoughtcrime.securesms.ui.ThemeResPreviewParameterProvider @@ -57,7 +58,6 @@ import org.thoughtcrime.securesms.ui.components.FilledButton import org.thoughtcrime.securesms.ui.components.OutlineButton import org.thoughtcrime.securesms.ui.contentDescription import org.thoughtcrime.securesms.ui.large -import org.thoughtcrime.securesms.ui.session_accent import org.thoughtcrime.securesms.util.setUpActionBarSessionLogo import org.thoughtcrime.securesms.util.start import kotlin.time.Duration.Companion.milliseconds @@ -226,8 +226,8 @@ private fun MessageText(text: String, isOutgoing: Boolean, modifier: Modifier) { Box(modifier = modifier then Modifier.fillMaxWidth()) { MessageText( text, - color = if (isOutgoing) session_accent else classicDarkColors[2], - textColor = if (isOutgoing) MaterialTheme.colors.primary else Color.Unspecified, + color = if (isOutgoing) LocalColors.current.backgroundBubbleSent else LocalColors.current.backgroundBubbleReceived, + textColor = if (isOutgoing) LocalColors.current.textBubbleSent else LocalColors.current.textBubbleReceived, modifier = Modifier.align(if (isOutgoing) Alignment.TopEnd else Alignment.TopStart) ) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsActivity.kt index 9bcb03584f..5634e493dc 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsActivity.kt @@ -38,6 +38,7 @@ import org.thoughtcrime.securesms.BaseActionBarActivity import org.thoughtcrime.securesms.home.HomeActivity import org.thoughtcrime.securesms.notifications.PushRegistry import org.thoughtcrime.securesms.ui.AppTheme +import org.thoughtcrime.securesms.ui.LocalColors import org.thoughtcrime.securesms.ui.LocalDimensions import org.thoughtcrime.securesms.ui.PreviewTheme import org.thoughtcrime.securesms.ui.ThemeResPreviewParameterProvider @@ -46,7 +47,6 @@ import org.thoughtcrime.securesms.ui.components.OutlineButton import org.thoughtcrime.securesms.ui.contentDescription import org.thoughtcrime.securesms.ui.h8 import org.thoughtcrime.securesms.ui.h9 -import org.thoughtcrime.securesms.ui.session_accent import org.thoughtcrime.securesms.ui.small import org.thoughtcrime.securesms.util.setUpActionBarSessionLogo import javax.inject.Inject @@ -153,7 +153,7 @@ fun NotificationRadioButton( onClick = onClick, modifier = Modifier.weight(1f).contentDescription(contentDescription), colors = ButtonDefaults.outlinedButtonColors(backgroundColor = MaterialTheme.colors.background, contentColor = Color.White), - border = if (selected) BorderStroke(ButtonDefaults.OutlinedBorderSize, session_accent) else ButtonDefaults.outlinedBorder, + border = if (selected) BorderStroke(ButtonDefaults.OutlinedBorderSize, LocalColors.current.primary) else ButtonDefaults.outlinedBorder, shape = RoundedCornerShape(8.dp) ) { Column( @@ -161,7 +161,7 @@ fun NotificationRadioButton( ) { Text(stringResource(title), style = MaterialTheme.typography.h8) Text(stringResource(explanation), style = MaterialTheme.typography.small) - tag?.let { Text(stringResource(it), color = session_accent, style = MaterialTheme.typography.h9) } + tag?.let { Text(stringResource(it), color = LocalColors.current.primary, style = MaterialTheme.typography.h9) } } } RadioButton(selected = selected, modifier = Modifier.align(Alignment.CenterVertically), onClick = onClick) diff --git a/app/src/main/java/org/thoughtcrime/securesms/ui/Colors.kt b/app/src/main/java/org/thoughtcrime/securesms/ui/Colors.kt index 37a953c820..eed78a0497 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ui/Colors.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/Colors.kt @@ -1,5 +1,6 @@ package org.thoughtcrime.securesms.ui +import android.content.Context import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -16,6 +17,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter +import org.session.libsession.utilities.TextSecurePreferences val colorDestructive = Color(0xffFF453A) @@ -53,9 +55,6 @@ const val oceanLight5 = 0xffE7F3F4 const val oceanLight6 = 0xffECFAFB const val oceanLight7 = 0xffFCFFFF -val session_accent = Color(0xFF31F196) -val ocean_accent = Color(0xff57C9FA) - val Colors.disabled @Composable get() = onSurface.copy(alpha = ContentAlpha.disabled) val oceanLights = arrayOf(oceanLight0, oceanLight1, oceanLight2, oceanLight3, oceanLight4, oceanLight5, oceanLight6, oceanLight7) @@ -144,3 +143,13 @@ fun outlinedTextFieldColors( unfocusedBorderColor = Color(classicDark3), placeholderColor = if (isError) colorDestructive else MaterialTheme.colors.onSurface.copy(ContentAlpha.medium) ) + +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 +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt b/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt index ca41cf7369..02b56c2580 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt @@ -364,7 +364,7 @@ fun ProgressArc(progress: Float, modifier: Modifier = Modifier) { fun Arc( modifier: Modifier = Modifier, percentage: Float = 0.25f, - fillColor: Color = session_accent, + fillColor: Color = LocalColors.current.primary, backgroundColor: Color = classicDarkColors[3], strokeWidth: Dp = 18.dp, sweepAngle: Float = 310f, diff --git a/app/src/main/java/org/thoughtcrime/securesms/ui/Themes.kt b/app/src/main/java/org/thoughtcrime/securesms/ui/Themes.kt index 7cacc8a004..aaada78b07 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ui/Themes.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/Themes.kt @@ -30,6 +30,8 @@ import androidx.compose.ui.unit.sp import com.google.accompanist.themeadapter.appcompat.createAppCompatTheme import com.google.android.material.color.MaterialColors import network.loki.messenger.R +import org.session.libsession.utilities.AppTextSecurePreferences +import org.thoughtcrime.securesms.util.themeState val LocalCellColor = staticCompositionLocalOf { Color.Black } val LocalButtonColor = staticCompositionLocalOf { Color.Black } @@ -52,6 +54,81 @@ data class Dimensions( val dividerIndent: Dp = 80.dp, ) +val LocalColors = staticCompositionLocalOf { SessionColors() } + +data class SessionColors( + 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 backgroundBubbleSent get() = primary +} + +val primaryGreen = Color(0xFF31F196) +val primaryBlue = Color(0xFF57C9FA) +val primaryPurple = Color(0xFFC993FF) +val primaryPink = Color(0xFFFF95EF) +val primaryRed = Color(0xFFFF9C8E) +val primaryOrange = Color(0xFFFCB159) +val primaryYellow = Color(0xFFFAD657) + +val dangerDark = Color(0xFFFF3A3A) +val dangerLight = Color(0xFFE12D19) +val disabledDark = Color(0xFFA1A2A1) +val disabledLioht = Color(0xFF6D6D6D) + +val primaryColors = listOf( + primaryGreen, + primaryBlue, + primaryPurple, + primaryPink, + primaryRed, + primaryOrange, + primaryYellow, +) + +private class UnresolvedColor(val function: (Boolean, Boolean) -> Color) { + operator fun invoke(isLight: Boolean, isClassic: Boolean) = function(isLight, isClassic) + + constructor(light: Color, dark: Color): this(function = { isLight, _ -> if (isLight) light else dark }) + constructor(classicDark: Color, classicLight: Color, oceanDark: Color, oceanLight: Color): this(function = { isLight, isClassic -> if (isLight) if (isClassic) classicLight else oceanLight else if (isClassic) classicDark else oceanDark }) +} + +private class UnresolvedSessionColors( + val danger: UnresolvedColor = UnresolvedColor(dark = dangerDark, light = dangerLight), + val disabled: UnresolvedColor = UnresolvedColor(dark = disabledDark, light = disabledLioht), + val background: UnresolvedColor = UnresolvedColor(Color.Black, Color.White, oceanDarkColors[2], oceanLightColors[7]), + val backgroundSecondary: UnresolvedColor = UnresolvedColor(classicDarkColors[1], classicLightColors[5], oceanDarkColors[1], oceanLightColors[6]), + val text: UnresolvedColor = UnresolvedColor(Color.White, Color.Black, oceanDarkColors[1], oceanLightColors[1]), + val textSecondary: UnresolvedColor = UnresolvedColor(classicDarkColors[5], classicLightColors[1], oceanDarkColors[5], oceanLightColors[2]), + val borders: UnresolvedColor = UnresolvedColor(classicDarkColors[3], classicLightColors[3], oceanDarkColors[4], oceanLightColors[3]), + val textBubbleSent: UnresolvedColor = UnresolvedColor(Color.Black, Color.Black, Color.Black, oceanLightColors[1]), + val backgroundBubbleReceived: UnresolvedColor = UnresolvedColor(classicDarkColors[2], classicLightColors[4], oceanDarkColors[4], oceanLightColors[4]), + val textBubbleReceived: UnresolvedColor = UnresolvedColor(Color.White, classicLightColors[4], oceanDarkColors[4], oceanLightColors[4]), +) { + operator fun invoke(primary: Color, isLight: Boolean, isClassic: Boolean) = SessionColors( + primary = primary, + danger = danger(isLight, isClassic), + disabled = disabled(isLight, isClassic), + background = background(isLight, isClassic), + backgroundSecondary = backgroundSecondary(isLight, isClassic), + text = text(isLight, isClassic), + textSecondary = textSecondary(isLight, isClassic), + borders = borders(isLight, isClassic), + textBubbleSent = textBubbleSent(isLight, isClassic), + backgroundBubbleReceived = backgroundBubbleReceived(isLight, isClassic), + textBubbleReceived = textBubbleReceived(isLight, isClassic), + ) +} + /** * Converts current Theme to Compose Theme. */ @@ -63,6 +140,15 @@ fun AppTheme( val surface = context.getColorFromTheme(R.attr.colorSettingsBackground) + val themeState = AppTextSecurePreferences(context).themeState() + + val sessionColors = UnresolvedSessionColors()(themeState.accent, themeState.isLight, themeState.isClassic) + + val textSelectionColors = TextSelectionColors( + handleColor = MaterialTheme.colors.secondary, + backgroundColor = MaterialTheme.colors.secondary.copy(alpha = 0.5f) + ) + CompositionLocalProvider( *listOf( LocalCellColor to R.attr.colorSettingsBackground, @@ -72,10 +158,10 @@ fun AppTheme( ).map { (local, attr) -> local provides context.getColorFromTheme(attr) }.toTypedArray() ) { AppCompatTheme(surface = surface) { - CompositionLocalProvider(LocalTextSelectionColors provides TextSelectionColors( - handleColor = MaterialTheme.colors.secondary, - backgroundColor = MaterialTheme.colors.secondary.copy(alpha = 0.5f) - )) { + CompositionLocalProvider( + LocalColors provides sessionColors, + LocalTextSelectionColors provides textSelectionColors + ) { content() } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/ActivityUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/util/ActivityUtilities.kt index adb53889e2..072782b322 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/ActivityUtilities.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/ActivityUtilities.kt @@ -12,6 +12,13 @@ import androidx.fragment.app.DialogFragment import network.loki.messenger.R import org.session.libsession.utilities.TextSecurePreferences import org.thoughtcrime.securesms.BaseActionBarActivity +import org.thoughtcrime.securesms.ui.primaryBlue +import org.thoughtcrime.securesms.ui.primaryGreen +import org.thoughtcrime.securesms.ui.primaryOrange +import org.thoughtcrime.securesms.ui.primaryPink +import org.thoughtcrime.securesms.ui.primaryPurple +import org.thoughtcrime.securesms.ui.primaryRed +import org.thoughtcrime.securesms.ui.primaryYellow fun BaseActionBarActivity.setUpActionBarSessionLogo(hideBackButton: Boolean = false) { val actionbar = supportActionBar!! @@ -100,7 +107,21 @@ data class ThemeState ( @StyleRes val theme: Int, @StyleRes val accentStyle: Int, val followSystem: Boolean -) +) { + val isLight = theme in setOf(R.style.Classic_Light, R.style.Ocean_Light) + val isClassic = theme in setOf(R.style.Classic_Light, R.style.Classic_Dark) + + val accent = when(accentStyle) { + R.style.PrimaryGreen -> primaryGreen + R.style.PrimaryBlue -> primaryBlue + R.style.PrimaryPurple -> primaryPurple + R.style.PrimaryPink -> primaryPink + R.style.PrimaryRed -> primaryRed + R.style.PrimaryOrange -> primaryOrange + R.style.PrimaryYellow -> primaryYellow + else -> primaryGreen + } +} inline fun Activity.show() = Intent(this, T::class.java).also(::startActivity).also { overridePendingTransition(R.anim.slide_from_bottom, R.anim.fade_scale_out) } inline fun Activity.push() = Intent(this, T::class.java).also(::startActivity).also { overridePendingTransition(R.anim.slide_from_right, R.anim.fade_scale_out) } diff --git a/libsession/src/main/java/org/session/libsession/utilities/TextSecurePreferences.kt b/libsession/src/main/java/org/session/libsession/utilities/TextSecurePreferences.kt index be2ca1eca6..86be93304e 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/TextSecurePreferences.kt +++ b/libsession/src/main/java/org/session/libsession/utilities/TextSecurePreferences.kt @@ -1,6 +1,7 @@ package org.session.libsession.utilities import android.content.Context +import android.graphics.Color import android.hardware.Camera import android.net.Uri import android.provider.Settings @@ -986,18 +987,19 @@ interface TextSecurePreferences { setBooleanPreference(context, FINGERPRINT_KEY_GENERATED, true) } + @JvmStatic + fun getAccentColorName(context: Context): String? = getStringPreference(context, SELECTED_ACCENT_COLOR, ORANGE_ACCENT) + @JvmStatic @StyleRes - fun getAccentColorStyle(context: Context): Int? { - return when (getStringPreference(context, SELECTED_ACCENT_COLOR, ORANGE_ACCENT)) { - GREEN_ACCENT -> R.style.PrimaryGreen - BLUE_ACCENT -> R.style.PrimaryBlue - PURPLE_ACCENT -> R.style.PrimaryPurple - PINK_ACCENT -> R.style.PrimaryPink - RED_ACCENT -> R.style.PrimaryRed - ORANGE_ACCENT -> R.style.PrimaryOrange - YELLOW_ACCENT -> R.style.PrimaryYellow - else -> null - } + fun getAccentColorStyle(context: Context): Int? = when (getAccentColorName(context)) { + GREEN_ACCENT -> R.style.PrimaryGreen + BLUE_ACCENT -> R.style.PrimaryBlue + PURPLE_ACCENT -> R.style.PrimaryPurple + PINK_ACCENT -> R.style.PrimaryPink + RED_ACCENT -> R.style.PrimaryRed + ORANGE_ACCENT -> R.style.PrimaryOrange + YELLOW_ACCENT -> R.style.PrimaryYellow + else -> null } @JvmStatic