feat: sync Playlists, wip: pair songs

This commit is contained in:
2026-05-14 02:43:49 +02:00
parent 26115f773f
commit e2ab026e84
36 changed files with 2324 additions and 34 deletions

View File

@@ -1,41 +1,71 @@
package at.lockstep.player
import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import at.lockstep.player.ui.NowPlayingScreen
import at.lockstep.player.ui.NowPlayingUiState
import androidx.compose.ui.platform.LocalContext
import androidx.core.util.Consumer
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.compose.rememberNavController
import at.lockstep.player.auth.OAuthCallbackParser
import at.lockstep.player.ui.LockstepAppNavHost
import at.lockstep.player.ui.theme.LockstepTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
Surface(modifier = Modifier.fillMaxSize()) {
var progress by remember { mutableFloatStateOf(0f) }
var playing by remember { mutableStateOf(false) }
NowPlayingScreen(
state = NowPlayingUiState(
title = "No track",
artist = "",
progress = progress,
durationSeconds = 180,
isPlaying = playing,
),
onProgressChange = { progress = it },
onPrevious = { /* TODO: service / JNI */ },
onTogglePlayPause = { playing = !playing },
onNext = { /* TODO: service / JNI */ },
LockstepTheme {
val viewModel: LockstepViewModel =
viewModel(
factory = LockstepViewModelFactory(application),
)
val context = LocalContext.current
val onboardingDone by viewModel.onboardingComplete.collectAsStateWithLifecycle()
LaunchedEffect(Unit) {
intent?.data?.let { uri ->
OAuthCallbackParser.parseAccessToken(uri)?.let { token ->
viewModel.saveSpotifyAccessToken(token)
}
}
}
DisposableEffect(viewModel) {
val listener =
Consumer<Intent> { newIntent ->
newIntent.data?.let { uri ->
OAuthCallbackParser.parseAccessToken(uri)?.let { token ->
viewModel.saveSpotifyAccessToken(token)
}
}
}
addOnNewIntentListener(listener)
onDispose { removeOnNewIntentListener(listener) }
}
Surface(modifier = Modifier.fillMaxSize()) {
if (!onboardingDone) {
at.lockstep.player.ui.onboarding.OnboardingScreen(
viewModel = viewModel,
onFinished = { },
)
} else {
val navController = rememberNavController()
LockstepAppNavHost(
activity = this@MainActivity,
navController = navController,
viewModel = viewModel,
)
}
}
}
}