1
0
Fork 0
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:
Evgenii Kozlov 2025-03-27 20:05:07 +01:00 committed by GitHub
parent 5a7a58e0f9
commit 8abc29f526
Signed by: github
GPG key ID: B5690EEEBB952194
13 changed files with 470 additions and 96 deletions

View file

@ -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() {

View file

@ -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
)
}
}
}

View file

@ -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")
}
}
}
}
}

View 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>

View file

@ -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>

View file

@ -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))
) {

View file

@ -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

View file

@ -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

View file

@ -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"
)
)
}

View file

@ -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>

View file

@ -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
}

View file

@ -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()

View file

@ -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()