diff --git a/app/src/main/kotlin/com/example/myapplication/navigation/AppNavHost.kt b/app/src/main/kotlin/com/example/myapplication/navigation/AppNavHost.kt index fa69db5..70a2170 100644 --- a/app/src/main/kotlin/com/example/myapplication/navigation/AppNavHost.kt +++ b/app/src/main/kotlin/com/example/myapplication/navigation/AppNavHost.kt @@ -43,6 +43,7 @@ import com.example.myapplication.screens.SettingsScreen import com.example.myapplication.screens.SettingsTopBar import com.example.myapplication.screens.VideoPlayerScreen import com.example.myapplication.ui.design.LumaLoading +import kotlinx.coroutines.CancellationException import top.yukonga.miuix.kmp.basic.Text @OptIn(ExperimentalAnimationApi::class) @@ -244,10 +245,16 @@ private fun MediaDetailDestination( LaunchedEffect(server?.id, itemId) { loading = true - item = if (server == null || server.apiKey.isBlank() || itemId.isBlank()) { + item = try { + if (server == null || server.apiKey.isBlank() || itemId.isBlank()) { + null + } else { + EmbyRepository.getItem(server, itemId) + } + } catch (error: CancellationException) { + throw error + } catch (_: Exception) { null - } else { - EmbyRepository.getItem(server, itemId) } loading = false } @@ -280,19 +287,31 @@ private fun PlayerDestination( LaunchedEffect(server?.id, itemId) { itemLoading = true - item = if (server == null || server.apiKey.isBlank() || itemId.isBlank()) { + item = try { + if (server == null || server.apiKey.isBlank() || itemId.isBlank()) { + null + } else { + EmbyRepository.getItem(server, itemId) + } + } catch (error: CancellationException) { + throw error + } catch (_: Exception) { null - } else { - EmbyRepository.getItem(server, itemId) } itemLoading = false } LaunchedEffect(server?.id, seriesId, seasonId) { - episodes = if (server == null || seriesId.isNullOrBlank() || seasonId.isNullOrBlank()) { + episodes = try { + if (server == null || seriesId.isNullOrBlank() || seasonId.isNullOrBlank()) { + emptyList() + } else { + EmbyRepository.getEpisodes(server, seriesId, seasonId) + } + } catch (error: CancellationException) { + throw error + } catch (_: Exception) { emptyList() - } else { - EmbyRepository.getEpisodes(server, seriesId, seasonId) } } @@ -301,8 +320,16 @@ private fun PlayerDestination( if (server == null || server.apiKey.isBlank() || target == null) return@LaunchedEffect playbackLoading = true playbackError = null - playbackSession = EmbyRepository.resolvePlaybackSession(server, target) - playbackUrl = playbackSession?.streamUrl + try { + playbackSession = EmbyRepository.resolvePlaybackSession(server, target) + playbackUrl = playbackSession?.streamUrl + } catch (error: CancellationException) { + throw error + } catch (_: Exception) { + playbackSession = null + playbackUrl = null + playbackError = playbackUrlFailedMessage + } playbackLoading = false if (playbackUrl.isNullOrBlank()) playbackError = playbackUrlFailedMessage } diff --git a/app/src/main/kotlin/com/example/myapplication/screens/HomeScreen.kt b/app/src/main/kotlin/com/example/myapplication/screens/HomeScreen.kt index c11a597..dcd6a81 100644 --- a/app/src/main/kotlin/com/example/myapplication/screens/HomeScreen.kt +++ b/app/src/main/kotlin/com/example/myapplication/screens/HomeScreen.kt @@ -31,8 +31,6 @@ import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material3.Icon import androidx.compose.material3.LocalTextStyle import androidx.compose.runtime.staticCompositionLocalOf import androidx.compose.runtime.Composable @@ -92,7 +90,6 @@ import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.Spring import androidx.compose.animation.core.spring import androidx.compose.foundation.layout.wrapContentWidth -import androidx.compose.material.icons.filled.ArrowDropDown import androidx.compose.ui.draw.rotate import androidx.compose.ui.draw.shadow import androidx.compose.ui.text.TextStyle diff --git a/app/src/main/kotlin/com/example/myapplication/screens/LibraryScreen.kt b/app/src/main/kotlin/com/example/myapplication/screens/LibraryScreen.kt index 2ddc76d..d2cd865 100644 --- a/app/src/main/kotlin/com/example/myapplication/screens/LibraryScreen.kt +++ b/app/src/main/kotlin/com/example/myapplication/screens/LibraryScreen.kt @@ -45,7 +45,6 @@ import com.example.myapplication.ui.GlassDialog import com.example.myapplication.ui.GlassSheet import com.example.myapplication.ui.GlassInputField import com.example.myapplication.ui.GlassPopupItem -import androidx.compose.material3.Icon import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect @@ -83,21 +82,6 @@ import androidx.compose.ui.unit.sp import androidx.compose.ui.res.stringResource import com.example.myapplication.R as Res import top.yukonga.miuix.kmp.basic.Text -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ArrowBack -import androidx.compose.material.icons.filled.GridView -import androidx.compose.material.icons.filled.ViewAgenda -import androidx.compose.material.icons.filled.PlayArrow -import androidx.compose.material.icons.outlined.Add -import androidx.compose.material.icons.outlined.MoreHoriz -import androidx.compose.material.icons.outlined.PhotoLibrary -import androidx.compose.material.icons.outlined.Delete -import androidx.compose.material.icons.outlined.Edit -import androidx.compose.material.icons.outlined.Close -import androidx.compose.material.icons.outlined.Image -import androidx.compose.material.icons.outlined.Search -import androidx.compose.material.icons.outlined.Visibility -import androidx.compose.material.icons.outlined.VisibilityOff import com.example.myapplication.data.EmbyServer import com.example.myapplication.data.IconItem import com.example.myapplication.data.IconLibrary @@ -223,7 +207,7 @@ private fun ServerCard(server: EmbyServer, tint: Color, onClick: () -> Unit, onC .clickable(indication = null, interactionSource = remember { MutableInteractionSource() }) { onMoreClick() }, contentAlignment = Alignment.Center, ) { - Icon(Icons.Outlined.MoreHoriz, contentDescription = stringResource(Res.string.server_actions), tint = GlassTokens.subtext, modifier = Modifier.size(24.dp)) + LumaIconView(LumaIcon.More, contentDescription = stringResource(Res.string.server_actions), tint = GlassTokens.subtext, modifier = Modifier.size(24.dp)) } } } @@ -284,7 +268,7 @@ private fun ServerGridCard(server: EmbyServer, tint: Color, onClick: () -> Unit, .clickable(indication = null, interactionSource = remember { MutableInteractionSource() }) { onMoreClick() }, contentAlignment = Alignment.Center, ) { - Icon(Icons.Outlined.MoreHoriz, contentDescription = stringResource(Res.string.server_actions), tint = GlassTokens.subtext, modifier = Modifier.size(24.dp)) + LumaIconView(LumaIcon.More, contentDescription = stringResource(Res.string.server_actions), tint = GlassTokens.subtext, modifier = Modifier.size(24.dp)) } } Box(Modifier.height(22.dp)) { @@ -1453,7 +1437,7 @@ fun AddServerScreen( .clickable(indication = null, interactionSource = remember { MutableInteractionSource() }, onClick = onDismiss), contentAlignment = Alignment.Center, ) { - Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = stringResource(Res.string.back), tint = GlassTokens.text, modifier = Modifier.size(20.dp)) + LumaIconView(LumaIcon.Back, contentDescription = stringResource(Res.string.back), tint = GlassTokens.text, modifier = Modifier.size(20.dp)) } Spacer(Modifier.width(12.dp)) Text(stringResource(Res.string.add_server), color = GlassTokens.text, fontSize = 22.sp, fontWeight = FontWeight.Bold) @@ -1618,8 +1602,8 @@ private fun ServerFormContent( onValueChange = { password = it }, visualTransformation = if (showPassword) VisualTransformation.None else PasswordVisualTransformation(), trailingContent = { - Icon( - imageVector = if (showPassword) Icons.Outlined.VisibilityOff else Icons.Outlined.Visibility, + LumaIconView( + icon = if (showPassword) LumaIcon.EyeOff else LumaIcon.Eye, contentDescription = stringResource(if (showPassword) Res.string.server_hide_password else Res.string.server_show_password), tint = GlassTokens.subtext, modifier = Modifier.size(24.dp).clickable( diff --git a/app/src/main/kotlin/com/example/myapplication/screens/MediaDetailScreen.kt b/app/src/main/kotlin/com/example/myapplication/screens/MediaDetailScreen.kt index 512ea13..448809e 100644 --- a/app/src/main/kotlin/com/example/myapplication/screens/MediaDetailScreen.kt +++ b/app/src/main/kotlin/com/example/myapplication/screens/MediaDetailScreen.kt @@ -28,11 +28,6 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ArrowBack -import androidx.compose.material.icons.filled.PlayArrow -import androidx.compose.material.icons.filled.Star -import androidx.compose.material3.Icon import androidx.compose.material3.LocalTextStyle import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider @@ -378,8 +373,8 @@ fun MediaDetailScreen( .clickable(onClick = onClose), contentAlignment = Alignment.Center, ) { - Icon( - imageVector = Icons.AutoMirrored.Filled.ArrowBack, + LumaIconView( + icon = LumaIcon.Back, contentDescription = stringResource(Res.string.back), tint = Color.White, modifier = Modifier.size(19.dp), @@ -523,7 +518,7 @@ private fun DetailHeadline(detail: EmbyItem, refreshing: Boolean, errorText: Str Spacer(Modifier.height(9.dp)) Row(verticalAlignment = Alignment.CenterVertically) { detail.communityRating?.takeIf { it > 0.0 }?.let { rating -> - Icon(imageVector = Icons.Filled.Star, contentDescription = null, tint = Color(0xFFFFD54F), modifier = Modifier.size(14.dp)) + LumaIconView(LumaIcon.Star, contentDescription = null, tint = Color(0xFFFFD54F), modifier = Modifier.size(14.dp)) Spacer(Modifier.width(3.dp)) Text(text = String.format("%.1f", rating), color = LocalDetailText.current, fontSize = 12.sp, fontWeight = FontWeight.SemiBold) Spacer(Modifier.width(9.dp)) diff --git a/app/src/main/kotlin/com/example/myapplication/screens/SettingsChildScreens.kt b/app/src/main/kotlin/com/example/myapplication/screens/SettingsChildScreens.kt index e3dca02..268cfdb 100644 --- a/app/src/main/kotlin/com/example/myapplication/screens/SettingsChildScreens.kt +++ b/app/src/main/kotlin/com/example/myapplication/screens/SettingsChildScreens.kt @@ -20,11 +20,6 @@ import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ArrowBack -import androidx.compose.material.icons.outlined.Delete -import androidx.compose.material.icons.outlined.Info -import androidx.compose.material3.Icon import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.getValue @@ -73,7 +68,7 @@ private fun PageTopBar(title: String, onBack: () -> Unit) { .clickable(indication = null, interactionSource = remember { androidx.compose.foundation.interaction.MutableInteractionSource() }, onClick = onBack), contentAlignment = Alignment.Center, ) { - Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = stringResource(R.string.back), tint = LumaColors.text, modifier = Modifier.size(20.dp)) + LumaIconView(LumaIcon.Back, contentDescription = stringResource(R.string.back), tint = LumaColors.text, modifier = Modifier.size(20.dp)) } Spacer(Modifier.size(12.dp)) Text(title, color = GlassTokens.text, fontSize = 20.sp, fontWeight = FontWeight.Bold) diff --git a/app/src/main/kotlin/com/example/myapplication/screens/SettingsScreen.kt b/app/src/main/kotlin/com/example/myapplication/screens/SettingsScreen.kt index 94a5854..8cf6294 100644 --- a/app/src/main/kotlin/com/example/myapplication/screens/SettingsScreen.kt +++ b/app/src/main/kotlin/com/example/myapplication/screens/SettingsScreen.kt @@ -27,9 +27,6 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.ChevronRight -import androidx.compose.material3.Icon import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect @@ -276,9 +273,9 @@ private fun SettingRowItem( Text(subtitle, color = LumaColors.textSecondary, fontSize = 12.sp) } } - Icon( - Icons.Outlined.ChevronRight, - null, + LumaIconView( + icon = LumaIcon.ChevronRight, + contentDescription = null, tint = LumaColors.textTertiary, modifier = Modifier .size(20.dp) diff --git a/app/src/main/kotlin/com/example/myapplication/ui/AppBottomBar.kt b/app/src/main/kotlin/com/example/myapplication/ui/AppBottomBar.kt index e791ab2..2765346 100644 --- a/app/src/main/kotlin/com/example/myapplication/ui/AppBottomBar.kt +++ b/app/src/main/kotlin/com/example/myapplication/ui/AppBottomBar.kt @@ -74,7 +74,7 @@ fun LiquidAppBottomBar( selected = selectedTab == index, contentDescription = stringResource(tab.labelRes), tint = if (isGhostLayer) Color.White else if (selectedTab == index) LumaColors.accent else inactive, - modifier = Modifier.size(30.dp), + modifier = Modifier.size(33.dp), ) Spacer(Modifier.height(3.dp)) Text( @@ -136,7 +136,7 @@ fun LiquidAppBottomBar( icon = LumaIcon.Search, contentDescription = null, tint = if (searchSelected) LumaColors.accent else inactive, - modifier = Modifier.size(34.dp), + modifier = Modifier.size(37.dp), ) Text( text = stringResource(Res.string.search), diff --git a/app/src/main/kotlin/com/example/myapplication/ui/LiquidGlass.kt b/app/src/main/kotlin/com/example/myapplication/ui/LiquidGlass.kt index 95fa978..12dc0ef 100644 --- a/app/src/main/kotlin/com/example/myapplication/ui/LiquidGlass.kt +++ b/app/src/main/kotlin/com/example/myapplication/ui/LiquidGlass.kt @@ -63,7 +63,6 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.CompositingStrategy import androidx.compose.ui.graphics.graphicsLayer -import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.geometry.Rect import androidx.compose.ui.text.font.FontWeight @@ -84,13 +83,11 @@ import androidx.compose.runtime.LaunchedEffect import kotlinx.coroutines.delay import kotlin.math.roundToInt import androidx.compose.ui.zIndex -import androidx.compose.material.icons.outlined.ChevronRight import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.asPaddingValues -import androidx.compose.material3.Icon import top.yukonga.miuix.kmp.basic.Text import com.example.myapplication.ui.design.LumaColors import com.example.myapplication.ui.design.LumaIcon @@ -101,21 +98,6 @@ import com.example.myapplication.ui.design.LumaShapes import com.example.myapplication.ui.design.LumaTypography import com.example.myapplication.ui.design.LumaGlassRuntime import com.example.myapplication.ui.design.lumaGlass -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Apps -import androidx.compose.material.icons.filled.GridView -import androidx.compose.material.icons.filled.Favorite -import androidx.compose.material.icons.filled.Home -import androidx.compose.material.icons.filled.Search -import androidx.compose.material.icons.filled.Movie -import androidx.compose.material.icons.filled.Settings -import androidx.compose.material.icons.filled.Storage -import androidx.compose.material.icons.outlined.GridView -import androidx.compose.material.icons.outlined.FavoriteBorder -import androidx.compose.material.icons.outlined.Home -import androidx.compose.material.icons.outlined.Search -import androidx.compose.material.icons.outlined.Settings -import androidx.compose.material.icons.outlined.Storage internal data class NavTab( val icon: LumaIcon, @@ -509,30 +491,6 @@ fun LiquidGlassPopupOverlay( } } -@Composable -fun GlassPopupItem( - text: String, - icon: ImageVector? = null, - tint: Color = Color(0xFF374151), - onClick: () -> Unit, -) { - val interactionSource = remember { MutableInteractionSource() } - Row( - modifier = Modifier - .fillMaxWidth() - .heightIn(min = 48.dp) - .clickable(indication = null, interactionSource = interactionSource, onClick = onClick) - .padding(horizontal = 16.dp, vertical = 12.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(12.dp), - ) { - if (icon != null) { - Icon(imageVector = icon, contentDescription = null, tint = tint, modifier = Modifier.size(18.dp)) - } - Text(text = text, color = tint, fontSize = 14.sp, fontWeight = FontWeight.Medium) - } -} - @Composable fun GlassPopupItem( text: String, diff --git a/app/src/main/kotlin/com/example/myapplication/ui/design/LumaDesignSystem.kt b/app/src/main/kotlin/com/example/myapplication/ui/design/LumaDesignSystem.kt index 0aff493..8ce3bb8 100644 --- a/app/src/main/kotlin/com/example/myapplication/ui/design/LumaDesignSystem.kt +++ b/app/src/main/kotlin/com/example/myapplication/ui/design/LumaDesignSystem.kt @@ -231,10 +231,10 @@ fun Modifier.lumaFallbackGlass( if (light) { Brush.horizontalGradient( listOf( - LumaColors.accent.copy(alpha = 0.24f), - Color.White.copy(alpha = 0.36f), - Color.White.copy(alpha = 0.22f), - LumaColors.accent.copy(alpha = 0.12f), + LumaColors.accent.copy(alpha = 0.10f), + Color.White.copy(alpha = 0.40f), + Color.White.copy(alpha = 0.30f), + LumaColors.accent.copy(alpha = 0.08f), ), ) } else { @@ -251,14 +251,15 @@ fun Modifier.lumaFallbackGlass( Brush.verticalGradient(listOf(top, bottom)) } return this + .clip(shape) .background(fill, shape) .then( if (selected) { Modifier.drawWithCache { val leftGlow = Brush.radialGradient( colors = listOf( - LumaColors.accent.copy(alpha = if (light) 0.22f else 0.26f), - LumaColors.accent.copy(alpha = 0.06f), + LumaColors.accent.copy(alpha = if (light) 0.14f else 0.18f), + LumaColors.accent.copy(alpha = 0.04f), Color.Transparent, ), center = Offset(size.width * 0.14f, size.height * 0.18f), @@ -266,7 +267,7 @@ fun Modifier.lumaFallbackGlass( ) val rightGlow = Brush.radialGradient( colors = listOf( - Color.White.copy(alpha = if (light) 0.22f else 0.12f), + Color.White.copy(alpha = if (light) 0.28f else 0.16f), Color.Transparent, ), center = Offset(size.width * 0.86f, size.height * 0.22f), @@ -283,6 +284,7 @@ fun Modifier.lumaFallbackGlass( }, ) .border(0.6.dp, edge, shape) + .clip(shape) } enum class LumaGlassLevel { diff --git a/app/src/main/kotlin/com/example/myapplication/ui/design/LumaIcons.kt b/app/src/main/kotlin/com/example/myapplication/ui/design/LumaIcons.kt index 8b8a053..12aebe0 100644 --- a/app/src/main/kotlin/com/example/myapplication/ui/design/LumaIcons.kt +++ b/app/src/main/kotlin/com/example/myapplication/ui/design/LumaIcons.kt @@ -89,6 +89,11 @@ enum class LumaIcon( Calendar(R.drawable.aurora_calendar, R.drawable.aurora_calendar_selected), Check(R.drawable.aurora_check, R.drawable.aurora_check_selected), Close(R.drawable.aurora_close, R.drawable.aurora_close_selected), + Back(R.drawable.aurora_back, R.drawable.aurora_back_selected), + ChevronRight(R.drawable.aurora_chevron_right, R.drawable.aurora_chevron_right_selected), + More(R.drawable.aurora_more, R.drawable.aurora_more_selected), + EyeOff(R.drawable.aurora_eye_off, R.drawable.aurora_eye_off_selected), + Star(R.drawable.aurora_star, R.drawable.aurora_star_selected), } @Composable diff --git a/app/src/main/kotlin/com/example/myapplication/ui/liquidglass/LiquidBottomTabs.kt b/app/src/main/kotlin/com/example/myapplication/ui/liquidglass/LiquidBottomTabs.kt index 445573d..0b891a1 100644 --- a/app/src/main/kotlin/com/example/myapplication/ui/liquidglass/LiquidBottomTabs.kt +++ b/app/src/main/kotlin/com/example/myapplication/ui/liquidglass/LiquidBottomTabs.kt @@ -51,7 +51,6 @@ import com.kyant.backdrop.shadow.Shadow import com.kyant.shapes.Capsule import com.example.myapplication.ui.design.LumaColors import com.example.myapplication.ui.design.LumaGlassRuntime -import com.example.myapplication.ui.design.LumaShapes import com.example.myapplication.ui.design.LumaSpacing import com.example.myapplication.ui.design.lumaFallbackGlass import com.example.myapplication.ui.design.rememberLumaLayerBackdrop @@ -206,7 +205,8 @@ fun LiquidBottomTabs( .then(interactiveHighlight.modifier) .height(64f.dp) .fillMaxWidth() - .padding(LumaSpacing.xxs), + .padding(LumaSpacing.xxs) + .clip(Capsule()), verticalAlignment = Alignment.CenterVertically, content = { CompositionLocalProvider( @@ -287,10 +287,9 @@ fun LiquidBottomTabs( backdrop = rememberCombinedBackdrop(backdrop, tabsBackdrop!!), shape = { Capsule() }, effects = { - val progress = dampedDragAnimation.pressProgress lens( - 10f.dp.toPx() * progress, - 14f.dp.toPx() * progress, + 10f.dp.toPx(), + 14f.dp.toPx(), chromaticAberration = true, ) }, diff --git a/app/src/main/res/drawable/aurora_back.xml b/app/src/main/res/drawable/aurora_back.xml new file mode 100644 index 0000000..7fa71c0 --- /dev/null +++ b/app/src/main/res/drawable/aurora_back.xml @@ -0,0 +1,10 @@ + + + + diff --git a/app/src/main/res/drawable/aurora_back_selected.xml b/app/src/main/res/drawable/aurora_back_selected.xml new file mode 100644 index 0000000..066d9b6 --- /dev/null +++ b/app/src/main/res/drawable/aurora_back_selected.xml @@ -0,0 +1,10 @@ + + + + diff --git a/app/src/main/res/drawable/aurora_chevron_right.xml b/app/src/main/res/drawable/aurora_chevron_right.xml new file mode 100644 index 0000000..e4964db --- /dev/null +++ b/app/src/main/res/drawable/aurora_chevron_right.xml @@ -0,0 +1,14 @@ + + + + diff --git a/app/src/main/res/drawable/aurora_chevron_right_selected.xml b/app/src/main/res/drawable/aurora_chevron_right_selected.xml new file mode 100644 index 0000000..636c392 --- /dev/null +++ b/app/src/main/res/drawable/aurora_chevron_right_selected.xml @@ -0,0 +1,14 @@ + + + + diff --git a/app/src/main/res/drawable/aurora_eye_off.xml b/app/src/main/res/drawable/aurora_eye_off.xml new file mode 100644 index 0000000..c24e82d --- /dev/null +++ b/app/src/main/res/drawable/aurora_eye_off.xml @@ -0,0 +1,20 @@ + + + + + diff --git a/app/src/main/res/drawable/aurora_eye_off_selected.xml b/app/src/main/res/drawable/aurora_eye_off_selected.xml new file mode 100644 index 0000000..3cb1b6c --- /dev/null +++ b/app/src/main/res/drawable/aurora_eye_off_selected.xml @@ -0,0 +1,20 @@ + + + + + diff --git a/app/src/main/res/drawable/aurora_more.xml b/app/src/main/res/drawable/aurora_more.xml new file mode 100644 index 0000000..9236d95 --- /dev/null +++ b/app/src/main/res/drawable/aurora_more.xml @@ -0,0 +1,10 @@ + + + + diff --git a/app/src/main/res/drawable/aurora_more_selected.xml b/app/src/main/res/drawable/aurora_more_selected.xml new file mode 100644 index 0000000..aa7b45e --- /dev/null +++ b/app/src/main/res/drawable/aurora_more_selected.xml @@ -0,0 +1,10 @@ + + + + diff --git a/app/src/main/res/drawable/aurora_star.xml b/app/src/main/res/drawable/aurora_star.xml new file mode 100644 index 0000000..4e523b7 --- /dev/null +++ b/app/src/main/res/drawable/aurora_star.xml @@ -0,0 +1,10 @@ + + + + diff --git a/app/src/main/res/drawable/aurora_star_selected.xml b/app/src/main/res/drawable/aurora_star_selected.xml new file mode 100644 index 0000000..2bb3b3c --- /dev/null +++ b/app/src/main/res/drawable/aurora_star_selected.xml @@ -0,0 +1,10 @@ + + + + diff --git a/memory/2026-08-27.md b/memory/2026-08-27.md index 86ce9a1..4e167e4 100644 --- a/memory/2026-08-27.md +++ b/memory/2026-08-27.md @@ -112,3 +112,9 @@ 文件变更: data/EmbyApiModels.kt、data/EmbyRepository.kt、navigation/AppNavHost.kt、screens/VideoPlayerScreen.kt、screens/HomeScreen.kt、ui/design/LumaDesignSystem.kt、ui/AppBottomBar.kt、ui/liquidglass/LiquidBottomTabs.kt、ui/liquidglass/LiquidBottomTab.kt、memory/*。 教训: 模拟器不能安全采样 Kyant Backdrop,降级态需用连续胶囊渐变和局部高光保持玻璃层次;提交时排除本地参考仓库和媒体素材。 标签: #lumaplayer #emby #playback #cache #liquid-glass #renderthread + +[PROJECT:lumaplayer] 底栏图标与安全降级玻璃收尾 +结论: 底栏图标放大约 10%,降级玻璃固定最终 Capsule 裁剪并采用白色透光、弱蓝色选中层;原生 AndroidLiquidGlass-kmp 路径空闲态保留轻微 Lens,详情/播放器请求失败不再卡加载;Debug/Lint/Unit 均成功,API 35 模拟器启动和导航点击无崩溃。 +文件变更: ui/AppBottomBar.kt、ui/design/LumaDesignSystem.kt、ui/liquidglass/LiquidBottomTabs.kt、navigation/AppNavHost.kt、Aurora 图标资源、memory/*。 +教训: 模拟器仍不能安全启用 Kyant RenderEffect 采样,降级路径必须在最终尺寸上裁剪,原生路径只能在通过设备与帧率门控后启用。 +标签: #lumaplayer #bottom-bar #aurora #liquid-glass #renderthread #build diff --git a/memory/MEMORY.md b/memory/MEMORY.md index 17ec76b..2104d4d 100644 --- a/memory/MEMORY.md +++ b/memory/MEMORY.md @@ -2,9 +2,9 @@ - 项目:lumaplayer,Android Kotlin/Compose 媒体库客户端。 - 当前 Git 分支:`master`。 -- 最近同步:远端与本地基线均为 `5df288b`,当前工作区有 UI 设计改动。 +- 最近同步:`master` 已完成底栏图标与安全降级玻璃收尾,提交前工作区仅保留本地参考素材未跟踪。 - 当前实现:底栏与安全的 Glass 组件使用 Kyant0 Backdrop 2.0.1;安全且实测帧率不低于 48fps 时使用 Backdrop + blur/vibrancy/lens,模拟器、低帧率或低版本使用渐变毛玻璃降级;页面捕获层仅服务根 Tab/底栏,子页玻璃无源时安全降级;添加服务器为独立普通表单页面并支持 HTTP/HTTPS;页面导航使用 Navigation Compose。 - 最新稳定性策略:通过 `LumaGlassRuntime` 识别常见 Android Emulator GPU,模拟器跳过 Kyant RenderEffect/GraphicsLayer 采样,真机保留 Backdrop;播放器不捕获 AndroidView。 - 当前 UI:新增 `ui/design` 令牌、公共加载/空状态/按钮、Aurora 图标子集和授权说明;主要页面已接入统一颜色、间距、圆角和动效。 -- 构建验证:Backdrop 层级收敛、模拟器安全降级、播放器采样隔离和 GlassSheet 收尾后 `assembleDebug`、`lintDebug`、`testDebugUnitTest` 成功;已在 `sdk_gphone64_arm64` 模拟器安装启动复核,未出现 `SIGSEGV/RenderThread`,尚未做真机录屏比对。 +- 构建验证:Backdrop 层级收敛、模拟器安全降级、播放器采样隔离和 GlassSheet 收尾后 `assembleDebug`、`lintDebug`、`testDebugUnitTest` 成功;已在 `sdk_gphone64_arm64` API 35 模拟器安装启动并点击 Vision/Settings/语言菜单,未出现 `SIGSEGV/RenderThread`,尚未做真机录屏比对。 - 详细状态见 [projects.md](projects.md),踩坑见 [lessons.md](lessons.md)。 diff --git a/memory/projects.md b/memory/projects.md index b005a5b..12ee32d 100644 --- a/memory/projects.md +++ b/memory/projects.md @@ -32,3 +32,4 @@ - 2026-08-27:再次加强模拟器识别,增加 x86 ABI、board 和 emu 设备名拦截;详情返回按钮统一为 Luma glass,详情操作目标补足 48dp;`assembleDebug`、`lintDebug`、`testDebugUnitTest` 成功。 - 2026-08-27:播放器按 Emby Playback Check-in 约定补齐 `PlaySessionId`、`MediaSourceId`、`PositionTicks`、`CanSeek`、`QueueableMediaTypes` 和事件字段;播放开始/暂停/继续/拖动/播放中进度/停止统一进入串行队列,普通进度按 10 秒或位置变化阈值上报。 - 2026-08-27:首页增加按服务器身份隔离的进程内内容缓存,普通页面返回不重复请求,显式重试才刷新;玻璃运行时增加 Choreographer 帧率门控,底栏高帧率安全设备走本地 AndroidLiquidGlass-kmp 的 Lens,模拟器/低帧率使用连续胶囊毛玻璃和选中高光;`assembleDebug`、`lintDebug`、模拟器安装启动复核成功。 +- 2026-08-27:底栏普通图标调整为 33dp、搜索图标 37dp;降级玻璃增加最终 Capsule 裁剪并减弱蓝色选中填充,原生路径空闲态保留轻微 Lens;详情/播放器/剧集加载和播放地址失败时回落到错误态;最终 APK 在 API 35 模拟器启动、Vision/Settings/语言菜单点击复核成功。