mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-07-29 15:49:30 +00:00
Apply profile mesh background to loading screens
This commit is contained in:
parent
87670e7cb0
commit
d767f60d35
3 changed files with 116 additions and 15 deletions
|
|
@ -99,6 +99,7 @@ import com.nuvio.app.core.ui.configurePlatformImageLoader
|
|||
import com.nuvio.app.core.ui.NuvioToastHost
|
||||
import com.nuvio.app.core.ui.NuvioToastController
|
||||
import com.nuvio.app.core.ui.NuvioFloatingPrompt
|
||||
import com.nuvio.app.core.ui.ProfileMeshBackground
|
||||
import com.nuvio.app.core.ui.TraktListPickerDialog
|
||||
import com.nuvio.app.core.ui.NuvioTheme
|
||||
import com.nuvio.app.core.ui.NuvioTokens
|
||||
|
|
@ -166,6 +167,7 @@ import com.nuvio.app.features.profiles.ProfileEditScreen
|
|||
import com.nuvio.app.features.profiles.ProfileRepository
|
||||
import com.nuvio.app.features.profiles.ProfileSelectionScreen
|
||||
import com.nuvio.app.features.profiles.ProfileSwitcherTab
|
||||
import com.nuvio.app.features.profiles.parseHexColor
|
||||
import com.nuvio.app.features.profiles.profileAvatarImageUrl
|
||||
import com.nuvio.app.features.search.SearchScreen
|
||||
import com.nuvio.app.features.settings.SettingsScreen
|
||||
|
|
@ -733,6 +735,10 @@ private fun MainAppContent(
|
|||
}
|
||||
}
|
||||
val profileState by ProfileRepository.state.collectAsStateWithLifecycle()
|
||||
val launchOverlayProfileColor = remember(profileState.activeProfile, profileState.profiles) {
|
||||
val sourceProfile = profileState.activeProfile ?: profileState.profiles.firstOrNull()
|
||||
sourceProfile?.avatarColorHex?.let(::parseHexColor) ?: Color(0xFF1E88E5)
|
||||
}
|
||||
val playerSettingsUiState by remember {
|
||||
PlayerSettingsRepository.ensureLoaded()
|
||||
PlayerSettingsRepository.uiState
|
||||
|
|
@ -2913,7 +2919,10 @@ private fun MainAppContent(
|
|||
enter = fadeIn(),
|
||||
exit = fadeOut(androidx.compose.animation.core.tween(400)),
|
||||
) {
|
||||
AppLaunchOverlay(modifier = Modifier.fillMaxSize())
|
||||
AppLaunchOverlay(
|
||||
profileColor = launchOverlayProfileColor,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
)
|
||||
}
|
||||
|
||||
// Auto-dismiss profile switch overlay
|
||||
|
|
@ -3237,15 +3246,19 @@ private fun TabletTopPillItem(
|
|||
|
||||
@Composable
|
||||
private fun AppLaunchOverlay(
|
||||
profileColor: Color,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val tokens = MaterialTheme.nuvio
|
||||
Box(
|
||||
modifier = modifier
|
||||
.background(tokens.colors.background)
|
||||
.zIndex(NuvioTokens.Z.dialog),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
ProfileMeshBackground(
|
||||
profileColor = profileColor,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
)
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
package com.nuvio.app.core.ui
|
||||
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.drawBehind
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.lerp
|
||||
|
||||
@Composable
|
||||
fun ProfileMeshBackground(
|
||||
profileColor: Color,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val animatedProfileColor by animateColorAsState(
|
||||
targetValue = profileColor,
|
||||
animationSpec = tween(durationMillis = 520),
|
||||
label = "profileMeshBackgroundColor",
|
||||
)
|
||||
val baseColor = Color.Black
|
||||
val primaryMeshColor = lerp(baseColor, animatedProfileColor, 0.58f)
|
||||
val secondaryMeshColor = lerp(animatedProfileColor, MaterialTheme.colorScheme.secondary, 0.32f)
|
||||
val tertiaryMeshColor = lerp(animatedProfileColor, MaterialTheme.colorScheme.tertiary, 0.28f)
|
||||
|
||||
Box(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.drawBehind {
|
||||
val maxDimension = maxOf(size.width, size.height)
|
||||
|
||||
drawRect(color = baseColor, size = size)
|
||||
drawRect(
|
||||
brush = Brush.radialGradient(
|
||||
colorStops = arrayOf(
|
||||
0f to primaryMeshColor.copy(alpha = 0.46f),
|
||||
0.38f to primaryMeshColor.copy(alpha = 0.2f),
|
||||
0.72f to primaryMeshColor.copy(alpha = 0.05f),
|
||||
1f to Color.Transparent,
|
||||
),
|
||||
center = Offset(size.width * -0.08f, size.height * -0.02f),
|
||||
radius = maxDimension * 0.7f,
|
||||
),
|
||||
size = size,
|
||||
)
|
||||
drawRect(
|
||||
brush = Brush.radialGradient(
|
||||
colorStops = arrayOf(
|
||||
0f to animatedProfileColor.copy(alpha = 0.24f),
|
||||
0.44f to animatedProfileColor.copy(alpha = 0.09f),
|
||||
0.78f to animatedProfileColor.copy(alpha = 0.02f),
|
||||
1f to Color.Transparent,
|
||||
),
|
||||
center = Offset(size.width * 0.16f, size.height * 0.18f),
|
||||
radius = maxDimension * 0.46f,
|
||||
),
|
||||
size = size,
|
||||
)
|
||||
drawRect(
|
||||
brush = Brush.radialGradient(
|
||||
colorStops = arrayOf(
|
||||
0f to secondaryMeshColor.copy(alpha = 0.16f),
|
||||
0.5f to secondaryMeshColor.copy(alpha = 0.05f),
|
||||
1f to Color.Transparent,
|
||||
),
|
||||
center = Offset(size.width * 0.9f, size.height * 0.12f),
|
||||
radius = maxDimension * 0.36f,
|
||||
),
|
||||
size = size,
|
||||
)
|
||||
drawRect(
|
||||
brush = Brush.radialGradient(
|
||||
colorStops = arrayOf(
|
||||
0f to tertiaryMeshColor.copy(alpha = 0.08f),
|
||||
0.52f to tertiaryMeshColor.copy(alpha = 0.03f),
|
||||
1f to Color.Transparent,
|
||||
),
|
||||
center = Offset(size.width * 0.28f, size.height * 0.4f),
|
||||
radius = maxDimension * 0.28f,
|
||||
),
|
||||
size = size,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -46,7 +46,6 @@ import androidx.compose.runtime.setValue
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
|
|
@ -59,6 +58,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||
import coil3.compose.AsyncImage
|
||||
import com.nuvio.app.core.auth.AuthRepository
|
||||
import com.nuvio.app.core.auth.AuthState
|
||||
import com.nuvio.app.core.ui.ProfileMeshBackground
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import nuvio.composeapp.generated.resources.*
|
||||
|
|
@ -100,26 +100,23 @@ fun ProfileSelectionScreen(
|
|||
}
|
||||
|
||||
val statusBarTop = WindowInsets.statusBars.asPaddingValues().calculateTopPadding()
|
||||
val backgroundProfileColor = remember(profileState.activeProfile, profileState.profiles) {
|
||||
val sourceProfile = profileState.activeProfile ?: profileState.profiles.firstOrNull()
|
||||
sourceProfile?.avatarColorHex?.let(::parseHexColor) ?: Color(0xFF1E88E5)
|
||||
}
|
||||
|
||||
BoxWithConstraints(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.background(
|
||||
Brush.verticalGradient(
|
||||
colors = listOf(
|
||||
MaterialTheme.colorScheme.background,
|
||||
MaterialTheme.colorScheme.background,
|
||||
MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.15f),
|
||||
),
|
||||
),
|
||||
)
|
||||
.padding(top = statusBarTop),
|
||||
.fillMaxSize(),
|
||||
) {
|
||||
val isTabletLayout = maxWidth >= 768.dp
|
||||
|
||||
ProfileMeshBackground(profileColor = backgroundProfileColor)
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(top = statusBarTop)
|
||||
.then(
|
||||
if (isTabletLayout) {
|
||||
Modifier
|
||||
|
|
@ -137,7 +134,7 @@ fun ProfileSelectionScreen(
|
|||
text = stringResource(Res.string.profile_who_is_watching),
|
||||
style = MaterialTheme.typography.headlineLarge.copy(
|
||||
fontSize = 30.sp,
|
||||
letterSpacing = (-0.5).sp,
|
||||
letterSpacing = 0.sp,
|
||||
),
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
fontWeight = FontWeight.Bold,
|
||||
|
|
|
|||
Loading…
Reference in a new issue