refactor UI components to utilize MaterialTheme for consistent theming

This commit is contained in:
2026-01-20 17:01:28 +01:00
parent 00cf71e65e
commit bcf66fd393
9 changed files with 73 additions and 76 deletions

View File

@@ -176,10 +176,10 @@ fun HomeDrawerFooter (
HomeAvatar(
size = 32.dp,
borderWidth = 1.dp,
borderColor = Color.White.copy(alpha = 0.1f),
borderColor = colors.divider,
backgroundColor = colors.avatarBackground,
icon = Icons.Outlined.Person,
iconTint = Color.White
iconTint = colors.textPrimary
)
Column(modifier = Modifier.padding(start = 12.dp)
.clickable {viewModel.logout()}) {

View File

@@ -29,7 +29,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
@@ -112,14 +111,14 @@ fun ContinueWatchingCard(
Box(
modifier = Modifier
.matchParentSize()
.background(Color.Black.copy(alpha = 0.2f))
.background(colors.textPrimary.copy(alpha = 0.2f))
)
Box(
modifier = Modifier
.align(Alignment.BottomStart)
.fillMaxWidth()
.height(4.dp)
.background(Color.White.copy(alpha = 0.2f))
.background(colors.textPrimary.copy(alpha = 0.2f))
) {
Box(
modifier = Modifier

View File

@@ -19,7 +19,6 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@@ -41,7 +40,7 @@ fun HomeTopBar(
borderColor = colors.avatarBorder,
backgroundColor = colors.avatarBackground,
icon = Icons.Outlined.Person,
iconTint = Color.White
iconTint = colors.onPrimary
)
}
) {

View File

@@ -6,11 +6,11 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import hu.bbara.purefin.app.home.ui.PosterItem
@@ -44,7 +44,7 @@ fun LibraryPosterGrid(
contentPadding = PaddingValues(16.dp),
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp),
modifier = modifier.background(Color.Black)
modifier = modifier.background(MaterialTheme.colorScheme.background)
) {
items(libraryItems) { item ->
PosterCard(
@@ -53,4 +53,4 @@ fun LibraryPosterGrid(
)
}
}
}
}

View File

@@ -7,6 +7,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Visibility
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
@@ -30,15 +31,12 @@ fun PurefinComplexTextField(
trailingIcon: ImageVector? = null,
visualTransformation: VisualTransformation = VisualTransformation.None
) {
val JellyfinOrange = Color(0xFFBD542E)
val JellyfinBg = Color(0xFF141517)
val JellyfinSurface = Color(0xFF1E2124)
val TextSecondary = Color(0xFF9EA3A8)
val scheme = MaterialTheme.colorScheme
Column(modifier = Modifier.fillMaxWidth()) {
Text(
text = label,
color = Color.White,
color = scheme.onBackground,
fontWeight = FontWeight.Bold,
fontSize = 14.sp,
modifier = Modifier.padding(bottom = 8.dp)
@@ -49,22 +47,22 @@ fun PurefinComplexTextField(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(12.dp)),
placeholder = { Text(placeholder, color = TextSecondary) },
placeholder = { Text(placeholder, color = scheme.onSurfaceVariant) },
leadingIcon = if (leadingIcon != null) {
{ Icon(leadingIcon, contentDescription = null, tint = TextSecondary) }
{ Icon(leadingIcon, contentDescription = null, tint = scheme.onSurfaceVariant) }
} else null,
trailingIcon = if (trailingIcon != null) {
{ Icon(Icons.Default.Visibility, contentDescription = null, tint = TextSecondary) }
{ Icon(Icons.Default.Visibility, contentDescription = null, tint = scheme.onSurfaceVariant) }
} else null,
visualTransformation = visualTransformation,
colors = TextFieldDefaults.colors(
focusedContainerColor = JellyfinSurface,
unfocusedContainerColor = JellyfinSurface,
focusedContainerColor = scheme.surfaceVariant,
unfocusedContainerColor = scheme.surfaceVariant,
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
cursorColor = JellyfinOrange,
focusedTextColor = Color.White,
unfocusedTextColor = Color.White
cursorColor = scheme.primary,
focusedTextColor = scheme.onSurface,
unfocusedTextColor = scheme.onSurface
))
}
}
}

View File

@@ -8,6 +8,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Visibility
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
@@ -32,17 +33,14 @@ fun PurefinPasswordField(
placeholder: String,
leadingIcon: ImageVector,
) {
val JellyfinOrange = Color(0xFFBD542E)
val JellyfinBg = Color(0xFF141517)
val JellyfinSurface = Color(0xFF1E2124)
val TextSecondary = Color(0xFF9EA3A8)
val scheme = MaterialTheme.colorScheme
val showField = remember { mutableStateOf(false) }
Column(modifier = Modifier.fillMaxWidth()) {
Text(
text = label,
color = Color.White,
color = scheme.onBackground,
fontWeight = FontWeight.Bold,
fontSize = 14.sp,
modifier = Modifier.padding(bottom = 8.dp)
@@ -53,26 +51,26 @@ fun PurefinPasswordField(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(12.dp)),
placeholder = { Text(placeholder, color = TextSecondary) },
leadingIcon = { Icon(leadingIcon, contentDescription = null, tint = TextSecondary) },
placeholder = { Text(placeholder, color = scheme.onSurfaceVariant) },
leadingIcon = { Icon(leadingIcon, contentDescription = null, tint = scheme.onSurfaceVariant) },
trailingIcon =
{
IconButton(
onClick = { showField.value = !showField.value },
) {
Icon(Icons.Default.Visibility, contentDescription = null, tint = TextSecondary)
Icon(Icons.Default.Visibility, contentDescription = null, tint = scheme.onSurfaceVariant)
}
},
visualTransformation = if (showField.value) VisualTransformation.None else PasswordVisualTransformation(),
colors = TextFieldDefaults.colors(
focusedContainerColor = JellyfinSurface,
unfocusedContainerColor = JellyfinSurface,
focusedContainerColor = scheme.surfaceVariant,
unfocusedContainerColor = scheme.surfaceVariant,
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
cursorColor = JellyfinOrange,
focusedTextColor = Color.White,
unfocusedTextColor = Color.White
cursorColor = scheme.primary,
focusedTextColor = scheme.onSurface,
unfocusedTextColor = scheme.onSurface
)
)
}
}
}

