Build the Wolfskin TV shell and navigation

This commit is contained in:
justinzeus 2026-11-05 14:38:38 +01:00
parent de452448ba
commit f60a22e435
97 changed files with 4363 additions and 91 deletions

View file

@ -66,7 +66,6 @@ import com.github.damontecres.wholphin.ui.nav.Destination
import com.github.damontecres.wholphin.ui.playback.PlayExternalViewModel
import com.github.damontecres.wholphin.ui.showToast
import com.github.damontecres.wholphin.ui.theme.WholphinTheme
import com.github.damontecres.wholphin.ui.theme.colors.WolfskinThemeColors
import com.github.damontecres.wholphin.ui.util.ProvideLocalClock
import com.github.damontecres.wholphin.util.DebugLogTree
import com.github.damontecres.wholphin.util.ExceptionHandler
@ -234,7 +233,7 @@ class MainActivity : AppCompatActivity() {
viewModel.appStart(intent)
setContent {
MaterialTheme(colorScheme = WolfskinThemeColors.darkScheme) {
MaterialTheme {
Surface(Modifier.fillMaxSize()) {
val userPreferences by userPreferencesService.flow.collectAsState(null)
if (userPreferences == null) {

View file

@ -34,7 +34,7 @@ import com.github.damontecres.wholphin.services.NavigationManager
import com.github.damontecres.wholphin.services.ScreensaverService
import com.github.damontecres.wholphin.services.SetupDestination
import com.github.damontecres.wholphin.ui.components.AppScreensaver
import com.github.damontecres.wholphin.ui.nav.ApplicationContent
import org.justinvisser.wolfskin.tv.WolfskinApp
import com.github.damontecres.wholphin.ui.setup.SwitchServerContent
import com.github.damontecres.wholphin.ui.setup.SwitchUserContent
import com.github.damontecres.wholphin.ui.util.InterfaceCustomization
@ -111,7 +111,7 @@ fun MainContent(
}
if (showContent) {
ApplicationContent(
WolfskinApp(
user = current.user,
server = current.server,
navigationManager = navigationManager,

View file

@ -557,7 +557,7 @@ sealed interface AppPreference<Pref, T> {
val ThemeColors =
AppChoicePreference<AppPreferences, AppThemeColors>(
title = R.string.app_theme,
defaultValue = AppThemeColors.WOLFSKIN,
defaultValue = AppThemeColors.PURPLE,
getter = { it.interfacePreferences.appThemeColors },
setter = { prefs, value ->
prefs.updateInterfacePreferences { appThemeColors = value }
@ -647,6 +647,19 @@ sealed interface AppPreference<Pref, T> {
destination = Destination.Settings(PreferenceScreenOption.ADVANCED),
)
val WolfskinScreens =
AppSwitchPreference<AppPreferences>(
title = R.string.wolfskin_screens,
defaultValue = true,
getter = { org.justinvisser.wolfskin.tv.WolfskinScreenPreference.enabled },
setter = { prefs, value ->
org.justinvisser.wolfskin.tv.WolfskinScreenPreference.enabled = value
prefs
},
summaryOn = R.string.enabled,
summaryOff = R.string.disabled,
)
val UserProfileSettings =
AppDestinationPreference<AppPreferences>(
title = R.string.override_user_profile_settings,
@ -1306,6 +1319,7 @@ val advancedPreferences =
title = R.string.ui_interface,
preferences =
listOf(
AppPreference.WolfskinScreens,
AppPreference.ShowClock,
AppPreference.BackdropStylePref,
AppPreference.ShowLogos,

View file

@ -41,7 +41,6 @@ fun WatchedIconBackground(): Color =
when (LocalTheme.current) {
AppThemeColors.UNRECOGNIZED,
AppThemeColors.PURPLE,
AppThemeColors.WOLFSKIN,
AppThemeColors.BLUE,
AppThemeColors.GREEN,
AppThemeColors.ORANGE,
@ -56,8 +55,6 @@ fun WatchedIconBackground(): Color =
@Composable
fun WatchedIconColor(): Color =
when (LocalTheme.current) {
AppThemeColors.WOLFSKIN -> MaterialTheme.colorScheme.onPrimary
AppThemeColors.UNRECOGNIZED,
AppThemeColors.PURPLE,
AppThemeColors.BLUE,

View file

@ -143,7 +143,6 @@ fun sliderActiveColor(focused: Boolean): Color {
return when (theme) {
AppThemeColors.UNRECOGNIZED,
AppThemeColors.PURPLE,
AppThemeColors.WOLFSKIN,
AppThemeColors.BLUE,
AppThemeColors.GREEN,
AppThemeColors.ORANGE,
@ -180,7 +179,6 @@ fun sliderInactiveColor(focused: Boolean): Color {
return when (theme) {
AppThemeColors.UNRECOGNIZED,
AppThemeColors.PURPLE,
AppThemeColors.WOLFSKIN,
-> {
MaterialTheme.colorScheme.border
.copy(alpha = .25f)

View file

@ -35,6 +35,9 @@ import java.util.UUID
sealed class Destination(
val fullScreen: Boolean = false,
) : NavKey {
@Serializable
data class Wolfskin(val route: String) : Destination(false)
@Serializable
data class Home(
val id: Long = 0L,

View file

@ -69,6 +69,10 @@ fun DestinationContent(
LaunchedEffect(Unit) { onClearBackdrop.invoke() }
}
when (destination) {
is Destination.Wolfskin -> {
org.justinvisser.wolfskin.tv.WolfskinDestinationContent(destination.route, modifier)
}
is Destination.Home -> {
HomePage(
preferences = preferences,

View file

@ -771,7 +771,6 @@ fun navItemColor(
when (theme) {
AppThemeColors.UNRECOGNIZED,
AppThemeColors.PURPLE,
AppThemeColors.WOLFSKIN,
AppThemeColors.BLUE,
AppThemeColors.GREEN,
AppThemeColors.ORANGE,

View file

@ -70,7 +70,6 @@ fun SwitchColors(): SwitchColors {
return when (theme) {
AppThemeColors.UNRECOGNIZED,
AppThemeColors.PURPLE,
AppThemeColors.WOLFSKIN,
AppThemeColors.BLUE,
-> {
SwitchDefaults.colors()

View file

@ -13,10 +13,9 @@ import com.github.damontecres.wholphin.ui.theme.colors.OledThemeColors
import com.github.damontecres.wholphin.ui.theme.colors.OrangeThemeColors
import com.github.damontecres.wholphin.ui.theme.colors.PurpleThemeColors
import com.github.damontecres.wholphin.ui.theme.colors.RedThemeColors
import com.github.damontecres.wholphin.ui.theme.colors.WolfskinThemeColors
val LocalTheme =
compositionLocalOf<AppThemeColors> { AppThemeColors.WOLFSKIN }
compositionLocalOf<AppThemeColors> { AppThemeColors.PURPLE }
fun getThemeColors(appThemeColors: AppThemeColors): ThemeColors =
when (appThemeColors) {
@ -28,14 +27,13 @@ fun getThemeColors(appThemeColors: AppThemeColors): ThemeColors =
AppThemeColors.BOLD_BLUE -> BoldBlueThemeColors
AppThemeColors.RED -> RedThemeColors
AppThemeColors.BROWN -> BrownThemeColors
AppThemeColors.WOLFSKIN -> WolfskinThemeColors
AppThemeColors.UNRECOGNIZED -> WolfskinThemeColors
AppThemeColors.UNRECOGNIZED -> PurpleThemeColors
}
@Composable
fun WholphinTheme(
darkTheme: Boolean = true,
appThemeColors: AppThemeColors = AppThemeColors.WOLFSKIN,
appThemeColors: AppThemeColors = AppThemeColors.PURPLE,
content: @Composable () -> Unit,
) {
val themeColors = getThemeColors(appThemeColors)

View file

@ -1,59 +0,0 @@
package com.github.damontecres.wholphin.ui.theme.colors
import androidx.compose.ui.graphics.Color
import com.github.damontecres.wholphin.ui.theme.ThemeColors
/** Lilac accents on near-black surfaces, with upstream Purple available separately. */
val WolfskinThemeColors =
object : ThemeColors {
private val background = Color(0xFF07070A)
private val lilac = Color(0xFFD2BCFF)
private val onLilac = Color(0xFF241334)
private val container = Color(0xFF382A49)
private val onContainer = Color(0xFFEADCFF)
private val surfaceVariant = Color(0xFF24202D)
override val lightSchemeMaterial = PurpleThemeColors.lightSchemeMaterial
override val lightScheme = PurpleThemeColors.lightScheme
override val darkSchemeMaterial =
PurpleThemeColors.darkSchemeMaterial.copy(
primary = lilac,
onPrimary = onLilac,
primaryContainer = container,
onPrimaryContainer = onContainer,
secondary = lilac,
onSecondary = onLilac,
secondaryContainer = container,
onSecondaryContainer = onContainer,
tertiary = lilac,
onTertiary = onLilac,
tertiaryContainer = container,
onTertiaryContainer = onContainer,
background = background,
surface = background,
surfaceVariant = surfaceVariant,
inversePrimary = Color(0xFF705090),
)
override val darkScheme =
PurpleThemeColors.darkScheme.copy(
primary = lilac,
onPrimary = onLilac,
primaryContainer = container,
onPrimaryContainer = onContainer,
secondary = lilac,
onSecondary = onLilac,
secondaryContainer = container,
onSecondaryContainer = onContainer,
tertiary = lilac,
onTertiary = onLilac,
tertiaryContainer = container,
onTertiaryContainer = onContainer,
background = background,
surface = background,
surfaceVariant = surfaceVariant,
inversePrimary = Color(0xFF705090),
border = lilac.copy(alpha = .75f),
)
}

View file

@ -128,7 +128,7 @@ enum AppThemeColors {
OLED_BLACK = 5;
RED = 6;
BROWN = 7;
WOLFSKIN = 8;
reserved 8;
}
enum EdgeStyle{

View file

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@mipmap/ic_banner_foreground"
android:gravity="fill" />
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_banner_background"/>
<foreground>
<inset
android:inset="18%"
android:drawable="@mipmap/ic_banner_foreground"/>
</foreground>
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 7 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 6 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before After
Before After

View file

@ -1,6 +1,6 @@
<resources>
<string name="app_name" translatable="false">Wolfskin</string>
<string name="app_name_long" translatable="false">Wolfskin</string>
<string name="app_name" translatable="false">Wholphin</string>
<string name="app_name_long" translatable="false">Wholphin</string>
<string name="about">About</string>
<string name="active_recordings">Active Recordings</string>
@ -604,8 +604,8 @@
<string name="content_scale_fill">Fill</string>
<string name="content_scale_fill_width">Fill width</string>
<string name="content_scale_fill_height">Fill height</string>
<string name="display_preset_default">Wolfskin Default</string>
<string name="display_preset_compact">Wolfskin Compact</string>
<string name="display_preset_default">Wholphin Default</string>
<string name="display_preset_compact">Wholphin Compact</string>
<string name="display_preset_series_thumb">Series Thumb images</string>
<string name="display_preset_episode_thumbnails">Episode Thumbnail images</string>
@ -637,7 +637,6 @@
<item>@string/black</item>
<item>@string/red</item>
<item>@string/brown</item>
<item>@string/wolfskin_theme</item>
</string-array>
<string name="skip_ignore">Ignore</string>
@ -831,7 +830,7 @@
<string name="select_all">Select all</string>
<string name="separate_types">Separate types</string>
<string name="prefer_logos">Prefer showing logos for titles</string>
<string name="updated_toast">Wolfskin updated to %s</string>
<string name="updated_toast">Wholphin updated to %s</string>
<string name="remove_continue_watching">Remove from continue watching</string>
<string name="remove_next_up">Remove series from next up</string>
<string name="view_removed_next_up">View series removed from next up</string>

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="wolfskin_theme" translatable="false">Wolfskin</string>
<string name="wolfskin_screens" translatable="false">Wolfskin screens</string>
<string name="wolfskin_upstream_credit" translatable="false">based on Wholphin by damontecres</string>
<string name="wolfskin_upstream_url" translatable="false">https://github.com/damontecres/Wholphin</string>
</resources>