Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
## Fixed
- The startup screen follows the Material Sky and Material Mint app icons, and updates as soon as you switch icons
3 changes: 2 additions & 1 deletion app/src/main/java/io/github/aedev/flow/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,8 @@ class MainActivity : ComponentActivity() {

FlowTheme(theme) {
val splashTone = splashTone(MaterialTheme.colorScheme.background)
LaunchedEffect(splashTone) { splashController.rememberTheme(splashTone, appIconController.activeSuffix()) }
val selectedIcon by appIconController.selected.collectAsState(initial = null)
LaunchedEffect(splashTone, selectedIcon) { splashController.rememberTheme(splashTone, appIconController.activeSuffix()) }

// Date preferences: five DataStore flows used to be opened per video card,
// metadata line, info section, description sheet and info dialog.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext
import io.github.aedev.flow.data.local.PlayerPreferences
import io.github.aedev.flow.util.AppIcons
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.withContext
import javax.inject.Inject
import javax.inject.Singleton
Expand All @@ -25,6 +26,9 @@ class AppIconController
@ApplicationContext private val context: Context,
private val playerPreferences: PlayerPreferences,
) {
/** The saved selection; emits on every switch. */
val selected: Flow<String?> = playerPreferences.selectedAppIcon

/** The alias the launcher currently shows. Reads the package manager, so it runs off the main thread. */
suspend fun activeSuffix(): String =
withContext(Dispatchers.IO) {
Expand Down
34 changes: 23 additions & 11 deletions app/src/main/java/io/github/aedev/flow/ui/startup/SplashThemes.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,62 +17,74 @@ fun splashTone(background: Color): SplashTone =
else -> SplashTone.LIGHT
}

private class ExpressiveSplash(
private class AliasSplash(
@StyleRes val light: Int,
@StyleRes val dark: Int,
@StyleRes val black: Int,
)

private val ExpressiveSplashes =
private val AliasSplashes =
mapOf(
".IconExpressiveScallop" to
ExpressiveSplash(
AliasSplash(
R.style.Theme_Flow_Starting_Light_Expressive_Scallop,
R.style.Theme_Flow_Starting_Dark_Expressive_Scallop,
R.style.Theme_Flow_Starting_Black_Expressive_Scallop,
),
".IconExpressiveSegmented" to
ExpressiveSplash(
AliasSplash(
R.style.Theme_Flow_Starting_Light_Expressive_Segmented,
R.style.Theme_Flow_Starting_Dark_Expressive_Segmented,
R.style.Theme_Flow_Starting_Black_Expressive_Segmented,
),
".IconExpressivePlay" to
ExpressiveSplash(
AliasSplash(
R.style.Theme_Flow_Starting_Light_Expressive_Play,
R.style.Theme_Flow_Starting_Dark_Expressive_Play,
R.style.Theme_Flow_Starting_Black_Expressive_Play,
),
".IconExpressiveSky" to
ExpressiveSplash(
AliasSplash(
R.style.Theme_Flow_Starting_Light_Expressive_Sky,
R.style.Theme_Flow_Starting_Dark_Expressive_Sky,
R.style.Theme_Flow_Starting_Black_Expressive_Sky,
),
".IconExpressiveMint" to
ExpressiveSplash(
AliasSplash(
R.style.Theme_Flow_Starting_Light_Expressive_Mint,
R.style.Theme_Flow_Starting_Dark_Expressive_Mint,
R.style.Theme_Flow_Starting_Black_Expressive_Mint,
),
".IconExpressiveCookie" to
ExpressiveSplash(
AliasSplash(
R.style.Theme_Flow_Starting_Light_Expressive_Cookie,
R.style.Theme_Flow_Starting_Dark_Expressive_Cookie,
R.style.Theme_Flow_Starting_Black_Expressive_Cookie,
),
".IconExpressiveOval" to
ExpressiveSplash(
AliasSplash(
R.style.Theme_Flow_Starting_Light_Expressive_Oval,
R.style.Theme_Flow_Starting_Dark_Expressive_Oval,
R.style.Theme_Flow_Starting_Black_Expressive_Oval,
),
".IconExpressivePill" to
ExpressiveSplash(
AliasSplash(
R.style.Theme_Flow_Starting_Light_Expressive_Pill,
R.style.Theme_Flow_Starting_Dark_Expressive_Pill,
R.style.Theme_Flow_Starting_Black_Expressive_Pill,
),
".IconMaterialSky" to
AliasSplash(
R.style.Theme_Flow_Starting_Light_Material_Sky,
R.style.Theme_Flow_Starting_Dark_Material_Sky,
R.style.Theme_Flow_Starting_Black_Material_Sky,
),
".IconMaterialMint" to
AliasSplash(
R.style.Theme_Flow_Starting_Light_Material_Mint,
R.style.Theme_Flow_Starting_Dark_Material_Mint,
R.style.Theme_Flow_Starting_Black_Material_Mint,
),
)

/**
Expand All @@ -84,7 +96,7 @@ fun splashThemeFor(
iconSuffix: String,
tone: SplashTone,
): Int {
ExpressiveSplashes[iconSuffix]?.let { splash ->
AliasSplashes[iconSuffix]?.let { splash ->
return when (tone) {
SplashTone.LIGHT -> splash.light
SplashTone.DARK -> splash.dark
Expand Down
38 changes: 38 additions & 0 deletions app/src/main/res/values/themes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,44 @@
<item name="postSplashScreenTheme">@style/Theme.Flow</item>
</style>

<!-- Material icons: the Flow glyph on the tint of the launcher icon, like the dynamic one. -->
<style name="Theme.Flow.Starting.Light.Material.Sky" parent="Theme.SplashScreen.IconBackground">
<item name="windowSplashScreenBackground">@color/splash_background_light</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/ic_launcher_foreground</item>
<item name="windowSplashScreenIconBackgroundColor">@color/icon_bg_material_sky</item>
<item name="postSplashScreenTheme">@style/Theme.Flow</item>
</style>
<style name="Theme.Flow.Starting.Light.Material.Mint" parent="Theme.SplashScreen.IconBackground">
<item name="windowSplashScreenBackground">@color/splash_background_light</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/ic_launcher_foreground</item>
<item name="windowSplashScreenIconBackgroundColor">@color/icon_bg_material_mint</item>
<item name="postSplashScreenTheme">@style/Theme.Flow</item>
</style>
<style name="Theme.Flow.Starting.Dark.Material.Sky" parent="Theme.SplashScreen.IconBackground">
<item name="windowSplashScreenBackground">@color/splash_background_dark</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/ic_launcher_foreground</item>
<item name="windowSplashScreenIconBackgroundColor">@color/icon_bg_material_sky</item>
<item name="postSplashScreenTheme">@style/Theme.Flow</item>
</style>
<style name="Theme.Flow.Starting.Dark.Material.Mint" parent="Theme.SplashScreen.IconBackground">
<item name="windowSplashScreenBackground">@color/splash_background_dark</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/ic_launcher_foreground</item>
<item name="windowSplashScreenIconBackgroundColor">@color/icon_bg_material_mint</item>
<item name="postSplashScreenTheme">@style/Theme.Flow</item>
</style>
<style name="Theme.Flow.Starting.Black.Material.Sky" parent="Theme.SplashScreen.IconBackground">
<item name="windowSplashScreenBackground">@color/splash_background_black</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/ic_launcher_foreground</item>
<item name="windowSplashScreenIconBackgroundColor">@color/icon_bg_material_sky</item>
<item name="postSplashScreenTheme">@style/Theme.Flow</item>
</style>
<style name="Theme.Flow.Starting.Black.Material.Mint" parent="Theme.SplashScreen.IconBackground">
<item name="windowSplashScreenBackground">@color/splash_background_black</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/ic_launcher_foreground</item>
<item name="windowSplashScreenIconBackgroundColor">@color/icon_bg_material_mint</item>
<item name="postSplashScreenTheme">@style/Theme.Flow</item>
</style>

<!-- Expressive icons: their own art at logo size over the tone's window, like the Flow badge. -->
<style name="Theme.Flow.Starting.Light.Expressive" />
<style name="Theme.Flow.Starting.Light.Expressive.Scallop">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,26 @@ class SplashThemesTest {
assertThat(styles).doesNotContain(0)
}

@Test
fun `every alias with its own art gets a splash of its own on every tone`() {
val sharesDefault = setOf(".IconFlowRed", ".IconFlowLight")
val fallback =
mapOf(
SplashTone.LIGHT to R.style.Theme_Flow_Starting_Light,
SplashTone.DARK to R.style.Theme_Flow_Starting_Dark,
SplashTone.BLACK to R.style.Theme_Flow_Starting_Black,
)
val missing =
(AppIcons.ALL_SUFFIXES - sharesDefault).flatMap { suffix ->
SplashTone.entries
.filterNot { suffix == ".IconGhost" && it == SplashTone.LIGHT }
.filter { splashThemeFor(suffix, it) == fallback.getValue(it) }
.map { "$suffix on $it" }
}

assertThat(missing).isEmpty()
}

@Test
fun `aliases with their own art get their own splash`() {
assertThat(splashThemeFor(".IconAmoled", SplashTone.BLACK)).isEqualTo(R.style.Theme_Flow_Starting_Black_Amoled)
Expand Down
Loading