From 4f5dcb435f54a1c7d8fe94e202d9e5bc5874f402 Mon Sep 17 00:00:00 2001 From: Evgenii Kozlov Date: Fri, 4 Apr 2025 21:47:17 +0200 Subject: [PATCH] DROID-3518 Space settings | Enhancement | Add a setting item for disabling automated widgets creation logic (#2244) --- .../anytype/core_models/Relations.kt | 2 + .../ui_settings/space/new_settings/Items.kt | 66 +++++++++++++++++++ .../space/new_settings/NewSettings.kt | 16 ++++- localization/src/main/res/values/strings.xml | 1 + .../spaces/SpaceSettingsViewModel.kt | 57 ++++++++++++++-- .../anytype/presentation/spaces/UiEvent.kt | 5 ++ .../anytype/presentation/spaces/UiState.kt | 5 +- .../editor/file_layout/FileLayoutTest.kt | 3 +- 8 files changed, 148 insertions(+), 7 deletions(-) diff --git a/core-models/src/main/java/com/anytypeio/anytype/core_models/Relations.kt b/core-models/src/main/java/com/anytypeio/anytype/core_models/Relations.kt index 55588a8c6c..8ec0c54757 100644 --- a/core-models/src/main/java/com/anytypeio/anytype/core_models/Relations.kt +++ b/core-models/src/main/java/com/anytypeio/anytype/core_models/Relations.kt @@ -107,6 +107,8 @@ object Relations { const val LAYOUT_ALIGN = "layoutAlign" + const val AUTO_WIDGET_DISABLED = "autoWidgetDisabled" + val systemRelationKeys = listOf( "id", "name", diff --git a/feature-ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/space/new_settings/Items.kt b/feature-ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/space/new_settings/Items.kt index f84274226f..2e1432cb48 100644 --- a/feature-ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/space/new_settings/Items.kt +++ b/feature-ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/space/new_settings/Items.kt @@ -11,6 +11,7 @@ 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.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width @@ -22,6 +23,9 @@ 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.Switch +import androidx.compose.material3.SwitchColors +import androidx.compose.material3.SwitchDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -611,4 +615,66 @@ fun SpaceSettingsSection( title = text, textPaddingStart = 0.dp ) +} + +@Composable +fun AutoCreateWidgetItem( + onCheckedStatusChanged: (Boolean) -> Unit, + isChecked: Boolean +) { + + var checked = remember { mutableStateOf(isChecked) } + + Row( + modifier = Modifier + .border( + shape = RoundedCornerShape(16.dp), + width = 0.5.dp, + color = colorResource(id = R.color.shape_primary) + ) + .height(64.dp) + .fillMaxWidth() + .padding(horizontal = 16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + modifier = Modifier.weight(1f), + text = stringResource(id = R.string.space_settings_auto_create_widgets), + style = PreviewTitle1Regular, + color = colorResource(id = R.color.text_primary), + ) + Switch( + checked = checked.value, + onCheckedChange = { + checked.value = it + onCheckedStatusChanged(it) + }, + colors = SwitchDefaults.colors().copy( + checkedBorderColor = Color.Transparent, + uncheckedBorderColor = Color.Transparent, + checkedTrackColor = colorResource(R.color.palette_system_amber_50), + uncheckedTrackColor = colorResource(R.color.palette_system_amber_50), + uncheckedThumbColor = colorResource(R.color.glyph_white) + ) + ) + + } +} + +@DefaultPreviews +@Composable +private fun AutoCreateWidgetItemPreview() { + AutoCreateWidgetItem( + onCheckedStatusChanged = {}, + isChecked = true + ) +} + +@DefaultPreviews +@Composable +private fun AutoCreateWidgetItemUncheckedPreview() { + AutoCreateWidgetItem( + onCheckedStatusChanged = {}, + isChecked = false + ) } \ No newline at end of file diff --git a/feature-ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/space/new_settings/NewSettings.kt b/feature-ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/space/new_settings/NewSettings.kt index aab7fa649b..b0d101a1ba 100644 --- a/feature-ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/space/new_settings/NewSettings.kt +++ b/feature-ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/space/new_settings/NewSettings.kt @@ -336,7 +336,21 @@ fun NewSpaceSettingsScreen( ) } } - + is UiSpaceSettingsItem.AutoCreateWidgets -> { + item { + AutoCreateWidgetItem( + onCheckedStatusChanged = { isChecked -> + uiEvent( + UiEvent.OnAutoCreateWidgetSwitchChanged( + widget = item.widget, + isAutoCreateEnabled = isChecked + ) + ) + }, + isChecked = item.isAutoCreateEnabled + ) + } + } is UiSpaceSettingsItem.Spacer -> { item { Spacer(modifier = Modifier.height(item.height.dp)) diff --git a/localization/src/main/res/values/strings.xml b/localization/src/main/res/values/strings.xml index 9e9bb0ccdb..e44f65df2f 100644 --- a/localization/src/main/res/values/strings.xml +++ b/localization/src/main/res/values/strings.xml @@ -2020,5 +2020,6 @@ Please provide specific details of your needs here. Resolve layout conflict Suggested There is no widgets yet + Auto Create Type Widgets \ No newline at end of file diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/spaces/SpaceSettingsViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/spaces/SpaceSettingsViewModel.kt index 9cbd449206..ad5e5a86d6 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/spaces/SpaceSettingsViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/spaces/SpaceSettingsViewModel.kt @@ -20,7 +20,6 @@ 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 @@ -39,6 +38,8 @@ 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 +import com.anytypeio.anytype.domain.`object`.FetchObject +import com.anytypeio.anytype.domain.`object`.SetObjectDetails import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes import com.anytypeio.anytype.domain.payments.GetMembershipStatus import com.anytypeio.anytype.domain.search.ProfileSubscriptionManager @@ -79,7 +80,9 @@ class SpaceSettingsViewModel( private val observeWallpaper: ObserveWallpaper, private val storeOfObjectTypes: StoreOfObjectTypes, private val appActionManager: AppActionManager, - private val getSpaceInviteLink: GetSpaceInviteLink + private val getSpaceInviteLink: GetSpaceInviteLink, + private val fetchObject: FetchObject, + private val setObjectDetails: SetObjectDetails ): BaseViewModel() { val commands = MutableSharedFlow() @@ -124,6 +127,30 @@ class SpaceSettingsViewModel( viewModelScope.launch { + var widgetAutoCreationPreference: UiSpaceSettingsItem.AutoCreateWidgets? = null + + val config = spaceManager.getConfig(vmParams.space) + + if (config != null) { + val widget = fetchObject.async( + FetchObject.Params( + space = vmParams.space, + obj = config.widgets, + keys = listOf( + Relations.ID, + Relations.AUTO_WIDGET_DISABLED + ) + ) + ).getOrNull() + + if (widget != null) { + widgetAutoCreationPreference = UiSpaceSettingsItem.AutoCreateWidgets( + widget = widget.id, + isAutoCreateEnabled = widget.getValue(Relations.AUTO_WIDGET_DISABLED) != true + ) + } + } + val defaultObjectTypeResponse = getDefaultObjectType .async(params = vmParams.space) .getOrNull() @@ -229,6 +256,12 @@ class SpaceSettingsViewModel( add(defaultObjectTypeSettingItem) add(Spacer(height = 8)) add(UiSpaceSettingsItem.Wallpapers(current = wallpaper)) + if (widgetAutoCreationPreference != null) { + add(Spacer(height = 8)) + add( + widgetAutoCreationPreference + ) + } add(UiSpaceSettingsItem.Section.DataManagement) add(UiSpaceSettingsItem.RemoteStorage) @@ -355,6 +388,18 @@ class SpaceSettingsViewModel( ) } } + is UiEvent.OnAutoCreateWidgetSwitchChanged -> { + viewModelScope.launch { + setObjectDetails.async( + SetObjectDetails.Params( + ctx = uiEvent.widget, + details = mapOf( + Relations.AUTO_WIDGET_DISABLED to !uiEvent.isAutoCreateEnabled + ) + ) + ) + } + } } } @@ -701,7 +746,9 @@ class SpaceSettingsViewModel( private val observeWallpaper: ObserveWallpaper, private val appActionManager: AppActionManager, private val storeOfObjectTypes: StoreOfObjectTypes, - private val getSpaceInviteLink: GetSpaceInviteLink + private val getSpaceInviteLink: GetSpaceInviteLink, + private val fetchObject: FetchObject, + private val setObjectDetails: SetObjectDetails ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create( @@ -727,7 +774,9 @@ class SpaceSettingsViewModel( observeWallpaper = observeWallpaper, appActionManager = appActionManager, storeOfObjectTypes = storeOfObjectTypes, - getSpaceInviteLink = getSpaceInviteLink + getSpaceInviteLink = getSpaceInviteLink, + fetchObject = fetchObject, + setObjectDetails = setObjectDetails ) as T } diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/spaces/UiEvent.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/spaces/UiEvent.kt index c269315ae9..ae19431e57 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/spaces/UiEvent.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/spaces/UiEvent.kt @@ -21,6 +21,11 @@ sealed class UiEvent { data object OnInviteClicked : UiEvent() data object OnQrCodeClicked : UiEvent() + data class OnAutoCreateWidgetSwitchChanged( + val widget: Id, + val isAutoCreateEnabled: Boolean + ) : UiEvent() + sealed class IconMenu : UiEvent() { data object OnRemoveIconClicked : IconMenu() } diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/spaces/UiState.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/spaces/UiState.kt index 5da8f3de9f..c2cfc646b0 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/spaces/UiState.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/spaces/UiState.kt @@ -1,7 +1,6 @@ package com.anytypeio.anytype.presentation.spaces import com.anytypeio.anytype.core_models.Id -import com.anytypeio.anytype.core_models.ThemeColor import com.anytypeio.anytype.core_models.Wallpaper import com.anytypeio.anytype.core_models.ext.EMPTY_STRING_VALUE import com.anytypeio.anytype.core_models.primitives.SpaceId @@ -50,6 +49,10 @@ sealed class UiSpaceSettingsItem { data object Fields : UiSpaceSettingsItem() data class DefaultObjectType(val id: Id?, val name: String, val icon: ObjectIcon) : UiSpaceSettingsItem() data class Wallpapers(val current: Wallpaper?) : UiSpaceSettingsItem() + data class AutoCreateWidgets( + val widget: Id, + val isAutoCreateEnabled: Boolean + ) : UiSpaceSettingsItem() data object RemoteStorage : UiSpaceSettingsItem() data object Bin : UiSpaceSettingsItem() data object SpaceInfo : UiSpaceSettingsItem() diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/file_layout/FileLayoutTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/file_layout/FileLayoutTest.kt index b3c222a6e1..62ed28a4d8 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/file_layout/FileLayoutTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/file_layout/FileLayoutTest.kt @@ -125,7 +125,8 @@ class FileLayoutTest : EditorPresentationTestSetup() { mime = fileObject.fileMimeType, fileName = fileObject.name, extensions = fileExt - ) + ), + url = null ), BlockView.ButtonOpenFile.FileButton( id = fileBlock.id,