feat: Improve CustomRecordingNotificationsScreen layout

This commit is contained in:
Myzel394 2023-10-24 10:10:40 +02:00
parent 54ad067cdf
commit d0885ba877
No known key found for this signature in database
GPG Key ID: 50098FCA22080F0F
4 changed files with 182 additions and 69 deletions

View File

@ -0,0 +1,72 @@
package app.myzel394.alibi.ui.components.CustomRecordingNotificationsScreen.molecules
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp
import app.myzel394.alibi.R
import app.myzel394.alibi.db.NotificationSettings
import app.myzel394.alibi.ui.components.CustomRecordingNotificationsScreen.atoms.NotificationPresetSelect
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun NotificationPresetsRoulette(
onClick: (String, String, Int, Boolean) -> Unit,
) {
val state = rememberLazyListState()
LazyRow(
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically,
state = state,
flingBehavior = rememberSnapFlingBehavior(lazyListState = state)
) {
items(NotificationSettings.PRESETS.size) {
val preset = NotificationSettings.PRESETS[it]
val label = stringResource(
R.string.ui_settings_customNotifications_preset_apply_label,
stringResource(preset.titleID)
)
val presetTitle = stringResource(preset.titleID)
val presetDescription = stringResource(preset.messageID)
Box(
modifier = Modifier.width(
LocalConfiguration.current.screenWidthDp.dp,
)
) {
NotificationPresetSelect(
modifier = Modifier
.fillMaxWidth(.95f)
.align(Alignment.Center)
.semantics {
contentDescription = label
}
.clickable {
onClick(
presetTitle,
presetDescription,
preset.iconID,
preset.showOngoing,
)
},
preset = preset,
)
}
}
}
}

View File

