Skip to content

Commit

Permalink
Add desktop artist page, fix lowres artist image
Browse files Browse the repository at this point in the history
  • Loading branch information
toasterofbread committed Dec 7, 2023
1 parent b65cb85 commit a54c8b5
Show file tree
Hide file tree
Showing 33 changed files with 1,333 additions and 500 deletions.
2 changes: 1 addition & 1 deletion ComposeKit
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.toasterofbread.spmp.platform

import android.content.res.Configuration.ORIENTATION_PORTRAIT
import com.toasterofbread.spmp.ui.layout.apppage.mainpage.PlayerState

internal actual fun PlayerState.isPortrait(min_portrait_ratio: Float?): Boolean =
context.ctx.resources.configuration.orientation == ORIENTATION_PORTRAIT
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ fun <T, Q: Query<*>> Q.observeAsState(
mapValue: (Q) -> T = { it as T },
onExternalChange: (suspend (T) -> Unit)?
): MutableState<T> {
val state = remember(this) { mutableStateOf(mapValue(this)) }
var current_value by remember(state) { mutableStateOf(state.value) }
val state: MutableState<T> = remember { mutableStateOf(mapValue(this)) }
var current_value: T by remember(state) { mutableStateOf(state.value) }

DisposableEffect(state) {
val listener = Query.Listener {
val listener: Query.Listener = Query.Listener {
current_value = mapValue(this@observeAsState)
state.value = current_value
}
Expand All @@ -38,6 +38,7 @@ fun <T, Q: Query<*>> Q.observeAsState(
try {
onExternalChange(current_value)
} catch (e: Throwable) {
e.printStackTrace()
throw RuntimeException("onExternalChange failed for observed query (${this@observeAsState}, $current_value)", e)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,14 @@ data class MediaItemLayout(
square_item_max_text_rows: Int? = null,
show_download_indicators: Boolean = true,
grid_rows: Pair<Int, Int>? = null,
content_padding: PaddingValues = PaddingValues()
content_padding: PaddingValues = PaddingValues(),
itemSizeProvider: @Composable () -> DpSize = { getDefaultMediaItemPreviewSize() }
) {
when (this) {
// Why
GRID -> MediaItemGrid(layout, modifier, title_modifier, grid_rows, multiselect_context = multiselect_context, apply_filter = apply_filter, square_item_max_text_rows = square_item_max_text_rows, show_download_indicators = show_download_indicators, content_padding = content_padding)
GRID_ALT -> MediaItemGrid(layout, modifier, title_modifier, grid_rows, alt_style = true, multiselect_context = multiselect_context, apply_filter = apply_filter, square_item_max_text_rows = square_item_max_text_rows, show_download_indicators = show_download_indicators, content_padding = content_padding)
ROW -> MediaItemGrid(layout, modifier, title_modifier, Pair(1, 1), multiselect_context = multiselect_context, apply_filter = apply_filter, square_item_max_text_rows = square_item_max_text_rows, show_download_indicators = show_download_indicators, content_padding = content_padding)
GRID -> MediaItemGrid(layout, modifier, title_modifier, grid_rows, multiselect_context = multiselect_context, apply_filter = apply_filter, square_item_max_text_rows = square_item_max_text_rows, show_download_indicators = show_download_indicators, content_padding = content_padding, itemSizeProvider = itemSizeProvider)
GRID_ALT -> MediaItemGrid(layout, modifier, title_modifier, grid_rows, alt_style = true, multiselect_context = multiselect_context, apply_filter = apply_filter, square_item_max_text_rows = square_item_max_text_rows, show_download_indicators = show_download_indicators, content_padding = content_padding, itemSizeProvider = itemSizeProvider)
ROW -> MediaItemGrid(layout, modifier, title_modifier, Pair(1, 1), multiselect_context = multiselect_context, apply_filter = apply_filter, square_item_max_text_rows = square_item_max_text_rows, show_download_indicators = show_download_indicators, content_padding = content_padding, itemSizeProvider = itemSizeProvider)
LIST -> MediaItemList(layout, modifier, title_modifier, false, multiselect_context = multiselect_context, apply_filter = apply_filter, show_download_indicators = show_download_indicators, content_padding = content_padding)
NUMBERED_LIST -> MediaItemList(layout, modifier, title_modifier, true, multiselect_context = multiselect_context, apply_filter = apply_filter, show_download_indicators = show_download_indicators, content_padding = content_padding)
CARD -> com.toasterofbread.spmp.ui.component.mediaitemlayout.MediaItemCard(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.toasterofbread.spmp.model.settings.category.MiscSettings
import com.toasterofbread.spmp.platform.AppContext
import com.toasterofbread.spmp.platform.toByteArray
import com.toasterofbread.spmp.platform.toImageBitmap
import com.toasterofbread.spmp.ui.layout.apppage.mainpage.PlayerState
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
Expand Down Expand Up @@ -144,7 +145,7 @@ internal object MediaItemThumbnailLoader: ListenerLoader<MediaItemThumbnailLoade

@Composable
fun rememberItemState(item: MediaItem): ItemState {
val player = LocalPlayerState.current
val player: PlayerState = LocalPlayerState.current
val state = remember(item) {
object : ItemState {
override val loaded_images: MutableMap<MediaItemThumbnailProvider.Quality, WeakReference<ImageBitmap>> = mutableStateMapOf()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package com.toasterofbread.spmp.platform
import com.toasterofbread.composekit.platform.Platform
import com.toasterofbread.spmp.ui.layout.apppage.mainpage.PlayerState

private const val MIN_PORTRAIT_RATIO: Float = 1f / 2f

enum class FormFactor {
PORTRAIT,
LANDSCAPE,
Expand All @@ -13,17 +11,18 @@ enum class FormFactor {
val is_large: Boolean get() = this != PORTRAIT
}

val PlayerState.form_factor: FormFactor
get() {
if (isPortrait()) {
return FormFactor.PORTRAIT
}
fun PlayerState.getFormFactor(min_portrait_ratio: Float? = null): FormFactor {
if (isPortrait(min_portrait_ratio)) {
return FormFactor.PORTRAIT
}

return when (Platform.current) {
Platform.ANDROID -> FormFactor.LANDSCAPE
Platform.DESKTOP -> FormFactor.DESKTOP
}
return when (Platform.current) {
Platform.ANDROID -> FormFactor.LANDSCAPE
Platform.DESKTOP -> FormFactor.DESKTOP
}
}

val PlayerState.form_factor: FormFactor
get() = getFormFactor()

private fun PlayerState.isPortrait(): Boolean =
(screen_size.width / screen_size.height) <= MIN_PORTRAIT_RATIO
internal expect fun PlayerState.isPortrait(min_portrait_ratio: Float? = null): Boolean
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class YoutubeUILocalisation(languages: UILanguages) {
ARTIST_ROW_SINGLES,
ARTIST_ROW_SONGS,
ARTIST_ROW_VIDEOS,
ARTIST_ROW_ARTISTS,
ARTIST_ROW_OTHER
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,11 @@ fun getYoutubeArtistPageLocalisations(languages: UILanguages): YoutubeUILocalisa
)
add(
en to "Fans might also like",
en to "Similar artists",
ja to "おすすめのアーティスト" ,
es to "A los fans también podrían gustarles"
ja to "似てるかも",
es to "A los fans también podrían gustarles",
id = YoutubeUILocalisation.StringID.ARTIST_ROW_ARTISTS
)
add(
en to "Featured on",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ fun LikeDislikeButton(
)
}
},
modifier.bounceOnClick().appHover(true),
modifier = modifier.bounceOnClick().appHover(true),
enabled = getEnabled?.invoke() != false,
apply_minimum_size = false
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ class MusicTopBar(val player: PlayerState) {
can_show_key: SettingsKey,
modifier: Modifier = Modifier,
padding: PaddingValues = PaddingValues(),
getBottomBorderOffset: ((height: Int) -> Int)? = null,
getBottomBorderOffset: ((height: Float) -> Float)? = null,
getBottomBorderColour: (() -> Color)? = null
): MusicTopBarState {
val can_show: Boolean by can_show_key.rememberMutableState()
Expand Down Expand Up @@ -212,7 +212,7 @@ class MusicTopBar(val player: PlayerState) {
padding: PaddingValues = PaddingValues(),
alignment: Alignment = Alignment.Center,
innerContent: (@Composable (MusicTopBarMode) -> Unit)? = null,
getBottomBorderOffset: ((height: Int) -> Int)? = null,
getBottomBorderOffset: ((height: Float) -> Float)? = null,
getBottomBorderColour: (() -> Color)? = null,
onClick: (() -> Unit)? = null
): MusicTopBarState {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package com.toasterofbread.spmp.ui.component
import LocalPlayerState
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.material.LocalContentColor
Expand All @@ -13,6 +12,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Matrix
import androidx.compose.ui.graphics.Outline
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.Shape
Expand All @@ -26,11 +26,14 @@ import androidx.compose.ui.unit.dp
import com.toasterofbread.composekit.settings.ui.Theme
import com.toasterofbread.spmp.ui.layout.apppage.mainpage.PlayerState
import kotlin.math.ceil
import kotlin.math.roundToInt

const val WAVE_BORDER_HEIGHT_DP: Float = 20f

class WaveShape(val waves: Int, val offset: Float): Shape {
data class WaveShape(
val waves: Int,
val offset: Float,
val invert: Boolean = false
): Shape {
override fun createOutline(size: Size, layoutDirection: LayoutDirection, density: Density): Outline {
val path: Path = Path()

Expand All @@ -39,6 +42,15 @@ class WaveShape(val waves: Int, val offset: Float): Shape {
wavePath(path, size, 1, waves) { offset }
wavePath(path, size, -1, waves) { offset }

if (invert) {
path.transform(
Matrix().apply {
scale(y = -1f)
translate(y = -size.height)
}
)
}

return Outline.Generic(path)
}
}
Expand All @@ -48,8 +60,9 @@ fun WaveBorder(
modifier: Modifier = Modifier,
getColour: Theme.() -> Color = { background },
height: Dp = WAVE_BORDER_HEIGHT_DP.dp,
getOffset: ((height: Int) -> Int)? = null,
getOffset: ((height: Float) -> Float)? = null,
waves: Int = 3,
invert: Boolean = false,
getWaveOffset: (Density.() -> Float)? = null,
border_thickness: Dp = 0.dp,
border_colour: Color = LocalContentColor.current
Expand All @@ -60,18 +73,23 @@ fun WaveBorder(
val colour: Color = getColour(player.theme)
val offset: Float? = getWaveOffset?.invoke(density)
val shape: WaveShape = remember(waves, offset) {
WaveShape(waves, offset ?: 0f)
WaveShape(waves, offset ?: 0f, invert = invert)
}

Box(modifier.fillMaxWidth().requiredHeight(0.dp)) {
Box(modifier.requiredHeight(0.dp)) {
Box(
Modifier
.fillMaxWidth()
.matchParentSize()
.requiredHeight(height)
.offset(
0.dp,
with(density) {
(getOffset?.invoke(height.toPx().roundToInt())?.toDp() ?: 0.dp) + (height / 2) - 1.toDp() + border_thickness
val user_offset: Dp = getOffset?.invoke(height.toPx())?.toDp()
?: (
if (invert) -height / 2
else height / 2
)
user_offset + border_thickness
}
)
.background(border_colour, shape)
Expand All @@ -88,9 +106,9 @@ inline fun DrawScope.drawWave(
getWaveOffset: () -> Float,
getColour: () -> Color,
) {
val path = Path()
val colour = getColour()
val stroke = Stroke(stroke_width)
val path: Path = Path()
val colour: Color = getColour()
val stroke: Stroke = Stroke(stroke_width)

// Above equilibrium
wavePath(path, wave_size, -1, waves, getWaveOffset)
Expand All @@ -110,14 +128,14 @@ inline fun wavePath(
getOffset: () -> Float
): Path {
val y_offset: Float = size.height / 2
val half_period: Float = (size.width / (waves - 1)) / 2
val half_period: Float = size.width / waves
val offset_px: Float = getOffset().let { offset ->
offset % size.width - (if (offset > 0f) size.width else 0f)
}

path.moveTo(x = -half_period / 2 + offset_px, y = y_offset)
path.moveTo(x = offset_px, y = y_offset)

for (i in 0 until ceil((size.width * 2) / half_period + 1).toInt()) {
for (i in 0 until ceil(size.width / (half_period + 1)).toInt()) {
if ((i % 2 == 0) != (direction == 1)) {
path.relativeMoveTo(half_period, 0f)
continue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,16 +269,6 @@ internal fun DesktopLongPressMenu(
) {
val background_colour = player.theme.accent.blendWith(player.theme.background, 0.1f)

ShapedIconButton(
{ close() },
IconButtonDefaults.iconButtonColors(
containerColor = background_colour,
contentColor = background_colour.getContrasted()
)
) {
Icon(Icons.Default.Close, null)
}

LongPressMenuContent(
data,
shape,
Expand All @@ -297,6 +287,16 @@ internal fun DesktopLongPressMenu(
}
}
)

ShapedIconButton(
{ close() },
IconButtonDefaults.iconButtonColors(
containerColor = background_colour,
contentColor = background_colour.getContrasted()
)
) {
Icon(Icons.Default.Close, null)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp
import com.toasterofbread.composekit.utils.composable.PlatformClickableIconButton
import com.toasterofbread.composekit.utils.composable.WidthShrinkText
import com.toasterofbread.spmp.model.mediaitem.MediaItemHolder
import com.toasterofbread.spmp.model.mediaitem.layout.ViewMore
Expand All @@ -58,7 +59,7 @@ fun TitleBar(
) {
val player: PlayerState = LocalPlayerState.current

AnimatedVisibility(shouldShowTitleBar(title, subtitle, view_more, scrollable_state), modifier) {
AnimatedVisibility(shouldShowTitleBar(title, subtitle, view_more, scrollable_state)) {
val title_string: String? = remember { title?.getString(player.context) }
val subtitle_string: String? = remember { subtitle?.getString(player.context) }

Expand All @@ -69,7 +70,7 @@ fun TitleBar(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(10.dp)
) {
Column(verticalArrangement = Arrangement.Center, modifier = Modifier.weight(1f)) {
Column(verticalArrangement = Arrangement.Center, modifier = modifier.weight(1f)) {
if (subtitle_string != null) {
WidthShrinkText(subtitle_string, style = MaterialTheme.typography.titleSmall.copy(color = player.theme.on_background))
}
Expand Down Expand Up @@ -134,8 +135,8 @@ private fun ScrollableState.ScrollButtons() {
else -> null
}

IconButton(
{
PlatformClickableIconButton(
onClick = {
coroutine_scope.launch {
scrollToNext(-1, density, current_scroll_direction)
}
Expand All @@ -149,8 +150,8 @@ private fun ScrollableState.ScrollButtons() {
)
}

IconButton(
{
PlatformClickableIconButton(
onClick = {
coroutine_scope.launch {
scrollToNext(1, density, current_scroll_direction)
}
Expand Down
Loading

0 comments on commit a54c8b5

Please sign in to comment.