diff --git a/app/src/main/java/com/anytypeio/anytype/di/feature/spaces/SpaceSettingsDI.kt b/app/src/main/java/com/anytypeio/anytype/di/feature/spaces/SpaceSettingsDI.kt index 4819c97b82..c2e7d2effb 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/feature/spaces/SpaceSettingsDI.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/feature/spaces/SpaceSettingsDI.kt @@ -15,10 +15,12 @@ import com.anytypeio.anytype.domain.debugging.DebugSpace import com.anytypeio.anytype.domain.debugging.DebugSpaceContentSaver import com.anytypeio.anytype.domain.debugging.DebugSpaceShareDownloader import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer +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.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider +import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes import com.anytypeio.anytype.domain.payments.GetMembershipStatus import com.anytypeio.anytype.domain.search.ProfileSubscriptionManager import com.anytypeio.anytype.domain.workspace.SpaceManager @@ -104,13 +106,14 @@ object SpaceSettingsModule { interface SpaceSettingsDependencies : ComponentDependencies { fun blockRepo(): BlockRepository fun auth(): AuthRepository + fun appActions(): AppActionManager + fun storeOfObjectTypes(): StoreOfObjectTypes fun settings(): UserSettingsRepository fun urlBuilder(): UrlBuilder fun analytics(): Analytics fun dispatchers(): AppCoroutineDispatchers fun spaceManager(): SpaceManager fun container(): StorelessSubscriptionContainer - fun config(): ConfigStorage fun context(): Context fun userPermission(): UserPermissionProvider fun spaceViewSubscriptionContainer(): SpaceViewSubscriptionContainer diff --git a/app/src/main/java/com/anytypeio/anytype/ui/objects/types/pickers/AppDefaultObjectTypeFragment.kt b/app/src/main/java/com/anytypeio/anytype/ui/objects/types/pickers/AppDefaultObjectTypeFragment.kt index 8af143d27e..1be73e38c2 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/objects/types/pickers/AppDefaultObjectTypeFragment.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/objects/types/pickers/AppDefaultObjectTypeFragment.kt @@ -1,5 +1,6 @@ package com.anytypeio.anytype.ui.objects.types.pickers +import android.os.Bundle import androidx.core.os.bundleOf import com.anytypeio.anytype.R import com.anytypeio.anytype.core_models.Id @@ -47,5 +48,6 @@ class AppDefaultObjectTypeFragment : BaseObjectTypeChangeFragment() { fun newInstance(excludeTypes: List) = AppDefaultObjectTypeFragment().apply { arguments = bundleOf(ARG_EXCLUDE_TYPES to excludeTypes) } + fun args(excludeTypes: List) : Bundle = bundleOf(ARG_EXCLUDE_TYPES to excludeTypes) } } \ No newline at end of file diff --git a/app/src/main/java/com/anytypeio/anytype/ui/settings/PersonalizationSettingsFragment.kt b/app/src/main/java/com/anytypeio/anytype/ui/settings/PersonalizationSettingsFragment.kt index 374ba53358..34dbe4da27 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/settings/PersonalizationSettingsFragment.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/settings/PersonalizationSettingsFragment.kt @@ -19,6 +19,7 @@ import com.anytypeio.anytype.ui.objects.types.pickers.AppDefaultObjectTypeFragme import com.anytypeio.anytype.ui.objects.types.pickers.ObjectTypeSelectionListener import javax.inject.Inject +@Deprecated("To be deleted") class PersonalizationSettingsFragment : BaseBottomSheetFragment(), ObjectTypeSelectionListener { diff --git a/app/src/main/java/com/anytypeio/anytype/ui/settings/space/SpaceSettingsFragment.kt b/app/src/main/java/com/anytypeio/anytype/ui/settings/space/SpaceSettingsFragment.kt index e7b3acb50f..90dc7eb71b 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/settings/space/SpaceSettingsFragment.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/settings/space/SpaceSettingsFragment.kt @@ -14,6 +14,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.fragment.findNavController import com.anytypeio.anytype.R import com.anytypeio.anytype.core_models.Id +import com.anytypeio.anytype.core_models.ObjectWrapper import com.anytypeio.anytype.core_models.primitives.SpaceId import com.anytypeio.anytype.core_ui.common.ComposeDialogView import com.anytypeio.anytype.core_utils.ext.arg @@ -26,6 +27,8 @@ 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.ShareSpaceFragment +import com.anytypeio.anytype.ui.objects.types.pickers.AppDefaultObjectTypeFragment +import com.anytypeio.anytype.ui.objects.types.pickers.ObjectTypeSelectionListener import com.anytypeio.anytype.ui.settings.typography import com.anytypeio.anytype.ui.spaces.DeleteSpaceWarning import com.anytypeio.anytype.ui_settings.space.new_settings.SpaceSettingsContainer @@ -34,7 +37,7 @@ import javax.inject.Inject import timber.log.Timber // TODO convert to Fragment. -class SpaceSettingsFragment : BaseBottomSheetComposeFragment() { +class SpaceSettingsFragment : BaseBottomSheetComposeFragment(), ObjectTypeSelectionListener { private val space get() = arg(ARG_SPACE_ID_KEY) @@ -158,10 +161,23 @@ class SpaceSettingsFragment : BaseBottomSheetComposeFragment() { Timber.e(it, "Error while opening space wallpaper picker") } } + is Command.SelectDefaultObjectType -> { + runCatching { + AppDefaultObjectTypeFragment.newInstance( + excludeTypes = command.excludedTypeIds + ).showChildFragment() + }.onFailure { + Timber.e(it, "Error while opening set-default-object-type screen") + } + } } } } + override fun onSelectObjectType(objType: ObjectWrapper.Type) { + vm.onSelectObjectType(objType) + } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) expand() diff --git a/core-ui/src/main/res/drawable/ic_fields_24.xml b/core-ui/src/main/res/drawable/ic_fields_24.xml new file mode 100644 index 0000000000..44cfe631db --- /dev/null +++ b/core-ui/src/main/res/drawable/ic_fields_24.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/core-utils/src/main/java/com/anytypeio/anytype/core_utils/ext/Extensions.kt b/core-utils/src/main/java/com/anytypeio/anytype/core_utils/ext/Extensions.kt index d0a0f14288..62fa3ce1f8 100644 --- a/core-utils/src/main/java/com/anytypeio/anytype/core_utils/ext/Extensions.kt +++ b/core-utils/src/main/java/com/anytypeio/anytype/core_utils/ext/Extensions.kt @@ -8,6 +8,7 @@ import androidx.fragment.app.Fragment import java.text.DecimalFormat import kotlin.math.log10 import kotlin.math.pow +import timber.log.Timber fun MutableList.swap(index1: Int, index2: Int) { val tmp = this[index1] @@ -93,8 +94,12 @@ fun Fragment.dismissInnerDialog(tag: String) { fun String.isEndLineClick(range: IntRange): Boolean = range.first == length && range.last == length inline fun Fragment.withParent(action: T.() -> Unit) { - check(parentFragment is T) { "Parent is not ${T::class.java}. Please specify correct type" } - (parentFragment as T).action() + try { + check(parentFragment is T) { "Parent is not ${T::class.java}. Please specify correct type" } + (parentFragment as T).action() + } catch (e: Exception) { + Timber.e(e, "Error while executing an action with parent fragment") + } } fun MatchResult?.parseMatchedInt(index: Int): Int? = this?.groups?.get(index)?.value?.toIntOrNull() 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 b8cfcaf5b9..98888d82e8 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 @@ -90,6 +90,17 @@ fun ObjectTypesItem( ) } +@Composable +fun FieldsItem( + modifier: Modifier = Modifier +) { + BaseButton( + modifier = modifier, + title = stringResource(id = R.string.fields), + icon = R.drawable.ic_fields_24, + ) +} + @Composable fun DefaultTypeItem( modifier: Modifier = Modifier, 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 7a81295f75..22e5965784 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 @@ -32,12 +32,14 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip 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.unit.dp import com.anytypeio.anytype.core_ui.foundation.Dragger import com.anytypeio.anytype.core_ui.foundation.noRippleClickable import com.anytypeio.anytype.core_ui.views.PreviewTitle1Medium +import com.anytypeio.anytype.core_utils.ext.toast import com.anytypeio.anytype.core_utils.insets.EDGE_TO_EDGE_MIN_SDK import com.anytypeio.anytype.presentation.spaces.UiEvent import com.anytypeio.anytype.presentation.spaces.UiSpaceSettingsItem @@ -63,6 +65,7 @@ fun NewSpaceSettingsScreen( uiState: UiSpaceSettingsState.SpaceSettings, uiEvent: (UiEvent) -> Unit ) { + val localContext = LocalContext.current val initialName = uiState.name val initialDescription = uiState.description @@ -194,7 +197,10 @@ fun NewSpaceSettingsScreen( DefaultTypeItem( modifier = Modifier .fillMaxWidth() - .animateItem(), + .animateItem() + .clip(RoundedCornerShape(16.dp)) + .clickable { uiEvent(UiEvent.OnDefaultObjectTypeClicked(item.id)) } + , name = item.name, icon = item.icon ) @@ -216,7 +222,10 @@ fun NewSpaceSettingsScreen( MembersItem( modifier = Modifier .fillMaxWidth() - .animateItem(), + .animateItem() + .clip(RoundedCornerShape(16.dp)) + .clickable { uiEvent(UiEvent.OnSpaceMembersClicked) } + , item = item ) } @@ -228,10 +237,26 @@ fun NewSpaceSettingsScreen( modifier = Modifier .fillMaxWidth() .animateItem() + .clip(RoundedCornerShape(16.dp)) + .clickable { + localContext.toast("TODO") + } + ) + } + } + UiSpaceSettingsItem.Fields -> { + item { + FieldsItem( + modifier = Modifier + .fillMaxWidth() + .animateItem() + .clip(RoundedCornerShape(16.dp)) + .clickable { + localContext.toast("TODO") + } ) } } - is UiSpaceSettingsItem.RemoteStorage -> { // TODO } diff --git a/feature-ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/space/new_settings/Previews.kt b/feature-ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/space/new_settings/Previews.kt index 94d9e754fe..af6d741cb3 100644 --- a/feature-ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/space/new_settings/Previews.kt +++ b/feature-ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/space/new_settings/Previews.kt @@ -31,6 +31,7 @@ fun NewSpaceSettingsScreenPreview() { UiSpaceSettingsItem.ObjectTypes, UiSpaceSettingsItem.Section.Preferences, UiSpaceSettingsItem.DefaultObjectType( + id = "some id", name = "Taskwithveryverlylongname", icon = ObjectIcon.Empty.ObjectType ), diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/settings/PersonalizationSettingsViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/settings/PersonalizationSettingsViewModel.kt index 3d95747f9b..68a594bbbb 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/settings/PersonalizationSettingsViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/settings/PersonalizationSettingsViewModel.kt @@ -34,6 +34,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.launch import timber.log.Timber +@Deprecated("To be deleted") class PersonalizationSettingsViewModel( private val getDefaultObjectType: GetDefaultObjectType, private val setDefaultObjectType: SetDefaultObjectType, 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 ea091e3f4d..7a2657a79e 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 @@ -1,62 +1,74 @@ package com.anytypeio.anytype.presentation.spaces -import android.R import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope import com.anytypeio.anytype.analytics.base.Analytics import com.anytypeio.anytype.analytics.base.EventsDictionary +import com.anytypeio.anytype.analytics.base.EventsDictionary.defaultTypeChanged import com.anytypeio.anytype.analytics.base.EventsPropertiesKey import com.anytypeio.anytype.analytics.base.sendEvent +import com.anytypeio.anytype.analytics.event.EventAnalytics import com.anytypeio.anytype.analytics.props.Props import com.anytypeio.anytype.core_models.Block +import com.anytypeio.anytype.core_models.Block.Content.DataView.Filter +import com.anytypeio.anytype.core_models.DVFilterCondition import com.anytypeio.anytype.core_models.Filepath import com.anytypeio.anytype.core_models.Id +import com.anytypeio.anytype.core_models.Key +import com.anytypeio.anytype.core_models.ObjectType +import com.anytypeio.anytype.core_models.ObjectTypeUniqueKeys import com.anytypeio.anytype.core_models.ObjectWrapper import com.anytypeio.anytype.core_models.Relations import com.anytypeio.anytype.core_models.SpaceType -import com.anytypeio.anytype.core_models.ThemeColor +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.SpaceMemberPermissions import com.anytypeio.anytype.core_models.primitives.SpaceId -import com.anytypeio.anytype.domain.base.BaseUseCase +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.config.ConfigStorage import com.anytypeio.anytype.domain.debugging.DebugSpaceShareDownloader import com.anytypeio.anytype.domain.launch.GetDefaultObjectType +import com.anytypeio.anytype.domain.launch.SetDefaultObjectType 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.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider import com.anytypeio.anytype.domain.multiplayer.sharedSpaceCount +import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes import com.anytypeio.anytype.domain.payments.GetMembershipStatus import com.anytypeio.anytype.domain.search.ProfileSubscriptionManager +import com.anytypeio.anytype.domain.search.SearchObjects import com.anytypeio.anytype.domain.spaces.DeleteSpace import com.anytypeio.anytype.domain.spaces.SetSpaceDetails -import com.anytypeio.anytype.domain.wallpaper.GetSpaceWallpapers import com.anytypeio.anytype.domain.wallpaper.ObserveWallpaper import com.anytypeio.anytype.domain.workspace.SpaceManager import com.anytypeio.anytype.presentation.common.BaseViewModel +import com.anytypeio.anytype.presentation.objects.ObjectIcon +import com.anytypeio.anytype.presentation.settings.PersonalizationSettingsViewModel import com.anytypeio.anytype.presentation.spaces.UiSpaceSettingsItem.Spacer import javax.inject.Inject +import kotlin.collections.map +import kotlin.collections.sortedBy import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import timber.log.Timber class SpaceSettingsViewModel( - private val params: VmParams, + private val vmParams: VmParams, private val analytics: Analytics, private val setSpaceDetails: SetSpaceDetails, private val spaceManager: SpaceManager, private val gradientProvider: SpaceGradientProvider, private val urlBuilder: UrlBuilder, private val deleteSpace: DeleteSpace, - private val configStorage: ConfigStorage, private val debugSpaceShareDownloader: DebugSpaceShareDownloader, private val spaceGradientProvider: SpaceGradientProvider, private val userPermissionProvider: UserPermissionProvider, @@ -66,7 +78,10 @@ class SpaceSettingsViewModel( private val uploadFile: UploadFile, private val profileContainer: ProfileSubscriptionManager, private val getDefaultObjectType: GetDefaultObjectType, - private val observeWallpaper: ObserveWallpaper + private val setDefaultObjectType: SetDefaultObjectType, + private val observeWallpaper: ObserveWallpaper, + private val storeOfObjectTypes: StoreOfObjectTypes, + private val appActionManager: AppActionManager ): BaseViewModel() { val commands = MutableSharedFlow() @@ -77,7 +92,7 @@ class SpaceSettingsViewModel( val permissions = MutableStateFlow(SpaceMemberPermissions.NO_PERMISSIONS) init { - Timber.d("SpaceSettingsViewModel, Init, vmParams: $params") + Timber.d("SpaceSettingsViewModel, Init, vmParams: $vmParams") viewModelScope.launch { analytics.sendEvent( eventName = EventsDictionary.screenSettingSpacesSpaceIndex @@ -89,7 +104,7 @@ class SpaceSettingsViewModel( private fun proceedWithObservingSpaceView() { val restrictions = combine( - userPermissionProvider.observe(params.space), + userPermissionProvider.observe(vmParams.space), spaceViewContainer.sharedSpaceCount(userPermissionProvider.all()), profileContainer .observe() @@ -102,14 +117,35 @@ class SpaceSettingsViewModel( val otherFlows = combine( - spaceViewContainer.observe(params.space), - activeSpaceMemberSubscriptionContainer.observe(params.space), + spaceViewContainer.observe(vmParams.space), + activeSpaceMemberSubscriptionContainer.observe(vmParams.space), observeWallpaper.build() ) { spaceView, spaceMembers, wallpaper -> Triple(spaceView, spaceMembers, wallpaper) } viewModelScope.launch { + val defaultObjectTypeResponse = getDefaultObjectType + .async(params = vmParams.space) + .getOrNull() + + val defaultObjectTypeSettingItem: UiSpaceSettingsItem.DefaultObjectType + + if (defaultObjectTypeResponse != null) { + val defaultType = storeOfObjectTypes.get(defaultObjectTypeResponse.id.id) + defaultObjectTypeSettingItem = UiSpaceSettingsItem.DefaultObjectType( + id = defaultType?.id, + name = defaultType?.name.orEmpty(), + icon = ObjectIcon.Empty.ObjectType + ) + } else { + defaultObjectTypeSettingItem = UiSpaceSettingsItem.DefaultObjectType( + id = null, + name = EMPTY_STRING_VALUE, + icon = ObjectIcon.None + ) + } + combine( restrictions, otherFlows @@ -117,15 +153,18 @@ class SpaceSettingsViewModel( Timber.d("Got shared space limit: $sharedSpaceLimit, shared space count: $sharedSpaceCount") - val spaceMember = if (spaceMembers is ActiveSpaceMemberSubscriptionContainer.Store.Data) { + val spaceCreator = if (spaceMembers is ActiveSpaceMemberSubscriptionContainer.Store.Data) { spaceMembers.members.find { it.id == spaceView.getValue(Relations.CREATOR) } } else { null } - val createdBy = spaceMember?.globalName?.takeIf { it.isNotEmpty() } ?: spaceMember?.identity + val createdByNameOrId = spaceCreator?.globalName?.takeIf { it.isNotEmpty() } ?: spaceCreator?.identity - //todo add logic - val membersNumber = 3 + val spaceMemberCount = if (spaceMembers is ActiveSpaceMemberSubscriptionContainer.Store.Data) { + spaceMembers.members.size + } else { + 0 + } val requests: Int = if (spaceMembers is ActiveSpaceMemberSubscriptionContainer.Store.Data) { spaceMembers.members.count { it.status == ParticipantStatus.JOINING } @@ -134,13 +173,13 @@ class SpaceSettingsViewModel( } val spaceTechInfo = SpaceTechInfo( - spaceId = params.space, - createdBy = createdBy.orEmpty(), + spaceId = vmParams.space, + createdBy = createdByNameOrId.orEmpty(), creationDateInMillis = spaceView .getValue(Relations.CREATED_DATE) ?.let { timeInSeconds -> (timeInSeconds * 1000L).toLong() } , - networkId = spaceManager.getConfig(params.space)?.network.orEmpty() + networkId = spaceManager.getConfig(vmParams.space)?.network.orEmpty() ) UiSpaceSettingsState.SpaceSettings( @@ -164,11 +203,20 @@ class SpaceSettingsViewModel( UiSpaceSettingsItem.Multiplayer, Spacer(height = 8), UiSpaceSettingsItem.Section.Collaboration, - UiSpaceSettingsItem.Members(count = membersNumber), + 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.Misc, - UiSpaceSettingsItem.SpaceInfo + UiSpaceSettingsItem.SpaceInfo, + Spacer(height = 8), + UiSpaceSettingsItem.DeleteSpace, + Spacer(height = 32) ), isEditEnabled = permission?.isOwnerOrEditor() == true ) @@ -207,7 +255,7 @@ class SpaceSettingsViewModel( viewModelScope.launch { setSpaceDetails.async( params = SetSpaceDetails.Params( - space = params.space, + space = vmParams.space, details = mapOf( Relations.DESCRIPTION to uiEvent.description ) @@ -219,7 +267,7 @@ class SpaceSettingsViewModel( viewModelScope.launch { setSpaceDetails.async( params = SetSpaceDetails.Params( - space = params.space, + space = vmParams.space, details = mapOf( Relations.NAME to uiEvent.title ) @@ -238,6 +286,24 @@ class SpaceSettingsViewModel( commands.emit(Command.OpenWallpaperPicker) } } + is UiEvent.OnSpaceMembersClicked -> { + viewModelScope.launch { + commands.emit(Command.ManageSharedSpace(vmParams.space)) + } + } + is UiEvent.OnDefaultObjectTypeClicked -> { + viewModelScope.launch { + commands.emit( + Command.SelectDefaultObjectType( + space = vmParams.space, + excludedTypeIds = buildList { + val curr = uiEvent.currentDefaultObjectTypeId + if (!curr.isNullOrEmpty()) add(curr) + } + ) + ) + } + } } } @@ -253,7 +319,7 @@ class SpaceSettingsViewModel( viewModelScope.launch { setSpaceDetails.async( SetSpaceDetails.Params( - space = params.space, + space = vmParams.space, details = mapOf( Relations.ICON_OPTION to spaceGradientProvider.randomId().toDouble(), Relations.ICON_IMAGE to "", @@ -353,7 +419,7 @@ class SpaceSettingsViewModel( fun onManageSharedSpaceClicked() { viewModelScope.launch { commands.emit( - Command.ManageSharedSpace(params.space) + Command.ManageSharedSpace(vmParams.space) ) } } @@ -426,7 +492,7 @@ class SpaceSettingsViewModel( uploadFile.async( params = UploadFile.Params( path = path, - space = params.space, + space = vmParams.space, type = Block.Content.File.Type.IMAGE ) ).fold( @@ -443,7 +509,7 @@ class SpaceSettingsViewModel( private suspend fun proceedWithSettingSpaceIconImage(file: ObjectWrapper.File) { setSpaceDetails.async( SetSpaceDetails.Params( - space = params.space, + space = vmParams.space, details = mapOf( Relations.ICON_IMAGE to file.id, Relations.ICON_OPTION to null, @@ -460,6 +526,80 @@ class SpaceSettingsViewModel( ) } + fun onSelectObjectType(type: ObjectWrapper.Type) { + // Setting space default object type + viewModelScope.launch { + val params = SetDefaultObjectType.Params( + space = vmParams.space, + type = TypeId(type.id) + ) + setDefaultObjectType.async(params).fold( + onFailure = { + Timber.e(it, "Error while setting default object type") + }, + onSuccess = { + when(val state = uiState.value) { + is UiSpaceSettingsState.SpaceSettings -> { + uiState.value = state.copy( + items = state.items.map { item -> + if (item is UiSpaceSettingsItem.DefaultObjectType) { + UiSpaceSettingsItem.DefaultObjectType( + id = type.id, + name = type.name.orEmpty(), + icon = ObjectIcon.Empty.ObjectType + ) + } else { + item + } + } + ) + } + else -> { + Timber.w("Unexpected ui state when updating object type: $state") + } + } + analytics.registerEvent( + EventAnalytics.Anytype( + name = defaultTypeChanged, + props = Props( + mapOf( + EventsPropertiesKey.objectType to type.uniqueKey, + EventsPropertiesKey.route to "Settings" + ) + ), + duration = null + ) + ) + } + ) + } + // Updating app actions (app shortcuts): + viewModelScope.launch { + val types = buildList { + add(type) + val note = storeOfObjectTypes.getByKey( + ObjectTypeUniqueKeys.NOTE + ) + val page = storeOfObjectTypes.getByKey( + ObjectTypeUniqueKeys.PAGE + ) + val task = storeOfObjectTypes.getByKey( + ObjectTypeUniqueKeys.TASK + ) + if (note != null) add(note) + if (page != null) add(page) + if (task != null) add(task) + } + val actions = types.map { type -> + AppActionManager.Action.CreateNew( + type = TypeKey(type.uniqueKey), + name = type.name.orEmpty() + ) + } + appActionManager.setup(actions = actions) + } + } + data class SpaceData( val spaceId: Id?, val createdDateInMillis: Long?, @@ -486,6 +626,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 SelectDefaultObjectType(val space: SpaceId, val excludedTypeIds: List) : Command() data object ExitToVault : Command() data object ShowDeleteSpaceWarning : Command() data object ShowLeaveSpaceWarning : Command() @@ -504,7 +645,6 @@ class SpaceSettingsViewModel( private val gradientProvider: SpaceGradientProvider, private val spaceManager: SpaceManager, private val deleteSpace: DeleteSpace, - private val configStorage: ConfigStorage, private val debugFileShareDownloader: DebugSpaceShareDownloader, private val spaceGradientProvider: SpaceGradientProvider, private val userPermissionProvider: UserPermissionProvider, @@ -513,7 +653,10 @@ class SpaceSettingsViewModel( private val uploadFile: UploadFile, private val profileContainer: ProfileSubscriptionManager, private val getDefaultObjectType: GetDefaultObjectType, - private val observeWallpaper: ObserveWallpaper + private val setDefaultObjectType: SetDefaultObjectType, + private val observeWallpaper: ObserveWallpaper, + private val appActionManager: AppActionManager, + private val storeOfObjectTypes: StoreOfObjectTypes ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create( @@ -526,17 +669,19 @@ class SpaceSettingsViewModel( gradientProvider = gradientProvider, analytics = analytics, deleteSpace = deleteSpace, - configStorage = configStorage, debugSpaceShareDownloader = debugFileShareDownloader, spaceGradientProvider = spaceGradientProvider, - params = params, + vmParams = params, userPermissionProvider = userPermissionProvider, activeSpaceMemberSubscriptionContainer = activeSpaceMemberSubscriptionContainer, getMembership = getMembership, uploadFile = uploadFile, profileContainer = profileContainer, getDefaultObjectType = getDefaultObjectType, - observeWallpaper = observeWallpaper + setDefaultObjectType = setDefaultObjectType, + observeWallpaper = observeWallpaper, + appActionManager = appActionManager, + storeOfObjectTypes = storeOfObjectTypes ) 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 11d24d556b..6810747d0a 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 @@ -1,14 +1,21 @@ package com.anytypeio.anytype.presentation.spaces +import com.anytypeio.anytype.core_models.Id + sealed class UiEvent { data object OnBackPressed : UiEvent() + data class OnSaveDescriptionClicked(val description: String) : UiEvent() data class OnSaveTitleClicked(val title: String) : UiEvent() + data class OnSpaceImagePicked(val uri: String) : UiEvent() + + data object OnSpaceMembersClicked : UiEvent() + data class OnDefaultObjectTypeClicked(val currentDefaultObjectTypeId: Id?) : UiEvent() + data object OnDeleteSpaceClicked : UiEvent() data object OnFileStorageClick : UiEvent() data object OnPersonalizationClicked : UiEvent() data object OnSpaceIdClicked : UiEvent() - data class OnSpaceImagePicked(val uri: String) : UiEvent() data object OnInviteClicked : UiEvent() data object OnQrCodeClicked : UiEvent() data object OnWallpaperClicked : UiEvent() 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 0971588f2f..0d527fffaa 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 @@ -46,7 +46,8 @@ sealed class UiSpaceSettingsItem { data class Members(val count: Int) : UiSpaceSettingsItem() data class Chat(val isOn: Boolean) : UiSpaceSettingsItem() data object ObjectTypes : UiSpaceSettingsItem() - data class DefaultObjectType(val name: String, val icon: ObjectIcon) : 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 RemoteStorage(val size: Int) : UiSpaceSettingsItem() data object SpaceInfo : UiSpaceSettingsItem()