@@ -4,6 +4,7 @@ import android.graphics.Bitmap
44import android.graphics.drawable.BitmapDrawable
55import android.os.Build
66import android.util.Log
7+ import androidx.compose.animation.Crossfade
78import androidx.compose.animation.animateColorAsState
89import androidx.compose.animation.core.FastOutSlowInEasing
910import androidx.compose.animation.core.tween
@@ -40,6 +41,7 @@ import androidx.compose.ui.draw.clip
4041import androidx.compose.ui.draw.shadow
4142import androidx.compose.ui.graphics.Color
4243import androidx.compose.ui.layout.ContentScale
44+ import androidx.compose.ui.platform.LocalConfiguration
4345import androidx.compose.ui.platform.LocalContext
4446import androidx.compose.ui.res.painterResource
4547import 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
6669fun 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