Skip to content

Commit b150ac0

Browse files
committed
bump version to 1.7.3; enhance login handling with success flag; improve authentication checks in MusicService
1 parent 40c9d6a commit b150ac0

File tree

4 files changed

+50
-25
lines changed

4 files changed

+50
-25
lines changed

src/app/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ android {
1616
minSdk = 21
1717
targetSdk = 35
1818
versionCode = 11
19-
versionName = "1.7.2"
19+
versionName = "1.7.3"
2020

2121
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
2222
vectorDrawables {

src/app/src/main/java/com/melodee/autoplayer/presentation/ui/MainActivity.kt

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import androidx.compose.runtime.Composable
2727
import androidx.compose.runtime.LaunchedEffect
2828
import androidx.compose.runtime.getValue
2929
import androidx.compose.runtime.remember
30+
import androidx.compose.runtime.saveable.rememberSaveable
3031
import androidx.compose.ui.Modifier
3132
import androidx.compose.ui.platform.LocalContext
3233
import androidx.core.content.ContextCompat
@@ -249,30 +250,31 @@ fun MainScreen(
249250
}
250251
}
251252

252-
// Handle navigation based on authentication state changes
253+
// Handle navigation when user becomes unauthenticated (e.g., logout or session expiry)
253254
LaunchedEffect(isAuthenticated) {
254255
val currentRoute = navController.currentDestination?.route
256+
Log.d("MainActivity", "LaunchedEffect(isAuthenticated): isAuthenticated=$isAuthenticated, currentRoute=$currentRoute")
255257

256-
if (isAuthenticated && currentRoute == "login") {
257-
Log.d("MainActivity", "User became authenticated, navigating to home")
258-
navController.navigate("home") {
259-
popUpTo("login") { inclusive = true }
260-
}
261-
} else if (!isAuthenticated && currentRoute != "login") {
258+
// Only handle logout case - login navigation is handled directly in onLoginSuccess callback
259+
if (!isAuthenticated && currentRoute != null && currentRoute != "login") {
262260
Log.d("MainActivity", "User became unauthenticated, navigating to login")
263261
navController.navigate("login") {
264262
popUpTo(0) { inclusive = true }
265263
}
266264
}
267265
}
268266

269-
// Determine start destination based on authentication state
270-
val startDestination = if (isAuthenticated) {
271-
Log.d("MainActivity", "User is authenticated, starting with home screen")
272-
"home"
273-
} else {
274-
Log.d("MainActivity", "User not authenticated, starting with login screen")
275-
"login"
267+
// Determine start destination based on INITIAL authentication state only
268+
// Using rememberSaveable ensures this is only computed once and survives recomposition
269+
// Navigation after login is handled by LaunchedEffect(isAuthenticated) above
270+
val startDestination = rememberSaveable {
271+
if (authenticationManager.isAuthenticated.value) {
272+
Log.d("MainActivity", "User is authenticated, starting with home screen")
273+
"home"
274+
} else {
275+
Log.d("MainActivity", "User not authenticated, starting with login screen")
276+
"login"
277+
}
276278
}
277279

278280
// Set up ViewModels when user is authenticated
@@ -547,8 +549,11 @@ fun MainScreen(
547549
// Reinitialize scrobble manager with user information
548550
onLoginSuccess(authResponse)
549551

550-
// Don't manually navigate here - let LaunchedEffect(isAuthenticated) handle it
551-
// This prevents double navigation which can cause the app to minimize
552+
// Navigate to home screen after successful login
553+
Log.d("MainActivity", "Login successful, navigating to home")
554+
navController.navigate("home") {
555+
popUpTo("login") { inclusive = true }
556+
}
552557
}
553558
)
554559
}

src/app/src/main/java/com/melodee/autoplayer/presentation/ui/login/LoginScreen.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ fun LoginScreen(
3434
var emailOrUsername by remember { mutableStateOf("") }
3535
var password by remember { mutableStateOf("") }
3636
var serverUrl by remember { mutableStateOf(viewModel.serverUrl) }
37+
var hasHandledSuccess by remember { mutableStateOf(false) }
3738

3839
val loginState by viewModel.loginState.collectAsStateWithLifecycle()
3940
val isLoading by viewModel.isLoading.collectAsStateWithLifecycle()
@@ -53,11 +54,14 @@ fun LoginScreen(
5354
// Function to handle login
5455
val handleLogin = {
5556
keyboardController?.hide()
57+
hasHandledSuccess = false // Reset flag for new login attempt
5658
viewModel.login(emailOrUsername, password, serverUrl)
5759
}
5860

61+
// Handle login success only once per successful login
5962
LaunchedEffect(loginState) {
60-
if (loginState is LoginState.Success) {
63+
if (loginState is LoginState.Success && !hasHandledSuccess) {
64+
hasHandledSuccess = true
6165
onLoginSuccess((loginState as LoginState.Success).response)
6266
}
6367
}

src/app/src/main/java/com/melodee/autoplayer/service/MusicService.kt

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -313,8 +313,7 @@ class MusicService : MediaBrowserServiceCompat() {
313313

314314
private fun loadPlaylists(result: Result<List<MediaBrowserCompat.MediaItem>>) {
315315
// Check authentication first
316-
val authToken = NetworkModule.getAuthToken()
317-
if (authToken.isNullOrEmpty()) {
316+
if (!ensureAuthentication()) {
318317
Log.w("MusicService", "No auth token available for playlists")
319318
val errorItems = listOf(
320319
MediaBrowserCompat.MediaItem(
@@ -454,8 +453,7 @@ class MusicService : MediaBrowserServiceCompat() {
454453

455454
private fun loadPlaylistSongs(playlistId: String, result: Result<List<MediaBrowserCompat.MediaItem>>) {
456455
// Check authentication first
457-
val authToken = NetworkModule.getAuthToken()
458-
if (authToken.isNullOrEmpty()) {
456+
if (!ensureAuthentication()) {
459457
Log.w("MusicService", "No auth token available for playlist songs")
460458
val errorItems = listOf(
461459
MediaBrowserCompat.MediaItem(
@@ -698,10 +696,10 @@ class MusicService : MediaBrowserServiceCompat() {
698696
Log.d("MusicService", "Starting API search for: '$query'")
699697

700698
// Check if we have authentication
701-
val authToken = NetworkModule.getAuthToken()
702-
Log.d("MusicService", "Auth token available: ${!authToken.isNullOrEmpty()}")
699+
val isAuthenticated = ensureAuthentication()
700+
Log.d("MusicService", "Auth token available: $isAuthenticated")
703701

704-
if (authToken.isNullOrEmpty()) {
702+
if (!isAuthenticated) {
705703
Log.w("MusicService", "No auth token available for search")
706704
return@withContext listOf(
707705
MediaBrowserCompat.MediaItem(
@@ -2372,6 +2370,24 @@ class MusicService : MediaBrowserServiceCompat() {
23722370
return isFullyAuthenticated
23732371
}
23742372

2373+
private fun ensureAuthentication(): Boolean {
2374+
// Fast path: if NetworkModule has token, we are good
2375+
if (NetworkModule.isAuthenticated()) {
2376+
return true
2377+
}
2378+
2379+
Log.w("MusicService", "NetworkModule not authenticated, attempting to restore from storage")
2380+
2381+
// Try to restore from persistent storage
2382+
if (authenticationManager.restoreAuthenticationFromStorage()) {
2383+
Log.i("MusicService", "Authentication restored from storage")
2384+
return true
2385+
}
2386+
2387+
Log.w("MusicService", "Failed to restore authentication")
2388+
return false
2389+
}
2390+
23752391
private fun handlePlaybackFailure(song: Song, error: Exception) {
23762392
Log.e("MusicService", "=== PLAYBACK FAILURE HANDLER ===")
23772393
Log.e("MusicService", "Failed song: ${song.title}")

0 commit comments

Comments
 (0)