Skip to content

Commit

Permalink
Add WaveBorder
Browse files Browse the repository at this point in the history
Add WaveBorder, used to smooth edges where something is displayed over a scrolling list such as the song queue
  • Loading branch information
toasterofbread committed Jul 1, 2023
1 parent 608cf13 commit c655a1e
Show file tree
Hide file tree
Showing 26 changed files with 554 additions and 160 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,22 +66,26 @@ abstract class SettingsItem {
)

@Composable
protected fun ItemTitleText(text: String?, theme: Theme) {
protected fun ItemTitleText(text: String?, theme: Theme, modifier: Modifier = Modifier) {
if (text?.isNotBlank() == true) {
WidthShrinkText(text, style = LocalTextStyle.current.copy(color = theme.on_background))
WidthShrinkText(
text,
modifier,
style = MaterialTheme.typography.titleMedium.copy(color = theme.on_background)
)
}
}

@Composable
protected fun ItemText(text: String?, colour: Color, font_size: TextUnit = TextUnit.Unspecified) {
protected fun ItemText(text: String?, colour: Color) {
if (text?.isNotBlank() == true) {
Text(text, color = colour, fontSize = font_size)
Text(text, color = colour, style = MaterialTheme.typography.bodySmall)
}
}

@Composable
protected fun ItemText(text: String?, theme: Theme, font_size: TextUnit = TextUnit.Unspecified) {
ItemText(text, theme.on_background.setAlpha(0.75f), font_size)
protected fun ItemText(text: String?, theme: Theme) {
ItemText(text, theme.on_background.setAlpha(0.75f))
}
}

Expand Down Expand Up @@ -443,7 +447,7 @@ class SettingsItemSlider(
}
Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(10.dp)) {
if (min_label != null) {
ItemText(min_label, theme, 12.sp)
ItemText(min_label, theme)
}
SliderValueHorizontal(
value = getValue(),
Expand Down Expand Up @@ -513,7 +517,7 @@ class SettingsItemSlider(
valueRange = range
)
if (max_label != null) {
ItemText(max_label, theme, 12.sp)
ItemText(max_label, theme)
}
}
}
Expand Down Expand Up @@ -545,8 +549,8 @@ class SettingsItemMultipleChoice(
) {
Column {
Column(Modifier.fillMaxWidth()) {
ItemTitleText(title, theme)
ItemText(subtitle, theme, 15.sp)
ItemTitleText(title, theme, Modifier.padding(bottom = 7.dp))
ItemText(subtitle, theme)

Spacer(Modifier.height(10.dp))

Expand Down Expand Up @@ -742,7 +746,7 @@ class SettingsItemLargeToggle(
openPage: (Int) -> Unit,
openCustomPage: (SettingsPage) -> Unit
) {
val shape = RoundedCornerShape(20.dp)
val shape = RoundedCornerShape(25.dp)
var loading: Boolean by remember { mutableStateOf(false) }

var showing_dialog: (@Composable (dismiss: () -> Unit, openPage: (Int) -> Unit) -> Unit)? by remember { mutableStateOf(null) }
Expand All @@ -761,7 +765,7 @@ class SettingsItemLargeToggle(
shape
)
.border(2.dp, theme.vibrant_accent, shape)
.padding(horizontal = 10.dp)
.padding(horizontal = 10.dp, vertical = 5.dp)
.fillMaxWidth()
.height(IntrinsicSize.Max),
horizontalArrangement = Arrangement.spacedBy(3.dp), verticalAlignment = Alignment.CenterVertically
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import com.toasterofbread.spmp.platform.PlatformContext
import com.toasterofbread.spmp.platform.ProjectPreferences
import com.toasterofbread.spmp.ui.component.PillMenu
Expand Down Expand Up @@ -85,7 +86,12 @@ class SettingsInterface(
}
}

page.TitleBar(page.id == root_page, Modifier.requiredHeight(30.dp)) { go_back = true }
page.TitleBar(
page.id == root_page,
Modifier.zIndex(10f)
) {
go_back = true
}

Box(
contentAlignment = Alignment.TopCenter
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,57 @@
package com.toasterofbread.composesettings.ui

import androidx.compose.animation.Crossfade
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.Icon
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.ClipOp
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.drawscope.clipPath
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.toasterofbread.settings.model.SettingsGroup
import com.toasterofbread.settings.model.SettingsItem
import com.toasterofbread.spmp.platform.composable.BackHandler
import com.toasterofbread.spmp.ui.component.WaveBorder
import com.toasterofbread.spmp.ui.theme.Theme
import com.toasterofbread.utils.composable.WidthShrinkText
import kotlin.math.ceil

abstract class SettingsPage(
private val getTitle: (() -> String?)? = null,
private val getIcon: (@Composable () -> ImageVector?)? = null
) {
abstract class SettingsPage {
var id: Int? = null
internal set
internal lateinit var settings_interface: SettingsInterface

open val disable_padding: Boolean = false
open val scrolling: Boolean = true

open val title: String? = null
open val icon: ImageVector?
@Composable
get() = null

@Composable
fun Page(content_padding: PaddingValues, openPage: (Int) -> Unit, openCustomPage: (SettingsPage) -> Unit, goBack: () -> Unit) {
PageView(content_padding, openPage, openCustomPage, goBack)
Expand All @@ -37,27 +62,33 @@ abstract class SettingsPage(

@Composable
fun TitleBar(is_root: Boolean, modifier: Modifier = Modifier, goBack: () -> Unit) {
Crossfade(getTitle?.invoke()) { title ->
Row(modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) {
val icon = getIcon?.invoke()
if (icon != null) {
Icon(icon, null)
}
Crossfade(title, modifier) { title ->
Column(Modifier.fillMaxWidth()) {
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) {
icon?.also {
Icon(it, null)
}

if (title != null) {
WidthShrinkText(
title,
Modifier.padding(horizontal = 30.dp),
style = MaterialTheme.typography.headlineMedium.copy(
color = settings_interface.theme.on_background,
fontWeight = FontWeight.Light
if (title != null) {
WidthShrinkText(
title,
Modifier.padding(horizontal = 30.dp),
style = MaterialTheme.typography.headlineMedium.copy(
color = settings_interface.theme.on_background,
fontWeight = FontWeight.Light,
textAlign = TextAlign.Center
)
)
)
}
}

if (icon != null) {
Spacer(Modifier.width(24.dp))
if (icon != null) {
Spacer(Modifier.width(24.dp))
}
}

WaveBorder(
Modifier.requiredWidth(SpMp.context.getScreenWidth())
)
}
}
}
Expand All @@ -72,11 +103,17 @@ abstract class SettingsPage(
private const val SETTINGS_PAGE_WITH_ITEMS_SPACING = 20f

class SettingsPageWithItems(
getTitle: () -> String?,
val getTitle: () -> String?,
val getItems: () -> List<SettingsItem>,
val modifier: Modifier = Modifier,
getIcon: (@Composable () -> ImageVector?)? = null
): SettingsPage(getTitle, getIcon) {
val getIcon: (@Composable () -> ImageVector?)? = null
): SettingsPage() {

override val title: String?
get() = getTitle()
override val icon: ImageVector?
@Composable
get() = getIcon?.invoke()

@Composable
override fun PageView(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,13 @@ class SettingsItemThemeSelector(
) {
Column {
Row(verticalAlignment = Alignment.CenterVertically) {
ItemTitleText(title, theme)
Spacer(Modifier
.fillMaxWidth()
.weight(1f))
ItemTitleText(
title,
theme,
Modifier
.fillMaxWidth()
.weight(1f)
)

Text("${state.value + 1} / ${getThemeCount()}")

Expand Down Expand Up @@ -116,15 +119,15 @@ class SettingsItemThemeSelector(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(10.dp)
) {
Box(Modifier
.border(2.dp, theme_data.accent, CircleShape)
.fillMaxHeight()
.weight(1f)
.padding(start = 15.dp),
contentAlignment = Alignment.CenterStart
) {
WidthShrinkText(theme_data.name)
}
WidthShrinkText(
theme_data.name,
Modifier
.border(2.dp, theme_data.accent, CircleShape)
.fillMaxHeight()
.weight(1f)
.padding(start = 15.dp),
alignment = Alignment.CenterStart
)

IconButton(
{
Expand Down Expand Up @@ -160,7 +163,9 @@ private fun getEditPage(
theme: ThemeData,
onEditCompleted: (theme_data: ThemeData) -> Unit
): SettingsPage {
return object : SettingsPage({ editor_title }) {
return object : SettingsPage() {
override val title: String? = editor_title

private var reset by mutableStateOf(false)
private var close by mutableStateOf(false)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,9 @@ class PlayerService : MediaPlayerService() {
writer.newLine()
}

SpMp.Log.info("savePersistentQueue saved $song_count songs")
if (song_count > 0) {
SpMp.Log.info("savePersistentQueue saved $song_count songs")
}

writer.close()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ enum class MusicTopBarMode {
val default: MusicTopBarMode get() = LYRICS
}
}
enum class NowPlayingQueueWaveBorderMode {
TIME, TIME_SYNC, SCROLL, NONE, LINE
}

enum class Settings {
// Language
Expand Down Expand Up @@ -118,6 +121,7 @@ enum class Settings {

// Now playing queue
KEY_NP_QUEUE_RADIO_INFO_POSITION, // TODO prefs item
KEY_NP_QUEUE_WAVE_BORDER_MODE,

// Server
KEY_SPMS_PORT,
Expand Down Expand Up @@ -280,6 +284,7 @@ enum class Settings {
KEY_FEED_SHOW_CHARTS_ROW -> true

KEY_NP_QUEUE_RADIO_INFO_POSITION -> NowPlayingQueueRadioInfoPosition.TOP_BAR.ordinal
KEY_NP_QUEUE_WAVE_BORDER_MODE -> NowPlayingQueueWaveBorderMode.TIME.ordinal

KEY_YTM_AUTH -> {
with(ProjectBuildConfig) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ private fun TitleBar(

@Composable
fun LazyMediaItemLayoutColumn(
layoutsProvider: () -> List<MediaItemLayout>,
getLayouts: () -> List<MediaItemLayout>,
modifier: Modifier = Modifier,
layout_modifier: Modifier = Modifier,
padding: PaddingValues = PaddingValues(0.dp),
Expand All @@ -349,7 +349,7 @@ fun LazyMediaItemLayoutColumn(
multiselect_context: MediaItemMultiSelectContext? = null,
getType: ((MediaItemLayout) -> MediaItemLayout.Type)? = null
) {
val layouts = layoutsProvider()
val layouts = getLayouts()
require(getType != null || layouts.all { it.type != null })

LazyColumn(
Expand Down
Loading

0 comments on commit c655a1e

Please sign in to comment.