Skip to content

Commit

Permalink
refactor(ui): improve add account dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
Ashinch committed Feb 1, 2024
1 parent 7400cdf commit 39af42a
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,19 @@ import androidx.compose.material.icons.rounded.Close
import androidx.compose.material.icons.rounded.ContentPaste
import androidx.compose.material.icons.rounded.Visibility
import androidx.compose.material.icons.rounded.VisibilityOff
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
Expand All @@ -23,6 +34,7 @@ import me.ash.reader.R
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun RYOutlineTextField(
requestFocus: Boolean = true,
readOnly: Boolean = false,
value: String,
label: String = "",
Expand All @@ -40,8 +52,10 @@ fun RYOutlineTextField(
var showPassword by remember { mutableStateOf(false) }

LaunchedEffect(Unit) {
delay(100) // ???
focusRequester.requestFocus()
if (requestFocus) {
delay(100) // ???
focusRequester.requestFocus()
}
}

OutlinedTextField(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.DeleteSweep
import androidx.compose.material.icons.outlined.PersonOff
import androidx.compose.material.icons.rounded.ArrowBack
import androidx.compose.material.icons.rounded.Close
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
Expand Down Expand Up @@ -55,6 +56,7 @@ import me.ash.reader.ui.ext.getCurrentVersion
import me.ash.reader.ui.ext.showToast
import me.ash.reader.ui.ext.showToastLong
import me.ash.reader.ui.ext.toString
import me.ash.reader.ui.page.common.RouteName
import me.ash.reader.ui.page.settings.SettingItem
import me.ash.reader.ui.page.settings.accounts.connection.AccountConnection
import me.ash.reader.ui.theme.palette.onLight
Expand Down Expand Up @@ -113,6 +115,17 @@ fun AccountDetailsPage(
navController.popBackStack()
}
},
actions = {
FeedbackIconButton(
imageVector = Icons.Rounded.Close,
contentDescription = stringResource(R.string.close),
tint = MaterialTheme.colorScheme.onSurface
) {
navController.navigate(RouteName.FEEDS) {
launchSingleTop = true
}
}
},
content = {
LazyColumn {
item {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
Expand Down Expand Up @@ -38,6 +39,7 @@ class AccountViewModel @Inject constructor(
private val _accountUiState = MutableStateFlow(AccountUiState())
val accountUiState: StateFlow<AccountUiState> = _accountUiState.asStateFlow()
val accounts = accountService.getAccounts()
var addAccountJob: Job? = null

fun initData(accountId: Int) {
viewModelScope.launch(ioDispatcher) {
Expand Down Expand Up @@ -98,7 +100,8 @@ class AccountViewModel @Inject constructor(
}

fun addAccount(account: Account, callback: (account: Account?, exception: Exception?) -> Unit) {
viewModelScope.launch(ioDispatcher) {
setLoading(true)
addAccountJob = viewModelScope.launch(ioDispatcher) {
val addAccount = accountService.addAccount(account)
try {
if (rssService.get(addAccount.type.id).validCredentials(account)) {
Expand All @@ -113,6 +116,8 @@ class AccountViewModel @Inject constructor(
withContext(mainDispatcher) {
callback(null, e)
}
} finally {
setLoading(false)
}
}
}
Expand All @@ -135,13 +140,29 @@ class AccountViewModel @Inject constructor(
}
}
}

private fun setLoading(isLoading: Boolean) {
viewModelScope.launch {
_accountUiState.update {
it.copy(
isLoading = isLoading
)
}
}
}

fun cancelAdd() {
addAccountJob?.cancel()
setLoading(false)
}
}

data class AccountUiState(
val selectedAccount: Flow<Account?> = emptyFlow(),
val deleteDialogVisible: Boolean = false,
val clearDialogVisible: Boolean = false,
val exportOPMLMode: ExportOPMLMode = ExportOPMLMode.ATTACH_INFO,
val isLoading: Boolean = false,
)

sealed class ExportOPMLMode {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package me.ash.reader.ui.page.settings.accounts.addition

import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
Expand Down Expand Up @@ -44,6 +50,7 @@ fun AddFeverAccountDialog(
val context = LocalContext.current
val focusManager = LocalFocusManager.current
val uiState = viewModel.additionUiState.collectAsStateValue()
val accountUiState = accountViewModel.accountUiState.collectAsStateValue()

var feverServerUrl by rememberSaveable { mutableStateOf("") }
var feverUsername by rememberSaveable { mutableStateOf("") }
Expand All @@ -55,14 +62,22 @@ fun AddFeverAccountDialog(
properties = DialogProperties(usePlatformDefaultWidth = false),
onDismissRequest = {
focusManager.clearFocus()
accountViewModel.cancelAdd()
viewModel.hideAddFeverAccountDialog()
},
icon = {
Icon(
modifier = Modifier.size(24.dp),
painter = painterResource(id = R.drawable.ic_fever),
contentDescription = stringResource(R.string.fever),
)
if (accountUiState.isLoading) {
CircularProgressIndicator(
modifier = Modifier.size(24.dp),
color = MaterialTheme.colorScheme.onSurface,
)
} else {
Icon(
modifier = Modifier.size(24.dp),
painter = painterResource(id = R.drawable.ic_fever),
contentDescription = stringResource(R.string.fever),
)
}
},
title = {
Text(
Expand All @@ -77,6 +92,7 @@ fun AddFeverAccountDialog(
) {
Spacer(modifier = Modifier.height(10.dp))
RYOutlineTextField(
readOnly = accountUiState.isLoading,
value = feverServerUrl,
onValueChange = { feverServerUrl = it },
label = stringResource(R.string.server_url),
Expand All @@ -85,6 +101,8 @@ fun AddFeverAccountDialog(
)
Spacer(modifier = Modifier.height(10.dp))
RYOutlineTextField(
requestFocus = false,
readOnly = accountUiState.isLoading,
value = feverUsername,
onValueChange = { feverUsername = it },
label = stringResource(R.string.username),
Expand All @@ -93,6 +111,8 @@ fun AddFeverAccountDialog(
)
Spacer(modifier = Modifier.height(10.dp))
RYOutlineTextField(
requestFocus = false,
readOnly = accountUiState.isLoading,
value = feverPassword,
onValueChange = { feverPassword = it },
isPassword = true,
Expand All @@ -105,7 +125,10 @@ fun AddFeverAccountDialog(
},
confirmButton = {
TextButton(
enabled = feverServerUrl.isNotBlank() && feverUsername.isNotEmpty() && feverPassword.isNotEmpty(),
enabled = !accountUiState.isLoading
&& feverServerUrl.isNotBlank()
&& feverUsername.isNotEmpty()
&& feverPassword.isNotEmpty(),
onClick = {
focusManager.clearFocus()
accountViewModel.addAccount(Account(
Expand Down Expand Up @@ -136,6 +159,7 @@ fun AddFeverAccountDialog(
TextButton(
onClick = {
focusManager.clearFocus()
accountViewModel.cancelAdd()
viewModel.hideAddFeverAccountDialog()
}
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package me.ash.reader.ui.page.settings.accounts.addition

import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
Expand Down Expand Up @@ -44,6 +50,7 @@ fun AddFreshRSSAccountDialog(
val context = LocalContext.current
val focusManager = LocalFocusManager.current
val uiState = viewModel.additionUiState.collectAsStateValue()
val accountUiState = accountViewModel.accountUiState.collectAsStateValue()

var freshRSSServerUrl by rememberSaveable { mutableStateOf("") }
var freshRSSUsername by rememberSaveable { mutableStateOf("") }
Expand All @@ -55,14 +62,23 @@ fun AddFreshRSSAccountDialog(
properties = DialogProperties(usePlatformDefaultWidth = false),
onDismissRequest = {
focusManager.clearFocus()
accountViewModel.cancelAdd()
viewModel.hideAddFreshRSSAccountDialog()
},
icon = {
Icon(
modifier = Modifier.size(24.dp),
painter = painterResource(id = R.drawable.ic_freshrss),
contentDescription = stringResource(R.string.fresh_rss),
)
if (accountUiState.isLoading) {
CircularProgressIndicator(
modifier = Modifier
.size(24.dp),
color = MaterialTheme.colorScheme.onSurface,
)
} else {
Icon(
modifier = Modifier.size(24.dp),
painter = painterResource(id = R.drawable.ic_freshrss),
contentDescription = stringResource(R.string.fresh_rss),
)
}
},
title = {
Text(
Expand All @@ -77,6 +93,7 @@ fun AddFreshRSSAccountDialog(
) {
Spacer(modifier = Modifier.height(10.dp))
RYOutlineTextField(
readOnly = accountUiState.isLoading,
value = freshRSSServerUrl,
onValueChange = { freshRSSServerUrl = it },
label = stringResource(R.string.server_url),
Expand All @@ -85,6 +102,8 @@ fun AddFreshRSSAccountDialog(
)
Spacer(modifier = Modifier.height(10.dp))
RYOutlineTextField(
requestFocus = false,
readOnly = accountUiState.isLoading,
value = freshRSSUsername,
onValueChange = { freshRSSUsername = it },
label = stringResource(R.string.username),
Expand All @@ -93,6 +112,8 @@ fun AddFreshRSSAccountDialog(
)
Spacer(modifier = Modifier.height(10.dp))
RYOutlineTextField(
requestFocus = false,
readOnly = accountUiState.isLoading,
value = freshRSSPassword,
onValueChange = { freshRSSPassword = it },
isPassword = true,
Expand All @@ -105,7 +126,10 @@ fun AddFreshRSSAccountDialog(
},
confirmButton = {
TextButton(
enabled = freshRSSServerUrl.isNotBlank() && freshRSSUsername.isNotEmpty() && freshRSSPassword.isNotEmpty(),
enabled = !accountUiState.isLoading
&& freshRSSServerUrl.isNotBlank()
&& freshRSSUsername.isNotEmpty()
&& freshRSSPassword.isNotEmpty(),
onClick = {
focusManager.clearFocus()
if (!freshRSSServerUrl.endsWith("/")) {
Expand Down Expand Up @@ -138,6 +162,7 @@ fun AddFreshRSSAccountDialog(
dismissButton = {
TextButton(
onClick = {
accountViewModel.cancelAdd()
focusManager.clearFocus()
viewModel.hideAddFreshRSSAccountDialog()
}
Expand Down
Loading

0 comments on commit 39af42a

Please sign in to comment.