feat: use material icons
This commit is contained in:
+11
-1
@@ -23,7 +23,16 @@ android {
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
isMinifyEnabled = false
|
||||
// R8 code shrinking + resource shrinking. Critical with
|
||||
// material-icons-extended: it bundles thousands of vector icons, and
|
||||
// R8 strips everything we don't reference (debug builds can't shrink,
|
||||
// so the debug APK stays large — that's expected).
|
||||
isMinifyEnabled = true
|
||||
isShrinkResources = true
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,6 +115,7 @@ dependencies {
|
||||
implementation(libs.androidx.ui.graphics)
|
||||
implementation(libs.androidx.ui.tooling.preview)
|
||||
implementation(libs.androidx.material3)
|
||||
implementation(libs.androidx.material.icons.extended)
|
||||
debugImplementation(libs.androidx.ui.tooling)
|
||||
|
||||
testImplementation(libs.junit)
|
||||
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
# Project-specific ProGuard/R8 rules.
|
||||
#
|
||||
# AGP's default rules plus the consumer rules shipped by AndroidX/Compose cover
|
||||
# this app already (Compose, coroutines, DataStore, our own classes are all
|
||||
# either kept or safely shrunk/renamed). Add app-specific keeps here if release
|
||||
# builds ever misbehave.
|
||||
@@ -1,7 +1,6 @@
|
||||
package ca.ksamad.musicremote.ui
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
@@ -10,8 +9,17 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Pause
|
||||
import androidx.compose.material.icons.filled.PlayArrow
|
||||
import androidx.compose.material.icons.filled.Repeat
|
||||
import androidx.compose.material.icons.filled.Shuffle
|
||||
import androidx.compose.material.icons.filled.SkipNext
|
||||
import androidx.compose.material.icons.filled.SkipPrevious
|
||||
import androidx.compose.material.icons.filled.VolumeUp
|
||||
import androidx.compose.material3.FilledIconButton
|
||||
import androidx.compose.material3.FilterChip
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Slider
|
||||
@@ -29,7 +37,6 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import ca.ksamad.musicremote.mpd.model.MpdStatus
|
||||
import ca.ksamad.musicremote.mpd.model.PlayerState
|
||||
@@ -91,13 +98,25 @@ fun NowPlayingScreen(vm: PlayerViewModel) {
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
IconButton(onClick = vm::previous, modifier = Modifier.size(56.dp)) {
|
||||
GlyphText("⏮", 28.sp)
|
||||
Icon(
|
||||
Icons.Filled.SkipPrevious,
|
||||
contentDescription = "Previous",
|
||||
modifier = Modifier.size(36.dp),
|
||||
)
|
||||
}
|
||||
FilledIconButton(onClick = vm::togglePlayPause, modifier = Modifier.size(72.dp)) {
|
||||
GlyphText(if (playing) "⏸" else "▶", 32.sp)
|
||||
Icon(
|
||||
if (playing) Icons.Filled.Pause else Icons.Filled.PlayArrow,
|
||||
contentDescription = if (playing) "Pause" else "Play",
|
||||
modifier = Modifier.size(40.dp),
|
||||
)
|
||||
}
|
||||
IconButton(onClick = vm::next, modifier = Modifier.size(56.dp)) {
|
||||
GlyphText("⏭", 28.sp)
|
||||
Icon(
|
||||
Icons.Filled.SkipNext,
|
||||
contentDescription = "Next",
|
||||
modifier = Modifier.size(36.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,11 +132,25 @@ fun NowPlayingScreen(vm: PlayerViewModel) {
|
||||
selected = status?.repeat == true,
|
||||
onClick = { vm.setRepeat(status?.repeat != true) },
|
||||
label = { Text("Repeat") },
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
Icons.Filled.Repeat,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(18.dp),
|
||||
)
|
||||
},
|
||||
)
|
||||
FilterChip(
|
||||
selected = status?.random == true,
|
||||
onClick = { vm.setRandom(status?.random != true) },
|
||||
label = { Text("Shuffle") },
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
Icons.Filled.Shuffle,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(18.dp),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -181,7 +214,11 @@ private fun VolumeControl(volume: Int?, onSetVolume: (Int) -> Unit) {
|
||||
val shown = dragValue ?: (volume ?: 0).toFloat()
|
||||
|
||||
Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
|
||||
GlyphText("🔈", 18.sp)
|
||||
Icon(
|
||||
Icons.Filled.VolumeUp,
|
||||
contentDescription = "Volume",
|
||||
modifier = Modifier.size(24.dp),
|
||||
)
|
||||
Slider(
|
||||
value = shown,
|
||||
onValueChange = { dragValue = it },
|
||||
@@ -204,14 +241,6 @@ private fun VolumeControl(volume: Int?, onSetVolume: (Int) -> Unit) {
|
||||
}
|
||||
}
|
||||
|
||||
/** A centered glyph, used in place of vector icons to avoid an extra dependency. */
|
||||
@Composable
|
||||
private fun GlyphText(glyph: String, size: androidx.compose.ui.unit.TextUnit) {
|
||||
Box(contentAlignment = Alignment.Center) {
|
||||
Text(glyph, fontSize = size)
|
||||
}
|
||||
}
|
||||
|
||||
private fun formatTime(seconds: Double): String {
|
||||
val total = seconds.toInt().coerceAtLeast(0)
|
||||
val m = total / 60
|
||||
|
||||
Reference in New Issue
Block a user