Add new account dialog in AccountTab

This commit is contained in:
Shinokuni 2024-02-19 21:53:33 +01:00
parent 13557c00e6
commit 7b537123c8
6 changed files with 262 additions and 87 deletions

View File

@ -33,6 +33,8 @@ import cafe.adriel.voyager.navigator.currentOrThrow
import cafe.adriel.voyager.navigator.tab.Tab import cafe.adriel.voyager.navigator.tab.Tab
import cafe.adriel.voyager.navigator.tab.TabOptions import cafe.adriel.voyager.navigator.tab.TabOptions
import com.readrops.app.compose.R import com.readrops.app.compose.R
import com.readrops.app.compose.account.credentials.AccountCredentialsScreen
import com.readrops.app.compose.account.selection.AccountSelectionDialog
import com.readrops.app.compose.account.selection.AccountSelectionScreen import com.readrops.app.compose.account.selection.AccountSelectionScreen
import com.readrops.app.compose.util.components.SelectableIconText import com.readrops.app.compose.util.components.SelectableIconText
import com.readrops.app.compose.util.components.TwoChoicesDialog import com.readrops.app.compose.util.components.TwoChoicesDialog
@ -80,7 +82,13 @@ object AccountTab : Tab {
} }
DialogState.NewAccount -> { DialogState.NewAccount -> {
AccountSelectionDialog(
onDismiss = { viewModel.closeDialog() },
onValidate = { accountType ->
viewModel.closeDialog()
navigator.push(AccountCredentialsScreen(accountType, state.account))
}
)
} }
else -> {} else -> {}
@ -104,7 +112,7 @@ object AccountTab : Tab {
}, },
floatingActionButton = { floatingActionButton = {
FloatingActionButton( FloatingActionButton(
onClick = {} onClick = { viewModel.openDialog(DialogState.NewAccount) }
) { ) {
Icon( Icon(
painter = painterResource(id = R.drawable.ic_add_account), painter = painterResource(id = R.drawable.ic_add_account),
@ -142,6 +150,7 @@ object AccountTab : Tab {
icon = painterResource(id = R.drawable.ic_add_account), icon = painterResource(id = R.drawable.ic_add_account),
text = stringResource(R.string.credentials), text = stringResource(R.string.credentials),
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.titleMedium,
spacing = MaterialTheme.spacing.mediumSpacing,
padding = MaterialTheme.spacing.mediumSpacing, padding = MaterialTheme.spacing.mediumSpacing,
onClick = { } onClick = { }
) )
@ -150,6 +159,7 @@ object AccountTab : Tab {
icon = painterResource(id = R.drawable.ic_notifications), icon = painterResource(id = R.drawable.ic_notifications),
text = stringResource(R.string.notifications), text = stringResource(R.string.notifications),
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.titleMedium,
spacing = MaterialTheme.spacing.mediumSpacing,
padding = MaterialTheme.spacing.mediumSpacing, padding = MaterialTheme.spacing.mediumSpacing,
onClick = { } onClick = { }
) )
@ -158,6 +168,7 @@ object AccountTab : Tab {
icon = rememberVectorPainter(image = Icons.Default.AccountCircle), icon = rememberVectorPainter(image = Icons.Default.AccountCircle),
text = stringResource(R.string.delete_account), text = stringResource(R.string.delete_account),
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.titleMedium,
spacing = MaterialTheme.spacing.mediumSpacing,
padding = MaterialTheme.spacing.mediumSpacing, padding = MaterialTheme.spacing.mediumSpacing,
color = MaterialTheme.colorScheme.error, color = MaterialTheme.colorScheme.error,
tint = MaterialTheme.colorScheme.error, tint = MaterialTheme.colorScheme.error,

View File

@ -0,0 +1,80 @@
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.SelectableImageText
import com.readrops.app.compose.util.theme.MediumSpacer
import com.readrops.app.compose.util.theme.spacing
import com.readrops.db.entities.account.AccountType
@Composable
fun AccountSelectionDialog(
onDismiss: () -> Unit,
onValidate: (AccountType) -> Unit,
) {
Dialog(
onDismissRequest = 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) }
)
}
}
}
}
}

View File

