feat: enhance tablet layout with adaptive components and improve UI responsiveness
This commit is contained in:
parent
7f72ba1322
commit
d2c55fe434
16 changed files with 204 additions and 59 deletions
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
import com.android.build.gradle.internal.tasks.CompileArtProfileTask
|
||||
import java.util.Properties
|
||||
|
||||
|
|
@ -201,6 +202,7 @@ dependencies {
|
|||
androidTestImplementation(composeBom)
|
||||
implementation(libs.compose.material3.lib)
|
||||
implementation(libs.compose.material3.sizeclass)
|
||||
implementation(libs.compose.material3.adaptive)
|
||||
implementation(libs.compose.ui)
|
||||
implementation(libs.compose.material.ripple)
|
||||
implementation(libs.compose.material.icons.core)
|
||||
|
|
@ -302,11 +304,9 @@ dependencies {
|
|||
}
|
||||
/**
|
||||
* Task to generate the aboutlibraries.json file
|
||||
* Run with:
|
||||
./gradlew :app:exportLibraryDefinitions --no-daemon --no-configuration-cache --no-build-cache
|
||||
**/
|
||||
aboutLibraries {
|
||||
android.registerAndroidTasks = true
|
||||
collect.configPath = file("../config")
|
||||
export {
|
||||
exportVariant = "fullRelease"
|
||||
prettyPrint = true
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@
|
|||
|
||||
<activity
|
||||
android:name=".ui.MainActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize"
|
||||
android:configChanges="keyboardHidden|screenSize|screenLayout|smallestScreenSize"
|
||||
android:exported="true"
|
||||
android:supportsPictureInPicture="true"
|
||||
android:enableOnBackInvokedCallback="true"
|
||||
|
|
|
|||
|
|
@ -35,14 +35,14 @@ import androidx.compose.foundation.layout.width
|
|||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.rounded.ArrowForwardIos
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
|
||||
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
|
||||
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
|
||||
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
|
|
@ -53,6 +53,7 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.platform.LocalResources
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.TextLinkStyles
|
||||
|
|
@ -66,6 +67,7 @@ import androidx.core.os.LocaleListCompat
|
|||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import androidx.window.core.layout.WindowWidthSizeClass
|
||||
import com.kyant.backdrop.backdrops.layerBackdrop
|
||||
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
|
||||
import com.maxrave.common.FIRST_TIME_MIGRATION
|
||||
|
|
@ -147,7 +149,6 @@ class MainActivity : AppCompatActivity() {
|
|||
viewModel.setIntent(intent)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
|
||||
@ExperimentalMaterial3Api
|
||||
@ExperimentalFoundationApi
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
|
@ -238,7 +239,8 @@ class MainActivity : AppCompatActivity() {
|
|||
viewModel.getLocation()
|
||||
|
||||
setContent {
|
||||
val windowSize = calculateWindowSizeClass(activity = this)
|
||||
val windowSize = currentWindowAdaptiveInfo().windowSizeClass
|
||||
val resources = LocalResources.current
|
||||
val navController = rememberNavController()
|
||||
|
||||
val sleepTimerState by viewModel.sleepTimerState.collectAsStateWithLifecycle()
|
||||
|
|
@ -364,7 +366,8 @@ class MainActivity : AppCompatActivity() {
|
|||
var isScrolledToTop by rememberSaveable {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
val isTablet = windowSize.widthSizeClass == WindowWidthSizeClass.Medium || windowSize.widthSizeClass == WindowWidthSizeClass.Expanded
|
||||
val isTablet = windowSize.windowWidthSizeClass != WindowWidthSizeClass.COMPACT
|
||||
val isTabletLandscape = isTablet && resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||
AppTheme {
|
||||
Scaffold(
|
||||
bottomBar = {
|
||||
|
|
@ -426,7 +429,7 @@ class MainActivity : AppCompatActivity() {
|
|||
Modifier
|
||||
.fillMaxSize()
|
||||
.then(
|
||||
if (isLiquidGlassEnabled == TRUE) {
|
||||
if (isLiquidGlassEnabled == TRUE && !isTablet) {
|
||||
Modifier.layerBackdrop(backdrop)
|
||||
} else {
|
||||
Modifier
|
||||
|
|
@ -446,22 +449,34 @@ class MainActivity : AppCompatActivity() {
|
|||
Box(
|
||||
Modifier.fillMaxSize().weight(1f),
|
||||
) {
|
||||
AppNavigationGraph(
|
||||
innerPadding = innerPadding,
|
||||
navController = navController,
|
||||
hideNavBar = {
|
||||
isNavBarVisible = false
|
||||
},
|
||||
showNavBar = {
|
||||
isNavBarVisible = true
|
||||
},
|
||||
showNowPlayingSheet = {
|
||||
isShowNowPlaylistScreen = true
|
||||
},
|
||||
onScrolling = {
|
||||
isScrolledToTop = it
|
||||
},
|
||||
)
|
||||
Box(
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.then(
|
||||
if (isLiquidGlassEnabled == TRUE && isTablet) {
|
||||
Modifier.layerBackdrop(backdrop)
|
||||
} else {
|
||||
Modifier
|
||||
},
|
||||
),
|
||||
) {
|
||||
AppNavigationGraph(
|
||||
innerPadding = innerPadding,
|
||||
navController = navController,
|
||||
hideNavBar = {
|
||||
isNavBarVisible = false
|
||||
},
|
||||
showNavBar = {
|
||||
isNavBarVisible = true
|
||||
},
|
||||
showNowPlayingSheet = {
|
||||
isShowNowPlaylistScreen = true
|
||||
},
|
||||
onScrolling = {
|
||||
isScrolledToTop = it
|
||||
},
|
||||
)
|
||||
}
|
||||
this@Row.AnimatedVisibility(
|
||||
modifier =
|
||||
Modifier
|
||||
|
|
@ -474,7 +489,7 @@ class MainActivity : AppCompatActivity() {
|
|||
MiniPlayer(
|
||||
Modifier
|
||||
.height(56.dp)
|
||||
.fillMaxWidth(0.5f)
|
||||
.fillMaxWidth(0.8f)
|
||||
.padding(
|
||||
horizontal = 12.dp,
|
||||
).padding(
|
||||
|
|
@ -491,7 +506,7 @@ class MainActivity : AppCompatActivity() {
|
|||
)
|
||||
}
|
||||
}
|
||||
if (isTablet) {
|
||||
if (isTablet && isTabletLandscape) {
|
||||
AnimatedVisibility(
|
||||
isShowNowPlaylistScreen,
|
||||
enter = expandHorizontally() + fadeIn(),
|
||||
|
|
@ -508,6 +523,7 @@ class MainActivity : AppCompatActivity() {
|
|||
navController = navController,
|
||||
sharedViewModel = viewModel,
|
||||
isExpanded = true,
|
||||
dismissIcon = Icons.AutoMirrored.Rounded.ArrowForwardIos,
|
||||
onSwipeEnabledChange = {},
|
||||
) {
|
||||
isShowNowPlaylistScreen = false
|
||||
|
|
@ -519,7 +535,7 @@ class MainActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
if (isShowNowPlaylistScreen && !isTablet) {
|
||||
if (isShowNowPlaylistScreen && !isTabletLandscape) {
|
||||
NowPlayingScreen(
|
||||
navController = navController,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -326,6 +326,7 @@ fun HomeItemContentPlaylist(
|
|||
modifier =
|
||||
Modifier
|
||||
.size(thumbSize)
|
||||
.aspectRatio(1f)
|
||||
.clip(
|
||||
RoundedCornerShape(10.dp),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ fun AppNavigationRail(
|
|||
)
|
||||
}
|
||||
NavigationRail {
|
||||
Spacer(Modifier.height(32.dp))
|
||||
Spacer(Modifier.height(16.dp))
|
||||
Box(Modifier.padding(horizontal = 16.dp)) {
|
||||
Box(
|
||||
Modifier
|
||||
|
|
@ -228,6 +228,6 @@ fun AppNavigationRail(
|
|||
},
|
||||
)
|
||||
}
|
||||
Spacer(Modifier.height(64.dp))
|
||||
Spacer(Modifier.height(32.dp))
|
||||
}
|
||||
}
|
||||
|
|
@ -98,7 +98,7 @@ fun CollapsingToolbarParallaxEffect(
|
|||
TopAppBarDefaults.TopAppBarExpandedHeight + with(density) { WindowInsets.statusBars.getTop(this).toDp() * 2 }
|
||||
|
||||
val scroll: ScrollState = rememberScrollState(0)
|
||||
val headerHeight = getScreenSizeInfo().hDP.dp * 2 / 6
|
||||
val headerHeight = (getScreenSizeInfo().hDP.dp * 2 / 6).coerceAtLeast(200.dp)
|
||||
|
||||
val headerHeightPx = with(density) { headerHeight.toPx() }
|
||||
val toolbarHeightPx = with(density) { toolbarHeight.toPx() }
|
||||
|
|
|
|||
|
|
@ -6,9 +6,11 @@ import androidx.compose.foundation.MarqueeAnimationMode
|
|||
import androidx.compose.foundation.basicMarquee
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.focusable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
|
|
@ -107,7 +109,8 @@ inline fun <reified T> GridLibraryPlaylist(
|
|||
val list = (data as? LocalResource.Success)?.data ?: emptyList()
|
||||
if (data is LocalResource.Success && list.isNotEmpty() || createNewPlaylist != null) {
|
||||
LazyVerticalGrid(
|
||||
columns = GridCells.Adaptive(minSize = 125.dp),
|
||||
columns = GridCells.FixedSize(size = 132.dp),
|
||||
horizontalArrangement = Arrangement.SpaceEvenly,
|
||||
contentPadding = contentPadding,
|
||||
state = state,
|
||||
) {
|
||||
|
|
@ -126,7 +129,8 @@ inline fun <reified T> GridLibraryPlaylist(
|
|||
) {
|
||||
Box(
|
||||
Modifier
|
||||
.size(125.dp)
|
||||
.size(132.dp)
|
||||
.aspectRatio(1f)
|
||||
.clip(RoundedCornerShape(10.dp))
|
||||
.angledGradientBackground(
|
||||
colors =
|
||||
|
|
@ -152,7 +156,7 @@ inline fun <reified T> GridLibraryPlaylist(
|
|||
maxLines = 1,
|
||||
modifier =
|
||||
Modifier
|
||||
.width(125.dp)
|
||||
.width(132.dp)
|
||||
.wrapContentHeight(align = Alignment.CenterVertically)
|
||||
.padding(top = 8.dp)
|
||||
.basicMarquee(
|
||||
|
|
@ -214,7 +218,7 @@ inline fun <reified T> GridLibraryPlaylist(
|
|||
}
|
||||
},
|
||||
data = item,
|
||||
thumbSize = 125.dp,
|
||||
thumbSize = 132.dp,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -499,8 +499,6 @@ fun LiquidGlassAppBottomNavigationBar(
|
|||
.height(56.dp)
|
||||
.layoutId("miniPlayer"),
|
||||
backdrop = backdrop,
|
||||
layer = layer,
|
||||
luminanceAnimation = luminanceAnimation.value,
|
||||
onClick = {
|
||||
onOpenNowPlaying()
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.maxrave.simpmusic.ui.screen
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import androidx.compose.animation.Animatable
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.Crossfade
|
||||
|
|
@ -59,8 +60,9 @@ import androidx.compose.ui.draw.clipToBounds
|
|||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ImageBitmap
|
||||
import androidx.compose.ui.graphics.StrokeCap
|
||||
import androidx.compose.ui.graphics.asAndroidBitmap
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.graphics.layer.GraphicsLayer
|
||||
import androidx.compose.ui.graphics.rememberGraphicsLayer
|
||||
import androidx.compose.ui.input.pointer.PointerInputChange
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
|
|
@ -68,6 +70,7 @@ import androidx.compose.ui.platform.LocalContext
|
|||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.graphics.scale
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import coil3.compose.AsyncImage
|
||||
import coil3.request.ImageRequest
|
||||
|
|
@ -89,30 +92,72 @@ import com.maxrave.simpmusic.ui.theme.transparent
|
|||
import com.maxrave.simpmusic.ui.theme.typo
|
||||
import com.maxrave.simpmusic.viewModel.SharedViewModel
|
||||
import com.maxrave.simpmusic.viewModel.UIEvent
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koin.compose.koinInject
|
||||
import java.nio.IntBuffer
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
private const val TAG = "MiniPlayer"
|
||||
|
||||
@Composable
|
||||
fun MiniPlayer(
|
||||
modifier: Modifier,
|
||||
backdrop: Backdrop,
|
||||
layer: GraphicsLayer? = null,
|
||||
luminanceAnimation: Float? = null,
|
||||
sharedViewModel: SharedViewModel = koinInject(),
|
||||
onClose: () -> Unit,
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
val isLiquidGlassEnabled by sharedViewModel.getEnableLiquidGlass().collectAsStateWithLifecycle(DataStoreManager.FALSE)
|
||||
|
||||
val layer = rememberGraphicsLayer()
|
||||
val luminanceAnimation = remember { Animatable(0f) }
|
||||
|
||||
val textColor by animateColorAsState(
|
||||
targetValue = if (luminanceAnimation != null && luminanceAnimation > 0.6f) Color.Black else Color.White,
|
||||
targetValue = if (luminanceAnimation.value > 0.6f) Color.Black else Color.White,
|
||||
label = "MiniPlayerTextColor",
|
||||
animationSpec = tween(500),
|
||||
)
|
||||
|
||||
LaunchedEffect(layer, isLiquidGlassEnabled) {
|
||||
val buffer = IntBuffer.allocate(25)
|
||||
while (isActive && isLiquidGlassEnabled == DataStoreManager.TRUE) {
|
||||
try {
|
||||
withContext(Dispatchers.Main) {
|
||||
val imageBitmap = layer.toImageBitmap()
|
||||
val thumbnail =
|
||||
imageBitmap
|
||||
.asAndroidBitmap()
|
||||
.scale(5, 5, false)
|
||||
.copy(Bitmap.Config.ARGB_8888, false)
|
||||
buffer.rewind()
|
||||
thumbnail.copyPixelsToBuffer(buffer)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Logger.e(TAG, "Error getting pixels from layer: ${e.localizedMessage}")
|
||||
}
|
||||
val averageLuminance =
|
||||
(0 until 25).sumOf { index ->
|
||||
val color = buffer.get(index)
|
||||
val r = (color shr 16 and 0xFF) / 255f
|
||||
val g = (color shr 8 and 0xFF) / 255f
|
||||
val b = (color and 0xFF) / 255f
|
||||
0.2126 * r + 0.7152 * g + 0.0722 * b
|
||||
} / 25
|
||||
luminanceAnimation.animateTo(
|
||||
averageLuminance.coerceAtMost(0.8).toFloat(),
|
||||
tween(500),
|
||||
)
|
||||
delay(1.seconds)
|
||||
}
|
||||
}
|
||||
|
||||
val (songEntity, setSongEntity) =
|
||||
remember {
|
||||
mutableStateOf<SongEntity?>(null)
|
||||
|
|
@ -220,8 +265,8 @@ fun MiniPlayer(
|
|||
modifier =
|
||||
modifier
|
||||
.then(
|
||||
if (isLiquidGlassEnabled == DataStoreManager.TRUE && layer != null && luminanceAnimation != null) {
|
||||
Modifier.drawBackdropCustomShape(backdrop, layer, luminanceAnimation, RoundedCornerShape(16.dp))
|
||||
if (isLiquidGlassEnabled == DataStoreManager.TRUE) {
|
||||
Modifier.drawBackdropCustomShape(backdrop, layer, luminanceAnimation.value, RoundedCornerShape(16.dp))
|
||||
} else {
|
||||
Modifier
|
||||
},
|
||||
|
|
|
|||
|
|
@ -118,7 +118,6 @@ import com.maxrave.simpmusic.ui.navigation.destination.home.CreditDestination
|
|||
import com.maxrave.simpmusic.ui.navigation.destination.login.LoginDestination
|
||||
import com.maxrave.simpmusic.ui.navigation.destination.login.SpotifyLoginDestination
|
||||
import com.maxrave.simpmusic.ui.theme.DarkColors
|
||||
import com.maxrave.simpmusic.ui.theme.md_theme_dark_outline
|
||||
import com.maxrave.simpmusic.ui.theme.md_theme_dark_primary
|
||||
import com.maxrave.simpmusic.ui.theme.typo
|
||||
import com.maxrave.simpmusic.ui.theme.white
|
||||
|
|
@ -127,9 +126,10 @@ import com.maxrave.simpmusic.viewModel.SettingAlertState
|
|||
import com.maxrave.simpmusic.viewModel.SettingBasicAlertState
|
||||
import com.maxrave.simpmusic.viewModel.SettingsViewModel
|
||||
import com.maxrave.simpmusic.viewModel.SharedViewModel
|
||||
import com.mikepenz.aboutlibraries.entity.Library
|
||||
import com.mikepenz.aboutlibraries.ui.compose.ChipColors
|
||||
import com.mikepenz.aboutlibraries.ui.compose.LibraryDefaults
|
||||
import com.mikepenz.aboutlibraries.ui.compose.android.rememberLibraries
|
||||
import com.mikepenz.aboutlibraries.ui.compose.android.produceLibraries
|
||||
import com.mikepenz.aboutlibraries.ui.compose.m3.LibrariesContainer
|
||||
import com.mikepenz.aboutlibraries.ui.compose.m3.libraryColors
|
||||
import dev.chrisbanes.haze.hazeEffect
|
||||
|
|
@ -137,6 +137,7 @@ import dev.chrisbanes.haze.hazeSource
|
|||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||
import dev.chrisbanes.haze.materials.HazeMaterials
|
||||
import dev.chrisbanes.haze.rememberHazeState
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
|
|
@ -1819,7 +1820,7 @@ fun SettingScreen(
|
|||
}
|
||||
|
||||
if (showThirdPartyLibraries) {
|
||||
val libraries by rememberLibraries(com.maxrave.simpmusic.R.raw.aboutlibraries)
|
||||
val libraries by produceLibraries(com.maxrave.simpmusic.R.raw.aboutlibraries)
|
||||
val lazyListState = rememberLazyListState()
|
||||
val canScrollBackward by remember {
|
||||
derivedStateOf {
|
||||
|
|
@ -1849,17 +1850,25 @@ fun SettingScreen(
|
|||
shape = RectangleShape,
|
||||
) {
|
||||
LibrariesContainer(
|
||||
libraries,
|
||||
libraries?.copy(
|
||||
libraries =
|
||||
libraries
|
||||
?.libraries
|
||||
?.distinctBy {
|
||||
it.name
|
||||
}?.toImmutableList() ?: emptyList<Library>().toImmutableList(),
|
||||
),
|
||||
Modifier.fillMaxSize(),
|
||||
lazyListState = lazyListState,
|
||||
showDescription = true,
|
||||
contentPadding = innerPadding,
|
||||
typography = typo,
|
||||
colors =
|
||||
LibraryDefaults.libraryColors(
|
||||
licenseChipColors =
|
||||
object : ChipColors {
|
||||
override val containerColor: Color
|
||||
get() = md_theme_dark_outline
|
||||
get() = Color.DarkGray
|
||||
override val contentColor: Color
|
||||
get() = Color.White
|
||||
},
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ import androidx.compose.material.icons.outlined.Info
|
|||
import androidx.compose.material.icons.rounded.Add
|
||||
import androidx.compose.material.icons.rounded.Done
|
||||
import androidx.compose.material.icons.rounded.Forward5
|
||||
import androidx.compose.material.icons.rounded.KeyboardArrowDown
|
||||
import androidx.compose.material.icons.rounded.PauseCircle
|
||||
import androidx.compose.material.icons.rounded.PlayCircle
|
||||
import androidx.compose.material.icons.rounded.Repeat
|
||||
|
|
@ -105,6 +106,7 @@ import androidx.compose.ui.graphics.Color
|
|||
import androidx.compose.ui.graphics.RectangleShape
|
||||
import androidx.compose.ui.graphics.StrokeCap
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
|
|
@ -224,6 +226,7 @@ fun NowPlayingScreen(
|
|||
sharedViewModel = sharedViewModel,
|
||||
navController = navController,
|
||||
isExpanded = sheetState.currentValue == SheetValue.Expanded,
|
||||
dismissIcon = Icons.Rounded.KeyboardArrowDown,
|
||||
onSwipeEnabledChange = {
|
||||
swipeEnabled = it
|
||||
},
|
||||
|
|
@ -240,6 +243,7 @@ fun NowPlayingScreenContent(
|
|||
sharedViewModel: SharedViewModel = koinInject(),
|
||||
navController: NavController,
|
||||
isExpanded: Boolean,
|
||||
dismissIcon: ImageVector,
|
||||
onSwipeEnabledChange: (Boolean) -> Unit = {},
|
||||
onDismiss: () -> Unit = {},
|
||||
) {
|
||||
|
|
@ -702,7 +706,7 @@ fun NowPlayingScreenContent(
|
|||
onDismiss()
|
||||
}) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.baseline_keyboard_arrow_down_24),
|
||||
imageVector = dismissIcon,
|
||||
contentDescription = "",
|
||||
tint = Color.White,
|
||||
)
|
||||
|
|
@ -1086,7 +1090,7 @@ fun NowPlayingScreenContent(
|
|||
top = 15.dp,
|
||||
).padding(horizontal = 20.dp)
|
||||
.isElementVisible {
|
||||
shouldShowToolbar = !it && isExpanded
|
||||
shouldShowToolbar = !it && isExpanded && mainScrollState.value > 0
|
||||
},
|
||||
) {
|
||||
Box(
|
||||
|
|
@ -1247,7 +1251,8 @@ fun NowPlayingScreenContent(
|
|||
.size(42.dp)
|
||||
.clip(
|
||||
CircleShape,
|
||||
).clickable {
|
||||
).weight(1f)
|
||||
.clickable {
|
||||
sharedViewModel.onUIEvent(UIEvent.Shuffle)
|
||||
},
|
||||
contentAlignment = Alignment.Center,
|
||||
|
|
@ -1277,7 +1282,8 @@ fun NowPlayingScreenContent(
|
|||
.size(52.dp)
|
||||
.clip(
|
||||
CircleShape,
|
||||
).clickable {
|
||||
).weight(1f)
|
||||
.clickable {
|
||||
if (controllerState.isPreviousAvailable) {
|
||||
sharedViewModel.onUIEvent(UIEvent.Previous)
|
||||
}
|
||||
|
|
@ -1298,7 +1304,8 @@ fun NowPlayingScreenContent(
|
|||
.size(96.dp)
|
||||
.clip(
|
||||
CircleShape,
|
||||
).clickable {
|
||||
).weight(1f)
|
||||
.clickable {
|
||||
sharedViewModel.onUIEvent(UIEvent.PlayPause)
|
||||
},
|
||||
contentAlignment = Alignment.Center,
|
||||
|
|
@ -1328,7 +1335,8 @@ fun NowPlayingScreenContent(
|
|||
.size(52.dp)
|
||||
.clip(
|
||||
CircleShape,
|
||||
).clickable {
|
||||
).weight(1f)
|
||||
.clickable {
|
||||
if (controllerState.isNextAvailable) {
|
||||
sharedViewModel.onUIEvent(UIEvent.Next)
|
||||
}
|
||||
|
|
@ -1348,7 +1356,8 @@ fun NowPlayingScreenContent(
|
|||
.size(42.dp)
|
||||
.clip(
|
||||
CircleShape,
|
||||
).clickable {
|
||||
).weight(1f)
|
||||
.clickable {
|
||||
sharedViewModel.onUIEvent(UIEvent.Repeat)
|
||||
},
|
||||
contentAlignment = Alignment.Center,
|
||||
|
|
|
|||
25
config/libraries/innertune.json
Normal file
25
config/libraries/innertune.json
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"uniqueId": "com.zionhuang.music",
|
||||
"funding": [
|
||||
|
||||
],
|
||||
"developers": [
|
||||
{
|
||||
"name": "Zion Huang"
|
||||
}
|
||||
],
|
||||
"artifactVersion": "",
|
||||
"description": "A Material 3 YouTube Music client for Android",
|
||||
"scm": {
|
||||
"connection": "scm:git:https://github.com/z-huang/InnerTune.git",
|
||||
"url": "https://github.com/z-huang/InnerTune.git"
|
||||
},
|
||||
"name": "InnerTune",
|
||||
"website": "https://github.com/z-huang/InnerTune",
|
||||
"licenses": [
|
||||
"GPL-3.0"
|
||||
],
|
||||
"organization": {
|
||||
"name": "Zion Huang"
|
||||
}
|
||||
}
|
||||
25
config/libraries/smarttube.json
Normal file
25
config/libraries/smarttube.json
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"uniqueId": "com.yuliskov.smarttubetv",
|
||||
"funding": [
|
||||
|
||||
],
|
||||
"developers": [
|
||||
{
|
||||
"name": "Yuriy L"
|
||||
}
|
||||
],
|
||||
"artifactVersion": "",
|
||||
"description": "SmartTube is a free and open-source advanced media player for Android TVs and TV boxes. It allows you to play content from various public sources.",
|
||||
"scm": {
|
||||
"connection": "scm:git:https://github.com/yuliskov/SmartTube.git",
|
||||
"url": "https://github.com/yuliskov/SmartTube.git"
|
||||
},
|
||||
"name": "SmartTube",
|
||||
"website": "www.patreon.com/smarttube",
|
||||
"licenses": [
|
||||
"GNU"
|
||||
],
|
||||
"organization": {
|
||||
"name": "Yuriy L"
|
||||
}
|
||||
}
|
||||
6
config/licenses/gnu.json
Normal file
6
config/licenses/gnu.json
Normal file
File diff suppressed because one or more lines are too long
6
config/licenses/gpl3.json
Normal file
6
config/licenses/gpl3.json
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -39,7 +39,7 @@ datastore-preferences = "1.1.7"
|
|||
lottie = "6.6.9"
|
||||
paging = "3.3.6"
|
||||
customactivityoncrash = "2.4.0"
|
||||
aboutlibraries = "12.2.4"
|
||||
aboutlibraries = "13.0.0-rc01"
|
||||
balloon = "1.6.13"
|
||||
ktor = "3.3.0"
|
||||
brotli = "0.1.2"
|
||||
|
|
@ -70,6 +70,7 @@ desugaring = { group = "com.android.tools", name = "desugar_jdk_libs_nio", versi
|
|||
compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }
|
||||
compose-material3-lib = { group = "androidx.compose.material3", name = "material3", version.ref = "material3-expressive" }
|
||||
compose-material3-sizeclass = { group = "androidx.compose.material3", name = "material3-window-size-class" }
|
||||
compose-material3-adaptive = { group = "androidx.compose.material3.adaptive", name = "adaptive" }
|
||||
compose-ui = { group = "androidx.compose.ui", name = "ui" }
|
||||
compose-material-ripple = { group = "androidx.compose.material", name = "material-ripple" }
|
||||
compose-material-icons-core = { group = "androidx.compose.material", name = "material-icons-core" }
|
||||
|
|
@ -180,6 +181,6 @@ navigation-safeargs = { id = "androidx.navigation.safeargs.kotlin", version.ref
|
|||
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "serialization" }
|
||||
kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" }
|
||||
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
|
||||
aboutlibraries = { id = "com.mikepenz.aboutlibraries.plugin", version.ref = "aboutlibraries" }
|
||||
aboutlibraries = { id = "com.mikepenz.aboutlibraries.plugin.android", version.ref = "aboutlibraries" }
|
||||
room = { id = "androidx.room", version.ref = "room" }
|
||||
sentry-gradle = { id = "io.sentry.android.gradle", version.ref = "sentry-gradle" }
|
||||
Loading…
Reference in a new issue