more sapphire changes

This commit is contained in:
Chloe committed 2026-04-01 02:41:23 -07:00
1 parent 79632c9844
commit d3ad272ffc
7 files changed
+240 -52

No files matched your search

@@ -7,6 +7,8 @@ import android.text.format.Formatter
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.compose.animation.Crossfade
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.LinearEasing
@@ -70,6 +72,8 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalResources
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@@ -82,12 +86,14 @@ import com.geode.launcher.ui.theme.Theme
import com.geode.launcher.ui.theme.Theme.DARK
import com.geode.launcher.ui.theme.Theme.LIGHT
import com.geode.launcher.ui.theme.launcherTitleStyle
import com.geode.launcher.ui.theme.sapphireTitleStyle
import com.geode.launcher.updater.ReleaseManager
import com.geode.launcher.utils.ApplicationIcon
import com.geode.launcher.utils.Constants
import com.geode.launcher.utils.GamePackageUtils
import com.geode.launcher.utils.LaunchUtils
import com.geode.launcher.utils.PreferenceUtils
import com.geode.launcher.utils.checkIconDate
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.launch
import java.net.ConnectException
@@ -453,36 +459,105 @@ fun ExtraOptions(onSettings: () -> Unit) {
}
}
val lightOuterColorGradient = arrayOf(
data class ColorPalette(
val outerColors: List<Pair<Float, Color>>,
val innerColors: List<Pair<Float, Color>>,
)
data class BrandPalette(
val lightPalette: ColorPalette,
val darkPalette: ColorPalette,
@param:DrawableRes val innerId: Int,
@param:DrawableRes val outerId: Int,
@param:DrawableRes val darkLogo: Int,
@param:DrawableRes val lightLogo: Int,
@param:StringRes val title: Int,
val titleFont: TextStyle,
)
val geodeColorPalette = BrandPalette(
lightPalette = ColorPalette(
outerColors = listOf(
0.0f to Color(0xfff5b11d),
0.10f to Color(0xfff0834d),
0.24f to Color(0xffe85f6b),
0.49f to Color(0xffc9659e),
1.0f to Color(0xffb9588f)
)
val lightInnerColorGradient = arrayOf(
),
innerColors = listOf(
0.48f to Color(0xfff2ce00),
0.63f to Color(0xfff4b97e),
0.73f to Color(0xfff7b66a),
1.0f to Color(0xffeb8fac)
)
val darkOuterColorGradient = arrayOf(
),
darkPalette = ColorPalette(
outerColors = listOf(
0.0f to Color(0xfffffdff),
0.08f to Color(0xffF2EAF5),
0.12f to Color(0xffEDE5EF),
0.31f to Color(0xffCDB5CD),
0.49f to Color(0xffBA9BBC),
1.0f to Color(0xff8D7ACF),
)
val darkInnerColorGradient = arrayOf(
),
innerColors = listOf(
0.48f to Color(0xffffffff),
0.63f to Color(0xfff5e4c2),
0.73f to Color(0xffe5c7ad),
1.0f to Color(0xffb790a9),
)
),
innerId = R.drawable.geode_monochrome_inner,
outerId = R.drawable.geode_monochrome_outer,
darkLogo = R.drawable.geode_base,
lightLogo = R.drawable.geode_base_light,
title = R.string.launcher_title,
titleFont = launcherTitleStyle
)
val sapphireColorPalette = BrandPalette(
lightPalette = ColorPalette(
outerColors = listOf(
0.0f to Color(0xff906FFF),
0.08f to Color(0xff9E81FF),
0.12f to Color(0xffAB8DFF),
0.31f to Color(0xffBE89FF),
0.49f to Color(0xff979BD7),
1.0f to Color(0xff558DDA),
),
innerColors = listOf(
0.48f to Color(0xffFFB65C),
0.63f to Color(0xffFFADA4),
0.73f to Color(0xffF0A3A4),
1.0f to Color(0xffD066A6),
)
),
darkPalette = ColorPalette(
outerColors = listOf(
0.0f to Color(0xfffffdff),
0.08f to Color(0xffF2EAF5),
0.12f to Color(0xffEDE5EF),
0.31f to Color(0xffC0B5CD),
0.49f to Color(0xff9B9DBC),
1.0f to Color(0xff558DDA),
),
innerColors = listOf(
0.48f to Color(0xffFFF9F5),
0.63f to Color(0xffF2DCD3),
0.73f to Color(0xffDBA7A8),
1.0f to Color(0xffD066A6),
)
),
innerId = R.drawable.sapphire_monochrome_inner,
outerId = R.drawable.sapphire_monochrome_outer,
darkLogo = R.drawable.sapphire_base,
lightLogo = R.drawable.sapphire_base_light,
title = R.string.application_icon_sapphire,
titleFont = sapphireTitleStyle
)
@Preview(name = "non-animated, light")
@Preview(name = "non-animated, dark", uiMode = UI_MODE_NIGHT_YES)
@@ -512,18 +587,43 @@ fun GeodeLogoAnimatedPreview() {
}
}
@Preview(name = "sapphire, non-animated, light")
@Preview(name = "sapphire, non-animated, dark", uiMode = UI_MODE_NIGHT_YES)
@Composable
fun AnimatedLogo(modifier: Modifier = Modifier, sapphire: Boolean = false) {
val theme = LocalTheme.current
val innerColorPalette = remember(theme) {
if (theme == LIGHT) lightInnerColorGradient
else darkInnerColorGradient
fun SapphireLogoPreview() {
val theme = if (isSystemInDarkTheme()) DARK else LIGHT
CompositionLocalProvider(LocalTheme provides theme) {
GeodeLauncherTheme(theme = theme) {
Surface {
GeodeLogo(shouldAnimate = false, basePalette = sapphireColorPalette)
}
}
}
}
val outerColorPalette = remember(theme) {
if (theme == LIGHT) lightOuterColorGradient
else darkOuterColorGradient
@Preview(name = "sapphire, animated, light")
@Preview(name = "sapphire, animated, dark", uiMode = UI_MODE_NIGHT_YES)
@Composable
fun SapphireLogoAnimatedPreview() {
val theme = if (isSystemInDarkTheme()) DARK else LIGHT
CompositionLocalProvider(LocalTheme provides theme) {
GeodeLauncherTheme(theme = theme) {
Surface {
GeodeLogo(shouldAnimate = true, basePalette = sapphireColorPalette)
}
}
}
}
@Composable
fun AnimatedLogo(modifier: Modifier = Modifier, basePalette: BrandPalette) {
val theme = LocalTheme.current
val colorPalette = if (theme == LIGHT) basePalette.lightPalette
else basePalette.darkPalette
val innerColorPalette = colorPalette.innerColors
val outerColorPalette = colorPalette.outerColors
val infiniteTransition = rememberInfiniteTransition(label = "infinite transition")
val offset by infiniteTransition.animateFloat(
@@ -537,14 +637,14 @@ fun AnimatedLogo(modifier: Modifier = Modifier, sapphire: Boolean = false) {
)
val innerBrush = Brush.linearGradient(
colorStops = innerColorPalette,
colorStops = innerColorPalette.toTypedArray(),
start = Offset(0.0f, 0.0f + (165.06f * offset)),
end = Offset(0.0f, 165.06f + (165.06f * offset)),
tileMode = TileMode.Mirror
)
val outerBrush = Brush.linearGradient(
colorStops = outerColorPalette,
colorStops = outerColorPalette.toTypedArray(),
start = Offset(0.0f + (84.69f * offset), 0.0f + (165.06f * offset)),
end = Offset(84.69f + (84.69f * offset), 169.61f + (165.06f * offset)),
tileMode = TileMode.Mirror
@@ -552,8 +652,7 @@ fun AnimatedLogo(modifier: Modifier = Modifier, sapphire: Boolean = false) {
Box(modifier = modifier) {
Icon(
painter = if (sapphire) painterResource(R.drawable.sapphire_monochrome_inner)
else painterResource(id = R.drawable.geode_monochrome_inner),
painter = painterResource(basePalette.innerId),
contentDescription = null,
modifier = Modifier
.graphicsLayer(compositingStrategy = CompositingStrategy.Offscreen)
@@ -566,8 +665,7 @@ fun AnimatedLogo(modifier: Modifier = Modifier, sapphire: Boolean = false) {
}
)
Icon(
painter = if (sapphire) painterResource(R.drawable.sapphire_monochrome_outer)
else painterResource(id = R.drawable.geode_monochrome_outer),
painter = painterResource(basePalette.outerId),
contentDescription = null,
modifier = Modifier
.graphicsLayer(compositingStrategy = CompositingStrategy.Offscreen)
@@ -583,7 +681,7 @@ fun AnimatedLogo(modifier: Modifier = Modifier, sapphire: Boolean = false) {
}
@Composable
fun GeodeLogo(modifier: Modifier = Modifier, shouldAnimate: Boolean = false) {
fun GeodeLogo(modifier: Modifier = Modifier, shouldAnimate: Boolean = false, basePalette: BrandPalette = geodeColorPalette) {
Row(
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
@@ -591,28 +689,16 @@ fun GeodeLogo(modifier: Modifier = Modifier, shouldAnimate: Boolean = false) {
) {
val theme = LocalTheme.current
val context = LocalContext.current
val sapphireLogo = remember {
PreferenceUtils.get(context).getString(PreferenceUtils.Key.SELECTED_ICON) == ApplicationIcon.SAPPHIRE.toId()
}
if (sapphireLogo) {
Icon(
painterResource(R.drawable.sapphire_monochrome),
contentDescription = null,
modifier = Modifier.size(64.dp, 64.dp)
)
} else {
Crossfade(
targetState = shouldAnimate,
animationSpec = tween(durationMillis = 1000, easing = FastOutSlowInEasing),
label="logo fade"
) { screen ->
when (screen) {
true -> AnimatedLogo(modifier = Modifier.size(64.dp, 64.dp))
true -> AnimatedLogo(modifier = Modifier.size(64.dp, 64.dp), basePalette = basePalette)
false -> Image(
painterResource(if (theme == LIGHT)
R.drawable.geode_base_light else R.drawable.geode_base
basePalette.lightLogo else basePalette.darkLogo
),
contentDescription = null,
modifier = Modifier.size(64.dp, 64.dp)
@@ -620,12 +706,9 @@ fun GeodeLogo(modifier: Modifier = Modifier, shouldAnimate: Boolean = false) {
}
}
}
Text(
if (sapphireLogo) stringResource(R.string.application_icon_sapphire)
else stringResource(R.string.launcher_title),
style = launcherTitleStyle,
stringResource(basePalette.title),
style = basePalette.titleFont,
fontSize = 64.sp,
modifier = Modifier
.padding(12.dp)
@@ -713,7 +796,14 @@ fun AltMainScreen(
.padding(8.dp)
.verticalScroll(rememberScrollState())
) {
GeodeLogo(shouldAnimate = launchUIState.isInProgress())
val sapphireLogo = remember {
checkIconDate() || PreferenceUtils.get(context)
.getString(PreferenceUtils.Key.SELECTED_ICON) == ApplicationIcon.SAPPHIRE.toId()
}
val basePalette = if (sapphireLogo) sapphireColorPalette
else geodeColorPalette
GeodeLogo(shouldAnimate = launchUIState.isInProgress(), basePalette = basePalette)
Column(
verticalArrangement = Arrangement.spacedBy(8.dp),
@@ -60,10 +60,7 @@ import com.geode.launcher.utils.ApplicationIcon
import com.geode.launcher.utils.ApplicationIconDetails
import com.geode.launcher.utils.IconUtils
import com.geode.launcher.utils.adaptiveIconPainterResource
import kotlinx.datetime.Month
import kotlinx.datetime.TimeZone
import kotlinx.datetime.todayIn
import kotlin.time.Clock
import com.geode.launcher.utils.checkIconDate
class ApplicationIconActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
@@ -235,10 +232,7 @@ fun ApplicationIconScreen(
) {
val selectedIcon by PreferenceUtils.useStringPreference(PreferenceUtils.Key.SELECTED_ICON)
val aprilFools = remember {
val currentDate = Clock.System.todayIn(TimeZone.currentSystemDefault())
currentDate.month == Month.APRIL && currentDate.day <= 7
}
val aprilFools = remember { checkIconDate() }
Column(Modifier
.padding(horizontal = 12.dp)
@@ -16,9 +16,20 @@ val quicksandFamily = FontFamily(
Font(R.font.quicksand_semibold, FontWeight.SemiBold)
)
val googleSansFamily = FontFamily(
Font(R.font.googlesans_medium, FontWeight.Medium)
)
val launcherTitleStyle = TextStyle(
fontFamily = quicksandFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 32.sp,
letterSpacing = 0.sp
)
val sapphireTitleStyle = TextStyle(
fontFamily = googleSansFamily,
fontWeight = FontWeight.Medium,
fontSize = 32.sp,
letterSpacing = 0.sp
)
@@ -15,6 +15,10 @@ import androidx.compose.ui.res.painterResource
import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.drawable.toBitmap
import com.geode.launcher.R
import kotlinx.datetime.Month
import kotlinx.datetime.TimeZone
import kotlinx.datetime.todayIn
import kotlin.time.Clock
// https://gist.github.com/tkuenneth/ddf598663f041dc79960cda503d14448?permalink_comment_id=4660486#gistcomment-4660486
@Composable
@@ -66,6 +70,11 @@ enum class ApplicationIcon {
}
}
fun checkIconDate(): Boolean {
val currentDate = Clock.System.todayIn(TimeZone.currentSystemDefault())
return currentDate.month == Month.APRIL && currentDate.day <= 7
}
data class ApplicationIconDetails(
val id: String,
val component: String,
@@ -0,0 +1,42 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="643dp"
android:height="766dp"
android:viewportWidth="643"
android:viewportHeight="766">
<path
android:pathData="M299.94,5.95C313.01,-1.98 329.41,-1.98 342.48,5.95L374.73,25.52L264.09,96.01L264.15,96.04L74.11,211.97C66.07,216.88 61.17,225.61 61.17,235.02V520.77C61.17,530.18 66.07,538.92 74.11,543.82L306.15,685.38C314.78,690.65 325.64,690.65 334.27,685.38L566.31,543.82C574.34,538.92 579.25,530.18 579.25,520.77V235.02C579.25,234.53 579.23,234.05 579.2,233.56V149.6L622.68,175.99C634.93,183.42 642.41,196.71 642.41,211.04V554.72C642.41,569.05 634.93,582.34 622.68,589.78L342.48,759.82C329.41,767.75 313.01,767.75 299.94,759.82L19.73,589.78C7.48,582.34 0,569.05 0,554.72V211.04C0,196.71 7.48,183.42 19.73,175.99L299.94,5.95Z">
<aapt:attr name="android:fillColor">
<gradient
android:startX="206.94"
android:startY="68.6"
android:endX="555.74"
android:endY="656.64"
android:type="linear">
<item android:offset="0" android:color="#FFFFFDFF"/>
<item android:offset="0.08" android:color="#FFF2EAF5"/>
<item android:offset="0.12" android:color="#FFEDE5EF"/>
<item android:offset="0.31" android:color="#FFC0B5CD"/>
<item android:offset="0.49" android:color="#FF9B9DBC"/>
<item android:offset="1" android:color="#FF558DDA"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M311.75,142.59C318.78,138.31 327.62,138.31 334.65,142.59L507.79,248.08C514.34,252.08 518.34,259.2 518.34,266.87V479.95C518.34,487.62 514.34,494.74 507.79,498.74L334.65,604.23C327.62,608.51 318.78,608.51 311.75,604.23L138.61,498.74C132.06,494.74 128.06,487.62 128.06,479.95V422.46L189.93,460.76C190.22,460.98 190.52,461.19 190.84,461.39L315.4,538.8C318.95,541.01 323.46,541.01 327.01,538.8L451.58,461.39C454.8,459.38 456.77,455.85 456.77,452.04V295.77C456.77,291.97 454.8,288.44 451.58,286.43L327.01,209.02C323.46,206.81 318.95,206.81 315.4,209.02L190.84,286.43C190.32,286.76 189.83,287.12 189.37,287.52L128.06,325.98V266.87C128.06,259.2 132.06,252.08 138.61,248.08L311.75,142.59Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startX="323.2"
android:startY="-327.58"
android:endX="323.2"
android:endY="606.95"
android:type="linear">
<item android:offset="0.48" android:color="#FFFFF9F5"/>
<item android:offset="0.63" android:color="#FFF2DCD3"/>
<item android:offset="0.73" android:color="#FFDBA7A8"/>
<item android:offset="1" android:color="#FFD066A6"/>
</gradient>
</aapt:attr>
</path>
</vector>
@@ -0,0 +1,42 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="643dp"
android:height="766dp"
android:viewportWidth="643"
android:viewportHeight="766">
<path
android:pathData="M299.94,5.95C313.01,-1.98 329.41,-1.98 342.48,5.95L374.73,25.52L264.09,96.01L264.15,96.04L74.11,211.97C66.07,216.88 61.17,225.61 61.17,235.02V520.77C61.17,530.18 66.07,538.92 74.11,543.82L306.15,685.38C314.78,690.65 325.64,690.65 334.27,685.38L566.31,543.82C574.34,538.92 579.25,530.18 579.25,520.77V235.02C579.25,234.53 579.23,234.05 579.2,233.56V149.6L622.68,175.99C634.93,183.42 642.41,196.71 642.41,211.04V554.72C642.41,569.05 634.93,582.34 622.68,589.78L342.48,759.82C329.41,767.75 313.01,767.75 299.94,759.82L19.73,589.78C7.48,582.34 0,569.05 0,554.72V211.04C0,196.71 7.48,183.42 19.73,175.99L299.94,5.95Z">
<aapt:attr name="android:fillColor">
<gradient
android:startX="206.94"
android:startY="68.6"
android:endX="555.74"
android:endY="656.64"
android:type="linear">
<item android:offset="0" android:color="#FF906FFF"/>
<item android:offset="0.08" android:color="#FF9E81FF"/>
<item android:offset="0.12" android:color="#FFAB8DFF"/>
<item android:offset="0.31" android:color="#FFBE89FF"/>
<item android:offset="0.49" android:color="#FF979BD7"/>
<item android:offset="1" android:color="#FF558DDA"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M311.75,142.59C318.78,138.31 327.62,138.31 334.65,142.59L507.79,248.08C514.34,252.08 518.34,259.2 518.34,266.87V479.95C518.34,487.62 514.34,494.74 507.79,498.74L334.65,604.23C327.62,608.51 318.78,608.51 311.75,604.23L138.61,498.74C132.06,494.74 128.06,487.62 128.06,479.95V422.46L189.93,460.76C190.22,460.98 190.52,461.19 190.84,461.39L315.4,538.8C318.95,541.01 323.46,541.01 327.01,538.8L451.58,461.39C454.8,459.38 456.77,455.85 456.77,452.04V295.77C456.77,291.97 454.8,288.44 451.58,286.43L327.01,209.02C323.46,206.81 318.95,206.81 315.4,209.02L190.84,286.43C190.32,286.76 189.83,287.12 189.37,287.52L128.06,325.98V266.87C128.06,259.2 132.06,252.08 138.61,248.08L311.75,142.59Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startX="323.2"
android:startY="-327.58"
android:endX="323.2"
android:endY="606.95"
android:type="linear">
<item android:offset="0.48" android:color="#FFFFB65C"/>
<item android:offset="0.63" android:color="#FFFFADA4"/>
<item android:offset="0.73" android:color="#FFF0A3A4"/>
<item android:offset="1" android:color="#FFD066A6"/>
</gradient>
</aapt:attr>
</path>
</vector>
Binary file not shown.