mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-3375 New settings | Main screen, base ui (#2129)
This commit is contained in:
parent
4bc1e060f3
commit
77704b87d2
16 changed files with 1144 additions and 1 deletions
|
@ -32,6 +32,7 @@ dependencies {
|
|||
|
||||
implementation libs.appcompat
|
||||
implementation libs.compose
|
||||
implementation libs.composeMaterial3
|
||||
implementation libs.composeFoundation
|
||||
implementation libs.composeMaterial
|
||||
implementation libs.composeToolingPreview
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
package com.anytypeio.anytype.ui_settings.space.new_settings
|
||||
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.PickVisualMediaRequest
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Divider
|
||||
import androidx.compose.material.DropdownMenu
|
||||
import androidx.compose.material.DropdownMenuItem
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.DpOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.anytypeio.anytype.core_ui.features.SpaceIconView
|
||||
import com.anytypeio.anytype.core_ui.foundation.noRippleThrottledClickable
|
||||
import com.anytypeio.anytype.core_ui.views.BodyRegular
|
||||
import com.anytypeio.anytype.core_ui.views.Caption1Medium
|
||||
import com.anytypeio.anytype.presentation.spaces.SpaceIconView
|
||||
import com.anytypeio.anytype.presentation.spaces.UiEvent
|
||||
import com.anytypeio.anytype.ui_settings.R
|
||||
import timber.log.Timber
|
||||
|
||||
@Composable
|
||||
fun NewSpaceIcon(
|
||||
icon: SpaceIconView,
|
||||
modifier: Modifier = Modifier,
|
||||
uiEvent: (UiEvent) -> Unit,
|
||||
isEditEnabled: Boolean
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val singlePhotoPickerLauncher = rememberLauncherForActivityResult(
|
||||
contract = ActivityResultContracts.PickVisualMedia(),
|
||||
onResult = { uri ->
|
||||
if (uri != null) {
|
||||
uiEvent(UiEvent.OnSpaceImagePicked(uri.toString()))
|
||||
} else {
|
||||
Timber.w("Uri was null after picking image")
|
||||
}
|
||||
}
|
||||
)
|
||||
val isSpaceIconMenuExpanded = remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
Column(
|
||||
modifier = modifier,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
SpaceIconView(
|
||||
modifier = Modifier.size(112.dp),
|
||||
icon = icon,
|
||||
onSpaceIconClick = {
|
||||
if (isEditEnabled) {
|
||||
isSpaceIconMenuExpanded.value = !isSpaceIconMenuExpanded.value
|
||||
}
|
||||
}
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(top = 8.dp)
|
||||
.noRippleThrottledClickable {
|
||||
if (isEditEnabled) {
|
||||
isSpaceIconMenuExpanded.value = !isSpaceIconMenuExpanded.value
|
||||
}
|
||||
},
|
||||
text = stringResource(R.string.space_settings_icon_title),
|
||||
style = Caption1Medium
|
||||
)
|
||||
MaterialTheme(
|
||||
shapes = MaterialTheme.shapes.copy(medium = RoundedCornerShape(10.dp))
|
||||
) {
|
||||
DropdownMenu(
|
||||
modifier = Modifier
|
||||
.background(
|
||||
shape = RoundedCornerShape(10.dp),
|
||||
color = colorResource(id = R.color.background_secondary)
|
||||
),
|
||||
expanded = isSpaceIconMenuExpanded.value,
|
||||
offset = DpOffset(x = 0.dp, y = 6.dp),
|
||||
onDismissRequest = {
|
||||
isSpaceIconMenuExpanded.value = false
|
||||
}
|
||||
) {
|
||||
if (ActivityResultContracts.PickVisualMedia.isPhotoPickerAvailable(context)) {
|
||||
Divider(
|
||||
thickness = 0.5.dp,
|
||||
color = colorResource(id = R.color.shape_primary)
|
||||
)
|
||||
DropdownMenuItem(
|
||||
onClick = {
|
||||
singlePhotoPickerLauncher.launch(
|
||||
PickVisualMediaRequest(
|
||||
ActivityResultContracts.PickVisualMedia.ImageOnly
|
||||
)
|
||||
)
|
||||
isSpaceIconMenuExpanded.value = false
|
||||
},
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.space_settings_apply_upload_image),
|
||||
style = BodyRegular,
|
||||
color = colorResource(id = R.color.text_primary)
|
||||
)
|
||||
}
|
||||
}
|
||||
if (icon is SpaceIconView.Image) {
|
||||
DropdownMenuItem(
|
||||
onClick = {
|
||||
uiEvent(UiEvent.IconMenu.OnRemoveIconClicked)
|
||||
isSpaceIconMenuExpanded.value = false
|
||||
},
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.remove_image),
|
||||
style = BodyRegular,
|
||||
color = colorResource(id = R.color.text_primary)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,499 @@
|
|||
package com.anytypeio.anytype.ui_settings.space.new_settings
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.TextFieldDefaults
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.snapshotFlow
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.anytypeio.anytype.core_ui.extensions.light
|
||||
import com.anytypeio.anytype.core_ui.foundation.Section
|
||||
import com.anytypeio.anytype.core_ui.foundation.noRippleThrottledClickable
|
||||
import com.anytypeio.anytype.core_ui.views.BodyBold
|
||||
import com.anytypeio.anytype.core_ui.views.BodyCalloutRegular
|
||||
import com.anytypeio.anytype.core_ui.views.BodyRegular
|
||||
import com.anytypeio.anytype.core_ui.views.Caption1Regular
|
||||
import com.anytypeio.anytype.core_ui.views.PreviewTitle1Regular
|
||||
import com.anytypeio.anytype.core_ui.widgets.ListWidgetObjectIcon
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectIcon
|
||||
import com.anytypeio.anytype.presentation.spaces.UiEvent
|
||||
import com.anytypeio.anytype.presentation.spaces.UiSpaceSettingsItem
|
||||
import com.anytypeio.anytype.ui_settings.R
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.dropWhile
|
||||
import kotlinx.coroutines.flow.filter
|
||||
|
||||
@Composable
|
||||
fun MembersItem(
|
||||
modifier: Modifier = Modifier,
|
||||
item: UiSpaceSettingsItem.Members
|
||||
) {
|
||||
BaseButton(
|
||||
modifier = modifier,
|
||||
title = stringResource(id = R.string.space_settings_members_button_members),
|
||||
icon = R.drawable.ic_members_24,
|
||||
count = item.count
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ObjectTypesItem(
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
BaseButton(
|
||||
modifier = modifier,
|
||||
title = stringResource(id = R.string.space_settings_types_button),
|
||||
icon = R.drawable.ic_object_types_24,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DefaultTypeItem(
|
||||
modifier: Modifier = Modifier,
|
||||
name: String,
|
||||
icon: ObjectIcon
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.border(
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
width = 0.5.dp,
|
||||
color = colorResource(id = R.color.shape_primary)
|
||||
)
|
||||
.padding(vertical = 20.dp)
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = stringResource(id = R.string.space_settings_default_type_button),
|
||||
style = PreviewTitle1Regular,
|
||||
color = colorResource(id = R.color.text_primary),
|
||||
)
|
||||
ListWidgetObjectIcon(
|
||||
modifier = Modifier,
|
||||
iconSize = 20.dp,
|
||||
icon = icon
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.padding(start = 8.dp),
|
||||
text = name.take(10),
|
||||
style = PreviewTitle1Regular,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = colorResource(id = R.color.text_primary),
|
||||
)
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.ic_disclosure_8_24),
|
||||
contentDescription = "Members icon",
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun WallpaperItem(
|
||||
modifier: Modifier = Modifier,
|
||||
item: UiSpaceSettingsItem.Wallpapers
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.border(
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
width = 0.5.dp,
|
||||
color = colorResource(id = R.color.shape_primary)
|
||||
)
|
||||
.padding(vertical = 20.dp)
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = stringResource(id = R.string.space_settings_wallpaper_button),
|
||||
style = PreviewTitle1Regular,
|
||||
color = colorResource(id = R.color.text_primary),
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(20.dp)
|
||||
.background(
|
||||
color = light(item.color),
|
||||
shape = RoundedCornerShape(4.dp)
|
||||
)
|
||||
.padding(horizontal = 6.dp),
|
||||
)
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.ic_disclosure_8_24),
|
||||
contentDescription = "Members icon",
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SpaceInfoItem(
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
BaseButton(
|
||||
modifier = modifier,
|
||||
title = stringResource(id = R.string.space_settings_space_info_button),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DeleteSpaceItem(
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
BaseButton(
|
||||
modifier = modifier,
|
||||
title = stringResource(id = R.string.space_settings_delete_space_button),
|
||||
textColor = R.color.palette_dark_red
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun BaseButton(
|
||||
modifier: Modifier = Modifier,
|
||||
icon: Int? = null,
|
||||
title: String,
|
||||
count: Int? = null,
|
||||
textColor: Int = R.color.text_primary,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.border(
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
width = 0.5.dp,
|
||||
color = colorResource(id = R.color.shape_primary)
|
||||
)
|
||||
.padding(vertical = 20.dp)
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
if (icon != null) {
|
||||
Image(
|
||||
painter = painterResource(id = icon),
|
||||
contentDescription = "Members icon",
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
}
|
||||
Text(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = title,
|
||||
style = PreviewTitle1Regular,
|
||||
color = colorResource(id = textColor),
|
||||
)
|
||||
if (count != null) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.wrapContentSize()
|
||||
.background(
|
||||
color = colorResource(id = R.color.transparent_active),
|
||||
shape = CircleShape
|
||||
)
|
||||
.padding(horizontal = 6.dp),
|
||||
text = "$count",
|
||||
textAlign = TextAlign.Center,
|
||||
style = Caption1Regular,
|
||||
color = colorResource(id = R.color.text_white),
|
||||
)
|
||||
}
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.ic_disclosure_8_24),
|
||||
contentDescription = "Members icon",
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(FlowPreview::class)
|
||||
@Composable
|
||||
fun NewSpaceNameBlock(
|
||||
modifier: Modifier = Modifier,
|
||||
name: String,
|
||||
onNameSet: (String) -> Unit,
|
||||
isEditEnabled: Boolean
|
||||
) {
|
||||
|
||||
val nameValue = remember { mutableStateOf(name) }
|
||||
val focusManager = LocalFocusManager.current
|
||||
|
||||
LaunchedEffect(nameValue.value) {
|
||||
snapshotFlow { nameValue.value }
|
||||
.debounce(300L)
|
||||
.dropWhile { input -> input == name }
|
||||
.distinctUntilChanged()
|
||||
.filter { it.isNotEmpty() }
|
||||
.collect { query ->
|
||||
onNameSet(query)
|
||||
}
|
||||
}
|
||||
|
||||
Column(modifier = modifier) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.space_name),
|
||||
style = BodyCalloutRegular.copy(color = colorResource(id = R.color.text_primary)),
|
||||
color = colorResource(id = R.color.text_secondary)
|
||||
)
|
||||
NewSettingsTextField(
|
||||
value = nameValue.value,
|
||||
textStyle = BodyBold.copy(color = colorResource(id = R.color.text_primary)),
|
||||
onValueChange = {
|
||||
nameValue.value = it
|
||||
},
|
||||
keyboardActions = KeyboardActions(
|
||||
onDone = {
|
||||
focusManager.clearFocus()
|
||||
}
|
||||
),
|
||||
placeholderText = stringResource(id = R.string.space_settings_space_name_hint),
|
||||
isEditEnabled = isEditEnabled
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(FlowPreview::class)
|
||||
@Composable
|
||||
fun NewSpaceDescriptionBlock(
|
||||
modifier: Modifier = Modifier,
|
||||
description: String,
|
||||
onDescriptionSet: (String) -> Unit,
|
||||
isEditEnabled: Boolean
|
||||
) {
|
||||
|
||||
val descriptionValue = remember { mutableStateOf(description) }
|
||||
val focusManager = LocalFocusManager.current
|
||||
|
||||
LaunchedEffect(descriptionValue.value) {
|
||||
snapshotFlow { descriptionValue.value }
|
||||
.debounce(300L)
|
||||
.dropWhile { input -> input == description }
|
||||
.distinctUntilChanged()
|
||||
.filter { it.isNotEmpty() }
|
||||
.collect { query ->
|
||||
onDescriptionSet(query)
|
||||
}
|
||||
}
|
||||
|
||||
Column(modifier = modifier) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.space_settings_space_description_hint),
|
||||
style = BodyCalloutRegular,
|
||||
color = colorResource(id = R.color.text_secondary)
|
||||
)
|
||||
NewSettingsTextField(
|
||||
textStyle = BodyRegular.copy(color = colorResource(id = R.color.text_primary)),
|
||||
value = descriptionValue.value,
|
||||
onValueChange = {
|
||||
descriptionValue.value = it
|
||||
},
|
||||
keyboardActions = KeyboardActions(
|
||||
onDone = {
|
||||
focusManager.clearFocus()
|
||||
}
|
||||
),
|
||||
placeholderText = stringResource(id = R.string.space_settings_space_description_hint),
|
||||
isEditEnabled = isEditEnabled
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
fun NewSettingsTextField(
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
visualTransformation: VisualTransformation = VisualTransformation.None,
|
||||
keyboardActions: KeyboardActions = KeyboardActions.Default,
|
||||
textStyle: TextStyle = BodyBold,
|
||||
placeholderText: String,
|
||||
isEditEnabled: Boolean
|
||||
) {
|
||||
BasicTextField(
|
||||
value = value,
|
||||
modifier = Modifier
|
||||
.padding(top = 4.dp)
|
||||
.fillMaxWidth(),
|
||||
onValueChange = onValueChange,
|
||||
enabled = isEditEnabled,
|
||||
readOnly = !isEditEnabled,
|
||||
textStyle = textStyle,
|
||||
cursorBrush = SolidColor(colorResource(id = R.color.orange)),
|
||||
visualTransformation = visualTransformation,
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Text,
|
||||
imeAction = ImeAction.Done
|
||||
),
|
||||
keyboardActions = keyboardActions,
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
decorationBox = @Composable { innerTextField ->
|
||||
TextFieldDefaults.OutlinedTextFieldDecorationBox(
|
||||
value = value,
|
||||
visualTransformation = visualTransformation,
|
||||
innerTextField = innerTextField,
|
||||
label = null,
|
||||
leadingIcon = null,
|
||||
trailingIcon = null,
|
||||
singleLine = true,
|
||||
enabled = true,
|
||||
isError = false,
|
||||
placeholder = {
|
||||
androidx.compose.material.Text(
|
||||
style = textStyle,
|
||||
text = placeholderText,
|
||||
color = colorResource(id = R.color.text_tertiary)
|
||||
)
|
||||
},
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
colors = TextFieldDefaults.outlinedTextFieldColors(
|
||||
textColor = colorResource(id = R.color.text_primary),
|
||||
backgroundColor = Color.Transparent,
|
||||
disabledBorderColor = Color.Transparent,
|
||||
errorBorderColor = Color.Transparent,
|
||||
focusedBorderColor = Color.Transparent,
|
||||
unfocusedBorderColor = Color.Transparent,
|
||||
placeholderColor = colorResource(id = R.color.text_tertiary),
|
||||
cursorColor = colorResource(id = R.color.orange)
|
||||
),
|
||||
contentPadding = PaddingValues(),
|
||||
border = {}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MultiplayerButtons(
|
||||
modifier: Modifier = Modifier,
|
||||
uiEvent: (UiEvent) -> Unit
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.noRippleThrottledClickable {
|
||||
uiEvent(UiEvent.OnInviteClicked)
|
||||
}
|
||||
.weight(1f)
|
||||
.border(
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
width = 0.5.dp,
|
||||
color = colorResource(id = R.color.shape_primary)
|
||||
)
|
||||
.padding(vertical = 14.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.size(32.dp),
|
||||
painter = painterResource(id = R.drawable.ic_add_member_32),
|
||||
contentDescription = "Invite new member icon"
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.wrapContentSize(),
|
||||
text = stringResource(id = R.string.space_settings_invite),
|
||||
style = Caption1Regular,
|
||||
color = colorResource(id = R.color.text_primary)
|
||||
)
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.noRippleThrottledClickable {
|
||||
uiEvent(UiEvent.OnQrCodeClicked)
|
||||
}
|
||||
.weight(1f)
|
||||
.border(
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
width = 0.5.dp,
|
||||
color = colorResource(id = R.color.shape_primary)
|
||||
)
|
||||
.padding(vertical = 14.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.size(32.dp),
|
||||
painter = painterResource(id = R.drawable.ic_qr_code_32),
|
||||
contentDescription = "Share QR code icon"
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.wrapContentSize(),
|
||||
text = stringResource(id = R.string.space_settings_qrcode),
|
||||
style = Caption1Regular,
|
||||
color = colorResource(id = R.color.text_primary)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SpaceSettingsSection(
|
||||
modifier: Modifier = Modifier,
|
||||
item: UiSpaceSettingsItem.Section
|
||||
) {
|
||||
val text = when (item) {
|
||||
UiSpaceSettingsItem.Section.Collaboration ->
|
||||
stringResource(id = R.string.space_settings_section_collaboration)
|
||||
|
||||
UiSpaceSettingsItem.Section.ContentModel ->
|
||||
stringResource(id = R.string.space_settings_section_content_model)
|
||||
|
||||
UiSpaceSettingsItem.Section.DataManagement ->
|
||||
stringResource(id = R.string.space_settings_section_data_management)
|
||||
|
||||
UiSpaceSettingsItem.Section.Misc ->
|
||||
stringResource(id = R.string.space_settings_section_misc)
|
||||
|
||||
UiSpaceSettingsItem.Section.Preferences ->
|
||||
stringResource(id = R.string.space_settings_section_preferences)
|
||||
}
|
||||
Section(
|
||||
modifier = modifier,
|
||||
title = text,
|
||||
textPaddingStart = 0.dp
|
||||
)
|
||||
}
|
|
@ -0,0 +1,305 @@
|
|||
package com.anytypeio.anytype.ui_settings.space.new_settings
|
||||
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.statusBars
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.layout.wrapContentWidth
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
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.layout.ContentScale
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.anytypeio.anytype.core_ui.foundation.noRippleClickable
|
||||
import com.anytypeio.anytype.core_ui.views.PreviewTitle1Medium
|
||||
import com.anytypeio.anytype.core_utils.insets.EDGE_TO_EDGE_MIN_SDK
|
||||
import com.anytypeio.anytype.presentation.spaces.UiEvent
|
||||
import com.anytypeio.anytype.presentation.spaces.UiSpaceSettingsItem
|
||||
import com.anytypeio.anytype.presentation.spaces.UiSpaceSettingsState
|
||||
import com.anytypeio.anytype.ui_settings.R
|
||||
|
||||
@Composable
|
||||
fun SpaceSettingsContainer(
|
||||
uiState: UiSpaceSettingsState,
|
||||
uiEvent: (UiEvent) -> Unit
|
||||
) {
|
||||
if (uiState is UiSpaceSettingsState.SpaceSettings) {
|
||||
NewSpaceSettingsScreen(
|
||||
uiState = uiState,
|
||||
uiEvent = uiEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NewSpaceSettingsScreen(
|
||||
uiState: UiSpaceSettingsState.SpaceSettings,
|
||||
uiEvent: (UiEvent) -> Unit
|
||||
) {
|
||||
|
||||
// Get the initial values from your uiState items.
|
||||
val initialName = uiState.items.filterIsInstance<UiSpaceSettingsItem.Name>()
|
||||
.firstOrNull()?.name ?: ""
|
||||
val initialDescription = uiState.items.filterIsInstance<UiSpaceSettingsItem.Description>()
|
||||
.firstOrNull()?.description ?: ""
|
||||
|
||||
// Keep state of the current (edited) values.
|
||||
var nameInput by remember { mutableStateOf(initialName) }
|
||||
var descriptionInput by remember { mutableStateOf(initialDescription) }
|
||||
|
||||
// Compare against the initial values to know if something has changed.
|
||||
val isDirty = nameInput != initialName || descriptionInput != initialDescription
|
||||
|
||||
Scaffold(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
containerColor = colorResource(id = R.color.background_primary),
|
||||
topBar = {
|
||||
Box(
|
||||
modifier = if (Build.VERSION.SDK_INT >= EDGE_TO_EDGE_MIN_SDK)
|
||||
Modifier
|
||||
.windowInsetsPadding(WindowInsets.statusBars)
|
||||
.fillMaxWidth()
|
||||
.height(48.dp)
|
||||
else
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.height(48.dp)
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(R.drawable.ic_home_top_toolbar_back),
|
||||
contentDescription = "Back button",
|
||||
contentScale = ContentScale.Inside,
|
||||
modifier = Modifier
|
||||
.padding(start = 4.dp)
|
||||
.size(48.dp)
|
||||
.align(Alignment.CenterStart)
|
||||
.noRippleClickable {
|
||||
uiEvent(UiEvent.OnBackPressed)
|
||||
}
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.wrapContentWidth()
|
||||
.fillMaxHeight()
|
||||
.align(Alignment.CenterEnd)
|
||||
.clickable(enabled = isDirty) {
|
||||
uiEvent(UiEvent.OnSavedClicked(nameInput, descriptionInput))
|
||||
},
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.wrapContentSize()
|
||||
.padding(horizontal = 16.dp),
|
||||
text = stringResource(R.string.space_settings_save_button),
|
||||
style = PreviewTitle1Medium,
|
||||
color = if (isDirty) {
|
||||
colorResource(id = R.color.text_primary)
|
||||
} else {
|
||||
colorResource(id = R.color.text_tertiary)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
content = { paddingValues ->
|
||||
val contentModifier =
|
||||
if (Build.VERSION.SDK_INT >= EDGE_TO_EDGE_MIN_SDK)
|
||||
Modifier
|
||||
.windowInsetsPadding(WindowInsets.navigationBars)
|
||||
.fillMaxSize()
|
||||
.padding(top = paddingValues.calculateTopPadding())
|
||||
else
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
val lazyListState = rememberLazyListState()
|
||||
|
||||
LazyColumn(
|
||||
modifier = contentModifier
|
||||
.padding(horizontal = 16.dp),
|
||||
state = lazyListState,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
uiState.items.forEach { item ->
|
||||
when (item) {
|
||||
is UiSpaceSettingsItem.Icon -> {
|
||||
item {
|
||||
NewSpaceIcon(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.animateItem(),
|
||||
icon = item.icon,
|
||||
isEditEnabled = uiState.isEditEnabled,
|
||||
uiEvent = uiEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is UiSpaceSettingsItem.Name -> {
|
||||
item {
|
||||
NewSpaceNameBlock(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.border(
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
width = 0.5.dp,
|
||||
color = colorResource(id = R.color.shape_primary)
|
||||
)
|
||||
.padding(vertical = 12.dp, horizontal = 16.dp)
|
||||
.animateItem(),
|
||||
name = nameInput,
|
||||
onNameSet = { newName ->
|
||||
nameInput = newName
|
||||
},
|
||||
isEditEnabled = uiState.isEditEnabled
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is UiSpaceSettingsItem.Description -> {
|
||||
item {
|
||||
NewSpaceDescriptionBlock(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.border(
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
width = 0.5.dp,
|
||||
color = colorResource(id = R.color.shape_primary)
|
||||
)
|
||||
.padding(vertical = 12.dp, horizontal = 16.dp)
|
||||
.animateItem(),
|
||||
isEditEnabled = uiState.isEditEnabled,
|
||||
description = descriptionInput,
|
||||
onDescriptionSet = { newDescription ->
|
||||
descriptionInput = newDescription
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
UiSpaceSettingsItem.Multiplayer -> {
|
||||
item {
|
||||
MultiplayerButtons(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
uiEvent = uiEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is UiSpaceSettingsItem.Chat -> TODO()
|
||||
is UiSpaceSettingsItem.DefaultObjectType -> {
|
||||
item {
|
||||
DefaultTypeItem(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.animateItem(),
|
||||
name = item.name,
|
||||
icon = item.icon
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
UiSpaceSettingsItem.DeleteSpace -> {
|
||||
item {
|
||||
DeleteSpaceItem(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.animateItem()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is UiSpaceSettingsItem.Members -> {
|
||||
item {
|
||||
MembersItem(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.animateItem(),
|
||||
item = item
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
UiSpaceSettingsItem.ObjectTypes -> {
|
||||
item {
|
||||
ObjectTypesItem(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.animateItem()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is UiSpaceSettingsItem.RemoteStorage -> TODO()
|
||||
is UiSpaceSettingsItem.Section -> {
|
||||
item {
|
||||
SpaceSettingsSection(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.animateItem(),
|
||||
item = item
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
UiSpaceSettingsItem.SpaceInfo -> {
|
||||
item {
|
||||
SpaceInfoItem(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.animateItem()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is UiSpaceSettingsItem.Wallpapers -> {
|
||||
item {
|
||||
WallpaperItem(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.animateItem(),
|
||||
item = item
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is UiSpaceSettingsItem.Spacer -> {
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(item.height.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package com.anytypeio.anytype.ui_settings.space.new_settings
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.anytypeio.anytype.core_models.ThemeColor
|
||||
import com.anytypeio.anytype.core_ui.common.DefaultPreviews
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectIcon
|
||||
import com.anytypeio.anytype.presentation.spaces.SpaceIconView
|
||||
import com.anytypeio.anytype.presentation.spaces.UiSpaceSettingsItem
|
||||
import com.anytypeio.anytype.presentation.spaces.UiSpaceSettingsState
|
||||
|
||||
@Composable
|
||||
@DefaultPreviews
|
||||
fun NewSpaceSettingsScreenPreview() {
|
||||
NewSpaceSettingsScreen(
|
||||
uiState = UiSpaceSettingsState.SpaceSettings(
|
||||
items = listOf(
|
||||
UiSpaceSettingsItem.Spacer(height = 8),
|
||||
UiSpaceSettingsItem.Icon(SpaceIconView.Placeholder()),
|
||||
UiSpaceSettingsItem.Spacer(height = 16),
|
||||
UiSpaceSettingsItem.Name("Dream team"),
|
||||
UiSpaceSettingsItem.Spacer(height = 12),
|
||||
UiSpaceSettingsItem.Description("This is a dream team space"),
|
||||
UiSpaceSettingsItem.Spacer(height = 12),
|
||||
UiSpaceSettingsItem.Multiplayer,
|
||||
UiSpaceSettingsItem.Spacer(height = 8),
|
||||
UiSpaceSettingsItem.Section.Collaboration,
|
||||
UiSpaceSettingsItem.Members(5),
|
||||
UiSpaceSettingsItem.Section.ContentModel,
|
||||
UiSpaceSettingsItem.ObjectTypes,
|
||||
UiSpaceSettingsItem.Section.Preferences,
|
||||
UiSpaceSettingsItem.DefaultObjectType(
|
||||
name = "Taskwithveryverlylongname",
|
||||
icon = ObjectIcon.Empty.ObjectType
|
||||
),
|
||||
UiSpaceSettingsItem.Spacer(height = 8),
|
||||
UiSpaceSettingsItem.Wallpapers(color = ThemeColor.TEAL),
|
||||
UiSpaceSettingsItem.Spacer(height = 8),
|
||||
UiSpaceSettingsItem.Section.DataManagement,
|
||||
UiSpaceSettingsItem.Spacer(height = 8),
|
||||
UiSpaceSettingsItem.Section.Misc,
|
||||
UiSpaceSettingsItem.SpaceInfo,
|
||||
UiSpaceSettingsItem.Spacer(height = 8),
|
||||
UiSpaceSettingsItem.DeleteSpace,
|
||||
UiSpaceSettingsItem.Spacer(height = 32),
|
||||
|
||||
),
|
||||
isEditEnabled = true
|
||||
),
|
||||
uiEvent = {},
|
||||
)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue