Improve the use of BaseDialog

This commit is contained in:
Shinokuni 2024-02-19 22:43:53 +01:00
parent 7b537123c8
commit 5a0affdf3b
6 changed files with 189 additions and 304 deletions

View File

@ -1,26 +1,13 @@
package com.readrops.app.compose.account.selection
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import com.readrops.app.compose.R
import com.readrops.app.compose.util.components.BaseDialog
import com.readrops.app.compose.util.components.SelectableImageText
import com.readrops.app.compose.util.theme.MediumSpacer
import com.readrops.app.compose.util.theme.spacing
import com.readrops.db.entities.account.AccountType
@ -29,52 +16,26 @@ fun AccountSelectionDialog(
onDismiss: () -> Unit,
onValidate: (AccountType) -> Unit,
) {
Dialog(
onDismissRequest = onDismiss
BaseDialog(
title = stringResource(R.string.new_account),
icon = painterResource(id = R.drawable.ic_add_account),
onDismiss = onDismiss
) {
Card(
shape = RoundedCornerShape(24.dp)
) {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.background(MaterialTheme.colorScheme.background)
.padding(MaterialTheme.spacing.largeSpacing)
) {
Icon(
painter = painterResource(id = R.drawable.ic_add_account),
contentDescription = null,
modifier = Modifier.size(MaterialTheme.spacing.largeSpacing)
)
MediumSpacer()
Text(
text = stringResource(R.string.new_account),
style = MaterialTheme.typography.headlineSmall
)
MediumSpacer()
AccountType.values().forEach { type ->
SelectableImageText(
image = painterResource(
id = if (type != AccountType.LOCAL)
type.iconRes
else
R.drawable.ic_rss_feed_grey
),
text = stringResource(id = type.typeName),
style = MaterialTheme.typography.titleMedium,
spacing = MaterialTheme.spacing.mediumSpacing,
padding = MaterialTheme.spacing.shortSpacing,
imageSize = 36.dp,
onClick = { onValidate(type) }
)
}
}
AccountType.values().forEach { type ->
SelectableImageText(
image = painterResource(
id = if (type != AccountType.LOCAL)
type.iconRes
else
R.drawable.ic_rss_feed_grey
),
text = stringResource(id = type.typeName),
style = MaterialTheme.typography.titleMedium,
spacing = MaterialTheme.spacing.mediumSpacing,
padding = MaterialTheme.spacing.shortSpacing,
imageSize = 36.dp,
onClick = { onValidate(type) }
)
}
}
}

View File

@ -56,6 +56,8 @@ data class UpdateFeedDialogState(
val isFeedUrlReadOnly: Boolean
get() = accountType != null && !accountType.accountConfig!!.isFeedUrlEditable
val hasFolders = folders.isNotEmpty()
}
data class FolderState(

View File

@ -1,22 +1,13 @@
package com.readrops.app.compose.feeds.dialogs
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Clear
import androidx.compose.material3.Card
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.ExposedDropdownMenuDefaults
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.TextButton
@ -25,19 +16,15 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.readrops.app.compose.R
import com.readrops.app.compose.feeds.FeedViewModel
import com.readrops.app.compose.util.components.BaseDialog
import com.readrops.app.compose.util.theme.LargeSpacer
import com.readrops.app.compose.util.theme.MediumSpacer
import com.readrops.app.compose.util.theme.ShortSpacer
import com.readrops.app.compose.util.theme.spacing
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@ -49,96 +36,50 @@ fun AddFeedDialog(
var isExpanded by remember { mutableStateOf(false) }
Dialog(
onDismissRequest = onDismiss
BaseDialog(
title = stringResource(R.string.add_feed_item),
icon = painterResource(id = R.drawable.ic_rss_feed_grey),
onDismiss = onDismiss
) {
Card(
shape = RoundedCornerShape(24.dp),
) {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.background(MaterialTheme.colorScheme.background)
.padding(MaterialTheme.spacing.largeSpacing)
) {
Icon(
painter = painterResource(id = R.drawable.ic_rss_feed_grey),
contentDescription = null,
modifier = Modifier.size(MaterialTheme.spacing.largeSpacing)
)
MediumSpacer()
Text(
text = stringResource(R.string.add_feed_item),
style = MaterialTheme.typography.headlineSmall
)
MediumSpacer()
OutlinedTextField(
value = state.url,
label = {
Text(text = "URL")
},
onValueChange = { viewModel.setAddFeedDialogURL(it) },
singleLine = true,
trailingIcon = {
if (state.url.isNotEmpty()) {
IconButton(
onClick = { viewModel.setAddFeedDialogURL("") }
) {
Icon(
imageVector = Icons.Default.Clear,
contentDescription = null
)
}
}
},
isError = state.isError,
supportingText = { Text(state.error?.errorText().orEmpty()) }
)
ShortSpacer()
ExposedDropdownMenuBox(
expanded = isExpanded,
onExpandedChange = { isExpanded = isExpanded.not() }
) {
ExposedDropdownMenu(
expanded = isExpanded,
onDismissRequest = { isExpanded = false }
OutlinedTextField(
value = state.url,
label = {
Text(text = "URL")
},
onValueChange = { viewModel.setAddFeedDialogURL(it) },
singleLine = true,
trailingIcon = {
if (state.url.isNotEmpty()) {
IconButton(
onClick = { viewModel.setAddFeedDialogURL("") }
) {
for (account in state.accounts) {
DropdownMenuItem(
text = { Text(text = account.accountName!!) },
onClick = {
isExpanded = false
viewModel.setAddFeedDialogSelectedAccount(account)
},
leadingIcon = {
Icon(
painter = painterResource(
id = if (state.selectedAccount.isLocal) {
R.drawable.ic_rss_feed_grey
} else
state.selectedAccount.accountType!!.iconRes
),
contentDescription = null
)
}
)
}
Icon(
imageVector = Icons.Default.Clear,
contentDescription = null
)
}
}
},
isError = state.isError,
supportingText = { Text(state.error?.errorText().orEmpty()) }
)
OutlinedTextField(
value = state.selectedAccount.accountName!!,
readOnly = true,
onValueChange = {},
trailingIcon = {
ExposedDropdownMenuDefaults.TrailingIcon(expanded = isExpanded)
ShortSpacer()
ExposedDropdownMenuBox(
expanded = isExpanded,
onExpandedChange = { isExpanded = isExpanded.not() }
) {
ExposedDropdownMenu(
expanded = isExpanded,
onDismissRequest = { isExpanded = false }
) {
for (account in state.accounts) {
DropdownMenuItem(
text = { Text(text = account.accountName!!) },
onClick = {
isExpanded = false
viewModel.setAddFeedDialogSelectedAccount(account)
},
leadingIcon = {
Icon(
@ -150,19 +91,39 @@ fun AddFeedDialog(
),
contentDescription = null
)
},
modifier = Modifier.menuAnchor()
}
)
}
LargeSpacer()
TextButton(
onClick = { viewModel.addFeedDialogValidate() },
) {
Text(text = stringResource(R.string.validate))
}
}
OutlinedTextField(
value = state.selectedAccount.accountName!!,
readOnly = true,
onValueChange = {},
trailingIcon = {
ExposedDropdownMenuDefaults.TrailingIcon(expanded = isExpanded)
},
leadingIcon = {
Icon(
painter = painterResource(
id = if (state.selectedAccount.isLocal) {
R.drawable.ic_rss_feed_grey
} else
state.selectedAccount.accountType!!.iconRes
),
contentDescription = null
)
},
modifier = Modifier.menuAnchor()
)
}
LargeSpacer()
TextButton(
onClick = { viewModel.addFeedDialogValidate() },
) {
Text(text = stringResource(R.string.validate))
}
}
}

View File

@ -6,6 +6,7 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.res.painterResource
@ -14,6 +15,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.readrops.app.compose.R
import com.readrops.app.compose.feeds.FeedViewModel
import com.readrops.app.compose.util.components.BaseDialog
import com.readrops.app.compose.util.theme.LargeSpacer
@Composable
fun FolderDialog(
@ -27,8 +29,7 @@ fun FolderDialog(
BaseDialog(
title = stringResource(id = if (updateFolder) R.string.edit_folder else R.string.add_folder),
icon = painterResource(id = if (updateFolder) R.drawable.ic_folder_grey else R.drawable.ic_new_folder),
onDismiss = onDismiss,
onValidate = onValidate
onDismiss = onDismiss
) {
OutlinedTextField(
value = state.name.orEmpty(),
@ -52,5 +53,13 @@ fun FolderDialog(
isError = state.isError,
supportingText = { Text(text = state.nameError?.errorText().orEmpty()) }
)
LargeSpacer()
TextButton(
onClick = { onValidate() },
) {
Text(text = stringResource(R.string.validate))
}
}
}

View File

@ -1,36 +1,24 @@
package com.readrops.app.compose.feeds.dialogs
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.readrops.app.compose.R
import com.readrops.app.compose.feeds.FeedViewModel
import com.readrops.app.compose.util.components.BaseDialog
import com.readrops.app.compose.util.theme.LargeSpacer
import com.readrops.app.compose.util.theme.MediumSpacer
import com.readrops.app.compose.util.theme.spacing
@OptIn(ExperimentalMaterial3Api::class)
@ -41,122 +29,97 @@ fun UpdateFeedDialog(
) {
val state by viewModel.updateFeedDialogState.collectAsStateWithLifecycle()
Dialog(
onDismissRequest = onDismissRequest
BaseDialog(
title = stringResource(R.string.edit_feed),
icon = painterResource(id = R.drawable.ic_rss_feed_grey),
onDismiss = onDismissRequest
) {
Card(
shape = RoundedCornerShape(24.dp)
) {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxWidth()
.background(MaterialTheme.colorScheme.background)
.padding(MaterialTheme.spacing.largeSpacing)
) {
Icon(
painter = painterResource(id = R.drawable.ic_rss_feed_grey),
contentDescription = null,
modifier = Modifier.size(MaterialTheme.spacing.largeSpacing)
)
MediumSpacer()
Text(
text = stringResource(R.string.edit_feed),
style = MaterialTheme.typography.headlineSmall
)
MediumSpacer()
OutlinedTextField(
value = state.feedName,
onValueChange = { viewModel.setUpdateFeedDialogStateFeedName(it) },
label = { Text(text = stringResource(R.string.feed_name)) },
singleLine = true,
isError = state.isFeedNameError,
supportingText = {
if (state.isFeedNameError) {
Text(
text = state.feedNameError?.errorText().orEmpty()
)
}
}
)
MediumSpacer()
OutlinedTextField(
value = state.feedUrl,
onValueChange = { viewModel.setUpdateFeedDialogFeedUrl(it) },
label = { Text(text = stringResource(R.string.feed_url)) },
singleLine = true,
readOnly = state.isFeedUrlReadOnly,
isError = state.isFeedUrlError,
supportingText = {
if (state.isFeedUrlError) {
Text(
text = state.feedUrlError?.errorText().orEmpty()
)
}
}
)
MediumSpacer()
ExposedDropdownMenuBox(
expanded = state.isAccountDropDownExpanded,
onExpandedChange = { viewModel.setAccountDropDownState(state.isAccountDropDownExpanded.not()) }
) {
ExposedDropdownMenu(
expanded = state.isAccountDropDownExpanded,
onDismissRequest = { viewModel.setAccountDropDownState(false) }
) {
for (folder in state.folders) {
DropdownMenuItem(
text = { Text(text = folder.name!!) },
onClick = {
viewModel.setSelectedFolder(folder)
viewModel.setAccountDropDownState(false)
},
leadingIcon = {
Icon(
painterResource(id = R.drawable.ic_folder_grey),
contentDescription = null,
)
}
)
}
}
OutlinedTextField(
value = state.selectedFolder?.name.orEmpty(),
readOnly = true,
onValueChange = {},
trailingIcon = {
ExposedDropdownMenuDefaults.TrailingIcon(expanded = state.isAccountDropDownExpanded)
},
leadingIcon = {
if (state.selectedFolder != null) {
Icon(
painterResource(id = R.drawable.ic_folder_grey),
contentDescription = null,
)
}
},
modifier = Modifier.menuAnchor()
OutlinedTextField(
value = state.feedName,
onValueChange = { viewModel.setUpdateFeedDialogStateFeedName(it) },
label = { Text(text = stringResource(R.string.feed_name)) },
singleLine = true,
isError = state.isFeedNameError,
supportingText = {
if (state.isFeedNameError) {
Text(
text = state.feedNameError?.errorText().orEmpty()
)
}
}
)
LargeSpacer()
MediumSpacer()
TextButton(
onClick = { viewModel.updateFeedDialogValidate() },
) {
Text(text = stringResource(R.string.validate))
OutlinedTextField(
value = state.feedUrl,
onValueChange = { viewModel.setUpdateFeedDialogFeedUrl(it) },
label = { Text(text = stringResource(R.string.feed_url)) },
singleLine = true,
readOnly = state.isFeedUrlReadOnly,
isError = state.isFeedUrlError,
supportingText = {
if (state.isFeedUrlError) {
Text(
text = state.feedUrlError?.errorText().orEmpty()
)
}
}
)
MediumSpacer()
ExposedDropdownMenuBox(
expanded = state.isAccountDropDownExpanded && state.hasFolders,
onExpandedChange = { viewModel.setAccountDropDownState(state.isAccountDropDownExpanded.not()) }
) {
ExposedDropdownMenu(
expanded = state.isAccountDropDownExpanded && state.hasFolders,
onDismissRequest = { viewModel.setAccountDropDownState(false) }
) {
for (folder in state.folders) {
DropdownMenuItem(
text = { Text(text = folder.name!!) },
onClick = {
viewModel.setSelectedFolder(folder)
viewModel.setAccountDropDownState(false)
},
leadingIcon = {
Icon(
painterResource(id = R.drawable.ic_folder_grey),
contentDescription = null,
)
}
)
}
}
OutlinedTextField(
value = state.selectedFolder?.name.orEmpty(),
readOnly = true,
enabled = state.hasFolders,
onValueChange = {},
trailingIcon = {
ExposedDropdownMenuDefaults.TrailingIcon(expanded = state.isAccountDropDownExpanded)
},
leadingIcon = {
if (state.selectedFolder != null) {
Icon(
painterResource(id = R.drawable.ic_folder_grey),
contentDescription = null,
)
}
},
modifier = Modifier.menuAnchor()
)
}
LargeSpacer()
TextButton(
onClick = { viewModel.updateFeedDialogValidate() },
) {
Text(text = stringResource(R.string.validate))
}
}
}

View File

@ -11,14 +11,12 @@ import androidx.compose.material3.Card
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
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import com.readrops.app.compose.util.theme.LargeSpacer
import com.readrops.app.compose.util.theme.MediumSpacer
import com.readrops.app.compose.util.theme.spacing
@ -27,7 +25,6 @@ fun BaseDialog(
title: String,
icon: Painter,
onDismiss: () -> Unit,
onValidate: () -> Unit,
content: @Composable () -> Unit
) {
Dialog(
@ -60,14 +57,6 @@ fun BaseDialog(
MediumSpacer()
content()
LargeSpacer()
TextButton(
onClick = { onValidate() },
) {
Text(text = "Validate")
}
}
}
}