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/语言菜单点击复核成功。