From 9a7297281e3e97423c20e37887251594e144db8a Mon Sep 17 00:00:00 2001 From: Owen LeJeune Date: Wed, 31 May 2023 21:43:17 -0400 Subject: [PATCH] remove guest session code --- .../api/tmdb/api/v3/AuthenticationApi.kt | 15 -- .../api/tmdb/api/v3/AuthenticationService.kt | 20 -- .../tvtime/ui/components/SignInDialog.kt | 176 ------------------ .../tvtime/ui/screens/main/AccountTab.kt | 102 +--------- .../tvtime/ui/screens/main/MediaDetailView.kt | 32 ---- .../tvtime/ui/screens/main/SettingsTab.kt | 5 - .../tvtime/utils/SessionManager.kt | 125 +------------ 7 files changed, 13 insertions(+), 462 deletions(-) delete mode 100644 app/src/main/java/com/owenlejeune/tvtime/ui/components/SignInDialog.kt diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/AuthenticationApi.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/AuthenticationApi.kt index ce576aa..90393b7 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/AuthenticationApi.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/AuthenticationApi.kt @@ -9,21 +9,6 @@ import retrofit2.http.POST interface AuthenticationApi { - @GET("authentication/guest_session/new") - suspend fun getNewGuestSession(): Response - - @HTTP(method = "DELETE", path = "authentication/session", hasBody = true) - suspend fun deleteSession(@Body body: SessionBody): Response - - @GET("authentication/token/new") - suspend fun createRequestToken(): Response - - @POST("authentication/session/new") - suspend fun createSession(@Body body: TokenSessionBody): Response - - @POST("authentication/token/validate_with_login") - suspend fun validateTokenWithLogin(@Body body: TokenValidationBody): Response - @POST("authentication/session/convert/4") suspend fun createSessionFromV4Token(@Body body: V4TokenBody): Response } \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/AuthenticationService.kt b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/AuthenticationService.kt index f24e76d..1cce944 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/AuthenticationService.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/api/tmdb/api/v3/AuthenticationService.kt @@ -8,26 +8,6 @@ class AuthenticationService { private val service by lazy { TmdbClient().createAuthenticationService() } - suspend fun getNewGuestSession(): Response { - return service.getNewGuestSession() - } - - suspend fun deleteSession(body: SessionBody): Response { - return service.deleteSession(body) - } - - suspend fun createRequestToken(): Response { - return service.createRequestToken() - } - - suspend fun createSession(body: TokenSessionBody): Response { - return service.createSession(body) - } - - suspend fun validateTokenWithLogin(body: TokenValidationBody): Response { - return service.validateTokenWithLogin(body) - } - suspend fun createSessionFromV4Token(body: V4TokenBody): Response { return service.createSessionFromV4Token(body) } diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/components/SignInDialog.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/components/SignInDialog.kt deleted file mode 100644 index 4395507..0000000 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/components/SignInDialog.kt +++ /dev/null @@ -1,176 +0,0 @@ -package com.owenlejeune.tvtime.ui.components - -import android.content.Intent -import android.net.Uri -import android.text.TextUtils -import android.widget.Toast -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.text.KeyboardActions -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.ui.ExperimentalComposeUiApi -import androidx.compose.ui.Modifier -import androidx.compose.ui.focus.FocusDirection -import androidx.compose.ui.input.key.Key -import androidx.compose.ui.input.key.key -import androidx.compose.ui.input.key.onPreviewKeyEvent -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalFocusManager -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.input.ImeAction -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import com.owenlejeune.tvtime.R -import com.owenlejeune.tvtime.utils.SessionManager -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext - -@OptIn(ExperimentalComposeUiApi::class) -@Composable -fun SignInDialog( - showDialog: MutableState, - onSuccess: (success: Boolean) -> Unit -) { - val context = LocalContext.current - - var usernameState by rememberSaveable { mutableStateOf("") } - var usernameHasErrors by rememberSaveable { mutableStateOf(false) } - var usernameError = "" - - var passwordState by rememberSaveable { mutableStateOf("") } - var passwordHasErrors by rememberSaveable { mutableStateOf(false) } - var passwordError = "" - - fun validate(): Boolean { - usernameError = "" - passwordError = "" - - if (TextUtils.isEmpty(usernameState)) { - usernameError = context.getString(R.string.username_not_empty_error) - } - - if (TextUtils.isEmpty(passwordState)) { - passwordError = context.getString(R.string.password_empty_error) - } - - usernameHasErrors = usernameError.isNotEmpty() - passwordHasErrors = passwordError.isNotEmpty() - - return !usernameHasErrors && !passwordHasErrors - } - - val focusManager = LocalFocusManager.current - - AlertDialog( - title = { Text(text = stringResource(R.string.action_sign_in)) }, - onDismissRequest = { showDialog.value = false }, - confirmButton = { CancelButton(showDialog = showDialog) }, - text = { - Column( - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - Text( - text = stringResource(R.string.sign_in_dialog_message) - ) - ThemedOutlineTextField( - value = usernameState, - onValueChange = { - usernameHasErrors = false - usernameState = it - }, - label = { Text(text = stringResource(R.string.username_label)) }, - isError = usernameHasErrors, - errorMessage = usernameError, - singleLine = true - ) - PasswordOutlineTextField( - value = passwordState, - onValueChange = { - passwordHasErrors = false - passwordState = it - }, - label = { Text(text = stringResource(R.string.password_label)) }, - isError = passwordHasErrors, - errorMessage = passwordError, - singleLine = true - ) - SignInButton(username = usernameState, password = passwordState, validate = ::validate) { success -> - if (success) { - showDialog.value = false - } else { - Toast.makeText(context, "An error occurred, please try again", Toast.LENGTH_SHORT).show() - } - onSuccess(success) - } - CreateAccountLink() - } - } - ) -} - -@Composable -private fun CancelButton(showDialog: MutableState) { - TextButton(onClick = { showDialog.value = false }) { - Text(text = stringResource(R.string.action_cancel)) - } -} - -@Composable -private fun SignInButton(username: String, password: String, validate: () -> Boolean, onSuccess: (success: Boolean) -> Unit) { - var signInInProgress by remember { mutableStateOf(false) } - Button( - modifier = Modifier.fillMaxWidth(), - onClick = { - if (!signInInProgress) { - if (validate()) { - signInInProgress = true - CoroutineScope(Dispatchers.IO).launch { - val success = SessionManager.signInWithLogin(username, password) - withContext(Dispatchers.Main) { - signInInProgress = false - onSuccess(success) - } - } - } - } - } - ) { - if (signInInProgress) { - CircularProgressIndicator( - modifier = Modifier.size(20.dp), - color = MaterialTheme.colorScheme.background, - strokeWidth = 2.dp - ) - } else { - Text(text = stringResource(id = R.string.action_sign_in), color = MaterialTheme.colorScheme.background) - } - } - -} - -@Composable -private fun CreateAccountLink() { - val context = LocalContext.current - LinkableText( - text = stringResource(R.string.no_account_message), - textAlign = TextAlign.Center, - modifier = Modifier - .fillMaxWidth() - .clickable( - onClick = { - val url = "https://www.themoviedb.org/signup" - val intent = Intent(Intent.ACTION_VIEW) - intent.data = Uri.parse(url) - context.startActivity(intent) - } - ) - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/main/AccountTab.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/main/AccountTab.kt index 3463512..999ee6f 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/main/AccountTab.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/main/AccountTab.kt @@ -1,12 +1,9 @@ package com.owenlejeune.tvtime.ui.screens.main import android.content.Context -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.AccountCircle import androidx.compose.material3.* @@ -16,19 +13,13 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.blur import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.constraintlayout.compose.ConstraintLayout -import androidx.constraintlayout.compose.Dimension import androidx.navigation.NavHostController import androidx.paging.compose.collectAsLazyPagingItems import coil.compose.AsyncImage @@ -43,7 +34,6 @@ import com.owenlejeune.tvtime.extensions.unlessEmpty import com.owenlejeune.tvtime.preferences.AppPreferences import com.owenlejeune.tvtime.ui.components.PagingPosterGrid import com.owenlejeune.tvtime.ui.components.RoundedLetterImage -import com.owenlejeune.tvtime.ui.components.SignInDialog import com.owenlejeune.tvtime.ui.navigation.AccountTabNavItem import com.owenlejeune.tvtime.ui.navigation.ListFetchFun import com.owenlejeune.tvtime.ui.navigation.MainNavItem @@ -114,13 +104,8 @@ fun AccountTab( } Column { - when (session.isAuthorized) { - true -> { - AuthorizedSessionIcon() - } - false -> { - GuestSessionIcon() - } + if (session.isAuthorized) { + AuthorizedSessionIcon() } val pagerState = rememberPagerState() @@ -342,7 +327,8 @@ private fun AccountDropdownMenu( ) { when(session?.isAuthorized) { true -> { AuthorizedSessionMenuItems(expanded = expanded, lastSelectedOption = lastSelectedOption) } - false -> { GuestSessionMenuItems(expanded = expanded, lastSelectedOption = lastSelectedOption) } +// false -> { GuestSessionMenuItems(expanded = expanded, lastSelectedOption = lastSelectedOption) } + false -> {} null -> { NoSessionMenuItems(expanded = expanded, lastSelectedOption = lastSelectedOption) } } } @@ -360,60 +346,19 @@ private fun AuthorizedSessionMenuItems( if (preferences.useV4Api) { signOutV4(lastSelectedOption) } else { - signOut(lastSelectedOption) +// signOut(lastSelectedOption) } expanded.value = false } ) } -@Composable -private fun GuestSessionMenuItems( - expanded: MutableState, - lastSelectedOption: MutableState -) { - val showSignInDialog = remember { mutableStateOf(false) } - - if (showSignInDialog.value) { - SignInDialog(showDialog = showSignInDialog) { success -> - if (success) { - lastSelectedOption.value = GUEST_SIGN_IN - expanded.value = false - } - } - } - - DropdownMenuItem( - text = { Text(text = stringResource(id = R.string.action_sign_in)) }, - onClick = { showSignInDialog.value = true } - ) - - DropdownMenuItem( - text = { Text(text = stringResource(id = R.string.action_sign_out)) }, - onClick = { - signOut(lastSelectedOption) - expanded.value = false - } - ) -} - @Composable private fun NoSessionMenuItems( expanded: MutableState, lastSelectedOption: MutableState, preferences: AppPreferences = get(AppPreferences::class.java) ) { - val showSignInDialog = remember { mutableStateOf(false) } - - if (showSignInDialog.value) { - SignInDialog(showDialog = showSignInDialog) { success -> - if (success) { - lastSelectedOption.value = NO_SESSION_SIGN_IN - expanded.value = false - } - } - } - val context = LocalContext.current DropdownMenuItem( text = { Text(text = stringResource(id = R.string.action_sign_in)) }, @@ -421,18 +366,10 @@ private fun NoSessionMenuItems( if (preferences.useV4Api) { v4SignInPart1(context) } else { - showSignInDialog.value = true +// showSignInDialog.value = true } } ) - - DropdownMenuItem( - text = { Text(text = stringResource(id = R.string.action_sign_in_as_guest)) }, - onClick = { - createGuestSession(lastSelectedOption) - expanded.value = false - } - ) } private fun v4SignInPart1(context: Context) { @@ -452,12 +389,6 @@ private fun v4SignInPart2(lastSelectedOption: MutableState) { } } -@Composable -private fun GuestSessionIcon() { - val guestName = stringResource(id = R.string.account_name_guest) - RoundedLetterImage(size = 60.dp, character = guestName[0]) -} - @Composable private fun AuthorizedSessionIcon() { val accountDetails = SessionManager.currentSession?.accountDetails @@ -492,27 +423,6 @@ private fun AuthorizedSessionIcon() { } } -private fun createGuestSession(lastSelectedOption: MutableState) { - CoroutineScope(Dispatchers.IO).launch { - val session = SessionManager.requestNewGuestSession() - if (session != null) { - withContext(Dispatchers.Main) { - lastSelectedOption.value = NO_SESSION_SIGN_IN_GUEST - } - } - } -} - -private fun signOut(lastSelectedOption: MutableState) { - CoroutineScope(Dispatchers.IO).launch { - SessionManager.clearSession { isSuccessful -> - if (isSuccessful) { - lastSelectedOption.value = SIGN_OUT - } - } - } -} - private fun signOutV4(lastSelectedOption: MutableState) { CoroutineScope(Dispatchers.IO).launch { SessionManager.clearSessionV4 { isSuccessful -> diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/main/MediaDetailView.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/main/MediaDetailView.kt index 777fd53..71b4754 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/main/MediaDetailView.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/main/MediaDetailView.kt @@ -531,22 +531,6 @@ private fun CreateSessionDialog(showDialog: MutableState, onSessionRetu }, text = { Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { - Button( - modifier = Modifier.fillMaxWidth(), - onClick = { - CoroutineScope(Dispatchers.IO).launch { - SessionManager.requestNewGuestSession()?.let { - withContext(Dispatchers.Main) { - showDialog.value = false - onSessionReturned(true) - } - } - } - } - ) { - Text(text = stringResource(R.string.action_continue_as_guest)) - } - Button( modifier = Modifier.fillMaxWidth(), onClick = { @@ -1318,20 +1302,4 @@ private fun addToFavorite( } } } -} - -@Composable -private fun ActionSnackBar( - message: String -) { - val scope = rememberCoroutineScope() - val snackbarHostState = remember { SnackbarHostState() } - - SnackbarHost(hostState = snackbarHostState) - - LaunchedEffect(Unit) { - scope.launch { - snackbarHostState.showSnackbar(message) - } - } } \ No newline at end of file diff --git a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/main/SettingsTab.kt b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/main/SettingsTab.kt index 44449b5..550d3b5 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/ui/screens/main/SettingsTab.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/ui/screens/main/SettingsTab.kt @@ -482,11 +482,6 @@ private fun DevPreferences( onClick = { preferences.guestSessionId = "" coroutineScope.launch { - SessionManager.clearSession { - Toast - .makeText(context, "Cleared session: $it", Toast.LENGTH_SHORT) - .show() - } SessionManager.clearSessionV4 { Toast .makeText( diff --git a/app/src/main/java/com/owenlejeune/tvtime/utils/SessionManager.kt b/app/src/main/java/com/owenlejeune/tvtime/utils/SessionManager.kt index baf3fd3..70a8ea6 100644 --- a/app/src/main/java/com/owenlejeune/tvtime/utils/SessionManager.kt +++ b/app/src/main/java/com/owenlejeune/tvtime/utils/SessionManager.kt @@ -1,19 +1,13 @@ package com.owenlejeune.tvtime.utils -import android.accounts.Account import android.content.Context import android.content.Intent import android.net.Uri -import android.widget.Toast import com.google.gson.annotations.SerializedName import com.owenlejeune.tvtime.R -import com.owenlejeune.tvtime.api.tmdb.api.v3.AccountService -import com.owenlejeune.tvtime.api.tmdb.api.v3.AuthenticationService -import com.owenlejeune.tvtime.api.tmdb.api.v3.GuestSessionService import com.owenlejeune.tvtime.api.tmdb.TmdbClient -import com.owenlejeune.tvtime.api.tmdb.api.v3.AccountApi +import com.owenlejeune.tvtime.api.tmdb.api.v3.AccountService import com.owenlejeune.tvtime.api.tmdb.api.v3.model.* -import com.owenlejeune.tvtime.api.tmdb.api.v4.AccountV4Api import com.owenlejeune.tvtime.api.tmdb.api.v4.AccountV4Service import com.owenlejeune.tvtime.api.tmdb.api.v4.AuthenticationV4Service import com.owenlejeune.tvtime.api.tmdb.api.v4.model.AuthAccessBody @@ -48,22 +42,6 @@ object SessionManager: KoinComponent { @SerializedName("account_id") val accountId: String ) - suspend fun clearSession(onResponse: (isSuccessful: Boolean) -> Unit) { - currentSession?.let { session -> - CoroutineScope(Dispatchers.IO).launch { - val deleteResponse = authenticationService.deleteSession(SessionBody(session.sessionId)) - withContext(Dispatchers.Main) { - if (deleteResponse.isSuccessful) { - _currentSession = null - preferences.guestSessionId = "" - preferences.authorizedSessionValues = null - } - onResponse(deleteResponse.isSuccessful) - } - } - } - } - fun clearSessionV4(onResponse: (isSuccessful: Boolean) -> Unit) { currentSession?.let { session -> CoroutineScope(Dispatchers.IO).launch { @@ -81,68 +59,17 @@ object SessionManager: KoinComponent { } suspend fun initialize() { - if (preferences.guestSessionId.isNotEmpty()) { - val session = GuestSession() - session.initialize() + preferences.authorizedSessionValues?.let { values -> + val session = AuthorizedSession( + sessionId = values.sessionId, + accessToken = values.accessToken, + accountId = values.accountId + ) _currentSession = session - } else if (preferences.authorizedSessionId.isNotEmpty()) { - val session = AuthorizedSession() session.initialize() - _currentSession = session - } else { - preferences.authorizedSessionValues?.let { values -> - val session = AuthorizedSession( - sessionId = values.sessionId, - accessToken = values.accessToken, - accountId = values.accountId - ) - _currentSession = session - session.initialize() - } } } - suspend fun requestNewGuestSession(): Session? { - val response = authenticationService.getNewGuestSession() - if (response.isSuccessful) { - preferences.guestSessionId = response.body()?.guestSessionId ?: "" - _currentSession = GuestSession() - } - return _currentSession - } - - suspend fun signInWithLogin(username: String, password: String): Boolean { - val service = AuthenticationService() - val createTokenResponse = service.createRequestToken() - if (createTokenResponse.isSuccessful) { - createTokenResponse.body()?.let { ctr -> - val body = TokenValidationBody(username, password, ctr.requestToken) - val loginResponse = service.validateTokenWithLogin(body) - if (loginResponse.isSuccessful) { - loginResponse.body()?.let { lr -> - if (lr.success) { - val sessionBody = TokenSessionBody(lr.requestToken) - val sessionResponse = service.createSession(sessionBody) - if (sessionResponse.isSuccessful) { - sessionResponse.body()?.let { sr -> - if (sr.isSuccess) { - preferences.authorizedSessionId = sr.sessionId - preferences.guestSessionId = "" - preferences.authorizedSessionValues = null - _currentSession = AuthorizedSession() - _currentSession?.initialize() - return true - } - } - } - } - } - } - } - } - return false - } - suspend fun signInWithV4Part1(context: Context) { isV4SignInInProgress = true @@ -409,42 +336,4 @@ object SessionManager: KoinComponent { } } - private class GuestSession: Session(preferences.guestSessionId, false) { - private val service by lazy { GuestSessionService() } - - override suspend fun initialize() { - refresh() - } - - override suspend fun refresh(changed: Array) { - if (changed.contains(Changed.RatedMovies)) { - service.getRatedMovies(sessionId).apply { - if (isSuccessful) { - withContext(Dispatchers.Main) { - _ratedMovies = body()?.results ?: _ratedMovies - } - } - } - } - if (changed.contains(Changed.RatedTv)) { - service.getRatedTvShows(sessionId).apply { - if (isSuccessful) { - withContext(Dispatchers.Main) { - _ratedTvShows = body()?.results ?: _ratedTvShows - } - } - } - } - if (changed.contains(Changed.RatedEpisodes)) { - service.getRatedTvEpisodes(sessionId).apply { - if (isSuccessful) { - withContext(Dispatchers.Main) { - _ratedTvEpisodes = body()?.results ?: _ratedTvEpisodes - } - } - } - } - } - } - } \ No newline at end of file