@ -4,7 +4,7 @@ import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AccountBox import androidx.compose.material.icons.filled.AccountCircle
import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.BottomAppBar import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
@ -15,6 +15,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import cafe.adriel.voyager.androidx.AndroidScreen import cafe.adriel.voyager.androidx.AndroidScreen
import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
@ -33,75 +34,74 @@ class HomeScreen : AndroidScreen() {
val navigator = LocalNavigator.currentOrThrow val navigator = LocalNavigator.currentOrThrow
TabNavigator( TabNavigator(
tab = TimelineTab tab = TimelineTab
) { tabNavigator -> ) { tabNavigator ->
CompositionLocalProvider(LocalNavigator provides navigator) { CompositionLocalProvider(LocalNavigator provides navigator) {
Scaffold( Scaffold(
bottomBar = { bottomBar = {
BottomAppBar { BottomAppBar {
NavigationBarItem( NavigationBarItem(
selected = tabNavigator.current.key == TimelineTab.key, selected = tabNavigator.current.key == TimelineTab.key,
onClick = { tabNavigator.current = TimelineTab }, onClick = { tabNavigator.current = TimelineTab },
icon = { icon = {
Icon( Icon(
painter = painterResource(R.drawable.ic_timeline), painter = painterResource(R.drawable.ic_timeline),
contentDescription = null contentDescription = null
) )
}, },
label = { Text("Timeline") } label = { Text("Timeline") }
) )
NavigationBarItem( NavigationBarItem(
selected = tabNavigator.current.key == FeedTab.key, selected = tabNavigator.current.key == FeedTab.key,
onClick = { tabNavigator.current = FeedTab }, onClick = { tabNavigator.current = FeedTab },
icon = { icon = {
Icon( Icon(
painter = painterResource(R.drawable.ic_rss_feed_grey), painter = painterResource(R.drawable.ic_rss_feed_grey),
contentDescription = null contentDescription = null
) )
}, },
label = { Text("Feeds") } label = { Text(text = stringResource(R.string.feeds)) }
) )
NavigationBarItem( NavigationBarItem(
selected = tabNavigator.current.key == AccountTab.key, selected = tabNavigator.current.key == AccountTab.key,
onClick = { tabNavigator.current = AccountTab }, onClick = { tabNavigator.current = AccountTab },
icon = { icon = {
Icon( Icon(
imageVector = Icons.Default.AccountBox, imageVector = Icons.Default.AccountCircle,
contentDescription = null, contentDescription = null,
) )
}, },
label = { Text("Account") } label = { Text(text = stringResource(R.string.account)) }
) )
NavigationBarItem( NavigationBarItem(
selected = tabNavigator.current.key == MoreTab.key, selected = tabNavigator.current.key == MoreTab.key,
onClick = { tabNavigator.current = MoreTab }, onClick = { tabNavigator.current = MoreTab },
icon = { icon = {
Icon( Icon(
imageVector = Icons.Default.MoreVert, imageVector = Icons.Default.MoreVert,
contentDescription = null, contentDescription = null,
) )
}, },
label = { Text("More") } label = { Text("More") }
) )
} }
}, },
) { paddingValues -> ) { paddingValues ->
Box( Box(
modifier = Modifier.padding(paddingValues) modifier = Modifier.padding(paddingValues)
) { ) {
CurrentTab() CurrentTab()
} }
BackHandler( BackHandler(
enabled = tabNavigator.current != TimelineTab, enabled = tabNavigator.current != TimelineTab,
onBack = { tabNavigator.current = TimelineTab } onBack = { tabNavigator.current = TimelineTab }
) )
} }
} }
} }
} }
} }

View File

@ -66,7 +66,7 @@ object MoreTab : Tab {
icon = painterResource(id = R.drawable.ic_settings), icon = painterResource(id = R.drawable.ic_settings),
text = stringResource(R.string.settings), text = stringResource(R.string.settings),
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.titleMedium,
padding = MaterialTheme.spacing.mediumSpacing, spacing = MaterialTheme.spacing.mediumSpacing,
onClick = { } onClick = { }
) )
@ -74,7 +74,7 @@ object MoreTab : Tab {
icon = painterResource(id = R.drawable.ic_settings), icon = painterResource(id = R.drawable.ic_settings),
text = "Backup", text = "Backup",
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.titleMedium,
padding = MaterialTheme.spacing.mediumSpacing, spacing = MaterialTheme.spacing.mediumSpacing,
onClick = { } onClick = { }
) )
@ -82,7 +82,7 @@ object MoreTab : Tab {
icon = painterResource(id = R.drawable.ic_settings), icon = painterResource(id = R.drawable.ic_settings),
text = "Open-source libraries", text = "Open-source libraries",
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.titleMedium,
padding = MaterialTheme.spacing.mediumSpacing, spacing = MaterialTheme.spacing.mediumSpacing,
onClick = { } onClick = { }
) )
} }

View File

