diff --git a/app/src/main/java/com/anytypeio/anytype/di/feature/PrimitivesObjectTypeDI.kt b/app/src/main/java/com/anytypeio/anytype/di/feature/PrimitivesObjectTypeDI.kt
index d7ae4c0c18..4c8718c204 100644
--- a/app/src/main/java/com/anytypeio/anytype/di/feature/PrimitivesObjectTypeDI.kt
+++ b/app/src/main/java/com/anytypeio/anytype/di/feature/PrimitivesObjectTypeDI.kt
@@ -222,6 +222,14 @@ interface SpaceTypesComponent {
@Module
object SpaceTypesModule {
+ @JvmStatic
+ @PerScreen
+ @Provides
+ fun getSetObjectListIsArchived(
+ repo: BlockRepository,
+ dispatchers: AppCoroutineDispatchers
+ ): SetObjectListIsArchived = SetObjectListIsArchived(repo, dispatchers)
+
@Module
interface Declarations {
@PerScreen
@@ -268,6 +276,14 @@ interface SpacePropertiesComponent {
@Module
object SpacePropertiesModule {
+ @JvmStatic
+ @PerScreen
+ @Provides
+ fun getSetObjectListIsArchived(
+ repo: BlockRepository,
+ dispatchers: AppCoroutineDispatchers
+ ): SetObjectListIsArchived = SetObjectListIsArchived(repo, dispatchers)
+
@JvmStatic
@Provides
@PerScreen
diff --git a/app/src/main/java/com/anytypeio/anytype/ui/primitives/SpacePropertiesFragment.kt b/app/src/main/java/com/anytypeio/anytype/ui/primitives/SpacePropertiesFragment.kt
index 92aa555537..86476270a0 100644
--- a/app/src/main/java/com/anytypeio/anytype/ui/primitives/SpacePropertiesFragment.kt
+++ b/app/src/main/java/com/anytypeio/anytype/ui/primitives/SpacePropertiesFragment.kt
@@ -49,7 +49,8 @@ class SpacePropertiesFragment : BaseComposeFragment() {
uiState = vm.uiItemsState.collectAsStateWithLifecycle().value,
onBackPressed = vm::onBackClicked,
onPropertyClicked = vm::onPropertyClicked,
- onAddIconClicked = vm::onCreateNewPropertyClicked
+ onAddIconClicked = vm::onCreateNewPropertyClicked,
+ onMoveToBin = vm::onMoveToBinProperty
)
SpacePropertyScreen(
uiState = vm.uiEditPropertyScreen.collectAsStateWithLifecycle().value
diff --git a/app/src/main/java/com/anytypeio/anytype/ui/primitives/SpaceTypesFragment.kt b/app/src/main/java/com/anytypeio/anytype/ui/primitives/SpaceTypesFragment.kt
index 062d9991f8..de7da0142f 100644
--- a/app/src/main/java/com/anytypeio/anytype/ui/primitives/SpaceTypesFragment.kt
+++ b/app/src/main/java/com/anytypeio/anytype/ui/primitives/SpaceTypesFragment.kt
@@ -46,6 +46,7 @@ class SpaceTypesFragment : BaseComposeFragment() {
onBackPressed = vm::onBackClicked,
onTypeClicked = vm::onTypeClicked,
onAddIconClicked = vm::onCreateNewTypeClicked,
+ onMoveToBin = vm::onMoveToBin
)
}
LaunchedEffect(Unit) {
diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/fields/FieldsListScreen.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/fields/FieldsListScreen.kt
index a82aa7d792..910543029a 100644
--- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/fields/FieldsListScreen.kt
+++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/fields/FieldsListScreen.kt
@@ -336,8 +336,8 @@ private fun SectionLocal(
) {
val text = stringResource(id = R.string.object_properties_section_local)
val iconRes = when (item) {
- is Model.Section.Local.Shown -> R.drawable.ic_arrow_up_18
- is Model.Section.Local.Unshown -> R.drawable.ic_list_arrow_18
+ is Model.Section.Local.Shown -> R.drawable.ic_list_arrow_18
+ is Model.Section.Local.Unshown -> R.drawable.ic_arrow_right_18
}
Box(
modifier = Modifier
@@ -409,8 +409,8 @@ private fun SectionHidden(
) {
val text = stringResource(id = R.string.object_properties_section_hidden)
val iconRes = when (item) {
- is Model.Section.Hidden.Shown -> R.drawable.ic_arrow_up_18
- is Model.Section.Hidden.Unshown -> R.drawable.ic_list_arrow_18
+ is Model.Section.Hidden.Shown -> R.drawable.ic_list_arrow_18
+ is Model.Section.Hidden.Unshown -> R.drawable.ic_arrow_right_18
}
Box(
modifier = Modifier
diff --git a/core-ui/src/main/res/drawable/ic_arrow_right_18.xml b/core-ui/src/main/res/drawable/ic_arrow_right_18.xml
new file mode 100644
index 0000000000..bf81934c60
--- /dev/null
+++ b/core-ui/src/main/res/drawable/ic_arrow_right_18.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/feature-object-type/src/main/java/com/anytypeio/anytype/feature_object_type/fields/ui/InfoScreen.kt b/feature-object-type/src/main/java/com/anytypeio/anytype/feature_object_type/fields/ui/InfoScreen.kt
index bc1602f8ef..1ee4c78d15 100644
--- a/feature-object-type/src/main/java/com/anytypeio/anytype/feature_object_type/fields/ui/InfoScreen.kt
+++ b/feature-object-type/src/main/java/com/anytypeio/anytype/feature_object_type/fields/ui/InfoScreen.kt
@@ -20,6 +20,7 @@ import androidx.compose.ui.unit.dp
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.common.DefaultPreviews
import com.anytypeio.anytype.core_ui.views.BodyCalloutRegular
+import com.anytypeio.anytype.core_ui.views.ButtonPrimary
import com.anytypeio.anytype.core_ui.views.ButtonSecondary
import com.anytypeio.anytype.core_ui.views.ButtonSize
import com.anytypeio.anytype.core_ui.views.HeadlineHeading
@@ -91,12 +92,12 @@ fun LocalInfoScreen(
text = stringResource(description)
)
Spacer(modifier = Modifier.height(30.dp))
- ButtonSecondary(
+ ButtonPrimary(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp),
text = stringResource(R.string.object_type_fields_local_info_button),
- size = ButtonSize.LargeSecondary,
+ size = ButtonSize.Large,
onClick = {
onDismiss()
}
diff --git a/feature-object-type/src/main/java/com/anytypeio/anytype/feature_object_type/ui/space/SpaceTypesListScreen.kt b/feature-object-type/src/main/java/com/anytypeio/anytype/feature_object_type/ui/space/SpaceTypesListScreen.kt
index 54dbf4dcbf..ce561f9295 100644
--- a/feature-object-type/src/main/java/com/anytypeio/anytype/feature_object_type/ui/space/SpaceTypesListScreen.kt
+++ b/feature-object-type/src/main/java/com/anytypeio/anytype/feature_object_type/ui/space/SpaceTypesListScreen.kt
@@ -1,9 +1,10 @@
package com.anytypeio.anytype.feature_object_type.ui.space
import android.os.Build
+import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
-import androidx.compose.foundation.clickable
+import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
@@ -21,10 +22,14 @@ import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.DropdownMenu
+import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateListOf
+import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.CenterVertically
@@ -34,14 +39,17 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.common.DefaultPreviews
import com.anytypeio.anytype.core_ui.extensions.swapList
import com.anytypeio.anytype.core_ui.foundation.Divider
import com.anytypeio.anytype.core_ui.foundation.noRippleThrottledClickable
+import com.anytypeio.anytype.core_ui.views.Caption1Medium
import com.anytypeio.anytype.core_ui.views.PreviewTitle1Regular
import com.anytypeio.anytype.core_ui.views.Title1
+import com.anytypeio.anytype.core_ui.views.UxSmallTextRegular
import com.anytypeio.anytype.core_ui.widgets.ListWidgetObjectIcon
import com.anytypeio.anytype.core_utils.insets.EDGE_TO_EDGE_MIN_SDK
import com.anytypeio.anytype.presentation.objects.ObjectIcon
@@ -52,9 +60,10 @@ import com.anytypeio.anytype.presentation.types.UiSpaceTypesScreenState
@Composable
fun SpaceTypesListScreen(
uiState: UiSpaceTypesScreenState,
- onTypeClicked: (UiSpaceTypeItem) -> Unit,
+ onTypeClicked: (UiSpaceTypeItem.Type) -> Unit,
onBackPressed: () -> Unit,
- onAddIconClicked: () -> Unit
+ onAddIconClicked: () -> Unit,
+ onMoveToBin: (UiSpaceTypeItem.Type) -> Unit
) {
Column(
modifier = Modifier
@@ -91,17 +100,24 @@ fun SpaceTypesListScreen(
key = { index -> items[index].id },
itemContent = {
val item = items[it]
- Type(
- modifier = Modifier
- .fillMaxWidth()
- .height(52.dp)
- .padding(start = 12.dp, end = 20.dp)
- .clickable {
- onTypeClicked(item)
- },
- item = item
- )
- Divider()
+ when (item) {
+ is UiSpaceTypeItem.Section -> {
+ Section(item)
+ }
+
+ is UiSpaceTypeItem.Type -> {
+ Type(
+ modifier = Modifier
+ .fillMaxWidth()
+ .height(52.dp)
+ .padding(start = 12.dp, end = 20.dp),
+ item = item,
+ onTypeClicked = onTypeClicked,
+ onMoveToBin = onMoveToBin
+ )
+ Divider()
+ }
+ }
}
)
item {
@@ -115,13 +131,48 @@ fun SpaceTypesListScreen(
}
}
+@Composable
+private fun Section(section: UiSpaceTypeItem.Section) {
+ val text = when (section) {
+ is UiSpaceTypeItem.Section.MyTypes ->
+ stringResource(R.string.space_types_screen_section_my_types)
+
+ is UiSpaceTypeItem.Section.System ->
+ stringResource(R.string.space_types_screen_section_system_types)
+ }
+ Column {
+ Box(
+ modifier = Modifier
+ .fillMaxWidth()
+ .height(52.dp)
+ ) {
+ Text(
+ modifier = Modifier
+ .padding(bottom = 8.dp, start = 20.dp)
+ .align(Alignment.BottomStart),
+ text = text,
+ style = Caption1Medium,
+ color = colorResource(R.color.text_secondary),
+ )
+ }
+ }
+}
+
+@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun Type(
modifier: Modifier,
- item: UiSpaceTypeItem
+ item: UiSpaceTypeItem.Type,
+ onTypeClicked: (UiSpaceTypeItem.Type) -> Unit,
+ onMoveToBin: (UiSpaceTypeItem.Type) -> Unit
) {
+ val isMenuExpanded = remember { mutableStateOf(false) }
Row(
- modifier = modifier.fillMaxWidth(),
+ modifier = modifier.fillMaxWidth()
+ .combinedClickable(
+ onClick = { onTypeClicked(item) },
+ onLongClick = { isMenuExpanded.value = true }
+ ),
verticalAlignment = CenterVertically
) {
ListWidgetObjectIcon(
@@ -141,6 +192,51 @@ private fun Type(
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
+
+ if (item.isPossibleMoveToBin) {
+ ItemDropDownMenu(
+ item = item,
+ showMenu = isMenuExpanded.value,
+ onDismissRequest = { isMenuExpanded.value = false },
+ onMoveToBin = {
+ isMenuExpanded.value = false
+ onMoveToBin(it)
+ }
+ )
+ }
+ }
+}
+
+@Composable
+fun ItemDropDownMenu(
+ item: UiSpaceTypeItem.Type,
+ showMenu: Boolean,
+ onDismissRequest: () -> Unit,
+ onMoveToBin: (UiSpaceTypeItem.Type) -> Unit
+) {
+ DropdownMenu(
+ modifier = Modifier
+ .width(244.dp),
+ expanded = showMenu,
+ offset = DpOffset(x = 0.dp, y = 0.dp),
+ onDismissRequest = {
+ onDismissRequest()
+ },
+ shape = RoundedCornerShape(10.dp),
+ containerColor = colorResource(id = R.color.background_secondary),
+ ) {
+ DropdownMenuItem(
+ text = {
+ Text(
+ text = stringResource(R.string.space_properties_screen_menu_move_to_bin),
+ style = UxSmallTextRegular,
+ color = colorResource(id = R.color.text_primary)
+ )
+ },
+ onClick = {
+ onMoveToBin(item)
+ },
+ )
}
}
@@ -208,7 +304,8 @@ fun SpaceTypesListScreenPreview() {
SpaceTypesListScreen(
uiState = UiSpaceTypesScreenState(
items = listOf(
- UiSpaceTypeItem(
+ UiSpaceTypeItem.Section.MyTypes(),
+ UiSpaceTypeItem.Type(
id = "1",
name = "Type 1",
icon = ObjectIcon.TypeIcon.Default(
@@ -216,7 +313,8 @@ fun SpaceTypesListScreenPreview() {
color = CustomIconColor.Teal
)
),
- UiSpaceTypeItem(
+ UiSpaceTypeItem.Section.System(),
+ UiSpaceTypeItem.Type(
id = "2",
name = "Type 2",
icon = ObjectIcon.TypeIcon.Default(
@@ -228,6 +326,7 @@ fun SpaceTypesListScreenPreview() {
),
onBackPressed = {},
onTypeClicked = {},
- onAddIconClicked = {}
+ onAddIconClicked = {},
+ onMoveToBin = {}
)
}
\ No newline at end of file
diff --git a/feature-object-type/src/main/java/com/anytypeio/anytype/feature_object_type/viewmodel/ObjectTypeViewModel.kt b/feature-object-type/src/main/java/com/anytypeio/anytype/feature_object_type/viewmodel/ObjectTypeViewModel.kt
index 876022a414..b37926b51f 100644
--- a/feature-object-type/src/main/java/com/anytypeio/anytype/feature_object_type/viewmodel/ObjectTypeViewModel.kt
+++ b/feature-object-type/src/main/java/com/anytypeio/anytype/feature_object_type/viewmodel/ObjectTypeViewModel.kt
@@ -351,9 +351,10 @@ class ObjectTypeViewModel(
(uiTitleAndIconUpdateState.value as? UiTypeSetupTitleAndIconState.Visible.EditType)?.let {
uiTitleAndIconUpdateState.value = it.copy(icon = newIcon)
}
- if (objectPermissions.canDelete) {
- uiEditButtonState.value = UiEditButton.Visible
- }
+ //turn off button, we give Move to Bin logic in Library now
+// if (objectPermissions.canDelete) {
+// uiEditButtonState.value = UiEditButton.Visible
+// }
objType.recommendedLayout?.let { layout ->
if (_objectTypePermissionsState.value?.canChangeRecommendedLayoutForThisType == true) {
uiHorizontalButtonsState.value =
diff --git a/feature-properties/src/main/java/com/anytypeio/anytype/feature_properties/space/SpacePropertiesViewModel.kt b/feature-properties/src/main/java/com/anytypeio/anytype/feature_properties/space/SpacePropertiesViewModel.kt
index b549c2a5d6..d696e5adb8 100644
--- a/feature-properties/src/main/java/com/anytypeio/anytype/feature_properties/space/SpacePropertiesViewModel.kt
+++ b/feature-properties/src/main/java/com/anytypeio/anytype/feature_properties/space/SpacePropertiesViewModel.kt
@@ -9,10 +9,12 @@ import com.anytypeio.anytype.core_models.RelationFormat
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_models.primitives.RelationKey
import com.anytypeio.anytype.core_models.primitives.SpaceId
+import com.anytypeio.anytype.core_models.restrictions.ObjectRestriction
import com.anytypeio.anytype.core_ui.extensions.simpleIcon
import com.anytypeio.anytype.domain.base.fold
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
import com.anytypeio.anytype.domain.`object`.SetObjectDetails
+import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.objects.mapLimitObjectTypes
@@ -53,7 +55,8 @@ class SpacePropertiesViewModel(
private val storeOfRelations: StoreOfRelations,
private val stringResourceProvider: StringResourceProvider,
private val setObjectDetails: SetObjectDetails,
- private val createRelation: CreateRelation
+ private val createRelation: CreateRelation,
+ private val setObjectListIsArchived: SetObjectListIsArchived
) : ViewModel(), AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
// Main UI states
@@ -76,24 +79,64 @@ class SpacePropertiesViewModel(
storeOfRelations.trackChanges()
.collectLatest { event ->
val allProperties = storeOfRelations.getAll().mapNotNull { property ->
- if (property.isHidden == true) {
+ if (property.isHidden == true || property.isDeleted == true || property.isArchived == true) {
null
} else {
- UiSpacePropertyItem(
+ property
+ }
+ }
+ val (myProperties, systemProperties) =
+ allProperties.partition { !it.restrictions.contains(ObjectRestriction.DELETE) }
+ val list = buildList {
+ add(UiSpacePropertyItem.Section.MyProperties())
+ addAll(myProperties.map { property ->
+ UiSpacePropertyItem.Item(
id = property.id,
key = RelationKey(property.key),
name = property.name.orEmpty(),
format = property.format,
isEditableField = fieldParser.isPropertyEditable(property),
- limitObjectTypes = storeOfObjectTypes.mapLimitObjectTypes(property = property)
+ limitObjectTypes = storeOfObjectTypes.mapLimitObjectTypes(property = property),
+ isPossibleMoveToBin = true
)
- }
- }.sortedBy { it.name }
- uiItemsState.value = UiSpacePropertiesScreenState(allProperties)
+ }.sortedBy { it.name })
+ add(UiSpacePropertyItem.Section.SystemProperties())
+ addAll(systemProperties.map { property ->
+ UiSpacePropertyItem.Item(
+ id = property.id,
+ key = RelationKey(property.key),
+ name = property.name.orEmpty(),
+ format = property.format,
+ isEditableField = fieldParser.isPropertyEditable(property),
+ limitObjectTypes = storeOfObjectTypes.mapLimitObjectTypes(property = property),
+ isPossibleMoveToBin = false
+ )
+ }.sortedBy { it.name })
+ }
+
+ uiItemsState.value = UiSpacePropertiesScreenState(list)
}
}
}
+ fun onMoveToBinProperty(item: UiSpacePropertyItem.Item) {
+ val propertyId = item.id
+ viewModelScope.launch {
+ val params = SetObjectListIsArchived.Params(
+ targets = listOf(propertyId),
+ isArchived = true
+ )
+ setObjectListIsArchived.async(params).fold(
+ onSuccess = {
+ Timber.d("Property $propertyId moved to bin")
+ },
+ onFailure = {
+ Timber.e(it, "Error while moving property $propertyId to bin")
+ }
+ )
+ }
+ }
+
fun onBackClicked() {
viewModelScope.launch {
commands.emit(Command.Back)
@@ -124,7 +167,7 @@ class SpacePropertiesViewModel(
}
}
- fun onPropertyClicked(item: UiSpacePropertyItem) {
+ fun onPropertyClicked(item: UiSpacePropertyItem.Item) {
viewModelScope.launch {
val computedLimitTypes = computeLimitTypes(item = item)
val formatName = stringResourceProvider.getPropertiesFormatPrettyString(item.format)
@@ -158,7 +201,7 @@ class SpacePropertiesViewModel(
}
}
- private suspend fun computeLimitTypes(item: UiSpacePropertyItem): List {
+ private suspend fun computeLimitTypes(item: UiSpacePropertyItem.Item): List {
return item.limitObjectTypes.mapNotNull { id ->
storeOfObjectTypes.get(id = id)?.let { objType ->
UiPropertyLimitTypeItem(
@@ -329,7 +372,8 @@ class SpacePropertiesVmFactory @Inject constructor(
private val storeOfRelations: StoreOfRelations,
private val stringResourceProvider: StringResourceProvider,
private val setObjectDetails: SetObjectDetails,
- private val createRelation: CreateRelation
+ private val createRelation: CreateRelation,
+ private val setObjectListIsArchived: SetObjectListIsArchived
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun create(modelClass: Class): T =
@@ -343,7 +387,8 @@ class SpacePropertiesVmFactory @Inject constructor(
storeOfRelations = storeOfRelations,
stringResourceProvider = stringResourceProvider,
setObjectDetails = setObjectDetails,
- createRelation = createRelation
+ createRelation = createRelation,
+ setObjectListIsArchived = setObjectListIsArchived
) as T
}
@@ -355,11 +400,22 @@ data class UiSpacePropertiesScreenState(
}
}
-data class UiSpacePropertyItem(
- val id: Id,
- val key: RelationKey,
- val name: String,
- val format: RelationFormat,
- val isEditableField: Boolean,
- val limitObjectTypes: List
-)
\ No newline at end of file
+sealed class UiSpacePropertyItem{
+
+ abstract val id: Id
+
+ sealed class Section : UiSpacePropertyItem() {
+ data class MyProperties(override val id: Id = "section_my_properties") : Section()
+ data class SystemProperties(override val id: Id = "section_system_properties") : Section()
+ }
+
+ data class Item(
+ override val id: Id,
+ val key: RelationKey,
+ val name: String,
+ val format: RelationFormat,
+ val isEditableField: Boolean,
+ val limitObjectTypes: List,
+ val isPossibleMoveToBin: Boolean = false
+ ) : UiSpacePropertyItem()
+}
\ No newline at end of file
diff --git a/feature-properties/src/main/java/com/anytypeio/anytype/feature_properties/space/ui/SpacePropertiesListScreen.kt b/feature-properties/src/main/java/com/anytypeio/anytype/feature_properties/space/ui/SpacePropertiesListScreen.kt
index 94768d8300..142863fca8 100644
--- a/feature-properties/src/main/java/com/anytypeio/anytype/feature_properties/space/ui/SpacePropertiesListScreen.kt
+++ b/feature-properties/src/main/java/com/anytypeio/anytype/feature_properties/space/ui/SpacePropertiesListScreen.kt
@@ -1,9 +1,10 @@
package com.anytypeio.anytype.feature_properties.space.ui
import android.os.Build
+import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
-import androidx.compose.foundation.clickable
+import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
@@ -24,10 +25,14 @@ import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.DropdownMenu
+import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateListOf
+import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.CenterVertically
@@ -38,14 +43,17 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.extensions.simpleIcon
import com.anytypeio.anytype.core_ui.extensions.swapList
import com.anytypeio.anytype.core_ui.foundation.Divider
import com.anytypeio.anytype.core_ui.foundation.noRippleThrottledClickable
+import com.anytypeio.anytype.core_ui.views.Caption1Medium
import com.anytypeio.anytype.core_ui.views.PreviewTitle1Regular
import com.anytypeio.anytype.core_ui.views.Title1
+import com.anytypeio.anytype.core_ui.views.UxSmallTextRegular
import com.anytypeio.anytype.core_utils.insets.EDGE_TO_EDGE_MIN_SDK
import com.anytypeio.anytype.feature_properties.space.UiSpacePropertiesScreenState
import com.anytypeio.anytype.feature_properties.space.UiSpacePropertyItem
@@ -53,9 +61,10 @@ import com.anytypeio.anytype.feature_properties.space.UiSpacePropertyItem
@Composable
fun SpacePropertiesListScreen(
uiState: UiSpacePropertiesScreenState,
- onPropertyClicked: (UiSpacePropertyItem) -> Unit,
+ onPropertyClicked: (UiSpacePropertyItem.Item) -> Unit,
onBackPressed: () -> Unit,
- onAddIconClicked: () -> Unit
+ onAddIconClicked: () -> Unit,
+ onMoveToBin: (UiSpacePropertyItem.Item) -> Unit
) {
Column(
modifier = Modifier
@@ -93,17 +102,23 @@ fun SpacePropertiesListScreen(
key = { index -> items[index].id },
itemContent = {
val item = items[it]
- Relation(
- modifier = Modifier
- .fillMaxWidth()
- .height(52.dp)
- .padding(start = 20.dp, end = 20.dp)
- .clickable {
- onPropertyClicked(item)
- },
- item = item
- )
- Divider()
+ when (item ) {
+ is UiSpacePropertyItem.Item -> {
+ Property(
+ modifier = Modifier
+ .fillMaxWidth()
+ .height(52.dp)
+ .padding(start = 20.dp, end = 20.dp),
+ item = item,
+ onPropertyClicked = onPropertyClicked,
+ onMoveToBin = onMoveToBin
+ )
+ Divider()
+ }
+ is UiSpacePropertyItem.Section -> {
+ Section(item)
+ }
+ }
}
)
item {
@@ -118,12 +133,47 @@ fun SpacePropertiesListScreen(
}
@Composable
-private fun Relation(
+private fun Section(section: UiSpacePropertyItem.Section) {
+ val text = when (section) {
+ is UiSpacePropertyItem.Section.MyProperties ->
+ stringResource(R.string.space_properties_screen_section_my_types)
+ is UiSpacePropertyItem.Section.SystemProperties ->
+ stringResource(R.string.space_properties_screen_section_system_types)
+ }
+ Column {
+ Box(
+ modifier = Modifier
+ .fillMaxWidth()
+ .height(52.dp)
+ ) {
+ Text(
+ modifier = Modifier
+ .padding(bottom = 8.dp, start = 20.dp)
+ .align(Alignment.BottomStart),
+ text = text,
+ style = Caption1Medium,
+ color = colorResource(R.color.text_secondary),
+ )
+ }
+ }
+}
+
+@OptIn(ExperimentalFoundationApi::class)
+@Composable
+private fun Property(
modifier: Modifier,
- item: UiSpacePropertyItem
+ item: UiSpacePropertyItem.Item,
+ onPropertyClicked: (UiSpacePropertyItem.Item) -> Unit,
+ onMoveToBin: (UiSpacePropertyItem.Item) -> Unit
) {
+ val isMenuExpanded = remember { mutableStateOf(false) }
Row(
- modifier = modifier.fillMaxWidth(),
+ modifier = modifier
+ .fillMaxWidth()
+ .combinedClickable(
+ onClick = { onPropertyClicked(item) },
+ onLongClick = { isMenuExpanded.value = true }
+ ),
verticalAlignment = CenterVertically
) {
val icon = item.format.simpleIcon()
@@ -143,6 +193,50 @@ private fun Relation(
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
+ if (item.isPossibleMoveToBin) {
+ ItemDropDownMenu(
+ item = item,
+ showMenu = isMenuExpanded.value,
+ onDismissRequest = { isMenuExpanded.value = false },
+ onMoveToBin = {
+ isMenuExpanded.value = false
+ onMoveToBin(it)
+ }
+ )
+ }
+ }
+}
+
+@Composable
+fun ItemDropDownMenu(
+ item: UiSpacePropertyItem.Item,
+ showMenu: Boolean,
+ onDismissRequest: () -> Unit,
+ onMoveToBin: (UiSpacePropertyItem.Item) -> Unit
+) {
+ DropdownMenu(
+ modifier = Modifier
+ .width(244.dp),
+ expanded = showMenu,
+ offset = DpOffset(x = 0.dp, y = 0.dp),
+ onDismissRequest = {
+ onDismissRequest()
+ },
+ shape = RoundedCornerShape(10.dp),
+ containerColor = colorResource(id = R.color.background_secondary),
+ ) {
+ DropdownMenuItem(
+ text = {
+ Text(
+ text = stringResource(R.string.space_properties_screen_menu_move_to_bin),
+ style = UxSmallTextRegular,
+ color = colorResource(id = R.color.text_primary)
+ )
+ },
+ onClick = {
+ onMoveToBin(item)
+ },
+ )
}
}
diff --git a/localization/src/main/res/values/strings.xml b/localization/src/main/res/values/strings.xml
index 3b5f343ac4..e4ad6e14bd 100644
--- a/localization/src/main/res/values/strings.xml
+++ b/localization/src/main/res/values/strings.xml
@@ -2034,6 +2034,12 @@ Please provide specific details of your needs here.
Auto Create Type Widgets
Object types
+ My Types
+ System Types
+
Properties
+ My Properties
+ System Properties
+ Move to bin
\ No newline at end of file
diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/types/SpaceTypesViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/types/SpaceTypesViewModel.kt
index 5b840bc9d0..3e75bc4efc 100644
--- a/presentation/src/main/java/com/anytypeio/anytype/presentation/types/SpaceTypesViewModel.kt
+++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/types/SpaceTypesViewModel.kt
@@ -6,9 +6,11 @@ import androidx.lifecycle.viewModelScope
import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectType
-import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.primitives.SpaceId
+import com.anytypeio.anytype.core_models.restrictions.ObjectRestriction
+import com.anytypeio.anytype.domain.base.fold
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
+import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
@@ -29,6 +31,7 @@ class SpaceTypesViewModel(
private val fieldParser: FieldParser,
private val storeOfObjectTypes: StoreOfObjectTypes,
private val userPermissionProvider: UserPermissionProvider,
+ private val setObjectListIsArchived: SetObjectListIsArchived
) : ViewModel(), AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
val uiItemsState =
@@ -60,19 +63,64 @@ class SpaceTypesViewModel(
.collectLatest { event ->
val allTypes =
storeOfObjectTypes.getAll().mapNotNull { objectType ->
- val resolvedLayout = objectType.recommendedLayout ?: return@mapNotNull null
+ val resolvedLayout =
+ objectType.recommendedLayout ?: return@mapNotNull null
if (notAllowedTypesLayouts.contains(resolvedLayout)) {
return@mapNotNull null
} else {
- objectType.toUiItem()
+ objectType
}
}
- .sortedBy { it.name }
- uiItemsState.value = UiSpaceTypesScreenState(allTypes)
+ val (myTypes, systemTypes) = allTypes.partition {
+ !it.restrictions.contains(
+ ObjectRestriction.DELETE
+ )
+ }
+
+ val list = buildList {
+ add(UiSpaceTypeItem.Section.MyTypes())
+ addAll(myTypes.map { type ->
+ UiSpaceTypeItem.Type(
+ id = type.id,
+ name = fieldParser.getObjectName(type),
+ icon = type.objectIcon(),
+ isPossibleMoveToBin = true
+ )
+ }.sortedBy { it.name })
+ add(UiSpaceTypeItem.Section.System())
+ addAll(systemTypes.map { type ->
+ UiSpaceTypeItem.Type(
+ id = type.id,
+ name = fieldParser.getObjectName(type),
+ icon = type.objectIcon(),
+ isPossibleMoveToBin = false
+ )
+ }.sortedBy { it.name })
+ }
+
+ uiItemsState.value = UiSpaceTypesScreenState(list)
}
}
}
+ fun onMoveToBin(item: UiSpaceTypeItem.Type) {
+ val typeId = item.id
+ viewModelScope.launch {
+ val params = SetObjectListIsArchived.Params(
+ targets = listOf(typeId),
+ isArchived = true
+ )
+ setObjectListIsArchived.async(params).fold(
+ onSuccess = {
+ Timber.d("Object Type $typeId moved to bin")
+ },
+ onFailure = {
+ Timber.e(it, "Error while moving pbject type $typeId to bin")
+ }
+ )
+ }
+ }
+
fun onBackClicked() {
viewModelScope.launch {
commands.emit(Command.Back)
@@ -80,7 +128,7 @@ class SpaceTypesViewModel(
}
fun onCreateNewTypeClicked() {
- if (permission.value?.isOwnerOrEditor() == true) {
+ if (permission.value?.isOwnerOrEditor() == true) {
viewModelScope.launch {
commands.emit(Command.CreateNewType(vmParams.spaceId.id))
}
@@ -91,7 +139,7 @@ class SpaceTypesViewModel(
}
}
- fun onTypeClicked(type: UiSpaceTypeItem) {
+ fun onTypeClicked(type: UiSpaceTypeItem.Type) {
viewModelScope.launch {
commands.emit(
Command.OpenType(
@@ -109,13 +157,6 @@ class SpaceTypesViewModel(
data class ShowToast(val message: String) : Command()
}
- private fun ObjectWrapper.Type.toUiItem() = UiSpaceTypeItem(
- id = id,
- name = fieldParser.getObjectName(this),
- icon = this.objectIcon()
-
- )
-
data class VmParams(
val spaceId: SpaceId
)
@@ -127,7 +168,8 @@ class SpaceTypesVmFactory @Inject constructor(
private val analytics: Analytics,
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
private val userPermissionProvider: UserPermissionProvider,
- private val fieldParser: FieldParser
+ private val fieldParser: FieldParser,
+ private val setObjectListIsArchived: SetObjectListIsArchived
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun create(modelClass: Class): T =
@@ -137,14 +179,26 @@ class SpaceTypesVmFactory @Inject constructor(
analytics = analytics,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
userPermissionProvider = userPermissionProvider,
- fieldParser = fieldParser
+ fieldParser = fieldParser,
+ setObjectListIsArchived = setObjectListIsArchived
) as T
}
data class UiSpaceTypesScreenState(val items: List)
-data class UiSpaceTypeItem(
- val id: Id,
- val name: String,
- val icon: ObjectIcon.TypeIcon
-)
\ No newline at end of file
+
+sealed class UiSpaceTypeItem {
+ abstract val id: Id
+
+ data class Type(
+ override val id: Id,
+ val name: String,
+ val icon: ObjectIcon.TypeIcon,
+ val isPossibleMoveToBin: Boolean = false
+ ) : UiSpaceTypeItem()
+
+ sealed class Section : UiSpaceTypeItem() {
+ data class MyTypes(override val id: Id = "section_my_types") : Section()
+ data class System(override val id: Id = "section_system") : Section()
+ }
+}
\ No newline at end of file