From 814aeacaac0b0629d043722a0cd609fd0a563c4a Mon Sep 17 00:00:00 2001 From: Ash Date: Thu, 18 Jan 2024 19:49:04 +0800 Subject: [PATCH] feat(freshrss): support fresh rss api --- .../account/security/FreshRSSSecurityKey.kt | 22 +++ .../domain/service/GoogleReaderRssService.kt | 1 + .../ash/reader/domain/service/RssService.kt | 1 + .../page/settings/accounts/AddAccountsPage.kt | 8 +- .../addition/AddFeverAccountDialog.kt | 6 +- .../addition/AddFreshRSSAccountDialog.kt | 149 ++++++++++++++++++ .../addition/AddGoogleReaderAccountDialog.kt | 9 +- .../addition/AddLocalAccountDialog.kt | 6 +- .../accounts/addition/AdditionViewModel.kt | 17 ++ .../accounts/connection/AccountConnection.kt | 4 +- .../accounts/connection/FreshRSSConnection.kt | 132 ++++++++++++++++ .../connection/GoogleReaderConnection.kt | 132 ++++++++++++++++ 12 files changed, 468 insertions(+), 19 deletions(-) create mode 100644 app/src/main/java/me/ash/reader/domain/model/account/security/FreshRSSSecurityKey.kt create mode 100644 app/src/main/java/me/ash/reader/ui/page/settings/accounts/addition/AddFreshRSSAccountDialog.kt create mode 100644 app/src/main/java/me/ash/reader/ui/page/settings/accounts/connection/FreshRSSConnection.kt create mode 100644 app/src/main/java/me/ash/reader/ui/page/settings/accounts/connection/GoogleReaderConnection.kt diff --git a/app/src/main/java/me/ash/reader/domain/model/account/security/FreshRSSSecurityKey.kt b/app/src/main/java/me/ash/reader/domain/model/account/security/FreshRSSSecurityKey.kt new file mode 100644 index 000000000..8ab1f3b7e --- /dev/null +++ b/app/src/main/java/me/ash/reader/domain/model/account/security/FreshRSSSecurityKey.kt @@ -0,0 +1,22 @@ +package me.ash.reader.domain.model.account.security + +class FreshRSSSecurityKey private constructor() : SecurityKey() { + + var serverUrl: String? = null + var username: String? = null + var password: String? = null + + constructor(serverUrl: String?, username: String?, password: String?) : this() { + this.serverUrl = serverUrl + this.username = username + this.password = password + } + + constructor(value: String? = DESUtils.empty) : this() { + decode(value, FreshRSSSecurityKey::class.java).let { + serverUrl = it.serverUrl + username = it.username + password = it.password + } + } +} diff --git a/app/src/main/java/me/ash/reader/domain/service/GoogleReaderRssService.kt b/app/src/main/java/me/ash/reader/domain/service/GoogleReaderRssService.kt index 63ae9b27e..d87716c0c 100644 --- a/app/src/main/java/me/ash/reader/domain/service/GoogleReaderRssService.kt +++ b/app/src/main/java/me/ash/reader/domain/service/GoogleReaderRssService.kt @@ -83,6 +83,7 @@ class GoogleReaderRssService @Inject constructor( accountDao.update(account.copy(name = it)) } } catch (ignore: Exception) { + Log.e("RLog", "get user info is failed: ", ignore) } } } diff --git a/app/src/main/java/me/ash/reader/domain/service/RssService.kt b/app/src/main/java/me/ash/reader/domain/service/RssService.kt index 94c30db7a..48fd07015 100644 --- a/app/src/main/java/me/ash/reader/domain/service/RssService.kt +++ b/app/src/main/java/me/ash/reader/domain/service/RssService.kt @@ -20,6 +20,7 @@ class RssService @Inject constructor( AccountType.Local.id -> localRssService AccountType.Fever.id -> feverRssService AccountType.GoogleReader.id -> googleReaderRssService + AccountType.FreshRSS.id -> googleReaderRssService AccountType.Inoreader.id -> localRssService AccountType.Feedly.id -> localRssService else -> localRssService diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/accounts/AddAccountsPage.kt b/app/src/main/java/me/ash/reader/ui/page/settings/accounts/AddAccountsPage.kt index 80bfb6359..75abf8e3f 100644 --- a/app/src/main/java/me/ash/reader/ui/page/settings/accounts/AddAccountsPage.kt +++ b/app/src/main/java/me/ash/reader/ui/page/settings/accounts/AddAccountsPage.kt @@ -23,10 +23,7 @@ import me.ash.reader.ui.component.base.FeedbackIconButton import me.ash.reader.ui.component.base.RYScaffold import me.ash.reader.ui.component.base.Subtitle import me.ash.reader.ui.page.settings.SettingItem -import me.ash.reader.ui.page.settings.accounts.addition.AddFeverAccountDialog -import me.ash.reader.ui.page.settings.accounts.addition.AddGoogleReaderAccountDialog -import me.ash.reader.ui.page.settings.accounts.addition.AddLocalAccountDialog -import me.ash.reader.ui.page.settings.accounts.addition.AdditionViewModel +import me.ash.reader.ui.page.settings.accounts.addition.* import me.ash.reader.ui.theme.palette.onLight @OptIn(ExperimentalAnimationApi::class) @@ -101,7 +98,7 @@ fun AddAccountsPage( desc = stringResource(R.string.fresh_rss_desc), iconPainter = painterResource(id = R.drawable.ic_freshrss), onClick = { - additionViewModel.showAddGoogleReaderAccountDialog() + additionViewModel.showAddFreshRSSAccountDialog() }, ) {} SettingItem( @@ -133,6 +130,7 @@ fun AddAccountsPage( AddLocalAccountDialog(navController) AddFeverAccountDialog(navController) AddGoogleReaderAccountDialog(navController) + AddFreshRSSAccountDialog(navController) } @Preview diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/accounts/addition/AddFeverAccountDialog.kt b/app/src/main/java/me/ash/reader/ui/page/settings/accounts/addition/AddFeverAccountDialog.kt index 298368bf9..c90afb625 100644 --- a/app/src/main/java/me/ash/reader/ui/page/settings/accounts/addition/AddFeverAccountDialog.kt +++ b/app/src/main/java/me/ash/reader/ui/page/settings/accounts/addition/AddFeverAccountDialog.kt @@ -1,9 +1,6 @@ package me.ash.reader.ui.page.settings.accounts.addition -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.* import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll @@ -62,6 +59,7 @@ fun AddFeverAccountDialog( }, icon = { Icon( + modifier = Modifier.size(24.dp), painter = painterResource(id = R.drawable.ic_fever), contentDescription = stringResource(R.string.fever), ) diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/accounts/addition/AddFreshRSSAccountDialog.kt b/app/src/main/java/me/ash/reader/ui/page/settings/accounts/addition/AddFreshRSSAccountDialog.kt new file mode 100644 index 000000000..1cd459b5a --- /dev/null +++ b/app/src/main/java/me/ash/reader/ui/page/settings/accounts/addition/AddFreshRSSAccountDialog.kt @@ -0,0 +1,149 @@ +package me.ash.reader.ui.page.settings.accounts.addition + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.DialogProperties +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavHostController +import me.ash.reader.R +import me.ash.reader.domain.model.account.Account +import me.ash.reader.domain.model.account.AccountType +import me.ash.reader.domain.model.account.security.FreshRSSSecurityKey +import me.ash.reader.ui.component.base.RYDialog +import me.ash.reader.ui.component.base.RYOutlineTextField +import me.ash.reader.ui.ext.collectAsStateValue +import me.ash.reader.ui.ext.showToast +import me.ash.reader.ui.page.common.RouteName +import me.ash.reader.ui.page.settings.accounts.AccountViewModel + +@OptIn(androidx.compose.ui.ExperimentalComposeUiApi::class) +@Composable +fun AddFreshRSSAccountDialog( + navController: NavHostController, + viewModel: AdditionViewModel = hiltViewModel(), + accountViewModel: AccountViewModel = hiltViewModel(), +) { + val context = LocalContext.current + val focusManager = LocalFocusManager.current + val uiState = viewModel.additionUiState.collectAsStateValue() + + var freshRSSServerUrl by rememberSaveable { mutableStateOf("") } + var freshRSSUsername by rememberSaveable { mutableStateOf("") } + var freshRSSPassword by rememberSaveable { mutableStateOf("") } + + RYDialog( + modifier = Modifier.padding(horizontal = 44.dp), + visible = uiState.addFreshRSSAccountDialogVisible, + properties = DialogProperties(usePlatformDefaultWidth = false), + onDismissRequest = { + focusManager.clearFocus() + viewModel.hideAddFreshRSSAccountDialog() + }, + icon = { + Icon( + modifier = Modifier.size(24.dp), + painter = painterResource(id = R.drawable.ic_freshrss), + contentDescription = stringResource(R.string.fresh_rss), + ) + }, + title = { + Text( + text = stringResource(R.string.fresh_rss), + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + }, + text = { + Column( + modifier = Modifier.verticalScroll(rememberScrollState()) + ) { + Spacer(modifier = Modifier.height(10.dp)) + RYOutlineTextField( + value = freshRSSServerUrl, + onValueChange = { freshRSSServerUrl = it }, + label = stringResource(R.string.server_url), + placeholder = "https://demo.freshrss.org/api/greader.php", + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Uri), + ) + Spacer(modifier = Modifier.height(10.dp)) + RYOutlineTextField( + value = freshRSSUsername, + onValueChange = { freshRSSUsername = it }, + label = stringResource(R.string.username), + placeholder = "demo", + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Email), + ) + Spacer(modifier = Modifier.height(10.dp)) + RYOutlineTextField( + value = freshRSSPassword, + onValueChange = { freshRSSPassword = it }, + isPassword = true, + label = stringResource(R.string.password), + placeholder = "demodemo", + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password), + ) + Spacer(modifier = Modifier.height(10.dp)) + } + }, + confirmButton = { + TextButton( + enabled = freshRSSServerUrl.isNotBlank() && freshRSSUsername.isNotEmpty() && freshRSSPassword.isNotEmpty(), + onClick = { + focusManager.clearFocus() + if (!freshRSSServerUrl.endsWith("/")) { + freshRSSServerUrl += "/" + } + accountViewModel.addAccount(Account( + type = AccountType.FreshRSS, + name = context.getString(R.string.fresh_rss), + securityKey = FreshRSSSecurityKey( + serverUrl = freshRSSServerUrl, + username = freshRSSUsername, + password = freshRSSPassword, + ).toString(), + )) { account, exception -> + if (account == null) { + context.showToast(exception?.message ?: "Not valid credentials") + } else { + viewModel.hideAddFreshRSSAccountDialog() + navController.popBackStack() + navController.navigate("${RouteName.ACCOUNT_DETAILS}/${account.id}") { + launchSingleTop = true + } + } + } + } + ) { + Text(stringResource(R.string.add)) + } + }, + dismissButton = { + TextButton( + onClick = { + focusManager.clearFocus() + viewModel.hideAddFreshRSSAccountDialog() + } + ) { + Text(stringResource(R.string.cancel)) + } + }, + ) +} diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/accounts/addition/AddGoogleReaderAccountDialog.kt b/app/src/main/java/me/ash/reader/ui/page/settings/accounts/addition/AddGoogleReaderAccountDialog.kt index 6374559ff..4f0b841da 100644 --- a/app/src/main/java/me/ash/reader/ui/page/settings/accounts/addition/AddGoogleReaderAccountDialog.kt +++ b/app/src/main/java/me/ash/reader/ui/page/settings/accounts/addition/AddGoogleReaderAccountDialog.kt @@ -1,9 +1,6 @@ package me.ash.reader.ui.page.settings.accounts.addition -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.* import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll @@ -63,6 +60,7 @@ fun AddGoogleReaderAccountDialog( }, icon = { Icon( + modifier = Modifier.size(24.dp), imageVector = Icons.Rounded.RssFeed, contentDescription = stringResource(R.string.google_reader), ) @@ -111,6 +109,9 @@ fun AddGoogleReaderAccountDialog( enabled = googleReaderServerUrl.isNotBlank() && googleReaderUsername.isNotEmpty() && googleReaderPassword.isNotEmpty(), onClick = { focusManager.clearFocus() + if (!googleReaderServerUrl.endsWith("/")) { + googleReaderServerUrl += "/" + } accountViewModel.addAccount(Account( type = AccountType.GoogleReader, name = context.getString(R.string.google_reader), diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/accounts/addition/AddLocalAccountDialog.kt b/app/src/main/java/me/ash/reader/ui/page/settings/accounts/addition/AddLocalAccountDialog.kt index c35ad0146..3b5f82aa3 100644 --- a/app/src/main/java/me/ash/reader/ui/page/settings/accounts/addition/AddLocalAccountDialog.kt +++ b/app/src/main/java/me/ash/reader/ui/page/settings/accounts/addition/AddLocalAccountDialog.kt @@ -1,9 +1,6 @@ package me.ash.reader.ui.page.settings.accounts.addition -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.* import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll @@ -56,6 +53,7 @@ fun AddLocalAccountDialog( }, icon = { Icon( + modifier = Modifier.size(24.dp), imageVector = Icons.Rounded.RssFeed, contentDescription = stringResource(R.string.local), ) diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/accounts/addition/AdditionViewModel.kt b/app/src/main/java/me/ash/reader/ui/page/settings/accounts/addition/AdditionViewModel.kt index 17ff9dd26..e3c0c704c 100644 --- a/app/src/main/java/me/ash/reader/ui/page/settings/accounts/addition/AdditionViewModel.kt +++ b/app/src/main/java/me/ash/reader/ui/page/settings/accounts/addition/AdditionViewModel.kt @@ -70,10 +70,27 @@ class AdditionViewModel @Inject constructor( ) } } + + fun showAddFreshRSSAccountDialog() { + _additionUiState.update { + it.copy( + addFreshRSSAccountDialogVisible = true, + ) + } + } + + fun hideAddFreshRSSAccountDialog() { + _additionUiState.update { + it.copy( + addFreshRSSAccountDialogVisible = false, + ) + } + } } data class AdditionUiState( val addLocalAccountDialogVisible: Boolean = false, val addFeverAccountDialogVisible: Boolean = false, val addGoogleReaderAccountDialogVisible: Boolean = false, + val addFreshRSSAccountDialogVisible: Boolean = false, ) diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/accounts/connection/AccountConnection.kt b/app/src/main/java/me/ash/reader/ui/page/settings/accounts/connection/AccountConnection.kt index d9418368c..b775f1766 100644 --- a/app/src/main/java/me/ash/reader/ui/page/settings/accounts/connection/AccountConnection.kt +++ b/app/src/main/java/me/ash/reader/ui/page/settings/accounts/connection/AccountConnection.kt @@ -25,8 +25,8 @@ fun LazyItemScope.AccountConnection( } when (account.type.id) { AccountType.Fever.id -> FeverConnection(account) - AccountType.GoogleReader.id -> {} - AccountType.FreshRSS.id -> {} + AccountType.GoogleReader.id -> GoogleReaderConnection(account) + AccountType.FreshRSS.id -> FreshRSSConnection(account) AccountType.Feedly.id -> {} AccountType.Inoreader.id -> {} } diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/accounts/connection/FreshRSSConnection.kt b/app/src/main/java/me/ash/reader/ui/page/settings/accounts/connection/FreshRSSConnection.kt new file mode 100644 index 000000000..6e54749d6 --- /dev/null +++ b/app/src/main/java/me/ash/reader/ui/page/settings/accounts/connection/FreshRSSConnection.kt @@ -0,0 +1,132 @@ +package me.ash.reader.ui.page.settings.accounts.connection + +import androidx.compose.foundation.lazy.LazyItemScope +import androidx.compose.runtime.* +import androidx.compose.ui.res.stringResource +import androidx.hilt.navigation.compose.hiltViewModel +import me.ash.reader.R +import me.ash.reader.domain.model.account.Account +import me.ash.reader.domain.model.account.security.FreshRSSSecurityKey +import me.ash.reader.ui.component.base.TextFieldDialog +import me.ash.reader.ui.ext.mask +import me.ash.reader.ui.page.settings.SettingItem +import me.ash.reader.ui.page.settings.accounts.AccountViewModel + +@Composable +fun LazyItemScope.FreshRSSConnection( + account: Account, + viewModel: AccountViewModel = hiltViewModel(), +) { + val securityKey by remember { + derivedStateOf { FreshRSSSecurityKey(account.securityKey) } + } + + var passwordMask by remember { mutableStateOf(securityKey.password?.mask()) } + + var serverUrlValue by remember { mutableStateOf(securityKey.serverUrl) } + var usernameValue by remember { mutableStateOf(securityKey.username) } + var passwordValue by remember { mutableStateOf(securityKey.password) } + + var serverUrlDialogVisible by remember { mutableStateOf(false) } + var usernameDialogVisible by remember { mutableStateOf(false) } + var passwordDialogVisible by remember { mutableStateOf(false) } + + LaunchedEffect(securityKey.password) { + passwordMask = securityKey.password?.mask() + } + + SettingItem( + title = stringResource(R.string.server_url), + desc = securityKey.serverUrl ?: "", + onClick = { + serverUrlDialogVisible = true + }, + ) {} + SettingItem( + title = stringResource(R.string.username), + desc = securityKey.username ?: "", + onClick = { + usernameDialogVisible = true + }, + ) {} + SettingItem( + title = stringResource(R.string.password), + desc = passwordMask, + onClick = { + passwordDialogVisible = true + }, + ) {} + + TextFieldDialog( + visible = serverUrlDialogVisible, + title = stringResource(R.string.server_url), + value = serverUrlValue ?: "", + placeholder = "https://demo.freshrss.org/api/greader.php", + onValueChange = { + serverUrlValue = it + }, + onDismissRequest = { + serverUrlDialogVisible = false + }, + onConfirm = { + if (securityKey.serverUrl?.isNotBlank() == true) { + securityKey.serverUrl = serverUrlValue + save(account, viewModel, securityKey) + serverUrlDialogVisible = false + } + } + ) + + TextFieldDialog( + visible = usernameDialogVisible, + title = stringResource(R.string.username), + value = usernameValue ?: "", + placeholder = "demo", + onValueChange = { + usernameValue = it + }, + onDismissRequest = { + usernameDialogVisible = false + }, + onConfirm = { + if (securityKey.username?.isNotEmpty() == true) { + securityKey.username = usernameValue + save(account, viewModel, securityKey) + usernameDialogVisible = false + } + } + ) + + TextFieldDialog( + visible = passwordDialogVisible, + title = stringResource(R.string.password), + value = passwordValue ?: "", + placeholder = "demodemo", + isPassword = true, + onValueChange = { + passwordValue = it + }, + onDismissRequest = { + passwordDialogVisible = false + }, + onConfirm = { + if (securityKey.password?.isNotEmpty() == true) { + securityKey.password = passwordValue + save(account, viewModel, securityKey) + passwordDialogVisible = false + } + } + ) +} + +private fun save( + account: Account, + viewModel: AccountViewModel, + securityKey: FreshRSSSecurityKey, +) { + account.id?.let { + viewModel.update(it) { + this.securityKey = securityKey.toString() + } + } +} diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/accounts/connection/GoogleReaderConnection.kt b/app/src/main/java/me/ash/reader/ui/page/settings/accounts/connection/GoogleReaderConnection.kt new file mode 100644 index 000000000..1980964af --- /dev/null +++ b/app/src/main/java/me/ash/reader/ui/page/settings/accounts/connection/GoogleReaderConnection.kt @@ -0,0 +1,132 @@ +package me.ash.reader.ui.page.settings.accounts.connection + +import androidx.compose.foundation.lazy.LazyItemScope +import androidx.compose.runtime.* +import androidx.compose.ui.res.stringResource +import androidx.hilt.navigation.compose.hiltViewModel +import me.ash.reader.R +import me.ash.reader.domain.model.account.Account +import me.ash.reader.domain.model.account.security.GoogleReaderSecurityKey +import me.ash.reader.ui.component.base.TextFieldDialog +import me.ash.reader.ui.ext.mask +import me.ash.reader.ui.page.settings.SettingItem +import me.ash.reader.ui.page.settings.accounts.AccountViewModel + +@Composable +fun LazyItemScope.GoogleReaderConnection( + account: Account, + viewModel: AccountViewModel = hiltViewModel(), +) { + val securityKey by remember { + derivedStateOf { GoogleReaderSecurityKey(account.securityKey) } + } + + var passwordMask by remember { mutableStateOf(securityKey.password?.mask()) } + + var serverUrlValue by remember { mutableStateOf(securityKey.serverUrl) } + var usernameValue by remember { mutableStateOf(securityKey.username) } + var passwordValue by remember { mutableStateOf(securityKey.password) } + + var serverUrlDialogVisible by remember { mutableStateOf(false) } + var usernameDialogVisible by remember { mutableStateOf(false) } + var passwordDialogVisible by remember { mutableStateOf(false) } + + LaunchedEffect(securityKey.password) { + passwordMask = securityKey.password?.mask() + } + + SettingItem( + title = stringResource(R.string.server_url), + desc = securityKey.serverUrl ?: "", + onClick = { + serverUrlDialogVisible = true + }, + ) {} + SettingItem( + title = stringResource(R.string.username), + desc = securityKey.username ?: "", + onClick = { + usernameDialogVisible = true + }, + ) {} + SettingItem( + title = stringResource(R.string.password), + desc = passwordMask, + onClick = { + passwordDialogVisible = true + }, + ) {} + + TextFieldDialog( + visible = serverUrlDialogVisible, + title = stringResource(R.string.server_url), + value = serverUrlValue ?: "", + placeholder = "https://demo.freshrss.org/api/greader.php", + onValueChange = { + serverUrlValue = it + }, + onDismissRequest = { + serverUrlDialogVisible = false + }, + onConfirm = { + if (securityKey.serverUrl?.isNotBlank() == true) { + securityKey.serverUrl = serverUrlValue + save(account, viewModel, securityKey) + serverUrlDialogVisible = false + } + } + ) + + TextFieldDialog( + visible = usernameDialogVisible, + title = stringResource(R.string.username), + value = usernameValue ?: "", + placeholder = "demo", + onValueChange = { + usernameValue = it + }, + onDismissRequest = { + usernameDialogVisible = false + }, + onConfirm = { + if (securityKey.username?.isNotEmpty() == true) { + securityKey.username = usernameValue + save(account, viewModel, securityKey) + usernameDialogVisible = false + } + } + ) + + TextFieldDialog( + visible = passwordDialogVisible, + title = stringResource(R.string.password), + value = passwordValue ?: "", + placeholder = "demodemo", + isPassword = true, + onValueChange = { + passwordValue = it + }, + onDismissRequest = { + passwordDialogVisible = false + }, + onConfirm = { + if (securityKey.password?.isNotEmpty() == true) { + securityKey.password = passwordValue + save(account, viewModel, securityKey) + passwordDialogVisible = false + } + } + ) +} + +private fun save( + account: Account, + viewModel: AccountViewModel, + securityKey: GoogleReaderSecurityKey, +) { + account.id?.let { + viewModel.update(it) { + this.securityKey = securityKey.toString() + } + } +}