@ -1,5 +1,6 @@
package com.readrops.app.compose.util.components package com.readrops.app.compose.util.components
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
@ -23,28 +24,22 @@ import com.readrops.app.compose.util.theme.spacing
import com.readrops.app.compose.util.toDp import com.readrops.app.compose.util.toDp
@Composable @Composable
fun IconText( fun BaseText(
icon: Painter,
text: String, text: String,
style: TextStyle, style: TextStyle,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
color: Color = LocalContentColor.current, color: Color = LocalContentColor.current,
tint: Color = LocalContentColor.current, spacing: Dp = MaterialTheme.spacing.veryShortSpacing,
padding: Dp = MaterialTheme.spacing.veryShortSpacing,
onClick: (() -> Unit)? = null, onClick: (() -> Unit)? = null,
leftContent: @Composable () -> Unit
) { ) {
Row( Row(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = if (onClick != null) modifier.clickable { onClick() } else modifier, modifier = if (onClick != null) modifier.clickable { onClick() } else modifier,
) { ) {
Icon( leftContent()
painter = icon,
tint = tint,
contentDescription = null,
modifier = Modifier.size(style.toDp()),
)
Spacer(Modifier.width(padding)) Spacer(Modifier.width(spacing))
Text( Text(
text = text, text = text,
@ -54,6 +49,63 @@ fun IconText(
} }
} }
@Composable
fun IconText(
icon: Painter,
text: String,
style: TextStyle,
modifier: Modifier = Modifier,
color: Color = LocalContentColor.current,
tint: Color = LocalContentColor.current,
spacing: Dp = MaterialTheme.spacing.veryShortSpacing,
onClick: (() -> Unit)? = null,
) {
BaseText(
text = text,
style = style,
color = color,
spacing = spacing,
modifier = modifier,
onClick = onClick
) {
Icon(
painter = icon,
tint = tint,
contentDescription = null,
modifier = Modifier.size(style.toDp()),
)
}
}
@Composable
fun ImageText(
image: Painter,
text: String,
style: TextStyle,
modifier: Modifier = Modifier,
color: Color = LocalContentColor.current,
spacing: Dp = MaterialTheme.spacing.veryShortSpacing,
imageSize: Dp = style.toDp(),
onClick: (() -> Unit)? = null
) {
BaseText(
text = text,
style = style,
color = color,
spacing = spacing,
modifier = modifier,
onClick = onClick
) {
Image(
painter = image,
contentDescription = null,
modifier = Modifier.size(imageSize),
)
}
}
@Composable @Composable
fun SelectableIconText( fun SelectableIconText(
icon: Painter, icon: Painter,
@ -63,27 +115,59 @@ fun SelectableIconText(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
color: Color = LocalContentColor.current, color: Color = LocalContentColor.current,
tint: Color = LocalContentColor.current, tint: Color = LocalContentColor.current,
padding: Dp = MaterialTheme.spacing.veryShortSpacing, spacing: Dp = MaterialTheme.spacing.veryShortSpacing,
padding: Dp = MaterialTheme.spacing.shortSpacing
) { ) {
Box( Box(
modifier = modifier.clickable { onClick() } modifier = modifier
.fillMaxWidth()
.clickable { onClick() }
.padding(padding)
) { ) {
Row( BaseText(
verticalAlignment = Alignment.CenterVertically, text = text,
modifier = Modifier style = style,
.fillMaxWidth() color = color,
.padding( spacing = spacing
horizontal = MaterialTheme.spacing.mediumSpacing,
vertical = MaterialTheme.spacing.mediumSpacing
)
) { ) {
IconText( Icon(
icon = icon, painter = icon,
text = text,
style = style,
padding = padding,
tint = tint, tint = tint,
color = color contentDescription = null,
modifier = Modifier.size(style.toDp()),
)
}
}
}
@Composable
fun SelectableImageText(
image: Painter,
text: String,
style: TextStyle,
onClick: () -> Unit,
modifier: Modifier = Modifier,
color: Color = LocalContentColor.current,
spacing: Dp = MaterialTheme.spacing.veryShortSpacing,
padding: Dp = MaterialTheme.spacing.shortSpacing,
imageSize: Dp = style.toDp()
) {
Box(
modifier = modifier
.fillMaxWidth()
.clickable { onClick() }
.padding(padding)
) {
BaseText(
text = text,
style = style,
color = color,
spacing = spacing
) {
Image(
painter = image,
contentDescription = null,
modifier = Modifier.size(imageSize),
) )
} }
} }

View File

@ -12,6 +12,6 @@ enum class AccountType(@DrawableRes val iconRes: Int,
val accountConfig: AccountConfig?) : Parcelable { val accountConfig: AccountConfig?) : Parcelable {
LOCAL(R.mipmap.ic_launcher, R.string.local_account, AccountConfig.LOCAL), LOCAL(R.mipmap.ic_launcher, R.string.local_account, AccountConfig.LOCAL),
NEXTCLOUD_NEWS(R.drawable.ic_nextcloud_news, R.string.nextcloud_news, AccountConfig.NEXTCLOUD_NEWS), NEXTCLOUD_NEWS(R.drawable.ic_nextcloud_news, R.string.nextcloud_news, AccountConfig.NEXTCLOUD_NEWS),
FEEDLY(R.drawable.ic_feedly, R.string.feedly, null), /* FEEDLY(R.drawable.ic_feedly, R.string.feedly, null),*/
FRESHRSS(R.drawable.ic_freshrss, R.string.freshrss, AccountConfig.FRESHRSS); FRESHRSS(R.drawable.ic_freshrss, R.string.freshrss, AccountConfig.FRESHRSS);
} }