@ -1,28 +1,49 @@
package app.myzel394.alibi.ui.components.CustomRecordingNotificationsScreen.organisms package app.myzel394.alibi.ui.components.CustomRecordingNotificationsScreen.organisms
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.ScrollState import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.FlingBehavior
import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.CheckCircle
import androidx.compose.material.icons.filled.Notifications
import androidx.compose.material.icons.filled.Save
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Checkbox import androidx.compose.material3.Checkbox
import androidx.compose.material3.CheckboxColors import androidx.compose.material3.CheckboxColors
import androidx.compose.material3.CheckboxDefaults import androidx.compose.material3.CheckboxDefaults
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.contentDescription
@ -31,10 +52,14 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import app.myzel394.alibi.R import app.myzel394.alibi.R
import app.myzel394.alibi.db.NotificationSettings import app.myzel394.alibi.db.NotificationSettings
import app.myzel394.alibi.ui.BIG_PRIMARY_BUTTON_SIZE
import app.myzel394.alibi.ui.components.CustomRecordingNotificationsScreen.atoms.NotificationPresetSelect import app.myzel394.alibi.ui.components.CustomRecordingNotificationsScreen.atoms.NotificationPresetSelect
import app.myzel394.alibi.ui.components.CustomRecordingNotificationsScreen.molecules.EditNotificationInput import app.myzel394.alibi.ui.components.CustomRecordingNotificationsScreen.molecules.EditNotificationInput
import app.myzel394.alibi.ui.components.CustomRecordingNotificationsScreen.molecules.NotificationPresetsRoulette
@OptIn(ExperimentalMaterial3Api::class) val HORIZONTAL_PADDING = 16.dp;
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
@Composable @Composable
fun NotificationEditor( fun NotificationEditor(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
@ -53,93 +78,105 @@ fun NotificationEditor(
mutableStateOf(true) mutableStateOf(true)
} }
var icon: Int by rememberSaveable { var icon: Int by rememberSaveable {
mutableStateOf(R.drawable.launcher_monochrome_noopacity) mutableIntStateOf(R.drawable.launcher_monochrome_noopacity)
} }
// TODO: Add Preview functionality // TODO: Add Preview functionality
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.padding(horizontal = 16.dp)
.then(modifier), .then(modifier),
verticalArrangement = Arrangement.SpaceBetween, verticalArrangement = Arrangement.SpaceBetween,
) { ) {
EditNotificationInput( Column(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .padding(horizontal = HORIZONTAL_PADDING),
.padding(horizontal = 16.dp), verticalArrangement = Arrangement.spacedBy(16.dp),
showOngoing = showOngoing,
title = title,
description = description,
icon = painterResource(icon),
onShowOngoingChange = {
showOngoing = it
},
onTitleChange = {
title = it
},
onDescriptionChange = {
description = it
},
onIconChange = {
icon = it
},
)
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxSize()
.clip(MaterialTheme.shapes.medium)
.clickable {
showOngoing = showOngoing.not()
}
.background(MaterialTheme.colorScheme.tertiaryContainer)
.padding(8.dp),
) { ) {
Checkbox( EditNotificationInput(
checked = showOngoing, modifier = Modifier
onCheckedChange = { .fillMaxWidth()
.padding(horizontal = 16.dp),
showOngoing = showOngoing,
title = title,
description = description,
icon = painterResource(icon),
onShowOngoingChange = {
showOngoing = it showOngoing = it
}, },
colors = CheckboxDefaults.colors( onTitleChange = {
checkedColor = MaterialTheme.colorScheme.tertiary, title = it
checkmarkColor = MaterialTheme.colorScheme.onTertiary, },
onDescriptionChange = {
description = it
},
onIconChange = {
icon = it
},
)
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.clip(MaterialTheme.shapes.medium)
.clickable {
showOngoing = showOngoing.not()
}
.background(MaterialTheme.colorScheme.tertiaryContainer)
.padding(8.dp),
) {
Checkbox(
checked = showOngoing,
onCheckedChange = {
showOngoing = it
},
colors = CheckboxDefaults.colors(
checkedColor = MaterialTheme.colorScheme.tertiary,
checkmarkColor = MaterialTheme.colorScheme.onTertiary,
)
) )
) Text(
Text( text = stringResource(R.string.ui_settings_customNotifications_showOngoing_label),
text = stringResource(R.string.ui_settings_customNotifications_showOngoing_label), style = MaterialTheme.typography.bodyMedium,
style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onTertiaryContainer,
color = MaterialTheme.colorScheme.onTertiaryContainer, fontWeight = FontWeight.Bold,
fontWeight = FontWeight.Bold, )
) }
} }
Column( Column(
verticalArrangement = Arrangement.spacedBy(4.dp), verticalArrangement = Arrangement.spacedBy(32.dp),
) { ) {
for (preset in NotificationSettings.PRESETS) { NotificationPresetsRoulette(
val label = stringResource( onClick = { presetTitle, presetDescription, presetIcon, presetShowOngoing ->
R.string.ui_settings_customNotifications_preset_apply_label, title = presetTitle
stringResource(preset.titleID) description = presetDescription
) icon = presetIcon
val presetTitle = stringResource(preset.titleID) showOngoing = presetShowOngoing
val presetDescription = stringResource(preset.messageID) }
)
NotificationPresetSelect( Button(
onClick = { /*TODO*/ },
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = HORIZONTAL_PADDING)
.height(48.dp),
) {
Icon(
Icons.Default.CheckCircle,
contentDescription = null,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .size(ButtonDefaults.IconSize)
.semantics { )
contentDescription = label Spacer(
} modifier = Modifier
.clickable { .width(ButtonDefaults.IconSpacing)
title = presetTitle )
description = presetDescription Text(
icon = preset.iconID stringResource(R.string.ui_settings_customNotifications_save_label)
showOngoing = preset.showOngoing
},
preset = preset,
) )
} }
} }

View File

@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
@ -26,6 +27,8 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.navigation.NavController import androidx.navigation.NavController
import app.myzel394.alibi.R import app.myzel394.alibi.R
@ -77,7 +80,7 @@ fun CustomRecordingNotificationsScreen(
NotificationEditor( NotificationEditor(
modifier = Modifier modifier = Modifier
.padding(padding) .padding(padding)
.verticalScroll(scrollState), .padding(vertical = 16.dp),
scrollState = scrollState, scrollState = scrollState,
) )
} }

View File

@ -86,4 +86,5 @@
<string name="ui_audioRecorder_state_recording_fake_vpn_description">Connection Secured</string> <string name="ui_audioRecorder_state_recording_fake_vpn_description">Connection Secured</string>
<string name="ui_settings_customNotifications_preset_apply_label">Apply Preset \"%s\"</string> <string name="ui_settings_customNotifications_preset_apply_label">Apply Preset \"%s\"</string>
<string name="ui_settings_customNotifications_showOngoing_label">Show Duration</string> <string name="ui_settings_customNotifications_showOngoing_label">Show Duration</string>
<string name="ui_settings_customNotifications_save_label">Update notification</string>
</resources> </resources>