From a78dafe387e7abb30fb5b73e92bf1f5485c70d0f Mon Sep 17 00:00:00 2001 From: leekleak <142348248+leekleak@users.noreply.github.com> Date: Sat, 27 Apr 2024 19:39:45 +0300 Subject: [PATCH] feat: add login disclaimer support (#721) * add login disclaimer support * refactor: move disclaimer to `UiState.Normal` This makes more sense in the current architecture * feat: add login disclaimer to tv version * refactor: add margin to bottom of disclaimer * lint: add missing trailing comma --------- Co-authored-by: Jarne Demeulemeester --- .../jdtech/jellyfin/fragments/LoginFragment.kt | 9 +++++++-- .../src/main/res/layout/fragment_login.xml | 9 +++++++++ .../java/dev/jdtech/jellyfin/ui/LoginScreen.kt | 15 ++++++++++++++- .../jellyfin/viewmodels/LoginViewModel.kt | 17 ++++++++++++++--- 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/app/phone/src/main/java/dev/jdtech/jellyfin/fragments/LoginFragment.kt b/app/phone/src/main/java/dev/jdtech/jellyfin/fragments/LoginFragment.kt index a98864a6..813196ff 100644 --- a/app/phone/src/main/java/dev/jdtech/jellyfin/fragments/LoginFragment.kt +++ b/app/phone/src/main/java/dev/jdtech/jellyfin/fragments/LoginFragment.kt @@ -1,6 +1,7 @@ package dev.jdtech.jellyfin.fragments import android.os.Bundle +import android.text.Html.fromHtml import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -82,7 +83,7 @@ class LoginFragment : Fragment() { viewModel.uiState.collect { uiState -> Timber.d("$uiState") when (uiState) { - is LoginViewModel.UiState.Normal -> bindUiStateNormal() + is LoginViewModel.UiState.Normal -> bindUiStateNormal(uiState) is LoginViewModel.UiState.Error -> bindUiStateError(uiState) is LoginViewModel.UiState.Loading -> bindUiStateLoading() } @@ -135,11 +136,15 @@ class LoginFragment : Fragment() { return binding.root } - private fun bindUiStateNormal() { + private fun bindUiStateNormal(uiState: LoginViewModel.UiState.Normal) { binding.buttonLogin.isEnabled = true binding.progressCircular.isVisible = false binding.editTextUsernameLayout.isEnabled = true binding.editTextPasswordLayout.isEnabled = true + + uiState.disclaimer?.let { disclaimer -> + binding.loginDisclaimer.text = fromHtml(disclaimer, 0) + } } private fun bindUiStateError(uiState: LoginViewModel.UiState.Error) { diff --git a/app/phone/src/main/res/layout/fragment_login.xml b/app/phone/src/main/res/layout/fragment_login.xml index 79d80833..7b898e95 100644 --- a/app/phone/src/main/res/layout/fragment_login.xml +++ b/app/phone/src/main/res/layout/fragment_login.xml @@ -141,6 +141,15 @@ android:visibility="invisible" /> + + diff --git a/app/tv/src/main/java/dev/jdtech/jellyfin/ui/LoginScreen.kt b/app/tv/src/main/java/dev/jdtech/jellyfin/ui/LoginScreen.kt index 629f1ced..84e60508 100644 --- a/app/tv/src/main/java/dev/jdtech/jellyfin/ui/LoginScreen.kt +++ b/app/tv/src/main/java/dev/jdtech/jellyfin/ui/LoginScreen.kt @@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.text.KeyboardOptions @@ -110,6 +111,14 @@ private fun LoginScreenLayout( else -> Unit } + var disclaimer: String? by remember { + mutableStateOf(null) + } + + if (uiState is LoginViewModel.UiState.Normal) { + disclaimer = uiState.disclaimer + } + val isError = uiState is LoginViewModel.UiState.Error val isLoading = uiState is LoginViewModel.UiState.Loading @@ -241,6 +250,10 @@ private fun LoginScreenLayout( } } } + Text( + text = disclaimer ?: "", + modifier = Modifier.padding(MaterialTheme.spacings.default), + ) } } @@ -254,7 +267,7 @@ private fun LoginScreenLayout( private fun LoginScreenLayoutPreview() { FindroidTheme { LoginScreenLayout( - uiState = LoginViewModel.UiState.Normal, + uiState = LoginViewModel.UiState.Normal(), quickConnectUiState = LoginViewModel.QuickConnectUiState.Normal, onLoginClick = { _, _ -> }, onQuickConnectClick = {}, diff --git a/core/src/main/java/dev/jdtech/jellyfin/viewmodels/LoginViewModel.kt b/core/src/main/java/dev/jdtech/jellyfin/viewmodels/LoginViewModel.kt index 81f7fcea..7f2f2314 100644 --- a/core/src/main/java/dev/jdtech/jellyfin/viewmodels/LoginViewModel.kt +++ b/core/src/main/java/dev/jdtech/jellyfin/viewmodels/LoginViewModel.kt @@ -19,6 +19,7 @@ import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.jellyfin.sdk.api.client.extensions.authenticateWithQuickConnect +import org.jellyfin.sdk.api.client.extensions.brandingApi import org.jellyfin.sdk.model.api.AuthenticateUserByName import org.jellyfin.sdk.model.api.AuthenticationResult import javax.inject.Inject @@ -32,7 +33,7 @@ constructor( private val jellyfinApi: JellyfinApi, private val database: ServerDatabaseDao, ) : ViewModel() { - private val _uiState = MutableStateFlow(UiState.Normal) + private val _uiState = MutableStateFlow(UiState.Normal()) val uiState = _uiState.asStateFlow() private val _usersState = MutableStateFlow(UsersState.Loading) val usersState = _usersState.asStateFlow() @@ -44,8 +45,10 @@ constructor( private var quickConnectJob: Job? = null + private var loginDisclaimer: String? = null + sealed class UiState { - data object Normal : UiState() + data class Normal(val disclaimer: String? = null) : UiState() data object Loading : UiState() data class Error(val message: UiText) : UiState() } @@ -62,10 +65,18 @@ constructor( } init { + loadDisclaimer() loadPublicUsers() loadQuickConnectAvailable() } + private fun loadDisclaimer() { + viewModelScope.launch { + loginDisclaimer = jellyfinApi.api.brandingApi.getBrandingOptions().content.loginDisclaimer + _uiState.emit(UiState.Normal(loginDisclaimer)) + } + } + private fun loadPublicUsers() { viewModelScope.launch { _usersState.emit(UsersState.Loading) @@ -121,7 +132,7 @@ constructor( saveAuthenticationResult(authenticationResult) - _uiState.emit(UiState.Normal) + _uiState.emit(UiState.Normal(loginDisclaimer)) eventsChannel.send(LoginEvent.NavigateToHome) } catch (e: Exception) { val message =