diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a646259..a7dcea4 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,6 +1,7 @@ plugins { id("com.android.application") kotlin("android") + id("kotlin-parcelize") id("com.google.devtools.ksp") id("org.jetbrains.kotlin.plugin.serialization") version "1.9.23" } diff --git a/app/src/main/java/app/suhasdissa/vibeyou/MainActivity.kt b/app/src/main/java/app/suhasdissa/vibeyou/MainActivity.kt index c85512b..14a0e2e 100644 --- a/app/src/main/java/app/suhasdissa/vibeyou/MainActivity.kt +++ b/app/src/main/java/app/suhasdissa/vibeyou/MainActivity.kt @@ -28,7 +28,6 @@ import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.compose.rememberNavController import app.suhasdissa.vibeyou.navigation.AppNavHost import app.suhasdissa.vibeyou.navigation.Destination -import app.suhasdissa.vibeyou.navigation.navigateTo import app.suhasdissa.vibeyou.presentation.components.NavDrawerContent import app.suhasdissa.vibeyou.presentation.screens.player.model.PlayerViewModel import app.suhasdissa.vibeyou.presentation.screens.settings.model.SettingsModel @@ -84,7 +83,7 @@ class MainActivity : ComponentActivity() { scope.launch { drawerState.close() } - navHostController.navigateTo(it.route) + navHostController.navigate(it) currentDestination = it } ) diff --git a/app/src/main/java/app/suhasdissa/vibeyou/domain/models/primary/Album.kt b/app/src/main/java/app/suhasdissa/vibeyou/domain/models/primary/Album.kt index fbf3ee7..df9cefd 100644 --- a/app/src/main/java/app/suhasdissa/vibeyou/domain/models/primary/Album.kt +++ b/app/src/main/java/app/suhasdissa/vibeyou/domain/models/primary/Album.kt @@ -1,17 +1,24 @@ package app.suhasdissa.vibeyou.domain.models.primary import android.net.Uri +import android.os.Parcelable +import app.suhasdissa.vibeyou.utils.UriSerializer +import kotlinx.parcelize.Parcelize +import kotlinx.serialization.Serializable +@Serializable +@Parcelize data class Album( val id: String, val title: String, + @Serializable(with = UriSerializer::class) val thumbnailUri: Uri? = null, val artistsText: String, val numberOfSongs: Int? = null, val isLocal: Boolean = false, val type: Type = Type.ALBUM -) { +) : Parcelable { enum class Type { PLAYLIST, ALBUM } -} +} \ No newline at end of file diff --git a/app/src/main/java/app/suhasdissa/vibeyou/domain/models/primary/Artist.kt b/app/src/main/java/app/suhasdissa/vibeyou/domain/models/primary/Artist.kt index 4f89c82..ce1ce08 100644 --- a/app/src/main/java/app/suhasdissa/vibeyou/domain/models/primary/Artist.kt +++ b/app/src/main/java/app/suhasdissa/vibeyou/domain/models/primary/Artist.kt @@ -1,12 +1,19 @@ package app.suhasdissa.vibeyou.domain.models.primary import android.net.Uri +import android.os.Parcelable +import app.suhasdissa.vibeyou.utils.UriSerializer +import kotlinx.parcelize.Parcelize +import kotlinx.serialization.Serializable +@Parcelize +@Serializable data class Artist( val id: String, val artistsText: String, + @Serializable(with = UriSerializer::class) val thumbnailUri: Uri? = null, val description: String? = null, val numberOfTracks: Int? = null, val numberOfAlbums: Int? = null -) +) : Parcelable diff --git a/app/src/main/java/app/suhasdissa/vibeyou/navigation/CustomNavTypes.kt b/app/src/main/java/app/suhasdissa/vibeyou/navigation/CustomNavTypes.kt new file mode 100644 index 0000000..b85494a --- /dev/null +++ b/app/src/main/java/app/suhasdissa/vibeyou/navigation/CustomNavTypes.kt @@ -0,0 +1,50 @@ +package app.suhasdissa.vibeyou.navigation + +import android.os.Bundle +import androidx.navigation.NavType +import app.suhasdissa.vibeyou.domain.models.primary.Album +import app.suhasdissa.vibeyou.domain.models.primary.Artist +import kotlinx.serialization.json.Json +import java.net.URLDecoder +import java.net.URLEncoder + +val AlbumType = object : NavType( + isNullableAllowed = false +) { + override fun put(bundle: Bundle, key: String, value: Album) { + bundle.putParcelable(key, value) + } + + override fun get(bundle: Bundle, key: String): Album? { + return bundle.getParcelable(key) + } + + override fun parseValue(value: String): Album { + return Json.decodeFromString(URLDecoder.decode(value, "UTF-8")) + } + + override fun serializeAsValue(value: Album): String { + return URLEncoder.encode(Json.encodeToString(Album.serializer(), value), "UTF-8") + } +} + +val ArtistType = object : NavType( + isNullableAllowed = false +) { + override fun put(bundle: Bundle, key: String, value: Artist) { + bundle.putParcelable(key, value) + } + + override fun get(bundle: Bundle, key: String): Artist? { + return bundle.getParcelable(key) + } + + override fun parseValue(value: String): Artist { + return Json.decodeFromString(URLDecoder.decode(value, "UTF-8")) + } + + override fun serializeAsValue(value: Artist): String { + return URLEncoder.encode(Json.encodeToString(Artist.serializer(), value), "UTF-8") + } + +} \ No newline at end of file diff --git a/app/src/main/java/app/suhasdissa/vibeyou/navigation/Destination.kt b/app/src/main/java/app/suhasdissa/vibeyou/navigation/Destination.kt index edd7bb0..ee51116 100644 --- a/app/src/main/java/app/suhasdissa/vibeyou/navigation/Destination.kt +++ b/app/src/main/java/app/suhasdissa/vibeyou/navigation/Destination.kt @@ -1,18 +1,50 @@ package app.suhasdissa.vibeyou.navigation -sealed class Destination(val route: String) { - object PipedMusic : Destination("piped_music") - object LocalMusic : Destination("local_music") - object OnlineSearch : Destination("online_search") - object LocalSearch : Destination("local_search") - object Settings : Destination("settings") - object About : Destination("about") - object NetworkSettings : Destination("net_settings") - object DatabaseSettings : Destination("database_settings") - object AppearanceSettings : Destination("appearance_settings") - object Playlists : Destination("playlist_screen") - object LocalPlaylists : Destination("local_playlist_screen") - object SavedPlaylists : Destination("saved_playlist_screen") - object Artist : Destination("artist") - object LocalArtist : Destination("local_artist") +import app.suhasdissa.vibeyou.domain.models.primary.Album +import app.suhasdissa.vibeyou.domain.models.primary.Artist +import kotlinx.serialization.Serializable + +@Serializable +sealed class Destination { + @Serializable + object PipedMusic : Destination() + + @Serializable + object LocalMusic : Destination() + + @Serializable + object OnlineSearch : Destination() + + @Serializable + object LocalSearch : Destination() + + @Serializable + object Settings : Destination() + + @Serializable + object About : Destination() + + @Serializable + object NetworkSettings : Destination() + + @Serializable + object DatabaseSettings : Destination() + + @Serializable + object AppearanceSettings : Destination() + + @Serializable + data class Playlists(val album: Album) : Destination() + + @Serializable + data class LocalPlaylists(val album: Album) : Destination() + + @Serializable + data class SavedPlaylists(val album: Album) : Destination() + + @Serializable + data class OnlineArtist(val artist: Artist) : Destination() + + @Serializable + data class LocalArtist(val artist: Artist) : Destination() } diff --git a/app/src/main/java/app/suhasdissa/vibeyou/navigation/NavHost.kt b/app/src/main/java/app/suhasdissa/vibeyou/navigation/NavHost.kt index dc813a3..078ae95 100644 --- a/app/src/main/java/app/suhasdissa/vibeyou/navigation/NavHost.kt +++ b/app/src/main/java/app/suhasdissa/vibeyou/navigation/NavHost.kt @@ -7,128 +7,138 @@ import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable +import app.suhasdissa.vibeyou.domain.models.primary.Album +import app.suhasdissa.vibeyou.domain.models.primary.Artist import app.suhasdissa.vibeyou.presentation.screens.album.AlbumScreen +import app.suhasdissa.vibeyou.presentation.screens.album.model.LocalPlaylistViewModel +import app.suhasdissa.vibeyou.presentation.screens.album.model.OnlinePlaylistViewModel import app.suhasdissa.vibeyou.presentation.screens.artist.ArtistScreen +import app.suhasdissa.vibeyou.presentation.screens.artist.model.LocalArtistViewModel +import app.suhasdissa.vibeyou.presentation.screens.artist.model.OnlineArtistViewModel import app.suhasdissa.vibeyou.presentation.screens.home.HomeScreen -import app.suhasdissa.vibeyou.presentation.screens.localmusic.model.LocalSongViewModel import app.suhasdissa.vibeyou.presentation.screens.localsearch.LocalSearchScreen import app.suhasdissa.vibeyou.presentation.screens.localsearch.model.LocalSearchViewModel import app.suhasdissa.vibeyou.presentation.screens.onlinesearch.SearchScreen import app.suhasdissa.vibeyou.presentation.screens.onlinesearch.model.PipedSearchViewModel -import app.suhasdissa.vibeyou.presentation.screens.playlists.model.PlaylistViewModel +import app.suhasdissa.vibeyou.presentation.screens.playlists.model.PlaylistInfoViewModel import app.suhasdissa.vibeyou.presentation.screens.settings.AboutScreen import app.suhasdissa.vibeyou.presentation.screens.settings.AppearanceSettingsScreen import app.suhasdissa.vibeyou.presentation.screens.settings.DatabaseSettingsScreen import app.suhasdissa.vibeyou.presentation.screens.settings.NetworkSettingsScreen import app.suhasdissa.vibeyou.presentation.screens.settings.SettingsScreen +import app.suhasdissa.vibeyou.presentation.screens.settings.model.SettingsModel +import kotlin.reflect.typeOf @Composable fun AppNavHost(navHostController: NavHostController) { val viewModelStoreOwner = LocalViewModelStoreOwner.current!! + + val settingsModel: SettingsModel = viewModel(factory = SettingsModel.Factory) NavHost( navController = navHostController, - startDestination = Destination.PipedMusic.route + startDestination = Destination.PipedMusic ) { - composable(route = Destination.PipedMusic.route) { + composable { CompositionLocalProvider(LocalViewModelStoreOwner provides viewModelStoreOwner) { HomeScreen(onNavigate = { destination -> - navHostController.navigateTo(destination.route) + navHostController.navigate(destination) }) } } - composable( - route = Destination.OnlineSearch.route - ) { + composable { + val pipedSearchViewModel: PipedSearchViewModel = + viewModel(factory = PipedSearchViewModel.Factory) CompositionLocalProvider(LocalViewModelStoreOwner provides viewModelStoreOwner) { SearchScreen(onNavigate = { - navHostController.navigateTo(it.route) - }) + navHostController.navigate(it) + }, pipedSearchViewModel) } } - composable( - route = Destination.LocalSearch.route - ) { + composable { + val localSearchViewModel: LocalSearchViewModel = + viewModel(factory = LocalSearchViewModel.Factory) CompositionLocalProvider(LocalViewModelStoreOwner provides viewModelStoreOwner) { LocalSearchScreen(onNavigate = { - navHostController.navigateTo(it.route) - }) + navHostController.navigate(it) + }, localSearchViewModel) } } - composable(route = Destination.Settings.route) { + composable { SettingsScreen(onNavigate = { route -> - navHostController.navigateTo(route) + navHostController.navigate(route) }) } - composable(route = Destination.About.route) { + composable { AboutScreen() } - composable(route = Destination.NetworkSettings.route) { + composable { NetworkSettingsScreen() } - composable(route = Destination.DatabaseSettings.route) { + composable { DatabaseSettingsScreen() } - composable(route = Destination.AppearanceSettings.route) { - CompositionLocalProvider(LocalViewModelStoreOwner provides viewModelStoreOwner) { - AppearanceSettingsScreen() - } + composable { + AppearanceSettingsScreen(settingsModel) } - composable(Destination.Playlists.route) { + composable( + typeMap = mapOf(typeOf() to AlbumType) + ) { + val onlinePlaylistViewModel: OnlinePlaylistViewModel = + viewModel(factory = OnlinePlaylistViewModel.Factory) CompositionLocalProvider(LocalViewModelStoreOwner provides viewModelStoreOwner) { - val searchViewModel: PipedSearchViewModel = - viewModel(factory = PipedSearchViewModel.Factory) - AlbumScreen(searchViewModel.albumInfoState) + AlbumScreen(onlinePlaylistViewModel.albumInfoState) } } - composable(Destination.LocalPlaylists.route) { + composable( + typeMap = mapOf(typeOf() to AlbumType) + ) { + val localPlaylistViewModel: LocalPlaylistViewModel = + viewModel(factory = LocalPlaylistViewModel.Factory) CompositionLocalProvider(LocalViewModelStoreOwner provides viewModelStoreOwner) { - val searchViewModel: LocalSearchViewModel = - viewModel(factory = LocalSongViewModel.Factory) - AlbumScreen(searchViewModel.albumInfoState) + AlbumScreen(localPlaylistViewModel.albumInfoState) } } - composable(Destination.SavedPlaylists.route) { + composable( + typeMap = mapOf(typeOf() to AlbumType) + ) { + val playlistInfoViewModel: PlaylistInfoViewModel = + viewModel(factory = PlaylistInfoViewModel.Factory) CompositionLocalProvider(LocalViewModelStoreOwner provides viewModelStoreOwner) { - val searchViewModel: PlaylistViewModel = - viewModel(factory = PlaylistViewModel.Factory) - AlbumScreen(searchViewModel.albumInfoState) + AlbumScreen(playlistInfoViewModel.albumInfoState) } } - composable(route = Destination.Artist.route) { + composable( + typeMap = mapOf(typeOf() to ArtistType) + ) { + val onlineArtistViewModel: OnlineArtistViewModel = + viewModel(factory = OnlineArtistViewModel.Factory) CompositionLocalProvider(LocalViewModelStoreOwner provides viewModelStoreOwner) { - val searchViewModel: PipedSearchViewModel = - viewModel(factory = PipedSearchViewModel.Factory) ArtistScreen(onClickAlbum = { - searchViewModel.getPlaylistInfo(it) - navHostController.navigateTo(Destination.Playlists.route) - }, searchViewModel.artistInfoState) + navHostController.navigate(Destination.Playlists(it)) + }, onlineArtistViewModel.artistInfoState) } } - composable(route = Destination.LocalArtist.route) { + composable( + typeMap = mapOf(typeOf() to ArtistType) + ) { + val localArtistViewModel: LocalArtistViewModel = + viewModel(factory = LocalArtistViewModel.Factory) CompositionLocalProvider(LocalViewModelStoreOwner provides viewModelStoreOwner) { - val searchViewModel: LocalSearchViewModel = - viewModel(factory = LocalSearchViewModel.Factory) ArtistScreen(onClickAlbum = { - searchViewModel.getAlbumInfo(it) - navHostController.navigateTo(Destination.LocalPlaylists.route) - }, searchViewModel.artistInfoState) + navHostController.navigate(Destination.LocalPlaylists(it)) + }, localArtistViewModel.artistInfoState) } } } } - -fun NavHostController.navigateTo(route: String) = this.navigate(route) { - launchSingleTop = true - restoreState = true -} diff --git a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/album/AlbumScreen.kt b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/album/AlbumScreen.kt index fc56c60..69ae7a8 100644 --- a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/album/AlbumScreen.kt +++ b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/album/AlbumScreen.kt @@ -44,16 +44,16 @@ import app.suhasdissa.vibeyou.presentation.components.LoadingScreen import app.suhasdissa.vibeyou.presentation.components.MiniPlayerScaffold import app.suhasdissa.vibeyou.presentation.components.SongCard import app.suhasdissa.vibeyou.presentation.components.SongSettingsSheetSearchPage +import app.suhasdissa.vibeyou.presentation.screens.album.model.NewPlaylistViewModel import app.suhasdissa.vibeyou.presentation.screens.onlinesearch.model.state.AlbumInfoState import app.suhasdissa.vibeyou.presentation.screens.player.model.PlayerViewModel -import app.suhasdissa.vibeyou.presentation.screens.playlists.model.PlaylistViewModel import coil.compose.AsyncImage @Composable fun AlbumScreen( state: AlbumInfoState, playerViewModel: PlayerViewModel = viewModel(factory = PlayerViewModel.Factory), - playlistViewModel: PlaylistViewModel = viewModel(factory = PlaylistViewModel.Factory) + playlistViewModel: NewPlaylistViewModel = viewModel(factory = NewPlaylistViewModel.Factory) ) { MiniPlayerScaffold { when (state) { diff --git a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/album/model/LocalPlaylistViewModel.kt b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/album/model/LocalPlaylistViewModel.kt new file mode 100644 index 0000000..db7e0eb --- /dev/null +++ b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/album/model/LocalPlaylistViewModel.kt @@ -0,0 +1,63 @@ +package app.suhasdissa.vibeyou.presentation.screens.album.model + +import android.util.Log +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.createSavedStateHandle +import androidx.lifecycle.viewModelScope +import androidx.lifecycle.viewmodel.initializer +import androidx.lifecycle.viewmodel.viewModelFactory +import androidx.navigation.toRoute +import app.suhasdissa.vibeyou.MellowMusicApplication +import app.suhasdissa.vibeyou.backend.repository.LocalMusicRepository +import app.suhasdissa.vibeyou.domain.models.primary.Album +import app.suhasdissa.vibeyou.navigation.Destination +import app.suhasdissa.vibeyou.presentation.screens.onlinesearch.model.state.AlbumInfoState +import kotlinx.coroutines.launch + +class LocalPlaylistViewModel( + private val musicRepository: LocalMusicRepository, + savedStateHandle: SavedStateHandle +) : ViewModel() { + + val playlist = savedStateHandle.toRoute() + + var albumInfoState: AlbumInfoState by mutableStateOf(AlbumInfoState.Loading) + private set + + init { + getAlbumInfo(playlist.album) + } + + private fun getAlbumInfo(album: Album) { + viewModelScope.launch { + albumInfoState = AlbumInfoState.Loading + albumInfoState = try { + AlbumInfoState.Success( + album, + musicRepository.getAlbumInfo(album.id.toLong()) + ) + } catch (e: Exception) { + Log.e("Playlist Info", e.toString()) + AlbumInfoState.Error + } + } + } + + companion object { + val Factory: ViewModelProvider.Factory = viewModelFactory { + initializer { + val application = + (this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as MellowMusicApplication) + LocalPlaylistViewModel( + application.container.localMusicRepository, + this.createSavedStateHandle() + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/album/model/NewPlaylistViewModel.kt b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/album/model/NewPlaylistViewModel.kt new file mode 100644 index 0000000..926a911 --- /dev/null +++ b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/album/model/NewPlaylistViewModel.kt @@ -0,0 +1,32 @@ +package app.suhasdissa.vibeyou.presentation.screens.album.model + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.viewModelScope +import androidx.lifecycle.viewmodel.initializer +import androidx.lifecycle.viewmodel.viewModelFactory +import app.suhasdissa.vibeyou.MellowMusicApplication +import app.suhasdissa.vibeyou.backend.repository.PlaylistRepository +import app.suhasdissa.vibeyou.domain.models.primary.Album +import app.suhasdissa.vibeyou.domain.models.primary.Song +import kotlinx.coroutines.launch + +class NewPlaylistViewModel(private val playlistRepository: PlaylistRepository) : ViewModel() { + fun newPlaylistWithSongs(album: Album, songs: List) { + viewModelScope.launch { + playlistRepository.newPlaylistWithSongs(album, songs) + } + } + + companion object { + val Factory: ViewModelProvider.Factory = viewModelFactory { + initializer { + val application = + (this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as MellowMusicApplication) + NewPlaylistViewModel( + application.container.playlistRepository + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/album/model/OnlinePlaylistViewModel.kt b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/album/model/OnlinePlaylistViewModel.kt new file mode 100644 index 0000000..bec877a --- /dev/null +++ b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/album/model/OnlinePlaylistViewModel.kt @@ -0,0 +1,65 @@ +package app.suhasdissa.vibeyou.presentation.screens.album.model + +import android.util.Log +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.createSavedStateHandle +import androidx.lifecycle.viewModelScope +import androidx.lifecycle.viewmodel.initializer +import androidx.lifecycle.viewmodel.viewModelFactory +import androidx.navigation.toRoute +import app.suhasdissa.vibeyou.MellowMusicApplication +import app.suhasdissa.vibeyou.backend.repository.PipedMusicRepository +import app.suhasdissa.vibeyou.domain.models.primary.Album +import app.suhasdissa.vibeyou.navigation.Destination +import app.suhasdissa.vibeyou.presentation.screens.onlinesearch.model.state.AlbumInfoState +import app.suhasdissa.vibeyou.utils.asSong +import kotlinx.coroutines.launch + +class OnlinePlaylistViewModel( + private val musicRepository: PipedMusicRepository, + savedStateHandle: SavedStateHandle +) : ViewModel() { + + val playlist = savedStateHandle.toRoute() + + var albumInfoState: AlbumInfoState by mutableStateOf(AlbumInfoState.Loading) + private set + + init { + getPlaylistInfo(playlist.album) + } + + private fun getPlaylistInfo(playlist: Album) { + viewModelScope.launch { + albumInfoState = AlbumInfoState.Loading + albumInfoState = try { + val info = musicRepository.getPlaylistInfo(playlist.id) + AlbumInfoState.Success( + playlist, + info.relatedStreams.map { it.asSong } + ) + } catch (e: Exception) { + Log.e("Playlist Info", e.toString()) + AlbumInfoState.Error + } + } + } + + companion object { + val Factory: ViewModelProvider.Factory = viewModelFactory { + initializer { + val application = + (this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as MellowMusicApplication) + OnlinePlaylistViewModel( + application.container.pipedMusicRepository, + this.createSavedStateHandle() + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/artist/model/LocalArtistViewModel.kt b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/artist/model/LocalArtistViewModel.kt new file mode 100644 index 0000000..75ebee6 --- /dev/null +++ b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/artist/model/LocalArtistViewModel.kt @@ -0,0 +1,62 @@ +package app.suhasdissa.vibeyou.presentation.screens.artist.model + +import android.util.Log +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.createSavedStateHandle +import androidx.lifecycle.viewModelScope +import androidx.lifecycle.viewmodel.initializer +import androidx.lifecycle.viewmodel.viewModelFactory +import androidx.navigation.toRoute +import app.suhasdissa.vibeyou.MellowMusicApplication +import app.suhasdissa.vibeyou.backend.repository.LocalMusicRepository +import app.suhasdissa.vibeyou.domain.models.primary.Artist +import app.suhasdissa.vibeyou.navigation.Destination +import app.suhasdissa.vibeyou.presentation.screens.onlinesearch.model.state.ArtistInfoState +import kotlinx.coroutines.launch + +class LocalArtistViewModel( + private val musicRepository: LocalMusicRepository, + savedStateHandle: SavedStateHandle +) : ViewModel() { + + val artist = savedStateHandle.toRoute() + var artistInfoState: ArtistInfoState by mutableStateOf(ArtistInfoState.Loading) + private set + + init { + getArtistInfo(artist.artist) + } + + private fun getArtistInfo(artist: Artist) { + viewModelScope.launch { + artistInfoState = ArtistInfoState.Loading + artistInfoState = try { + ArtistInfoState.Success( + artist, + musicRepository.getArtistInfo(artist.artistsText) + ) + } catch (e: Exception) { + Log.e("Artist Info", e.toString()) + ArtistInfoState.Error + } + } + } + + companion object { + val Factory: ViewModelProvider.Factory = viewModelFactory { + initializer { + val application = + (this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as MellowMusicApplication) + LocalArtistViewModel( + application.container.localMusicRepository, + this.createSavedStateHandle() + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/artist/model/OnlineArtistViewModel.kt b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/artist/model/OnlineArtistViewModel.kt new file mode 100644 index 0000000..185f7b7 --- /dev/null +++ b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/artist/model/OnlineArtistViewModel.kt @@ -0,0 +1,67 @@ +package app.suhasdissa.vibeyou.presentation.screens.artist.model + +import android.util.Log +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.core.net.toUri +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.createSavedStateHandle +import androidx.lifecycle.viewModelScope +import androidx.lifecycle.viewmodel.initializer +import androidx.lifecycle.viewmodel.viewModelFactory +import androidx.navigation.toRoute +import app.suhasdissa.vibeyou.MellowMusicApplication +import app.suhasdissa.vibeyou.backend.repository.PipedMusicRepository +import app.suhasdissa.vibeyou.domain.models.primary.Artist +import app.suhasdissa.vibeyou.navigation.Destination +import app.suhasdissa.vibeyou.presentation.screens.onlinesearch.model.state.ArtistInfoState +import kotlinx.coroutines.launch + +class OnlineArtistViewModel( + private val musicRepository: PipedMusicRepository, + savedStateHandle: SavedStateHandle +) : ViewModel() { + val artist = savedStateHandle.toRoute() + var artistInfoState: ArtistInfoState by mutableStateOf(ArtistInfoState.Loading) + private set + + init { + getArtistInfo(artist.artist) + } + + private fun getArtistInfo(artist: Artist) { + viewModelScope.launch { + artistInfoState = ArtistInfoState.Loading + artistInfoState = try { + val info = musicRepository.getChannelInfo(artist.id) + val playlists = musicRepository.getChannelPlaylists(artist.id, info.tabs) + ArtistInfoState.Success( + artist.copy( + thumbnailUri = info.avatarUrl?.toUri(), + description = info.description + ), + playlists + ) + } catch (e: Exception) { + Log.e("Playlist Info", e.toString()) + ArtistInfoState.Error + } + } + } + + companion object { + val Factory: ViewModelProvider.Factory = viewModelFactory { + initializer { + val application = + (this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as MellowMusicApplication) + OnlineArtistViewModel( + application.container.pipedMusicRepository, + this.createSavedStateHandle() + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/home/HomeScreen.kt b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/home/HomeScreen.kt index fdb9248..2eba577 100644 --- a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/home/HomeScreen.kt +++ b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/home/HomeScreen.kt @@ -38,7 +38,6 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner -import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController @@ -46,11 +45,9 @@ import app.suhasdissa.vibeyou.MainActivity import app.suhasdissa.vibeyou.R import app.suhasdissa.vibeyou.backend.repository.LocalMusicRepository import app.suhasdissa.vibeyou.navigation.Destination -import app.suhasdissa.vibeyou.navigation.navigateTo import app.suhasdissa.vibeyou.presentation.components.MiniPlayerScaffold import app.suhasdissa.vibeyou.presentation.components.NavDrawerContent import app.suhasdissa.vibeyou.presentation.screens.localmusic.LocalMusicScreen -import app.suhasdissa.vibeyou.presentation.screens.localsearch.model.LocalSearchViewModel import app.suhasdissa.vibeyou.presentation.screens.onlinemusic.MusicScreen import app.suhasdissa.vibeyou.utils.PermissionHelper import kotlinx.coroutines.launch @@ -58,8 +55,7 @@ import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3Api::class) @Composable fun HomeScreen( - onNavigate: (Destination) -> Unit, - localSearchViewModel: LocalSearchViewModel = viewModel(factory = LocalSearchViewModel.Factory) + onNavigate: (Destination) -> Unit ) { val navController = rememberNavController() val drawerState = rememberDrawerState(DrawerValue.Closed) @@ -77,10 +73,10 @@ fun HomeScreen( scope.launch { drawerState.close() } - if (it == Destination.Settings) { + if (it is Destination.Settings) { onNavigate(it) } else { - navController.navigateTo(it.route) + navController.navigate(it) currentDestination = it } }) @@ -142,13 +138,13 @@ fun HomeScreen( val viewModelStoreOwner = LocalViewModelStoreOwner.current!! NavHost( navController, - startDestination = Destination.LocalMusic.route, + startDestination = Destination.LocalMusic, Modifier .fillMaxSize(), enterTransition = { EnterTransition.None }, exitTransition = { ExitTransition.None } ) { - composable(Destination.PipedMusic.route) { + composable { CompositionLocalProvider(LocalViewModelStoreOwner provides viewModelStoreOwner) { MusicScreen(onNavigate) LaunchedEffect(Unit) { @@ -156,7 +152,7 @@ fun HomeScreen( } } } - composable(Destination.LocalMusic.route) { + composable { LaunchedEffect(Unit) { currentDestination = Destination.LocalMusic PermissionHelper.checkPermissions( @@ -164,7 +160,7 @@ fun HomeScreen( LocalMusicRepository.permissions ) } - LocalMusicScreen(onNavigate, localSearchViewModel) + LocalMusicScreen(onNavigate) } } } diff --git a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/localmusic/LocalMusicScreen.kt b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/localmusic/LocalMusicScreen.kt index 38f5301..8dc7eee 100644 --- a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/localmusic/LocalMusicScreen.kt +++ b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/localmusic/LocalMusicScreen.kt @@ -45,7 +45,6 @@ import app.suhasdissa.vibeyou.presentation.screens.album.components.AlbumList import app.suhasdissa.vibeyou.presentation.screens.artist.components.ArtistList import app.suhasdissa.vibeyou.presentation.screens.localmusic.components.SortOrderDialog import app.suhasdissa.vibeyou.presentation.screens.localmusic.model.LocalSongViewModel -import app.suhasdissa.vibeyou.presentation.screens.localsearch.model.LocalSearchViewModel import app.suhasdissa.vibeyou.presentation.screens.player.model.PlayerViewModel import app.suhasdissa.vibeyou.utils.Pref import kotlinx.coroutines.launch @@ -54,7 +53,6 @@ import kotlinx.coroutines.launch @Composable fun LocalMusicScreen( onNavigate: (Destination) -> Unit, - localSearchViewModel: LocalSearchViewModel, localSongViewModel: LocalSongViewModel = viewModel(factory = LocalSongViewModel.Factory), playerViewModel: PlayerViewModel = viewModel(factory = PlayerViewModel.Factory) ) { @@ -174,15 +172,13 @@ fun LocalMusicScreen( } 1 -> AlbumList(items = localSongViewModel.albums, onClickCard = { - localSearchViewModel.getAlbumInfo(it) - onNavigate(Destination.LocalPlaylists) + onNavigate(Destination.LocalPlaylists(it)) }, onLongPress = {}) 2 -> ArtistList( items = localSongViewModel.artists, onClickCard = { - localSearchViewModel.getArtistInfo(it) - onNavigate(Destination.LocalArtist) + onNavigate(Destination.LocalArtist(it)) }, onLongPress = {} ) diff --git a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/localsearch/LocalSearchScreen.kt b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/localsearch/LocalSearchScreen.kt index 92a881a..2bab518 100644 --- a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/localsearch/LocalSearchScreen.kt +++ b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/localsearch/LocalSearchScreen.kt @@ -57,7 +57,7 @@ import app.suhasdissa.vibeyou.presentation.screens.player.model.PlayerViewModel @Composable fun LocalSearchScreen( onNavigate: (Destination) -> Unit, - localSearchViewModel: LocalSearchViewModel = viewModel(factory = LocalSearchViewModel.Factory), + localSearchViewModel: LocalSearchViewModel, playerViewModel: PlayerViewModel = viewModel(factory = PlayerViewModel.Factory) ) { var isPopupOpen by remember { @@ -209,8 +209,7 @@ fun LocalSearchScreen( AlbumList( items = searchState.items, onClickCard = { - localSearchViewModel.getAlbumInfo(it) - onNavigate(Destination.LocalPlaylists) + onNavigate(Destination.LocalPlaylists(it)) }, onLongPress = { } @@ -234,8 +233,7 @@ fun LocalSearchScreen( ArtistList( items = searchState.items, onClickCard = { - localSearchViewModel.getArtistInfo(it) - onNavigate(Destination.LocalArtist) + onNavigate(Destination.LocalArtist(it)) }, onLongPress = { } diff --git a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/localsearch/model/LocalSearchViewModel.kt b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/localsearch/model/LocalSearchViewModel.kt index 89aeb4f..cfdee7b 100644 --- a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/localsearch/model/LocalSearchViewModel.kt +++ b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/localsearch/model/LocalSearchViewModel.kt @@ -15,11 +15,7 @@ import androidx.lifecycle.viewmodel.viewModelFactory import app.suhasdissa.vibeyou.MellowMusicApplication import app.suhasdissa.vibeyou.backend.models.LocalSearchFilter import app.suhasdissa.vibeyou.backend.repository.LocalMusicRepository -import app.suhasdissa.vibeyou.domain.models.primary.Album -import app.suhasdissa.vibeyou.domain.models.primary.Artist import app.suhasdissa.vibeyou.domain.models.primary.Song -import app.suhasdissa.vibeyou.presentation.screens.onlinesearch.model.state.AlbumInfoState -import app.suhasdissa.vibeyou.presentation.screens.onlinesearch.model.state.ArtistInfoState import app.suhasdissa.vibeyou.presentation.screens.onlinesearch.model.state.SearchState import kotlinx.coroutines.launch @@ -30,10 +26,6 @@ class LocalSearchViewModel(private val musicRepository: LocalMusicRepository) : var searchFilter = LocalSearchFilter.Songs var search by mutableStateOf("") var songSearchSuggestion: List by mutableStateOf(listOf()) - var albumInfoState: AlbumInfoState by mutableStateOf(AlbumInfoState.Loading) - private set - var artistInfoState: ArtistInfoState by mutableStateOf(ArtistInfoState.Loading) - private set fun getSuggestions() { if (search.length < 3) return @@ -58,36 +50,6 @@ class LocalSearchViewModel(private val musicRepository: LocalMusicRepository) : } } - fun getAlbumInfo(album: Album) { - viewModelScope.launch { - albumInfoState = AlbumInfoState.Loading - albumInfoState = try { - AlbumInfoState.Success( - album, - musicRepository.getAlbumInfo(album.id.toLong()) - ) - } catch (e: Exception) { - Log.e("Playlist Info", e.toString()) - AlbumInfoState.Error - } - } - } - - fun getArtistInfo(artist: Artist) { - viewModelScope.launch { - artistInfoState = ArtistInfoState.Loading - artistInfoState = try { - ArtistInfoState.Success( - artist, - musicRepository.getArtistInfo(artist.artistsText) - ) - } catch (e: Exception) { - Log.e("Artist Info", e.toString()) - ArtistInfoState.Error - } - } - } - fun searchPiped() { if (search.isEmpty()) return viewModelScope.launch { @@ -143,3 +105,4 @@ class LocalSearchViewModel(private val musicRepository: LocalMusicRepository) : } } } + diff --git a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/onlinesearch/SearchScreen.kt b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/onlinesearch/SearchScreen.kt index 4999d90..b692f64 100644 --- a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/onlinesearch/SearchScreen.kt +++ b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/onlinesearch/SearchScreen.kt @@ -57,7 +57,7 @@ import app.suhasdissa.vibeyou.presentation.screens.player.model.PlayerViewModel @Composable fun SearchScreen( onNavigate: (Destination) -> Unit, - pipedSearchViewModel: PipedSearchViewModel = viewModel(factory = PipedSearchViewModel.Factory), + pipedSearchViewModel: PipedSearchViewModel, playerViewModel: PlayerViewModel = viewModel(factory = PlayerViewModel.Factory) ) { var isPopupOpen by remember { @@ -229,8 +229,7 @@ fun SearchScreen( AlbumList( items = searchState.items, onClickCard = { - pipedSearchViewModel.getPlaylistInfo(it) - onNavigate(Destination.Playlists) + onNavigate(Destination.Playlists(it)) }, onLongPress = { } @@ -257,8 +256,7 @@ fun SearchScreen( ArtistList( items = searchState.items, onClickCard = { - pipedSearchViewModel.getChannelInfo(it) - onNavigate(Destination.Artist) + onNavigate(Destination.OnlineArtist(it)) }, onLongPress = { } diff --git a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/onlinesearch/model/PipedSearchViewModel.kt b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/onlinesearch/model/PipedSearchViewModel.kt index 776c2d8..0ba7b1a 100644 --- a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/onlinesearch/model/PipedSearchViewModel.kt +++ b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/onlinesearch/model/PipedSearchViewModel.kt @@ -6,7 +6,6 @@ import android.util.Log import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue -import androidx.core.net.toUri import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY @@ -16,13 +15,8 @@ import androidx.lifecycle.viewmodel.viewModelFactory import app.suhasdissa.vibeyou.MellowMusicApplication import app.suhasdissa.vibeyou.backend.models.SearchFilter import app.suhasdissa.vibeyou.backend.repository.PipedMusicRepository -import app.suhasdissa.vibeyou.domain.models.primary.Album -import app.suhasdissa.vibeyou.domain.models.primary.Artist import app.suhasdissa.vibeyou.domain.models.primary.Song -import app.suhasdissa.vibeyou.presentation.screens.onlinesearch.model.state.AlbumInfoState -import app.suhasdissa.vibeyou.presentation.screens.onlinesearch.model.state.ArtistInfoState import app.suhasdissa.vibeyou.presentation.screens.onlinesearch.model.state.SearchState -import app.suhasdissa.vibeyou.utils.asSong import kotlinx.coroutines.launch class PipedSearchViewModel(private val musicRepository: PipedMusicRepository) : ViewModel() { @@ -33,10 +27,6 @@ class PipedSearchViewModel(private val musicRepository: PipedMusicRepository) : var searchFilter = SearchFilter.Songs var search by mutableStateOf("") var songSearchSuggestion: List by mutableStateOf(listOf()) - var albumInfoState: AlbumInfoState by mutableStateOf(AlbumInfoState.Loading) - private set - var artistInfoState: ArtistInfoState by mutableStateOf(ArtistInfoState.Loading) - private set fun getSuggestions() { if (search.length < 3) return @@ -59,42 +49,6 @@ class PipedSearchViewModel(private val musicRepository: PipedMusicRepository) : ) } - fun getPlaylistInfo(playlist: Album) { - viewModelScope.launch { - albumInfoState = AlbumInfoState.Loading - albumInfoState = try { - val info = musicRepository.getPlaylistInfo(playlist.id) - AlbumInfoState.Success( - playlist, - info.relatedStreams.map { it.asSong } - ) - } catch (e: Exception) { - Log.e("Playlist Info", e.toString()) - AlbumInfoState.Error - } - } - } - - fun getChannelInfo(artist: Artist) { - viewModelScope.launch { - artistInfoState = ArtistInfoState.Loading - artistInfoState = try { - val info = musicRepository.getChannelInfo(artist.id) - val playlists = musicRepository.getChannelPlaylists(artist.id, info.tabs) - ArtistInfoState.Success( - artist.copy( - thumbnailUri = info.avatarUrl?.toUri(), - description = info.description - ), - playlists - ) - } catch (e: Exception) { - Log.e("Playlist Info", e.toString()) - ArtistInfoState.Error - } - } - } - fun setSearchHistory() { viewModelScope.launch { history = musicRepository.getSearchHistory().takeLast(6).reversed().map { it.query } @@ -158,4 +112,4 @@ class PipedSearchViewModel(private val musicRepository: PipedMusicRepository) : } } } -} +} \ No newline at end of file diff --git a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/playlists/PlaylistsScreen.kt b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/playlists/PlaylistsScreen.kt index 4f079ec..18f385c 100644 --- a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/playlists/PlaylistsScreen.kt +++ b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/playlists/PlaylistsScreen.kt @@ -24,8 +24,7 @@ fun PlaylistsScreen( val albums by playlistViewModel.albums.collectAsState() var selectedAlbum: Album? by remember { mutableStateOf(null) } AlbumList(items = albums.map { it.asAlbum }, onClickCard = { - playlistViewModel.getPlaylistInfo(it) - onNavigate(Destination.SavedPlaylists) + onNavigate(Destination.SavedPlaylists(it)) }, onLongPress = { selectedAlbum = it }) diff --git a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/playlists/model/PlaylistInfoViewModel.kt b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/playlists/model/PlaylistInfoViewModel.kt new file mode 100644 index 0000000..67405a6 --- /dev/null +++ b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/playlists/model/PlaylistInfoViewModel.kt @@ -0,0 +1,65 @@ +package app.suhasdissa.vibeyou.presentation.screens.playlists.model + +import android.util.Log +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.createSavedStateHandle +import androidx.lifecycle.viewModelScope +import androidx.lifecycle.viewmodel.initializer +import androidx.lifecycle.viewmodel.viewModelFactory +import androidx.navigation.toRoute +import app.suhasdissa.vibeyou.MellowMusicApplication +import app.suhasdissa.vibeyou.backend.repository.PlaylistRepository +import app.suhasdissa.vibeyou.domain.models.primary.Album +import app.suhasdissa.vibeyou.navigation.Destination +import app.suhasdissa.vibeyou.presentation.screens.onlinesearch.model.state.AlbumInfoState +import app.suhasdissa.vibeyou.utils.asSong +import kotlinx.coroutines.launch + +class PlaylistInfoViewModel( + private val playlistRepository: PlaylistRepository, + savedStateHandle: SavedStateHandle +) : ViewModel() { + val playlist = savedStateHandle.toRoute() + + var albumInfoState: AlbumInfoState by mutableStateOf(AlbumInfoState.Loading) + private set + + init { + getPlaylistInfo(playlist.album) + } + + private fun getPlaylistInfo(playlist: Album) { + viewModelScope.launch { + albumInfoState = AlbumInfoState.Loading + albumInfoState = try { + Log.e("PlaylistViewModel", "Getting info") + val info = playlistRepository.getPlaylist(playlist.id) + AlbumInfoState.Success( + playlist, + info.songs.map { it.asSong } + ) + } catch (e: Exception) { + Log.e("Playlist Info", e.toString()) + AlbumInfoState.Error + } + } + } + + companion object { + val Factory: ViewModelProvider.Factory = viewModelFactory { + initializer { + val application = + (this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as MellowMusicApplication) + PlaylistInfoViewModel( + application.container.playlistRepository, + this.createSavedStateHandle() + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/playlists/model/PlaylistViewModel.kt b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/playlists/model/PlaylistViewModel.kt index 828559e..b256736 100644 --- a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/playlists/model/PlaylistViewModel.kt +++ b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/playlists/model/PlaylistViewModel.kt @@ -1,9 +1,5 @@ package app.suhasdissa.vibeyou.presentation.screens.playlists.model -import android.util.Log -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope @@ -12,16 +8,14 @@ import androidx.lifecycle.viewmodel.viewModelFactory import app.suhasdissa.vibeyou.MellowMusicApplication import app.suhasdissa.vibeyou.backend.repository.PlaylistRepository import app.suhasdissa.vibeyou.domain.models.primary.Album -import app.suhasdissa.vibeyou.domain.models.primary.Song -import app.suhasdissa.vibeyou.presentation.screens.onlinesearch.model.state.AlbumInfoState -import app.suhasdissa.vibeyou.utils.asSong import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch -class PlaylistViewModel(private val playlistRepository: PlaylistRepository) : ViewModel() { - var albumInfoState: AlbumInfoState by mutableStateOf(AlbumInfoState.Loading) - private set +class PlaylistViewModel( + private val playlistRepository: PlaylistRepository +) : ViewModel() { + var albums = playlistRepository.getPlaylists().stateIn( scope = viewModelScope, @@ -29,29 +23,6 @@ class PlaylistViewModel(private val playlistRepository: PlaylistRepository) : Vi initialValue = listOf() ) - fun getPlaylistInfo(playlist: Album) { - viewModelScope.launch { - albumInfoState = AlbumInfoState.Loading - albumInfoState = try { - Log.e("PlaylistViewModel", "Getting info") - val info = playlistRepository.getPlaylist(playlist.id) - AlbumInfoState.Success( - playlist, - info.songs.map { it.asSong } - ) - } catch (e: Exception) { - Log.e("Playlist Info", e.toString()) - AlbumInfoState.Error - } - } - } - - fun newPlaylistWithSongs(album: Album, songs: List) { - viewModelScope.launch { - playlistRepository.newPlaylistWithSongs(album, songs) - } - } - fun deletePlaylist(album: Album) { viewModelScope.launch { playlistRepository.deletePlaylist(album) @@ -82,3 +53,4 @@ class PlaylistViewModel(private val playlistRepository: PlaylistRepository) : Vi } } } + diff --git a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/settings/AppearanceSettingsScreen.kt b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/settings/AppearanceSettingsScreen.kt index 4cc73a3..8be5241 100644 --- a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/settings/AppearanceSettingsScreen.kt +++ b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/settings/AppearanceSettingsScreen.kt @@ -19,7 +19,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel import app.suhasdissa.vibeyou.R import app.suhasdissa.vibeyou.presentation.screens.settings.components.ButtonGroupPref import app.suhasdissa.vibeyou.presentation.screens.settings.components.ColorPref @@ -29,9 +28,8 @@ import app.suhasdissa.vibeyou.utils.Pref @OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class) @Composable -fun AppearanceSettingsScreen() { +fun AppearanceSettingsScreen(settingsModel: SettingsModel) { val topBarBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior() - val settingsModel: SettingsModel = viewModel(factory = SettingsModel.Factory) Scaffold(modifier = Modifier.fillMaxSize(), topBar = { LargeTopAppBar( diff --git a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/settings/SettingsScreen.kt b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/settings/SettingsScreen.kt index bd6d84d..6700e14 100644 --- a/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/settings/SettingsScreen.kt +++ b/app/src/main/java/app/suhasdissa/vibeyou/presentation/screens/settings/SettingsScreen.kt @@ -41,7 +41,7 @@ import app.suhasdissa.vibeyou.presentation.screens.settings.components.SettingIt @Composable fun SettingsScreen( modifier: Modifier = Modifier, - onNavigate: (route: String) -> Unit + onNavigate: (Destination) -> Unit ) { var showLoginDialog by remember { mutableStateOf(false) } val authViewModel: AuthViewModel = viewModel(factory = AuthViewModel.Factory) @@ -65,7 +65,7 @@ fun SettingsScreen( SettingItem( title = stringResource(R.string.backup_restore), description = stringResource(R.string.backup_restore_setting_description), - onClick = { onNavigate(Destination.DatabaseSettings.route) }, + onClick = { onNavigate(Destination.DatabaseSettings) }, icon = Icons.Rounded.SettingsBackupRestore ) } @@ -73,7 +73,7 @@ fun SettingsScreen( SettingItem( title = stringResource(R.string.network_settings), description = stringResource(R.string.network_settings_description), - onClick = { onNavigate(Destination.NetworkSettings.route) }, + onClick = { onNavigate(Destination.NetworkSettings) }, icon = Icons.Rounded.Web ) } @@ -81,7 +81,7 @@ fun SettingsScreen( SettingItem( title = stringResource(R.string.appearance_settings), description = stringResource(R.string.appearance_settings_description), - onClick = { onNavigate(Destination.AppearanceSettings.route) }, + onClick = { onNavigate(Destination.AppearanceSettings) }, icon = Icons.Rounded.Landscape ) } @@ -109,7 +109,7 @@ fun SettingsScreen( SettingItem( title = stringResource(R.string.about_title), description = stringResource(R.string.about_setting_description), - onClick = { onNavigate(Destination.About.route) }, + onClick = { onNavigate(Destination.About) }, icon = Icons.Outlined.Info ) } diff --git a/app/src/main/java/app/suhasdissa/vibeyou/utils/UriSerializer.kt b/app/src/main/java/app/suhasdissa/vibeyou/utils/UriSerializer.kt new file mode 100644 index 0000000..67edae1 --- /dev/null +++ b/app/src/main/java/app/suhasdissa/vibeyou/utils/UriSerializer.kt @@ -0,0 +1,24 @@ +package app.suhasdissa.vibeyou.utils + +import android.net.Uri +import androidx.core.net.toUri +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +class UriSerializer : KSerializer { + + override val descriptor: SerialDescriptor = + PrimitiveSerialDescriptor("Uri", PrimitiveKind.STRING) + + override fun deserialize(decoder: Decoder): Uri { + return decoder.decodeString().toUri() + } + + override fun serialize(encoder: Encoder, value: Uri) { + encoder.encodeString(value.toString()) + } +} \ No newline at end of file