diff --git a/app/src/main/java/com/infbyte/amuzic/data/Datastore.kt b/app/src/main/java/com/infbyte/amuzic/data/Datastore.kt index 34a1aaf..4eb9c88 100644 --- a/app/src/main/java/com/infbyte/amuzic/data/Datastore.kt +++ b/app/src/main/java/com/infbyte/amuzic/data/Datastore.kt @@ -4,6 +4,7 @@ import android.content.Context import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.booleanPreferencesKey import androidx.datastore.preferences.core.edit +import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.preferencesDataStore import kotlinx.coroutines.flow.collectLatest @@ -11,6 +12,7 @@ private const val NAME = "AmuzicDatastore" private val Context.Datastore by preferencesDataStore(NAME) val TERMS_ACCEPTED_KEY = booleanPreferencesKey("terms_accepted_key") +val LAST_PLAYED_SONG = stringPreferencesKey("last_played_song") suspend fun Context.writeBoolean( key: Preferences.Key, diff --git a/app/src/main/java/com/infbyte/amuzic/ui/activities/MainActivity.kt b/app/src/main/java/com/infbyte/amuzic/ui/activities/MainActivity.kt index 8bd9f95..eeab8d8 100644 --- a/app/src/main/java/com/infbyte/amuzic/ui/activities/MainActivity.kt +++ b/app/src/main/java/com/infbyte/amuzic/ui/activities/MainActivity.kt @@ -38,9 +38,11 @@ import com.infbyte.amuze.ui.screens.NoMediaPermissionScreen import com.infbyte.amuzic.BuildConfig import com.infbyte.amuzic.R import com.infbyte.amuzic.contracts.AppSettingsContract +import com.infbyte.amuzic.data.LAST_PLAYED_SONG import com.infbyte.amuzic.data.TERMS_ACCEPTED_KEY import com.infbyte.amuzic.data.readBoolean import com.infbyte.amuzic.data.writeBoolean +import com.infbyte.amuzic.data.writeString import com.infbyte.amuzic.playback.AmuzicPlayerService import com.infbyte.amuzic.ui.dialogs.AppSettingsRedirectDialog import com.infbyte.amuzic.ui.dialogs.PrivacyPolicyDialog @@ -110,7 +112,9 @@ class MainActivity : ComponentActivity() { } if (!songsViewModel.state.isLoaded) { - songsViewModel.setReadPermGranted(isReadPermissionGranted(this@MainActivity)) + songsViewModel.setReadPermGranted( + isReadPermissionGranted(this@MainActivity), + ) if (!songsViewModel.state.isReadPermGranted) { readBoolean(TERMS_ACCEPTED_KEY) { accepted -> songsViewModel.setTermsAccepted(accepted) @@ -327,6 +331,10 @@ class MainActivity : ComponentActivity() { } } + private suspend fun persistLastPlayedSong() { + writeString(LAST_PLAYED_SONG, songsViewModel.state.currentSong.id) + } + private fun onExit() { if (!songsViewModel.confirmExit) { Toast.makeText( @@ -337,7 +345,10 @@ class MainActivity : ComponentActivity() { .show() songsViewModel.confirmExit() } else { - finish() + lifecycleScope.launch { + persistLastPlayedSong() + finish() + } } } } diff --git a/app/src/main/java/com/infbyte/amuzic/ui/viewmodel/SongsViewModel.kt b/app/src/main/java/com/infbyte/amuzic/ui/viewmodel/SongsViewModel.kt index eb20bf2..d3d4635 100644 --- a/app/src/main/java/com/infbyte/amuzic/ui/viewmodel/SongsViewModel.kt +++ b/app/src/main/java/com/infbyte/amuzic/ui/viewmodel/SongsViewModel.kt @@ -8,13 +8,16 @@ import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.graphics.asImageBitmap import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import androidx.media3.common.MediaItem import androidx.media3.common.Player import androidx.media3.common.Player.RepeatMode +import com.infbyte.amuzic.data.LAST_PLAYED_SONG import com.infbyte.amuzic.data.model.Album import com.infbyte.amuzic.data.model.Artist import com.infbyte.amuzic.data.model.NotificationMessage import com.infbyte.amuzic.data.model.Playlist import com.infbyte.amuzic.data.model.Song +import com.infbyte.amuzic.data.readString import com.infbyte.amuzic.data.repo.PlaylistsRepo import com.infbyte.amuzic.data.repo.SongsRepo import com.infbyte.amuzic.playback.AmuzicPlayer @@ -111,12 +114,26 @@ class SongsViewModel } fun init(context: Context) { - viewModelScope.launch { playlistsRepo.init(Path(context.filesDir.path)) } + viewModelScope.launch { + playlistsRepo.init(Path(context.filesDir.path)) + context.readString(LAST_PLAYED_SONG) { mediaId -> + setCurrentSong(mediaId) + } + } refreshController(context) loadSongs() loadPlaylists() } + fun setCurrentSong(mediaId: String?) { + viewModelScope.launch { + if (mediaId != null) { + val song = Song(MediaItem.Builder().setMediaId(mediaId).build()) + state = state.copy(currentSong = song) + } + } + } + fun confirmExit() { viewModelScope.launch { confirmExit = true @@ -477,9 +494,13 @@ class SongsViewModel if (state.isRefreshing && songs.isEmpty()) { delay(1000) } + val currentSong = + songs.find { it.id == state.currentSong.id } + ?: songs.tryGetFirst { state.currentSong } + val currentSongIndex = songs.indexOf(currentSong) + state = state.copy( - currentSong = songs.tryGetFirst { state.currentSong }, songs = songs, currentSongs = songs, artists = songsRepo.artists, @@ -494,6 +515,7 @@ class SongsViewModel sideEffect = sideEffect.copy(showSplash = false) launch(Dispatchers.Main) { amuzicPlayer.createPlayList(songs.map { it.item }) + amuzicPlayer.selectSong(currentSongIndex, 0) } } },