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 90dc7eb71b..738a463309 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 @@ -6,21 +6,20 @@ import android.view.View import android.view.ViewGroup import androidx.compose.material.MaterialTheme import androidx.compose.runtime.LaunchedEffect -import androidx.compose.ui.platform.ViewCompositionStrategy import androidx.compose.ui.res.colorResource import androidx.core.os.bundleOf import androidx.fragment.app.viewModels +import androidx.fragment.compose.content 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 import com.anytypeio.anytype.core_utils.ext.shareFile import com.anytypeio.anytype.core_utils.ext.toast -import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetComposeFragment +import com.anytypeio.anytype.core_utils.ui.BaseComposeFragment import com.anytypeio.anytype.di.common.componentManager import com.anytypeio.anytype.presentation.spaces.SpaceSettingsViewModel import com.anytypeio.anytype.presentation.spaces.SpaceSettingsViewModel.Command @@ -29,6 +28,7 @@ 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.SpacesStorageFragment import com.anytypeio.anytype.ui.settings.typography import com.anytypeio.anytype.ui.spaces.DeleteSpaceWarning import com.anytypeio.anytype.ui_settings.space.new_settings.SpaceSettingsContainer @@ -36,8 +36,7 @@ import java.io.File import javax.inject.Inject import timber.log.Timber -// TODO convert to Fragment. -class SpaceSettingsFragment : BaseBottomSheetComposeFragment(), ObjectTypeSelectionListener { +class SpaceSettingsFragment : BaseComposeFragment(), ObjectTypeSelectionListener { private val space get() = arg(ARG_SPACE_ID_KEY) @@ -51,31 +50,26 @@ class SpaceSettingsFragment : BaseBottomSheetComposeFragment(), ObjectTypeSelect override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ) = ComposeDialogView( - context = requireContext(), dialog = requireDialog() - ).apply { - setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) - setContent { - MaterialTheme( - typography = typography, - colors = MaterialTheme.colors.copy( - surface = colorResource(id = R.color.context_menu_background) - ) - ) { - SpaceSettingsContainer( - uiState = vm.uiState.collectAsStateWithLifecycle().value, - uiEvent = vm::onUiEvent - ) - LaunchedEffect(Unit) { vm.toasts.collect { toast(it) } } - LaunchedEffect(Unit) { - vm.isDismissed.collect { isDismissed -> - if (isDismissed) dismiss() - } - } - LaunchedEffect(Unit) { - observeCommands() + ) = content { + MaterialTheme( + typography = typography, + colors = MaterialTheme.colors.copy( + surface = colorResource(id = R.color.context_menu_background) + ) + ) { + SpaceSettingsContainer( + uiState = vm.uiState.collectAsStateWithLifecycle().value, + uiEvent = vm::onUiEvent + ) + LaunchedEffect(Unit) { vm.toasts.collect { toast(it) } } + LaunchedEffect(Unit) { + vm.isDismissed.collect { isDismissed -> + if (isDismissed) findNavController().popBackStack() } } + LaunchedEffect(Unit) { + observeCommands() + } } } @@ -170,6 +164,16 @@ class SpaceSettingsFragment : BaseBottomSheetComposeFragment(), ObjectTypeSelect Timber.e(it, "Error while opening set-default-object-type screen") } } + is Command.ManageRemoteStorage -> { + runCatching { + findNavController().navigate( + resId = R.id.spacesStorageScreen, + args = SpacesStorageFragment.args(space = space) + ) + }.onFailure { + Timber.e(it, "Failed to execute nav command: $command") + } + } } } } @@ -180,8 +184,6 @@ class SpaceSettingsFragment : BaseBottomSheetComposeFragment(), ObjectTypeSelect override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - expand() - skipCollapsed() } override fun injectDependencies() { @@ -193,6 +195,10 @@ class SpaceSettingsFragment : BaseBottomSheetComposeFragment(), ObjectTypeSelect componentManager().spaceSettingsComponent.release() } + override fun onApplyWindowRootInsets(view: View) { + // Do nothing. Compose code will handle insets. + } + companion object { const val ARG_SPACE_ID_KEY = "arg.space-settings.space-id" fun args(space: SpaceId) = bundleOf(ARG_SPACE_ID_KEY to space.id) diff --git a/app/src/main/res/navigation/graph.xml b/app/src/main/res/navigation/graph.xml index 4d4c1b23dc..8794c892c5 100644 --- a/app/src/main/res/navigation/graph.xml +++ b/app/src/main/res/navigation/graph.xml @@ -307,7 +307,7 @@ android:name="com.anytypeio.anytype.ui.vault.IntroduceVaultFragment" android:label="IntroduceVaultScreen"/> - diff --git a/feature-ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/space/new_settings/Icon.kt b/feature-ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/space/new_settings/Icon.kt index 61d949a32d..7ffed430a4 100644 --- a/feature-ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/space/new_settings/Icon.kt +++ b/feature-ui-settings/src/main/java/com/anytypeio/anytype/ui_settings/space/new_settings/Icon.kt @@ -84,7 +84,8 @@ fun NewSpaceIcon( } }, text = stringResource(R.string.space_settings_icon_title), - style = Caption1Medium + style = Caption1Medium, + color = colorResource(R.color.text_secondary) ) MaterialTheme( shapes = MaterialTheme.shapes.copy(medium = RoundedCornerShape(10.dp)) 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 98888d82e8..c155b4f9c6 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 @@ -235,6 +235,16 @@ fun SpaceInfoItem( ) } +@Composable +fun RemoteStorageItem( + modifier: Modifier = Modifier +) { + BaseButton( + modifier = modifier, + title = stringResource(id = R.string.remote_storage), + ) +} + @Composable fun DeleteSpaceItem( 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 22e5965784..21c7a9def3 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 @@ -5,7 +5,6 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.border 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.WindowInsets import androidx.compose.foundation.layout.fillMaxSize @@ -135,6 +134,7 @@ fun NewSpaceSettingsScreen( ) } } + is UiSpaceSettingsItem.Name -> { item { NewSpaceNameInputField( @@ -149,8 +149,7 @@ fun NewSpaceSettingsScreen( .animateItem() .noRippleClickable { showEditTitle = true - } - , + }, name = item.name, isEditEnabled = false ) @@ -171,8 +170,7 @@ fun NewSpaceSettingsScreen( .animateItem() .noRippleClickable { showEditDescription = true - } - , + }, isEditEnabled = false, description = initialDescription ) @@ -192,6 +190,7 @@ fun NewSpaceSettingsScreen( is UiSpaceSettingsItem.Chat -> { // TODO } + is UiSpaceSettingsItem.DefaultObjectType -> { item { DefaultTypeItem( @@ -199,8 +198,7 @@ fun NewSpaceSettingsScreen( .fillMaxWidth() .animateItem() .clip(RoundedCornerShape(16.dp)) - .clickable { uiEvent(UiEvent.OnDefaultObjectTypeClicked(item.id)) } - , + .clickable { uiEvent(UiEvent.OnDefaultObjectTypeClicked(item.id)) }, name = item.name, icon = item.icon ) @@ -213,6 +211,8 @@ fun NewSpaceSettingsScreen( modifier = Modifier .fillMaxWidth() .animateItem() + .clip(RoundedCornerShape(16.dp)) + .clickable { uiEvent(UiEvent.OnDeleteSpaceClicked) }, ) } } @@ -224,8 +224,7 @@ fun NewSpaceSettingsScreen( .fillMaxWidth() .animateItem() .clip(RoundedCornerShape(16.dp)) - .clickable { uiEvent(UiEvent.OnSpaceMembersClicked) } - , + .clickable { uiEvent(UiEvent.OnSpaceMembersClicked) }, item = item ) } @@ -244,6 +243,7 @@ fun NewSpaceSettingsScreen( ) } } + UiSpaceSettingsItem.Fields -> { item { FieldsItem( @@ -257,9 +257,19 @@ fun NewSpaceSettingsScreen( ) } } + is UiSpaceSettingsItem.RemoteStorage -> { - // TODO + item { + RemoteStorageItem( + modifier = Modifier + .fillMaxWidth() + .animateItem() + .clip(RoundedCornerShape(16.dp)) + .clickable { uiEvent(UiEvent.OnRemoteStorageClick) } + ) + } } + is UiSpaceSettingsItem.Section -> { item { SpaceSettingsSection( @@ -284,7 +294,6 @@ fun NewSpaceSettingsScreen( ) } } - is UiSpaceSettingsItem.Wallpapers -> { item { WallpaperItem( @@ -293,9 +302,8 @@ fun NewSpaceSettingsScreen( .animateItem() .clip(RoundedCornerShape(16.dp)) .clickable { - uiEvent(UiEvent.OnWallpaperClicked) - } - , + uiEvent(UiEvent.OnSelectWallpaperClicked) + }, item = item ) } @@ -390,7 +398,11 @@ private fun EditNameField( modifier = Modifier.fillMaxWidth(), containerColor = colorResource(id = R.color.background_secondary), topBar = { - Box(modifier = Modifier.fillMaxWidth().height(48.dp)) { + Box( + modifier = Modifier + .fillMaxWidth() + .height(48.dp) + ) { Text( modifier = Modifier .align(Alignment.CenterEnd) @@ -433,8 +445,7 @@ private fun EditNameField( width = 2.dp, color = colorResource(id = R.color.palette_system_amber_50) ) - .padding(vertical = 12.dp, horizontal = 16.dp) - , + .padding(vertical = 12.dp, horizontal = 16.dp), name = fieldInput, onNameSet = { newName -> fieldInput = newName @@ -458,7 +469,11 @@ private fun EditDescriptionField( modifier = Modifier.fillMaxWidth(), containerColor = colorResource(id = R.color.background_secondary), topBar = { - Box(modifier = Modifier.fillMaxWidth().height(48.dp)) { + Box( + modifier = Modifier + .fillMaxWidth() + .height(48.dp) + ) { Text( modifier = Modifier .align(Alignment.CenterEnd) @@ -501,8 +516,7 @@ private fun EditDescriptionField( width = 2.dp, color = colorResource(id = R.color.palette_system_amber_50) ) - .padding(vertical = 12.dp, horizontal = 16.dp) - , + .padding(vertical = 12.dp, horizontal = 16.dp), description = fieldInput, isEditEnabled = true, onDescriptionSet = { 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 7a2657a79e..5183187ed1 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 @@ -11,12 +11,8 @@ 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 @@ -28,7 +24,6 @@ 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.config.ConfigStorage import com.anytypeio.anytype.domain.debugging.DebugSpaceShareDownloader import com.anytypeio.anytype.domain.launch.GetDefaultObjectType import com.anytypeio.anytype.domain.launch.SetDefaultObjectType @@ -42,18 +37,15 @@ 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.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 @@ -212,6 +204,8 @@ class SpaceSettingsViewModel( defaultObjectTypeSettingItem, Spacer(height = 8), UiSpaceSettingsItem.Wallpapers(current = wallpaper), + UiSpaceSettingsItem.Section.DataManagement, + UiSpaceSettingsItem.RemoteStorage, UiSpaceSettingsItem.Section.Misc, UiSpaceSettingsItem.SpaceInfo, Spacer(height = 8), @@ -237,10 +231,16 @@ class SpaceSettingsViewModel( isDismissed.value = true } UiEvent.OnDeleteSpaceClicked -> { - sendToast("Coming soon") + viewModelScope.launch { + commands.emit( + Command.ShowDeleteSpaceWarning + ) + } } - UiEvent.OnFileStorageClick -> { - sendToast("Coming soon") + UiEvent.OnRemoteStorageClick -> { + viewModelScope.launch { + commands.emit(Command.ManageRemoteStorage) + } } UiEvent.OnInviteClicked -> { sendToast("Coming soon") @@ -275,13 +275,10 @@ class SpaceSettingsViewModel( ) } } - UiEvent.OnSpaceIdClicked -> { - sendToast("Coming soon") - } is UiEvent.OnSpaceImagePicked -> { proceedWithSettingSpaceImage(uiEvent.uri) } - is UiEvent.OnWallpaperClicked -> { + is UiEvent.OnSelectWallpaperClicked -> { viewModelScope.launch { commands.emit(Command.OpenWallpaperPicker) } @@ -380,27 +377,21 @@ class SpaceSettingsViewModel( } private fun proceedWithSpaceDeletion() { -// val state = spaceViewState.value as? SpaceData.Success ?: return -// val space = state.spaceId -// if (space != null) { -// viewModelScope.launch { -// deleteSpace.async(params = SpaceId(space)).fold( -// onSuccess = { -// analytics.sendEvent( -// eventName = EventsDictionary.deleteSpace, -// props = Props(mapOf(EventsPropertiesKey.type to "Private")) -// ) -// spaceManager.clear() -// commands.emit(Command.ExitToVault) -// }, -// onFailure = { -// Timber.e(it, "Error while deleting space") -// } -// ) -// } -// } else { -// sendToast("Space not found. Please, try again later") -// } + viewModelScope.launch { + deleteSpace.async(params = vmParams.space).fold( + onSuccess = { + analytics.sendEvent( + eventName = EventsDictionary.deleteSpace, + props = Props(mapOf(EventsPropertiesKey.type to "Private")) + ) + spaceManager.clear() + commands.emit(Command.ExitToVault) + }, + onFailure = { + Timber.e(it, "Error while deleting space") + } + ) + } } private fun proceedWithSpaceDebug() { @@ -634,6 +625,7 @@ class SpaceSettingsViewModel( data object NavigateToMembership : Command() data object NavigateToMembershipUpdate : Command() data object OpenWallpaperPicker : Command() + data object ManageRemoteStorage : Command() } class Factory @Inject constructor( 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 6810747d0a..55eeda3a7c 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 @@ -8,17 +8,16 @@ sealed class UiEvent { data class OnSaveDescriptionClicked(val description: String) : UiEvent() data class OnSaveTitleClicked(val title: String) : UiEvent() data class OnSpaceImagePicked(val uri: String) : UiEvent() + data object OnSelectWallpaperClicked : UiEvent() data object OnSpaceMembersClicked : UiEvent() data class OnDefaultObjectTypeClicked(val currentDefaultObjectTypeId: Id?) : UiEvent() data object OnDeleteSpaceClicked : UiEvent() - data object OnFileStorageClick : UiEvent() + data object OnRemoteStorageClick : UiEvent() data object OnPersonalizationClicked : UiEvent() - data object OnSpaceIdClicked : UiEvent() data object OnInviteClicked : UiEvent() data object OnQrCodeClicked : UiEvent() - data object OnWallpaperClicked : 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 0d527fffaa..5caee611f2 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 @@ -49,7 +49,7 @@ 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 RemoteStorage(val size: Int) : UiSpaceSettingsItem() + data object RemoteStorage : UiSpaceSettingsItem() data object SpaceInfo : UiSpaceSettingsItem() data object DeleteSpace : UiSpaceSettingsItem() } \ No newline at end of file