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 <jarnedemeulemeester@gmail.com>
This commit is contained in:
leekleak 2024-04-27 19:39:45 +03:00 committed by GitHub
parent f470cbed6c
commit a78dafe387
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 44 additions and 6 deletions

View file

@ -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) {

View file

@ -141,6 +141,15 @@
android:visibility="invisible" />
</RelativeLayout>
<TextView
android:id="@+id/login_disclaimer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_margin="24dp"
android:textSize="16sp"
tools:text="Sample login disclaimer" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -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 = {},

View file

@ -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>(UiState.Normal)
private val _uiState = MutableStateFlow<UiState>(UiState.Normal())
val uiState = _uiState.asStateFlow()
private val _usersState = MutableStateFlow<UsersState>(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 =