Skip to content

Commit dee671b

Browse files
committed
Fixed landscape now-playing ui
1 parent 2412773 commit dee671b

File tree

5 files changed

+202
-109
lines changed

5 files changed

+202
-109
lines changed

app/src/main/java/com/craftworks/music/MainActivity.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,10 +318,10 @@ fun AnimatedBottomNavBar(
318318
)
319319
}
320320
NavigationRailItem(
321-
selected = Screen.NowPlaying_TV.route == backStackEntry.value?.destination?.route,
321+
selected = Screen.NowPlayingLandscape.route == backStackEntry.value?.destination?.route,
322322
onClick = {
323-
if (Screen.NowPlaying_TV.route == backStackEntry.value?.destination?.route) return@NavigationRailItem
324-
navController.navigate(Screen.NowPlaying_TV.route) {
323+
if (Screen.NowPlayingLandscape.route == backStackEntry.value?.destination?.route) return@NavigationRailItem
324+
navController.navigate(Screen.NowPlayingLandscape.route) {
325325
launchSingleTop = true
326326
restoreState = true
327327
popUpTo(navController.graph.findStartDestination().id) {

app/src/main/java/com/craftworks/music/NavGraph.kt

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -152,14 +152,13 @@ fun SetupNavGraph(
152152
S_PlaybackScreen(navController)
153153
}
154154

155-
composable(route = Screen.NowPlaying_TV.route){
156-
NowPlayingContent(
157-
LocalContext.current,
158-
//rememberBottomSheetScaffoldState(),
159-
//snackbarHostState = null,
160-
navController,
161-
mediaController
162-
)
155+
composable(route = Screen.NowPlayingLandscape.route){
156+
if ((LocalConfiguration.current.uiMode and Configuration.UI_MODE_TYPE_MASK == Configuration.UI_MODE_TYPE_TELEVISION) ||
157+
LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE) {
158+
NowPlayingContent(
159+
LocalContext.current, navController, mediaController
160+
)
161+
}
163162
}
164163
}
165164
}

app/src/main/java/com/craftworks/music/data/Screen.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ sealed class Screen(val route: String) {
55
data object Song : Screen("songs_screen")
66
data object Radio : Screen("radio_screen")
77

8-
data object NowPlaying_TV : Screen("playing_tv_screen")
8+
data object NowPlayingLandscape : Screen("playing_tv_screen")
99

1010
//Albums
1111
data object Albums : Screen("album_screen")

app/src/main/java/com/craftworks/music/ui/elements/BottomSpacer.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ fun bottomSpacerHeightDp(): Dp {
4040
return if (SongHelper.currentSong.title == "" &&
4141
SongHelper.currentSong.duration == 0 &&
4242
SongHelper.currentSong.imageUrl == "" ||
43-
LocalConfiguration.current.uiMode and Configuration.UI_MODE_TYPE_MASK == Configuration.UI_MODE_TYPE_TELEVISION) {
43+
LocalConfiguration.current.uiMode and Configuration.UI_MODE_TYPE_MASK == Configuration.UI_MODE_TYPE_TELEVISION ||
44+
LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE) {
4445
0.dp
4546
}
4647
else {

app/src/main/java/com/craftworks/music/ui/playing/NowPlayingLandscape.kt

Lines changed: 189 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.graphics.Bitmap
44
import android.graphics.drawable.BitmapDrawable
55
import android.os.Build
66
import android.util.Log
7+
import androidx.compose.animation.Crossfade
78
import androidx.compose.animation.animateColorAsState
89
import androidx.compose.animation.core.FastOutSlowInEasing
910
import androidx.compose.animation.core.tween
@@ -40,6 +41,7 @@ import androidx.compose.ui.draw.clip
4041
import androidx.compose.ui.draw.shadow
4142
import androidx.compose.ui.graphics.Color
4243
import androidx.compose.ui.layout.ContentScale
44+
import androidx.compose.ui.platform.LocalConfiguration
4345
import androidx.compose.ui.platform.LocalContext
4446
import androidx.compose.ui.res.painterResource
4547
import androidx.compose.ui.text.font.FontWeight
@@ -62,6 +64,7 @@ import com.gigamole.composefadingedges.marqueeHorizontalFadingEdges
6264

6365
@Preview(device = "spec:id=reference_tablet,shape=Normal,width=1280,height=800,unit=dp,dpi=240", showBackground = true, showSystemUi = true)
6466
@Preview(device = "id:tv_1080p", showBackground = true, showSystemUi = true)
67+
@Preview(device = "spec:parent=pixel_6,orientation=landscape", showBackground = true, showSystemUi = true)
6568
@Composable
6669
fun NowPlayingLandscape(
6770
mediaController: MediaController? = null,
@@ -93,111 +96,114 @@ fun NowPlayingLandscape(
9396
Row (
9497
Modifier.padding(start = 80.dp)
9598
) {
99+
96100
Column(Modifier.weight(1f).widthIn(min = 512.dp)) {
97101
// Top padding (for mini-player)
98102
Spacer(Modifier.height(24.dp))
99103

100-
// Album Art + Info
101-
Column(
102-
Modifier.focusable(false),
103-
horizontalAlignment = Alignment.CenterHorizontally
104-
) {
105-
Log.d("RECOMPOSITION", "Album cover or lyrics")
106-
107-
/* Album Cover + Lyrics */
108-
AsyncImage(
109-
model = ImageRequest.Builder(LocalContext.current)
110-
.data(SongHelper.currentSong.imageUrl)
111-
.allowHardware(false)
112-
.size(1024)
113-
.crossfade(true)
114-
.build(),
115-
contentDescription = "Album Cover Art",
116-
placeholder = painterResource(R.drawable.placeholder),
117-
fallback = painterResource(R.drawable.placeholder),
118-
contentScale = ContentScale.FillWidth,
119-
alignment = Alignment.Center,
120-
modifier = Modifier
121-
.fillMaxHeight(0.6f)
122-
.aspectRatio(1f)
123-
.shadow(4.dp, RoundedCornerShape(24.dp), clip = true)
124-
.background(MaterialTheme.colorScheme.surfaceVariant),
125-
onSuccess = { result ->
126-
// Dark or Light mode for UI elements
127-
val drawable = result.result.drawable
128-
val bitmap = (drawable as? BitmapDrawable)?.bitmap?.copy(Bitmap.Config.ARGB_8888, true)
129-
bitmap?.let {
130-
val scaledBitmap = Bitmap.createScaledBitmap(bitmap, 64, 64, true).copy(
131-
Bitmap.Config.ARGB_8888, true)
132-
133-
// Calculate average luminance
134-
135-
val totalPixels = scaledBitmap.width * scaledBitmap.height
136-
var totalLuminance = 0.0
137-
138-
for (x in 0 until scaledBitmap.width) {
139-
for (y in 0 until scaledBitmap.height) {
140-
val pixel = scaledBitmap.getPixel(x, y)
141-
totalLuminance += pixel.luminance
104+
// Album Art
105+
if (LocalConfiguration.current.screenHeightDp.dp > 512.dp){
106+
Column(
107+
Modifier.focusable(false).fillMaxWidth(),
108+
horizontalAlignment = Alignment.CenterHorizontally
109+
) {
110+
Log.d("RECOMPOSITION", "Album cover or lyrics")
111+
112+
/* Album Cover + Lyrics */
113+
AsyncImage(
114+
model = ImageRequest.Builder(LocalContext.current)
115+
.data(SongHelper.currentSong.imageUrl)
116+
.allowHardware(false)
117+
.size(1024)
118+
.crossfade(true)
119+
.build(),
120+
contentDescription = "Album Cover Art",
121+
placeholder = painterResource(R.drawable.placeholder),
122+
fallback = painterResource(R.drawable.placeholder),
123+
contentScale = ContentScale.FillWidth,
124+
alignment = Alignment.Center,
125+
modifier = Modifier
126+
.fillMaxHeight(0.6f)
127+
.aspectRatio(1f)
128+
.shadow(4.dp, RoundedCornerShape(24.dp), clip = true)
129+
.background(MaterialTheme.colorScheme.surfaceVariant),
130+
onSuccess = { result ->
131+
// Dark or Light mode for UI elements
132+
val drawable = result.result.drawable
133+
val bitmap = (drawable as? BitmapDrawable)?.bitmap?.copy(Bitmap.Config.ARGB_8888, true)
134+
bitmap?.let {
135+
val scaledBitmap = Bitmap.createScaledBitmap(bitmap, 64, 64, true).copy(
136+
Bitmap.Config.ARGB_8888, true)
137+
138+
// Calculate average luminance
139+
140+
val totalPixels = scaledBitmap.width * scaledBitmap.height
141+
var totalLuminance = 0.0
142+
143+
for (x in 0 until scaledBitmap.width) {
144+
for (y in 0 until scaledBitmap.height) {
145+
val pixel = scaledBitmap.getPixel(x, y)
146+
totalLuminance += pixel.luminance
147+
}
142148
}
143-
}
144149

145-
val averageLuminance = totalLuminance / totalPixels
146-
Log.d("LUMINANCE", "average luminance: $averageLuminance")
150+
val averageLuminance = totalLuminance / totalPixels
151+
Log.d("LUMINANCE", "average luminance: $averageLuminance")
147152

148-
val palette = Palette.from(scaledBitmap).generate().vibrantSwatch?.rgb
149-
backgroundDarkMode.value = (palette?.luminance ?: 0.5f) + (averageLuminance.toFloat()) / 2 < 0.5f
153+
val palette = Palette.from(scaledBitmap).generate().vibrantSwatch?.rgb
154+
backgroundDarkMode.value = (palette?.luminance ?: 0.5f) + (averageLuminance.toFloat()) / 2 < 0.5f
150155

151-
scaledBitmap.recycle()
156+
scaledBitmap.recycle()
157+
}
152158
}
153-
}
154-
)
159+
)
160+
}
161+
}
155162

156-
/* Song Title + Artist*/
157-
Column(
158-
modifier = Modifier
159-
.fillMaxWidth()
160-
.padding(top = 6.dp)
161-
.padding(horizontal = 32.dp),
162-
horizontalAlignment = Alignment.Start,
163-
verticalArrangement = Arrangement.Top
164-
) {
165-
Log.d("RECOMPOSITION", "Titles and artist")
166-
SongHelper.currentSong.title.let {
163+
/* Song Title + Artist*/
164+
Column(
165+
modifier = Modifier
166+
.fillMaxWidth()
167+
.padding(top = 6.dp)
168+
.padding(horizontal = 32.dp),
169+
horizontalAlignment = Alignment.Start,
170+
verticalArrangement = Arrangement.Top
171+
) {
172+
Log.d("RECOMPOSITION", "Titles and artist")
173+
SongHelper.currentSong.title.let {
174+
Text(
175+
text = it,
176+
fontSize = MaterialTheme.typography.headlineMedium.fontSize,
177+
fontWeight = FontWeight.SemiBold,
178+
color = iconTextColor,
179+
maxLines = 1, overflow = TextOverflow.Visible,
180+
softWrap = false,
181+
textAlign = TextAlign.Start,
182+
modifier = Modifier
183+
.fillMaxWidth()
184+
.marqueeHorizontalFadingEdges(marqueeProvider = { Modifier.basicMarquee() })
185+
)
186+
}
187+
188+
if (SettingsManager(LocalContext.current).showMoreInfoFlow.collectAsState(true).value){
189+
SongHelper.currentSong.artist.let { artistName ->
167190
Text(
168-
text = it,
169-
fontSize = MaterialTheme.typography.headlineMedium.fontSize,
170-
fontWeight = FontWeight.SemiBold,
191+
text = artistName + if (SongHelper.currentSong.year != 0) "" + SongHelper.currentSong.year else "",
192+
fontSize = MaterialTheme.typography.titleMedium.fontSize,
193+
fontWeight = FontWeight.Normal,
171194
color = iconTextColor,
172-
maxLines = 1, overflow = TextOverflow.Visible,
195+
maxLines = 1,
173196
softWrap = false,
174197
textAlign = TextAlign.Start,
198+
overflow = TextOverflow.Ellipsis,
175199
modifier = Modifier
176-
.fillMaxWidth()
200+
.clip(RoundedCornerShape(12.dp))
177201
.marqueeHorizontalFadingEdges(marqueeProvider = { Modifier.basicMarquee() })
178202
)
179203
}
180-
181-
if (SettingsManager(LocalContext.current).showMoreInfoFlow.collectAsState(true).value){
182-
SongHelper.currentSong.artist.let { artistName ->
183-
Text(
184-
text = artistName + if (SongHelper.currentSong.year != 0) "" + SongHelper.currentSong.year else "",
185-
fontSize = MaterialTheme.typography.titleMedium.fontSize,
186-
fontWeight = FontWeight.Normal,
187-
color = iconTextColor,
188-
maxLines = 1,
189-
softWrap = false,
190-
textAlign = TextAlign.Start,
191-
overflow = TextOverflow.Ellipsis,
192-
modifier = Modifier
193-
.clip(RoundedCornerShape(12.dp))
194-
.marqueeHorizontalFadingEdges(marqueeProvider = { Modifier.basicMarquee() })
195-
)
196-
}
197-
}
198-
199-
Spacer(Modifier.height(8.dp))
200204
}
205+
206+
Spacer(Modifier.height(8.dp))
201207
}
202208

203209
//Spacer(Modifier.height(24.dp))
@@ -228,20 +234,107 @@ fun NowPlayingLandscape(
228234

229235
RepeatButton(iconTextColor, mediaController, 32.dp)
230236
}
237+
if (LocalConfiguration.current.screenHeightDp.dp < 512.dp){
238+
Row(
239+
modifier = Modifier
240+
.wrapContentHeight()
241+
.fillMaxWidth()
242+
.padding(horizontal = 12.dp, vertical = 6.dp)
243+
.selectableGroup(),
244+
horizontalArrangement = Arrangement.Center,
245+
verticalAlignment = Alignment.CenterVertically
246+
) {
247+
LyricsButton(iconTextColor, 48.dp)
248+
}
249+
}
231250
}
232251

233252
val lyrics by LyricsManager.Lyrics.collectAsState()
234253

235-
if (SongHelper.currentSong.isRadio == false &&
236-
/*!*/(lyrics[0].content == "No Lyrics Found" && lyrics.size == 1)
237-
) {
238-
Box(Modifier.weight(0.75f).fillMaxHeight()){
239-
LyricsView(
240-
iconTextColor,
241-
true,
242-
mediaController,
243-
PaddingValues(horizontal = 32.dp, vertical = 16.dp)
244-
)
254+
if (LocalConfiguration.current.screenHeightDp.dp < 512.dp){
255+
Crossfade(
256+
lyricsOpen,
257+
label = ""
258+
) {
259+
if (it){
260+
Box(Modifier
261+
.padding(32.dp)
262+
.fillMaxHeight()
263+
.aspectRatio(1f)
264+
){
265+
LyricsView(
266+
iconTextColor,
267+
true,
268+
mediaController,
269+
PaddingValues(horizontal = 32.dp, vertical = 16.dp)
270+
)
271+
}
272+
}
273+
else {
274+
/* Album Cover + Lyrics */
275+
AsyncImage(
276+
model = ImageRequest.Builder(LocalContext.current)
277+
.data(SongHelper.currentSong.imageUrl)
278+
.allowHardware(false)
279+
.size(1024)
280+
.crossfade(true)
281+
.build(),
282+
contentDescription = "Album Cover Art",
283+
placeholder = painterResource(R.drawable.placeholder),
284+
fallback = painterResource(R.drawable.placeholder),
285+
contentScale = ContentScale.FillWidth,
286+
alignment = Alignment.Center,
287+
modifier = Modifier
288+
.padding(32.dp)
289+
.fillMaxHeight()
290+
.aspectRatio(1f)
291+
.shadow(4.dp, RoundedCornerShape(24.dp), clip = true)
292+
.background(MaterialTheme.colorScheme.surfaceVariant),
293+
onSuccess = { result ->
294+
// Dark or Light mode for UI elements
295+
val drawable = result.result.drawable
296+
val bitmap = (drawable as? BitmapDrawable)?.bitmap?.copy(Bitmap.Config.ARGB_8888, true)
297+
bitmap?.let {
298+
val scaledBitmap = Bitmap.createScaledBitmap(bitmap, 64, 64, true).copy(
299+
Bitmap.Config.ARGB_8888, true)
300+
301+
// Calculate average luminance
302+
303+
val totalPixels = scaledBitmap.width * scaledBitmap.height
304+
var totalLuminance = 0.0
305+
306+
for (x in 0 until scaledBitmap.width) {
307+
for (y in 0 until scaledBitmap.height) {
308+
val pixel = scaledBitmap.getPixel(x, y)
309+
totalLuminance += pixel.luminance
310+
}
311+
}
312+
313+
val averageLuminance = totalLuminance / totalPixels
314+
Log.d("LUMINANCE", "average luminance: $averageLuminance")
315+
316+
val palette = Palette.from(scaledBitmap).generate().vibrantSwatch?.rgb
317+
backgroundDarkMode.value = (palette?.luminance ?: 0.5f) + (averageLuminance.toFloat()) / 2 < 0.5f
318+
319+
scaledBitmap.recycle()
320+
}
321+
}
322+
)
323+
}
324+
}
325+
}
326+
else {
327+
if (SongHelper.currentSong.isRadio == false &&
328+
!(lyrics[0].content == "No Lyrics Found" && lyrics.size == 1)
329+
) {
330+
Box(Modifier.weight(0.75f).fillMaxHeight()){
331+
LyricsView(
332+
iconTextColor,
333+
true,
334+
mediaController,
335+
PaddingValues(horizontal = 32.dp, vertical = 16.dp)
336+
)
337+
}
245338
}
246339
}
247340
}

0 commit comments

Comments
 (0)