View File

@@ -22,6 +22,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Movie
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
@@ -39,11 +40,12 @@ import androidx.compose.ui.unit.sp
fun PurefinWaitingScreen(
modifier: Modifier = Modifier
) {
val accentColor = Color(0xFFBD542E)
val backgroundColor = Color(0xFF141517)
val surfaceColor = Color(0xFF1E2124)
val textPrimary = Color.White
val textSecondary = Color(0xFF9EA3A8)
val scheme = MaterialTheme.colorScheme
val accentColor = scheme.primary
val backgroundColor = scheme.background
val surfaceColor = scheme.surface
val textPrimary = scheme.onSurface
val textSecondary = scheme.onSurfaceVariant
val transition = rememberInfiniteTransition(label = "waiting-pulse")
val pulseScale = transition.animateFloat(
@@ -112,7 +114,7 @@ fun PurefinWaitingScreen(
Icon(
imageVector = Icons.Outlined.Movie,
contentDescription = null,
tint = Color.White,
tint = scheme.onPrimary,
modifier = Modifier.size(40.dp)
)
}
@@ -121,13 +123,13 @@ fun PurefinWaitingScreen(
Spacer(modifier = Modifier.height(20.dp))
Text(
text = "Connecting",
text = "Just a moment",
color = textPrimary,
fontSize = 20.sp,
fontWeight = FontWeight.Bold
)
Text(
text = "Summoning the media gnomes...",
text = "I am doing all I can...",
color = textSecondary,
fontSize = 14.sp
)

View File

@@ -21,6 +21,7 @@ import androidx.compose.material.icons.filled.Person
import androidx.compose.material.icons.filled.Search
import androidx.compose.material.icons.filled.Storage
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
@@ -32,7 +33,6 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@@ -49,9 +49,7 @@ fun LoginScreen(
viewModel: LoginViewModel = hiltViewModel(),
modifier: Modifier = Modifier
) {
val JellyfinOrange = Color(0xFFBD542E)
val JellyfinBg = Color(0xFF141517)
val TextSecondary = Color(0xFF9EA3A8)
val scheme = MaterialTheme.colorScheme
// Observe ViewModel state
val serverUrl by viewModel.url.collectAsState()
@@ -67,7 +65,7 @@ fun LoginScreen(
Column(
modifier = modifier
.fillMaxSize()
.background(JellyfinBg)
.background(scheme.background)
.padding(24.dp)
.verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.CenterHorizontally
@@ -78,27 +76,27 @@ fun LoginScreen(
Box(
modifier = Modifier
.size(100.dp)
.background(JellyfinOrange, RoundedCornerShape(24.dp)),
.background(scheme.primary, RoundedCornerShape(24.dp)),
contentAlignment = Alignment.Center
) {
Icon(
imageVector = Icons.Default.Movie, // Replace with actual logo resource
contentDescription = "Logo",
tint = Color.White,
tint = scheme.onPrimary,
modifier = Modifier.size(60.dp)
)
}
Text(
text = "Jellyfin",
color = Color.White,
color = scheme.onBackground,
fontSize = 32.sp,
fontWeight = FontWeight.Bold,
modifier = Modifier.padding(top = 16.dp)
)
Text(
text = "PERSONAL MEDIA SYSTEM",
color = TextSecondary,
color = scheme.onSurfaceVariant,
fontSize = 12.sp,
letterSpacing = 2.sp
)
@@ -108,14 +106,14 @@ fun LoginScreen(
// Form Section
Text(
text = "Connect to Server",
color = Color.White,
color = scheme.onBackground,
fontSize = 22.sp,
fontWeight = FontWeight.Bold,
modifier = Modifier.align(Alignment.Start)
)
Text(
text = "Enter your details to access your library",
color = TextSecondary,
color = scheme.onSurfaceVariant,
fontSize = 14.sp,
modifier = Modifier
.align(Alignment.Start)
@@ -175,12 +173,12 @@ fun LoginScreen(
) {
TextButton(onClick = {}) {
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(Icons.Default.Search, contentDescription = null, tint = TextSecondary, modifier = Modifier.size(18.dp))
Text(" Discover Servers", color = TextSecondary)
Icon(Icons.Default.Search, contentDescription = null, tint = scheme.onSurfaceVariant, modifier = Modifier.size(18.dp))
Text(" Discover Servers", color = scheme.onSurfaceVariant)
}
}
TextButton(onClick = {}) {
Text("Need Help?", color = TextSecondary)
Text("Need Help?", color = scheme.onSurfaceVariant)
}
}

View File

@@ -8,14 +8,15 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.viewinterop.AndroidView
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.media3.ui.PlayerView
import dagger.hilt.android.AndroidEntryPoint
import hu.bbara.purefin.player.viewmodel.PlayerViewModel
import hu.bbara.purefin.ui.theme.PurefinTheme
@AndroidEntryPoint
class PlayerActivity : ComponentActivity() {
@@ -23,22 +24,24 @@ class PlayerActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
setContent {
val viewModel = hiltViewModel<PlayerViewModel>()
Box(
modifier = Modifier.fillMaxSize()
.background(Color.Black)
) {
AndroidView(
factory = { context ->
PlayerView(context).also {
it.player = viewModel.player
}
},
modifier = Modifier.fillMaxHeight()
.align(Alignment.Center)
.aspectRatio(16f / 9f)
PurefinTheme {
val viewModel = hiltViewModel<PlayerViewModel>()
Box(
modifier = Modifier.fillMaxSize()
.background(MaterialTheme.colorScheme.background)
) {
AndroidView(
factory = { context ->
PlayerView(context).also {
it.player = viewModel.player
}
},
modifier = Modifier.fillMaxHeight()
.align(Alignment.Center)
.aspectRatio(16f / 9f)
)
)
}
}
}
}