mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-3375 New settings | Fix| UX fixes and improvements (#2200)
This commit is contained in:
parent
5a7a58e0f9
commit
8abc29f526
13 changed files with 470 additions and 96 deletions
|
@ -74,6 +74,10 @@ class WallpaperSelectFragment : BaseBottomSheetFragment<FragmentWallpaperSelectB
|
|||
subscribe(vm.state) { wallpaperSelectAdapter.update(it) }
|
||||
subscribe(vm.isDismissed) { isDismissed -> if (isDismissed) dismiss() }
|
||||
}
|
||||
|
||||
skipCollapsed()
|
||||
expand()
|
||||
|
||||
}
|
||||
|
||||
override fun injectDependencies() {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package com.anytypeio.anytype.ui.multiplayer
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
|
@ -11,18 +13,21 @@ import androidx.compose.material3.Text
|
|||
import androidx.compose.runtime.Composable
|
||||
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.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.anytypeio.anytype.R
|
||||
import com.anytypeio.anytype.core_ui.common.DefaultPreviews
|
||||
import com.anytypeio.anytype.core_ui.foundation.Dragger
|
||||
import com.anytypeio.anytype.core_ui.views.BodyCalloutRegular
|
||||
import com.anytypeio.anytype.core_ui.views.HeadlineHeading
|
||||
import com.anytypeio.anytype.core_ui.foundation.Header
|
||||
import com.anytypeio.anytype.core_ui.views.BodyRegular
|
||||
import com.anytypeio.anytype.core_utils.clipboard.copyPlainTextToClipboard
|
||||
import com.lightspark.composeqr.QrCodeView
|
||||
|
||||
@Preview
|
||||
@DefaultPreviews
|
||||
@Composable
|
||||
fun ShareQrCodeScreenPreview() {
|
||||
ShareQrCodeScreen(link ="https://github.com/anyproto/anytype-kotlin")
|
||||
|
@ -30,23 +35,15 @@ fun ShareQrCodeScreenPreview() {
|
|||
|
||||
@Composable
|
||||
fun ShareQrCodeScreen(link: String) {
|
||||
val context = LocalContext.current
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 20.dp),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Dragger(Modifier.padding(vertical = 6.dp))
|
||||
Text(
|
||||
text = stringResource(id = R.string.multiplayer_share_space),
|
||||
style = HeadlineHeading,
|
||||
color = colorResource(id = R.color.text_primary)
|
||||
)
|
||||
Spacer(modifier = Modifier.height(10.dp))
|
||||
Text(
|
||||
text = stringResource(R.string.multiplayer_how_to_share_space_qr_code),
|
||||
color = colorResource(id = R.color.text_primary),
|
||||
style = BodyCalloutRegular
|
||||
Header(
|
||||
text = stringResource(id = R.string.space_settings_qrcode)
|
||||
)
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
QrCodeView(
|
||||
|
@ -59,5 +56,36 @@ fun ShareQrCodeScreen(link: String) {
|
|||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(48.dp)
|
||||
.clickable {
|
||||
context.copyPlainTextToClipboard(
|
||||
plainText = link,
|
||||
label = "Space invite link",
|
||||
successToast = context.getString(R.string.space_invite_link_copied)
|
||||
)
|
||||
}
|
||||
.padding(horizontal = 20.dp)
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.align(Alignment.CenterStart),
|
||||
painter = painterResource(R.drawable.ic_copy_24),
|
||||
contentDescription = "Copy icon"
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(start = 36.dp)
|
||||
.fillMaxWidth()
|
||||
.align(Alignment.CenterStart)
|
||||
,
|
||||
text = link,
|
||||
color = colorResource(R.color.text_primary),
|
||||
style = BodyRegular,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@ import com.anytypeio.anytype.presentation.spaces.SpaceSettingsViewModel
|
|||
import com.anytypeio.anytype.presentation.spaces.SpaceSettingsViewModel.Command
|
||||
import com.anytypeio.anytype.presentation.util.downloader.UriFileProvider
|
||||
import com.anytypeio.anytype.ui.multiplayer.LeaveSpaceWarning
|
||||
import com.anytypeio.anytype.ui.multiplayer.ShareQrCodeSpaceInviteFragment
|
||||
import com.anytypeio.anytype.ui.multiplayer.ShareSpaceFragment
|
||||
import com.anytypeio.anytype.ui.objects.types.pickers.AppDefaultObjectTypeFragment
|
||||
import com.anytypeio.anytype.ui.objects.types.pickers.ObjectTypeSelectionListener
|
||||
|
@ -189,6 +190,16 @@ class SpaceSettingsFragment : BaseComposeFragment(), ObjectTypeSelectionListener
|
|||
Timber.w(it, "Error while opening bin from widgets")
|
||||
}
|
||||
}
|
||||
is Command.ShowInviteLinkQrCode -> {
|
||||
runCatching {
|
||||
findNavController().navigate(
|
||||
R.id.shareSpaceInviteQrCodeScreen,
|
||||
ShareQrCodeSpaceInviteFragment.args(link = command.link)
|
||||
)
|
||||
}.onFailure {
|
||||
Timber.w(it, "Error while showing invite QR code from space settings")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
15
core-ui/src/main/res/drawable/ic_more_32.xml
Normal file
15
core-ui/src/main/res/drawable/ic_more_32.xml
Normal file
|
@ -0,0 +1,15 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="32"
|
||||
android:viewportHeight="32">
|
||||
<path
|
||||
android:pathData="M9,16m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"
|
||||
android:fillColor="@color/glyph_active"/>
|
||||
<path
|
||||
android:pathData="M16,16m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"
|
||||
android:fillColor="@color/glyph_active"/>
|
||||
<path
|
||||
android:pathData="M23,16m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"
|
||||
android:fillColor="@color/glyph_active"/>
|
||||
</vector>
|
|
@ -0,0 +1,19 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M12,10.75C13.795,10.75 15.25,9.183 15.25,7.25C15.25,5.317 13.795,3.75 12,3.75C10.205,3.75 8.75,5.317 8.75,7.25C8.75,9.183 10.205,10.75 12,10.75ZM12,12.25C8.686,12.25 6,14.936 6,18.25C6,19.355 6.895,20.25 8,20.25H16C17.105,20.25 18,19.355 18,18.25C18,14.936 15.314,12.25 12,12.25Z"
|
||||
android:fillColor="@color/glyph_button"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M18,18m-4.75,0a4.75,4.75 0,1 1,9.5 0a4.75,4.75 0,1 1,-9.5 0"
|
||||
android:strokeWidth="1.5"
|
||||
android:fillColor="@color/glyph_button"
|
||||
android:strokeColor="#ffffff"/>
|
||||
<path
|
||||
android:pathData="M17.25,19.75C17.25,20.164 17.586,20.5 18,20.5C18.414,20.5 18.75,20.164 18.75,19.75V18.75H19.75C20.164,18.75 20.5,18.414 20.5,18C20.5,17.586 20.164,17.25 19.75,17.25H18.75V16.25C18.75,15.836 18.414,15.5 18,15.5C17.586,15.5 17.25,15.836 17.25,16.25V17.25H16.25C15.836,17.25 15.5,17.586 15.5,18C15.5,18.414 15.836,18.75 16.25,18.75H17.25V19.75Z"
|
||||
android:fillColor="@color/shape_primary"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
|
@ -75,18 +75,20 @@ fun NewSpaceIcon(
|
|||
}
|
||||
}
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(top = 8.dp)
|
||||
.noRippleThrottledClickable {
|
||||
if (isEditEnabled) {
|
||||
isSpaceIconMenuExpanded.value = !isSpaceIconMenuExpanded.value
|
||||
}
|
||||
},
|
||||
text = stringResource(R.string.space_settings_icon_title),
|
||||
style = Caption1Medium,
|
||||
color = colorResource(R.color.text_secondary)
|
||||
)
|
||||
if (isEditEnabled) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(top = 8.dp)
|
||||
.noRippleThrottledClickable {
|
||||
if (isEditEnabled) {
|
||||
isSpaceIconMenuExpanded.value = !isSpaceIconMenuExpanded.value
|
||||
}
|
||||
},
|
||||
text = stringResource(R.string.space_settings_icon_title),
|
||||
style = Caption1Medium,
|
||||
color = colorResource(R.color.text_secondary)
|
||||
)
|
||||
}
|
||||
MaterialTheme(
|
||||
shapes = MaterialTheme.shapes.copy(medium = RoundedCornerShape(10.dp))
|
||||
) {
|
||||
|
|
|
@ -30,6 +30,8 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.runtime.snapshotFlow
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.SolidColor
|
||||
|
@ -37,9 +39,11 @@ 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.TextRange
|
||||
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.TextFieldValue
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
|
@ -62,6 +66,7 @@ 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.delay
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.dropWhile
|
||||
|
@ -243,6 +248,7 @@ fun RemoteStorageItem(
|
|||
BaseButton(
|
||||
modifier = modifier,
|
||||
title = stringResource(id = R.string.remote_storage),
|
||||
icon = R.drawable.ic_remote_storage_24
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -444,12 +450,23 @@ fun NewSettingsTextField(
|
|||
placeholderText: String,
|
||||
isEditEnabled: Boolean
|
||||
) {
|
||||
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
|
||||
val textFieldValue = TextFieldValue(
|
||||
text = value,
|
||||
selection = TextRange(value.length)
|
||||
)
|
||||
BasicTextField(
|
||||
value = value,
|
||||
value = textFieldValue,
|
||||
modifier = Modifier
|
||||
.padding(top = 4.dp)
|
||||
.fillMaxWidth(),
|
||||
onValueChange = onValueChange,
|
||||
.fillMaxWidth()
|
||||
.focusRequester(focusRequester)
|
||||
,
|
||||
onValueChange = { update ->
|
||||
onValueChange(update.text)
|
||||
},
|
||||
enabled = isEditEnabled,
|
||||
readOnly = !isEditEnabled,
|
||||
textStyle = textStyle,
|
||||
|
@ -495,6 +512,12 @@ fun NewSettingsTextField(
|
|||
)
|
||||
}
|
||||
)
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
// Focusing with delay, awaiting the expansion of the bottom sheet
|
||||
delay(300)
|
||||
focusRequester.requestFocus()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
@ -22,6 +22,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
|||
import androidx.compose.material3.ModalBottomSheet
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.rememberModalBottomSheetState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
|
@ -34,6 +35,7 @@ import androidx.compose.ui.layout.ContentScale
|
|||
import androidx.compose.ui.platform.LocalContext
|
||||
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.Dragger
|
||||
import com.anytypeio.anytype.core_ui.foundation.noRippleClickable
|
||||
|
@ -229,7 +231,21 @@ fun NewSpaceSettingsScreen(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
is UiSpaceSettingsItem.InviteMembers -> {
|
||||
item {
|
||||
BaseButton(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.animateItem()
|
||||
.clip(RoundedCornerShape(16.dp))
|
||||
.clickable {
|
||||
uiEvent(UiEvent.OnInviteClicked)
|
||||
},
|
||||
title = stringResource(id = R.string.space_settings_invite_members),
|
||||
icon = R.drawable.ic_space_settings_invite_members
|
||||
)
|
||||
}
|
||||
}
|
||||
UiSpaceSettingsItem.ObjectTypes -> {
|
||||
item {
|
||||
ObjectTypesItem(
|
||||
|
@ -335,6 +351,8 @@ fun NewSpaceSettingsScreen(
|
|||
|
||||
if (showEditDescription) {
|
||||
ModalBottomSheet(
|
||||
sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true),
|
||||
modifier = Modifier.padding(top = 48.dp),
|
||||
containerColor = colorResource(R.color.background_secondary),
|
||||
onDismissRequest = {
|
||||
showEditDescription = false
|
||||
|
@ -357,6 +375,8 @@ fun NewSpaceSettingsScreen(
|
|||
}
|
||||
if (showEditTitle) {
|
||||
ModalBottomSheet(
|
||||
sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true),
|
||||
modifier = Modifier.padding(top = 48.dp),
|
||||
containerColor = colorResource(R.color.background_secondary),
|
||||
onDismissRequest = {
|
||||
showEditTitle = false
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
package com.anytypeio.anytype.ui_settings.space.new_settings
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.DropdownMenu
|
||||
import androidx.compose.material.DropdownMenuItem
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ModalBottomSheet
|
||||
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.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.DpOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.anytypeio.anytype.core_models.SystemColor
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
import com.anytypeio.anytype.core_ui.common.DefaultPreviews
|
||||
import com.anytypeio.anytype.core_ui.foundation.Dragger
|
||||
import com.anytypeio.anytype.core_ui.views.BodyCalloutRegular
|
||||
import com.anytypeio.anytype.core_ui.views.HeadlineHeading
|
||||
import com.anytypeio.anytype.presentation.spaces.SpaceIconView
|
||||
import com.anytypeio.anytype.presentation.spaces.SpaceTechInfo
|
||||
import com.anytypeio.anytype.presentation.spaces.UiEvent
|
||||
import com.anytypeio.anytype.ui_settings.R
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ViewerSpaceSettings(
|
||||
title: String,
|
||||
description: String,
|
||||
icon: SpaceIconView,
|
||||
info: SpaceTechInfo,
|
||||
uiEvent: (UiEvent) -> Unit,
|
||||
) {
|
||||
|
||||
val isTheeDotsMenuExpanded = remember { mutableStateOf(true) }
|
||||
var showTechInfo by remember { mutableStateOf(false) }
|
||||
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Dragger(
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.padding(vertical = 6.dp)
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.height(48.dp)
|
||||
.width(56.dp)
|
||||
.align(Alignment.End)
|
||||
.clickable {
|
||||
isTheeDotsMenuExpanded.value = true
|
||||
}
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.align(Alignment.Center),
|
||||
painter = painterResource(R.drawable.ic_more_32),
|
||||
contentDescription = "Three dots button"
|
||||
)
|
||||
}
|
||||
NewSpaceIcon(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
icon = icon,
|
||||
isEditEnabled = false,
|
||||
uiEvent = uiEvent
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Text(
|
||||
text = title.ifEmpty { stringResource(R.string.untitled) },
|
||||
style = HeadlineHeading,
|
||||
color = colorResource(R.color.text_primary),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
if (description.isNotEmpty()) {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Text(
|
||||
text = description,
|
||||
modifier = Modifier.padding(horizontal = 16.dp).fillMaxWidth(),
|
||||
style = BodyCalloutRegular,
|
||||
color = colorResource(R.color.text_primary),
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
MultiplayerButtons(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp),
|
||||
uiEvent = uiEvent
|
||||
)
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
}
|
||||
|
||||
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 = isTheeDotsMenuExpanded.value,
|
||||
offset = DpOffset(x = 0.dp, y = 6.dp),
|
||||
onDismissRequest = {
|
||||
isTheeDotsMenuExpanded.value = false
|
||||
}
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
onClick = {
|
||||
uiEvent(UiEvent.IconMenu.OnRemoveIconClicked)
|
||||
isTheeDotsMenuExpanded.value = false
|
||||
},
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.tech_info),
|
||||
style = BodyCalloutRegular,
|
||||
color = colorResource(id = R.color.text_primary)
|
||||
)
|
||||
}
|
||||
DropdownMenuItem(
|
||||
onClick = {
|
||||
isTheeDotsMenuExpanded.value = false
|
||||
uiEvent(UiEvent.OnLeaveSpaceClicked)
|
||||
},
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.multiplayer_leave_space),
|
||||
style = BodyCalloutRegular,
|
||||
color = colorResource(id = R.color.palette_system_red)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (showTechInfo) {
|
||||
ModalBottomSheet(
|
||||
containerColor = colorResource(R.color.background_secondary),
|
||||
onDismissRequest = { showTechInfo = false },
|
||||
dragHandle = null,
|
||||
content = { SpaceInfoScreen(spaceTechInfo = info) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@DefaultPreviews
|
||||
@Composable
|
||||
fun ViewerSpaceSettingsWithDescriptionPreview() {
|
||||
ViewerSpaceSettings(
|
||||
title = "Susan Sontag",
|
||||
description = stringResource(R.string.default_text_placeholder),
|
||||
uiEvent = {},
|
||||
icon = SpaceIconView.Placeholder(
|
||||
name = "Susan",
|
||||
color = SystemColor.SKY
|
||||
),
|
||||
info = SpaceTechInfo(
|
||||
spaceId = SpaceId("space-id"),
|
||||
createdBy = "Thomas",
|
||||
creationDateInMillis = null,
|
||||
networkId = "random network id"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@DefaultPreviews
|
||||
@Composable
|
||||
fun ViewerSpaceSettingsWithoutDescriptionPreview() {
|
||||
ViewerSpaceSettings(
|
||||
title = "Susan Sontag",
|
||||
description = "",
|
||||
uiEvent = {},
|
||||
icon = SpaceIconView.Placeholder(
|
||||
name = "Susan",
|
||||
color = SystemColor.SKY
|
||||
),
|
||||
info = SpaceTechInfo(
|
||||
spaceId = SpaceId("space-id"),
|
||||
createdBy = "Thomas",
|
||||
creationDateInMillis = null,
|
||||
networkId = "random network id"
|
||||
)
|
||||
)
|
||||
}
|
|
@ -1957,6 +1957,7 @@ Please provide specific details of your needs here.</string>
|
|||
<string name="space_settings_section_data_management">Data Management</string>
|
||||
<string name="space_settings_section_misc">Misc</string>
|
||||
<string name="space_settings_invite">Invite</string>
|
||||
<string name="space_settings_invite_members">Invite members</string>
|
||||
<string name="space_settings_qrcode">QR Code</string>
|
||||
<string name="space_settings_members_button_members">Members</string>
|
||||
<string name="space_settings_types_button">Object Types</string>
|
||||
|
@ -2003,5 +2004,6 @@ Please provide specific details of your needs here.</string>
|
|||
<string name="object_type_icon_change_title">Change icon</string>
|
||||
<string name="object_type_icon_remove">Remove</string>
|
||||
<string name="object_type_icon_change_title_search_hint">Search..."</string>
|
||||
<string name="space_invite_link_copied">Space invite link copied!</string>
|
||||
|
||||
</resources>
|
|
@ -19,11 +19,15 @@ import com.anytypeio.anytype.core_models.Relations
|
|||
import com.anytypeio.anytype.core_models.SpaceType
|
||||
import com.anytypeio.anytype.core_models.ext.EMPTY_STRING_VALUE
|
||||
import com.anytypeio.anytype.core_models.multiplayer.ParticipantStatus
|
||||
import com.anytypeio.anytype.core_models.multiplayer.SpaceAccessType
|
||||
import com.anytypeio.anytype.core_models.multiplayer.SpaceInviteView
|
||||
import com.anytypeio.anytype.core_models.multiplayer.SpaceMemberPermissions
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
import com.anytypeio.anytype.core_models.primitives.TypeId
|
||||
import com.anytypeio.anytype.core_models.primitives.TypeKey
|
||||
import com.anytypeio.anytype.domain.base.fold
|
||||
import com.anytypeio.anytype.domain.base.onFailure
|
||||
import com.anytypeio.anytype.domain.base.onSuccess
|
||||
import com.anytypeio.anytype.domain.debugging.DebugSpaceShareDownloader
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultObjectType
|
||||
import com.anytypeio.anytype.domain.launch.SetDefaultObjectType
|
||||
|
@ -31,6 +35,7 @@ import com.anytypeio.anytype.domain.media.UploadFile
|
|||
import com.anytypeio.anytype.domain.misc.AppActionManager
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.multiplayer.ActiveSpaceMemberSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.multiplayer.GetSpaceInviteLink
|
||||
import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
|
||||
import com.anytypeio.anytype.domain.multiplayer.sharedSpaceCount
|
||||
|
@ -73,7 +78,8 @@ class SpaceSettingsViewModel(
|
|||
private val setDefaultObjectType: SetDefaultObjectType,
|
||||
private val observeWallpaper: ObserveWallpaper,
|
||||
private val storeOfObjectTypes: StoreOfObjectTypes,
|
||||
private val appActionManager: AppActionManager
|
||||
private val appActionManager: AppActionManager,
|
||||
private val getSpaceInviteLink: GetSpaceInviteLink
|
||||
): BaseViewModel() {
|
||||
|
||||
val commands = MutableSharedFlow<Command>()
|
||||
|
@ -117,6 +123,7 @@ class SpaceSettingsViewModel(
|
|||
}
|
||||
|
||||
viewModelScope.launch {
|
||||
|
||||
val defaultObjectTypeResponse = getDefaultObjectType
|
||||
.async(params = vmParams.space)
|
||||
.getOrNull()
|
||||
|
@ -174,46 +181,70 @@ class SpaceSettingsViewModel(
|
|||
networkId = spaceManager.getConfig(vmParams.space)?.network.orEmpty()
|
||||
)
|
||||
|
||||
UiSpaceSettingsState.SpaceSettings(
|
||||
spaceTechInfo = spaceTechInfo,
|
||||
items = listOf(
|
||||
// TODO In the next PR : show different settings for viewer
|
||||
|
||||
val items = buildList<UiSpaceSettingsItem> {
|
||||
add(
|
||||
UiSpaceSettingsItem.Icon(
|
||||
icon = spaceView.spaceIcon(
|
||||
builder = urlBuilder,
|
||||
spaceGradientProvider = gradientProvider
|
||||
)
|
||||
),
|
||||
Spacer(height = 16),
|
||||
)
|
||||
)
|
||||
add(Spacer(height = 24))
|
||||
add(
|
||||
UiSpaceSettingsItem.Name(
|
||||
name = spaceView.name.orEmpty()
|
||||
),
|
||||
Spacer(height = 12),
|
||||
)
|
||||
)
|
||||
add(
|
||||
Spacer(height = 8),
|
||||
)
|
||||
add(
|
||||
UiSpaceSettingsItem.Description(
|
||||
description = spaceView.description.orEmpty()
|
||||
),
|
||||
Spacer(height = 12),
|
||||
UiSpaceSettingsItem.Multiplayer,
|
||||
Spacer(height = 8),
|
||||
UiSpaceSettingsItem.Section.Collaboration,
|
||||
UiSpaceSettingsItem.Members(count = spaceMemberCount),
|
||||
UiSpaceSettingsItem.Section.ContentModel,
|
||||
UiSpaceSettingsItem.ObjectTypes,
|
||||
Spacer(height = 8),
|
||||
UiSpaceSettingsItem.Fields,
|
||||
UiSpaceSettingsItem.Section.Preferences,
|
||||
defaultObjectTypeSettingItem,
|
||||
Spacer(height = 8),
|
||||
UiSpaceSettingsItem.Wallpapers(current = wallpaper),
|
||||
UiSpaceSettingsItem.Section.DataManagement,
|
||||
UiSpaceSettingsItem.RemoteStorage,
|
||||
Spacer(height = 8),
|
||||
UiSpaceSettingsItem.Bin,
|
||||
UiSpaceSettingsItem.Section.Misc,
|
||||
UiSpaceSettingsItem.SpaceInfo,
|
||||
Spacer(height = 8),
|
||||
UiSpaceSettingsItem.DeleteSpace,
|
||||
Spacer(height = 32)
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
if (spaceView.spaceAccessType == SpaceAccessType.SHARED) {
|
||||
add(Spacer(height = 8))
|
||||
add(UiSpaceSettingsItem.Multiplayer)
|
||||
}
|
||||
|
||||
add(UiSpaceSettingsItem.Section.Collaboration)
|
||||
|
||||
if (spaceView.spaceAccessType == SpaceAccessType.SHARED) {
|
||||
add(UiSpaceSettingsItem.Members(count = spaceMemberCount))
|
||||
} else {
|
||||
add(UiSpaceSettingsItem.InviteMembers)
|
||||
}
|
||||
|
||||
add(UiSpaceSettingsItem.Section.ContentModel)
|
||||
add(UiSpaceSettingsItem.ObjectTypes)
|
||||
add(Spacer(height = 8))
|
||||
add(UiSpaceSettingsItem.Fields)
|
||||
|
||||
add(UiSpaceSettingsItem.Section.Preferences)
|
||||
add(defaultObjectTypeSettingItem)
|
||||
add(Spacer(height = 8))
|
||||
add(UiSpaceSettingsItem.Wallpapers(current = wallpaper))
|
||||
|
||||
add(UiSpaceSettingsItem.Section.DataManagement)
|
||||
add(UiSpaceSettingsItem.RemoteStorage)
|
||||
add(Spacer(height = 8))
|
||||
add(UiSpaceSettingsItem.Bin)
|
||||
|
||||
add(UiSpaceSettingsItem.Section.Misc)
|
||||
add(UiSpaceSettingsItem.SpaceInfo)
|
||||
add(Spacer(height = 8))
|
||||
add(UiSpaceSettingsItem.DeleteSpace)
|
||||
add(Spacer(height = 32))
|
||||
}
|
||||
|
||||
UiSpaceSettingsState.SpaceSettings(
|
||||
spaceTechInfo = spaceTechInfo,
|
||||
items = items,
|
||||
isEditEnabled = permission?.isOwnerOrEditor() == true
|
||||
)
|
||||
|
||||
|
@ -233,11 +264,10 @@ class SpaceSettingsViewModel(
|
|||
isDismissed.value = true
|
||||
}
|
||||
UiEvent.OnDeleteSpaceClicked -> {
|
||||
viewModelScope.launch {
|
||||
commands.emit(
|
||||
Command.ShowDeleteSpaceWarning
|
||||
)
|
||||
}
|
||||
viewModelScope.launch { commands.emit(Command.ShowDeleteSpaceWarning) }
|
||||
}
|
||||
UiEvent.OnLeaveSpaceClicked -> {
|
||||
viewModelScope.launch { commands.emit(Command.ShowLeaveSpaceWarning) }
|
||||
}
|
||||
UiEvent.OnRemoteStorageClick -> {
|
||||
viewModelScope.launch {
|
||||
|
@ -250,13 +280,30 @@ class SpaceSettingsViewModel(
|
|||
}
|
||||
}
|
||||
UiEvent.OnInviteClicked -> {
|
||||
sendToast("Coming soon")
|
||||
viewModelScope.launch {
|
||||
commands.emit(
|
||||
Command.ManageSharedSpace(vmParams.space)
|
||||
)
|
||||
}
|
||||
}
|
||||
UiEvent.OnPersonalizationClicked -> {
|
||||
sendToast("Coming soon")
|
||||
}
|
||||
UiEvent.OnQrCodeClicked -> {
|
||||
sendToast("Coming soon")
|
||||
viewModelScope.launch {
|
||||
getSpaceInviteLink
|
||||
.async(vmParams.space)
|
||||
.onFailure {
|
||||
commands.emit(
|
||||
Command.ManageSharedSpace(vmParams.space)
|
||||
)
|
||||
}
|
||||
.onSuccess { link ->
|
||||
commands.emit(
|
||||
Command.ShowInviteLinkQrCode(link.scheme)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
is UiEvent.OnSaveDescriptionClicked -> {
|
||||
viewModelScope.launch {
|
||||
|
@ -401,26 +448,22 @@ class SpaceSettingsViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
private fun proceedWithSpaceDebug() {
|
||||
viewModelScope.launch {
|
||||
debugSpaceShareDownloader
|
||||
.stream(Unit)
|
||||
.collect { result ->
|
||||
result.fold(
|
||||
onLoading = { sendToast(SPACE_DEBUG_MSG) },
|
||||
onSuccess = { path -> commands.emit(Command.ShareSpaceDebug(path)) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
// What is below is candidate to legacy. Might be deleted soon.
|
||||
|
||||
fun onManageSharedSpaceClicked() {
|
||||
viewModelScope.launch {
|
||||
commands.emit(
|
||||
Command.ManageSharedSpace(vmParams.space)
|
||||
)
|
||||
}
|
||||
}
|
||||
// TODO add debug functionality
|
||||
|
||||
// private fun proceedWithSpaceDebug() {
|
||||
// viewModelScope.launch {
|
||||
// debugSpaceShareDownloader
|
||||
// .stream(Unit)
|
||||
// .collect { result ->
|
||||
// result.fold(
|
||||
// onLoading = { sendToast(SPACE_DEBUG_MSG) },
|
||||
// onSuccess = { path -> commands.emit(Command.ShareSpaceDebug(path)) }
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// fun onSharePrivateSpaceClicked() {
|
||||
// viewModelScope.launch {
|
||||
|
@ -459,9 +502,9 @@ class SpaceSettingsViewModel(
|
|||
// }
|
||||
// }
|
||||
|
||||
private fun resolveIsSpaceDeletable(spaceView: ObjectWrapper.SpaceView) : Boolean {
|
||||
return spaceView.spaceAccessType != null
|
||||
}
|
||||
// private fun resolveIsSpaceDeletable(spaceView: ObjectWrapper.SpaceView) : Boolean {
|
||||
// return spaceView.spaceAccessType != null
|
||||
// }
|
||||
|
||||
// fun onAddMoreSpacesClicked() {
|
||||
// viewModelScope.launch {
|
||||
|
@ -624,6 +667,7 @@ class SpaceSettingsViewModel(
|
|||
data class ShareSpaceDebug(val filepath: Filepath) : Command()
|
||||
data class SharePrivateSpace(val space: SpaceId) : Command()
|
||||
data class ManageSharedSpace(val space: SpaceId) : Command()
|
||||
data class ShowInviteLinkQrCode(val link: String) : Command()
|
||||
data class ManageBin(val space: SpaceId) : Command()
|
||||
data class SelectDefaultObjectType(val space: SpaceId, val excludedTypeIds: List<Id>) : Command()
|
||||
data object ExitToVault : Command()
|
||||
|
@ -656,7 +700,8 @@ class SpaceSettingsViewModel(
|
|||
private val setDefaultObjectType: SetDefaultObjectType,
|
||||
private val observeWallpaper: ObserveWallpaper,
|
||||
private val appActionManager: AppActionManager,
|
||||
private val storeOfObjectTypes: StoreOfObjectTypes
|
||||
private val storeOfObjectTypes: StoreOfObjectTypes,
|
||||
private val getSpaceInviteLink: GetSpaceInviteLink
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(
|
||||
|
@ -681,7 +726,8 @@ class SpaceSettingsViewModel(
|
|||
setDefaultObjectType = setDefaultObjectType,
|
||||
observeWallpaper = observeWallpaper,
|
||||
appActionManager = appActionManager,
|
||||
storeOfObjectTypes = storeOfObjectTypes
|
||||
storeOfObjectTypes = storeOfObjectTypes,
|
||||
getSpaceInviteLink = getSpaceInviteLink
|
||||
) as T
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ sealed class UiEvent {
|
|||
data class OnDefaultObjectTypeClicked(val currentDefaultObjectTypeId: Id?) : UiEvent()
|
||||
|
||||
data object OnDeleteSpaceClicked : UiEvent()
|
||||
data object OnLeaveSpaceClicked : UiEvent()
|
||||
data object OnRemoteStorageClick : UiEvent()
|
||||
data object OnBinClick : UiEvent()
|
||||
data object OnPersonalizationClicked : UiEvent()
|
||||
|
|
|
@ -44,6 +44,7 @@ sealed class UiSpaceSettingsItem {
|
|||
data class Description(val description: String) : UiSpaceSettingsItem()
|
||||
data object Multiplayer : UiSpaceSettingsItem()
|
||||
data class Members(val count: Int) : UiSpaceSettingsItem()
|
||||
data object InviteMembers : UiSpaceSettingsItem()
|
||||
data class Chat(val isOn: Boolean) : UiSpaceSettingsItem()
|
||||
data object ObjectTypes : UiSpaceSettingsItem()
|
||||
data object Fields : UiSpaceSettingsItem()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue