package at.lockstep.player.ui import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.ServiceConnection import android.os.IBinder import androidx.activity.ComponentActivity import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.core.content.ContextCompat import androidx.navigation.NavHostController import androidx.navigation.NavType import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.navArgument import at.lockstep.jukebox.PlaylistSummary import at.lockstep.player.LockstepViewModel import at.lockstep.player.playback.PlaybackService import at.lockstep.player.ui.library.LibraryScreen import at.lockstep.player.ui.navigation.Routes import at.lockstep.player.ui.pairing.PairingScreen import at.lockstep.player.ui.settings.SettingsScreen @Composable fun LockstepAppNavHost( activity: ComponentActivity, navController: NavHostController, viewModel: LockstepViewModel, ) { val annotationMode by viewModel.annotationMode.collectAsStateWithLifecycle() var playback by remember { mutableStateOf(null) } DisposableEffect(Unit) { val connection = object : ServiceConnection { override fun onServiceConnected( name: ComponentName?, binder: IBinder?, ) { playback = (binder as PlaybackService.LocalBinder).getService() } override fun onServiceDisconnected(name: ComponentName?) { playback = null } } activity.bindService( Intent(activity, PlaybackService::class.java), connection, Context.BIND_AUTO_CREATE, ) onDispose { activity.unbindService(connection) } } NavHost( navController = navController, startDestination = Routes.Library, ) { composable(Routes.Library) { LibraryScreen( viewModel = viewModel, onPlaylistSelected = { playlist: PlaylistSummary, hasPaired -> if (!hasPaired) { navController.navigate(Routes.pairing(playlist.id)) } else { startPlaylistPlayback(activity, playlist.id) if (annotationMode) { navController.navigate(Routes.annotation(playlist.id)) } else { navController.navigate(Routes.nowPlaying(playlist.id)) } } }, onOpenSettings = { navController.navigate(Routes.Settings) }, ) } composable(Routes.Settings) { SettingsScreen( viewModel = viewModel, onBack = { navController.popBackStack() }, ) } composable( route = Routes.Pairing, arguments = listOf( navArgument("playlistId") { type = NavType.StringType }, ), ) { entry -> val playlistId = entry.arguments?.getString("playlistId").orEmpty() PairingScreen( playlistId = playlistId, viewModel = viewModel, onBack = { navController.popBackStack() }, ) } composable( route = Routes.NowPlaying, arguments = listOf( navArgument("playlistId") { type = NavType.StringType }, ), ) { entry -> val playlistId = entry.arguments?.getString("playlistId").orEmpty() NowPlayingRoute( playlistId = playlistId, playback = playback, viewModel = viewModel, onBack = { navController.popBackStack() }, ) } composable( route = Routes.Annotation, arguments = listOf( navArgument("playlistId") { type = NavType.StringType }, ), ) { entry -> val playlistId = entry.arguments?.getString("playlistId").orEmpty() AnnotationRoute( playlistId = playlistId, playback = playback, viewModel = viewModel, onBack = { navController.popBackStack() }, ) } } } private fun startPlaylistPlayback( context: Context, playlistId: String, ) { ContextCompat.startForegroundService( context, Intent(context, PlaybackService::class.java).apply { action = PlaybackService.ACTION_START_PLAYLIST putExtra(PlaybackService.EXTRA_PLAYLIST_ID, playlistId) }, ) }