mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
resolvedCardHeight previously routed through a two-branch if(isWide) hidden inside the composable extension, so the regression tests for the global-slider reach bug only exercised the inner resolveCardHeight (which was never broken). Lift the aspect -> natural base mapping into a pure naturalCardBaseDp(AspectRatio) function with an exhaustive when, and test that directly. SQUARE and FOUR_THREE rows piggyback on the TALL global by design; the override branch still handles their absolute heightDp values (Music presets at 100dp, etc.). MainContent and DisplaySizePage's preview now both call a single scaledDensity(base, percent) helper instead of inlining Density(...) constructions. The double-fontScale-multiply regression has a real guard now: tests assert scaledDensity(2.0, 1.0, 150) returns density 3.0 and fontScale 1.0 (not 1.5), and a third test confirms an accessibility fontScale survives a UI scale change. Pure refactor + test sharpening; no behaviour change.
158 lines
7.3 KiB
Kotlin
158 lines
7.3 KiB
Kotlin
package com.github.damontecres.wholphin
|
|
|
|
import androidx.compose.animation.AnimatedVisibility
|
|
import androidx.compose.foundation.background
|
|
import androidx.compose.foundation.layout.Box
|
|
import androidx.compose.foundation.layout.fillMaxSize
|
|
import androidx.compose.foundation.layout.size
|
|
import androidx.compose.material3.CircularProgressIndicator
|
|
import androidx.compose.runtime.Composable
|
|
import androidx.compose.runtime.CompositionLocalProvider
|
|
import androidx.compose.runtime.LaunchedEffect
|
|
import androidx.compose.runtime.collectAsState
|
|
import androidx.compose.runtime.getValue
|
|
import androidx.compose.runtime.mutableStateOf
|
|
import androidx.compose.runtime.remember
|
|
import androidx.compose.runtime.rememberUpdatedState
|
|
import androidx.compose.runtime.setValue
|
|
import androidx.compose.ui.Alignment
|
|
import androidx.compose.ui.Modifier
|
|
import androidx.compose.ui.graphics.RectangleShape
|
|
import androidx.compose.ui.platform.LocalDensity
|
|
import androidx.compose.ui.unit.dp
|
|
import androidx.lifecycle.Lifecycle
|
|
import androidx.lifecycle.compose.LifecycleEventEffect
|
|
import androidx.lifecycle.viewmodel.navigation3.rememberViewModelStoreNavEntryDecorator
|
|
import androidx.navigation3.runtime.NavEntry
|
|
import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator
|
|
import androidx.navigation3.ui.NavDisplay
|
|
import androidx.tv.material3.MaterialTheme
|
|
import androidx.tv.material3.Surface
|
|
import com.github.damontecres.wholphin.preferences.AppPreferences
|
|
import com.github.damontecres.wholphin.preferences.UserPreferences
|
|
import com.github.damontecres.wholphin.services.BackdropService
|
|
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 com.github.damontecres.wholphin.ui.setup.SwitchServerContent
|
|
import com.github.damontecres.wholphin.ui.setup.SwitchUserContent
|
|
import com.github.damontecres.wholphin.ui.util.InterfaceCustomization
|
|
import com.github.damontecres.wholphin.ui.util.LocalInterfaceCustomization
|
|
import com.github.damontecres.wholphin.ui.util.scaledDensity
|
|
|
|
@Composable
|
|
fun MainContent(
|
|
backStack: MutableList<SetupDestination>,
|
|
navigationManager: NavigationManager,
|
|
appPreferences: AppPreferences,
|
|
backdropService: BackdropService,
|
|
screensaverService: ScreensaverService,
|
|
modifier: Modifier = Modifier,
|
|
) {
|
|
val preferences by rememberUpdatedState(UserPreferences(appPreferences))
|
|
Surface(
|
|
modifier =
|
|
modifier
|
|
.background(MaterialTheme.colorScheme.background),
|
|
shape = RectangleShape,
|
|
) {
|
|
// val backStack = rememberNavBackStack(SetupDestination.Loading)
|
|
// setupNavigationManager.backStack = backStack
|
|
val interfaceCustomization =
|
|
remember(appPreferences) { InterfaceCustomization(appPreferences) }
|
|
val baseDensity = LocalDensity.current
|
|
val uiScaleDensity =
|
|
remember(baseDensity, interfaceCustomization.uiScalePercent) {
|
|
scaledDensity(baseDensity, interfaceCustomization.uiScalePercent)
|
|
}
|
|
CompositionLocalProvider(
|
|
LocalInterfaceCustomization provides interfaceCustomization,
|
|
LocalDensity provides uiScaleDensity,
|
|
) {
|
|
NavDisplay(
|
|
backStack = backStack,
|
|
onBack = { backStack.removeLastOrNull() },
|
|
entryDecorators =
|
|
listOf(
|
|
rememberSaveableStateHolderNavEntryDecorator(),
|
|
rememberViewModelStoreNavEntryDecorator(),
|
|
),
|
|
entryProvider = { key ->
|
|
key as SetupDestination
|
|
NavEntry(key) {
|
|
when (key) {
|
|
SetupDestination.Loading -> {
|
|
Box(
|
|
modifier = Modifier.size(200.dp),
|
|
contentAlignment = Alignment.Center,
|
|
) {
|
|
CircularProgressIndicator(
|
|
color = MaterialTheme.colorScheme.border,
|
|
modifier = Modifier.align(Alignment.Center),
|
|
)
|
|
}
|
|
}
|
|
|
|
SetupDestination.ServerList -> {
|
|
SwitchServerContent(Modifier.fillMaxSize())
|
|
}
|
|
|
|
is SetupDestination.UserList -> {
|
|
SwitchUserContent(
|
|
server = key.server,
|
|
Modifier.fillMaxSize(),
|
|
)
|
|
}
|
|
|
|
is SetupDestination.AppContent -> {
|
|
LaunchedEffect(Unit) {
|
|
backdropService.clearBackdrop()
|
|
}
|
|
val current = key.current
|
|
var showContent by remember {
|
|
mutableStateOf(true)
|
|
}
|
|
LifecycleEventEffect(Lifecycle.Event.ON_STOP) {
|
|
if (!appPreferences.signInAutomatically) {
|
|
showContent = false
|
|
}
|
|
}
|
|
|
|
if (showContent) {
|
|
ApplicationContent(
|
|
user = current.user,
|
|
server = current.server,
|
|
navigationManager = navigationManager,
|
|
preferences = preferences,
|
|
modifier = Modifier.fillMaxSize(),
|
|
)
|
|
} else {
|
|
Box(
|
|
modifier = Modifier.size(200.dp),
|
|
contentAlignment = Alignment.Center,
|
|
) {
|
|
CircularProgressIndicator(
|
|
color = MaterialTheme.colorScheme.border,
|
|
modifier = Modifier.align(Alignment.Center),
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
)
|
|
val screenSaverState by screensaverService.state.collectAsState()
|
|
if (screenSaverState.enabled || screenSaverState.enabledTemp) {
|
|
AnimatedVisibility(
|
|
screenSaverState.show,
|
|
Modifier.fillMaxSize(),
|
|
) {
|
|
AppScreensaver(appPreferences, Modifier.fillMaxSize())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|