diff --git a/app/src/main/java/com/anytypeio/anytype/ui/editor/EditorFragment.kt b/app/src/main/java/com/anytypeio/anytype/ui/editor/EditorFragment.kt index 8c186ecadf..c2b103bd10 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/editor/EditorFragment.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/editor/EditorFragment.kt @@ -851,13 +851,9 @@ open class EditorFragment : NavigationFragment(R.layout.f // TODO }.launchIn(lifecycleScope) - vm.permission.onEach { permission -> + vm.navPanelState.onEach { if (hasBinding) { - if (permission?.isOwnerOrEditor() == true) { - binding.bottomToolbar.setIsReadOnly(false) - } else { - binding.bottomToolbar.setIsReadOnly(true) - } + binding.bottomToolbar.setState(it) } }.launchIn(lifecycleScope) diff --git a/app/src/main/java/com/anytypeio/anytype/ui/home/HomeScreen.kt b/app/src/main/java/com/anytypeio/anytype/ui/home/HomeScreen.kt index 9df64f5c45..6a9bf5dac4 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/home/HomeScreen.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/home/HomeScreen.kt @@ -46,6 +46,7 @@ import com.anytypeio.anytype.core_ui.foundation.components.BottomNavigationMenu import com.anytypeio.anytype.core_ui.foundation.noRippleClickable import com.anytypeio.anytype.core_ui.views.UXBody import com.anytypeio.anytype.presentation.home.InteractionMode +import com.anytypeio.anytype.presentation.navigation.NavPanelState import com.anytypeio.anytype.presentation.widgets.DropDownMenuAction import com.anytypeio.anytype.presentation.widgets.FromIndex import com.anytypeio.anytype.presentation.widgets.ToIndex @@ -72,6 +73,7 @@ import org.burnoutcrew.reorderable.reorderable @Composable fun HomeScreen( + navPanelState: NavPanelState, modifier: Modifier, mode: InteractionMode, widgets: List, @@ -88,7 +90,6 @@ fun HomeScreen( onSearchClicked: () -> Unit, onCreateNewObjectClicked: () -> Unit, onCreateNewObjectLongClicked: () -> Unit, - onBackClicked: () -> Unit, onShareButtonClicked: () -> Unit, onObjectCheckboxClicked: (Id, Boolean) -> Unit, onSpaceWidgetClicked: () -> Unit, @@ -96,8 +97,7 @@ fun HomeScreen( onSpaceShareIconClicked: (ObjectWrapper.SpaceView) -> Unit, onSeeAllObjectsClicked: (WidgetView.Gallery) -> Unit, onCreateObjectInsideWidget: (Id) -> Unit, - onCreateDataViewObject: (WidgetId, ViewId?) -> Unit, - onBackLongClicked: () -> Unit + onCreateDataViewObject: (WidgetId, ViewId?) -> Unit ) { Box(modifier = modifier.fillMaxSize()) { @@ -156,13 +156,11 @@ fun HomeScreen( exit = fadeOut() + slideOutVertically { it } ) { BottomNavigationMenu( + state = navPanelState, modifier = Modifier, - backClick = onBackClicked, - backLongClick = onBackLongClicked, searchClick = onSearchClicked, addDocClick = onCreateNewObjectClicked, addDocLongClick = onCreateNewObjectLongClicked, - isOwnerOrEditor = mode !is InteractionMode.ReadOnly, onShareButtonClicked = onShareButtonClicked ) } diff --git a/app/src/main/java/com/anytypeio/anytype/ui/home/HomeScreenFragment.kt b/app/src/main/java/com/anytypeio/anytype/ui/home/HomeScreenFragment.kt index dfbad9466e..f47d49e8e0 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/home/HomeScreenFragment.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/home/HomeScreenFragment.kt @@ -57,9 +57,6 @@ import com.anytypeio.anytype.ui.objects.types.pickers.ObjectTypeSelectionListene import com.anytypeio.anytype.ui.objects.types.pickers.WidgetObjectTypeListener import com.anytypeio.anytype.ui.objects.types.pickers.WidgetSourceTypeListener import com.anytypeio.anytype.ui.payments.MembershipFragment -import com.anytypeio.anytype.ui.profile.ParticipantFragment -import com.anytypeio.anytype.ui.search.GlobalSearchScreen -import com.anytypeio.anytype.ui.sets.ObjectSetFragment import com.anytypeio.anytype.ui.settings.space.SpaceSettingsFragment import com.anytypeio.anytype.ui.settings.typography import com.anytypeio.anytype.ui.widgets.SelectWidgetSourceFragment @@ -179,9 +176,6 @@ class HomeScreenFragment : BaseComposeFragment(), onCreateNewObjectLongClicked = throttledClick( onClick = { vm.onCreateNewObjectLongClicked() } ), - onBackClicked = throttledClick( - onClick = { vm.onBackClicked(isSpaceRootScreen()) } - ), onSpaceWidgetClicked = throttledClick( onClick = vm::onSpaceSettingsClicked ), @@ -192,8 +186,8 @@ class HomeScreenFragment : BaseComposeFragment(), onSeeAllObjectsClicked = vm::onSeeAllObjectsClicked, onCreateObjectInsideWidget = vm::onCreateObjectInsideWidget, onCreateDataViewObject = vm::onCreateDataViewObject, - onBackLongClicked = vm::onBackLongClicked, - onShareButtonClicked = vm::onSpaceShareIconClicked + onShareButtonClicked = vm::onSpaceShareIconClicked, + navPanelState = vm.navPanelState.collectAsStateWithLifecycle().value ) } diff --git a/app/src/main/java/com/anytypeio/anytype/ui/sets/ObjectSetFragment.kt b/app/src/main/java/com/anytypeio/anytype/ui/sets/ObjectSetFragment.kt index 45c71d500b..6117cf2168 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/sets/ObjectSetFragment.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/sets/ObjectSetFragment.kt @@ -537,13 +537,6 @@ open class ObjectSetFragment : lifecycleScope.subscribe(vm.isCustomizeViewPanelVisible) { isCustomizeViewPanelVisible -> if (isCustomizeViewPanelVisible) showBottomPanel() else hideBottomPanel() } - lifecycleScope.subscribe(vm.permission.filterNotNull()) { permission -> - if (permission.isOwnerOrEditor()) { - binding.bottomToolbar.setIsReadOnly(false) - } else { - binding.bottomToolbar.setIsReadOnly(true) - } - } } private fun setStatus(status: SpaceSyncAndP2PStatusState?) { @@ -1297,6 +1290,13 @@ open class ObjectSetFragment : override fun onStart() { super.onStart() + + vm.navPanelState.onEach { + if (hasBinding) { + binding.bottomToolbar.setState(it) + } + }.launchIn(lifecycleScope) + jobs += lifecycleScope.subscribe(vm.commands) { observeCommands(it) } jobs += lifecycleScope.subscribe(vm.header) { header -> when(header) { diff --git a/app/src/main/java/com/anytypeio/anytype/ui/widgets/collection/CollectionScreen.kt b/app/src/main/java/com/anytypeio/anytype/ui/widgets/collection/CollectionScreen.kt index b5f3916953..5216fe3b76 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/widgets/collection/CollectionScreen.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/widgets/collection/CollectionScreen.kt @@ -145,13 +145,11 @@ fun ScreenContent( .align(BottomCenter) .padding(bottom = 20.dp)) { BottomNavigationMenu( - backClick = { vm.onPrevClicked() }, searchClick = onSearchClicked, addDocClick = { vm.onAddClicked(null) }, addDocLongClick = onCreateObjectLongClicked, - backLongClick = vm::onBackLongClicked, - isOwnerOrEditor = uiState.isActionButtonVisible, - onShareButtonClicked = vm::onShareButtonClicked + onShareButtonClicked = vm::onShareButtonClicked, + state = vm.navPanelState.collectAsStateWithLifecycle().value ) } } diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/common/Constants.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/common/Constants.kt new file mode 100644 index 0000000000..b2e2acd4f4 --- /dev/null +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/common/Constants.kt @@ -0,0 +1,4 @@ +package com.anytypeio.anytype.core_ui.common + +const val DEFAULT_DISABLED_ALPHA = 0.5f +const val FULL_ALPHA = 1f \ No newline at end of file diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/foundation/components/BottomNavigationMenu.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/foundation/components/BottomNavigationMenu.kt index 560da17113..fd37e9591d 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/foundation/components/BottomNavigationMenu.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/foundation/components/BottomNavigationMenu.kt @@ -17,6 +17,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.layout.ContentScale @@ -28,18 +29,50 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import coil.compose.rememberAsyncImagePainter import com.anytypeio.anytype.core_ui.R +import com.anytypeio.anytype.core_ui.common.DEFAULT_DISABLED_ALPHA import com.anytypeio.anytype.core_ui.common.DefaultPreviews +import com.anytypeio.anytype.core_ui.common.FULL_ALPHA import com.anytypeio.anytype.core_ui.foundation.components.BottomNavigationDefaults.Height import com.anytypeio.anytype.core_ui.foundation.noRippleClickable import com.anytypeio.anytype.core_ui.foundation.noRippleCombinedClickable +import com.anytypeio.anytype.presentation.navigation.NavPanelState import com.anytypeio.anytype.presentation.profile.ProfileIconView +@DefaultPreviews +@Composable +private fun NavBarPreviewOwner() { + BottomNavigationMenu( + searchClick = {}, + addDocClick = {}, + addDocLongClick = {}, + state = NavPanelState.Default( + isCreateObjectButtonEnabled = true, + leftButtonState = NavPanelState.LeftButtonState.AddMembers( + isActive = true + ) + ) + ) +} + +@DefaultPreviews +@Composable +private fun NavBarPreviewReader() { + BottomNavigationMenu( + searchClick = {}, + addDocClick = {}, + addDocLongClick = {}, + state = NavPanelState.Default( + isCreateObjectButtonEnabled = false, + leftButtonState = NavPanelState.LeftButtonState.ViewMembers + ) + ) +} + + @DefaultPreviews @Composable private fun MyBottomNavigationMenu() { BottomNavigationMenu( - backClick = {}, - backLongClick = {}, searchClick = {}, addDocClick = {}, addDocLongClick = {}, @@ -51,8 +84,6 @@ private fun MyBottomNavigationMenu() { @Composable private fun MyBottomViewerNavigationMenu() { BottomNavigationMenu( - backClick = {}, - backLongClick = {}, searchClick = {}, addDocClick = {}, addDocLongClick = {}, @@ -63,8 +94,6 @@ private fun MyBottomViewerNavigationMenu() { @Composable fun BottomNavigationMenu( modifier: Modifier = Modifier, - backClick: () -> Unit = {}, - backLongClick: () -> Unit = {}, onShareButtonClicked: () -> Unit = {}, searchClick: () -> Unit = {}, addDocClick: () -> Unit = {}, @@ -86,20 +115,29 @@ fun BottomNavigationMenu( verticalAlignment = Alignment.CenterVertically ) { MenuItem( - modifier = Modifier.width(72.dp).height(52.dp), + modifier = Modifier + .width(72.dp) + .height(52.dp), contentDescription = stringResource(id = R.string.main_navigation_content_desc_members_button), - res = BottomNavigationItem.MEMBERS.res, + res = if (isOwnerOrEditor) + BottomNavigationItem.ADD_MEMBERS.res + else + BottomNavigationItem.MEMBERS.res, onClick = onShareButtonClicked ) MenuItem( - modifier = Modifier.width(72.dp).height(52.dp), + modifier = Modifier + .width(72.dp) + .height(52.dp), contentDescription = stringResource(id = R.string.main_navigation_content_desc_search_button), res = BottomNavigationItem.SEARCH.res, onClick = searchClick ) if (isOwnerOrEditor) { MenuItem( - modifier = Modifier.width(72.dp).height(52.dp), + modifier = Modifier + .width(72.dp) + .height(52.dp), contentDescription = stringResource(id = R.string.main_navigation_content_desc_create_button), res = BottomNavigationItem.ADD_DOC.res, onClick = addDocClick, @@ -109,13 +147,107 @@ fun BottomNavigationMenu( } } +@Composable +fun BottomNavigationMenu( + state: NavPanelState, + modifier: Modifier = Modifier, + onShareButtonClicked: () -> Unit = {}, + searchClick: () -> Unit = {}, + addDocClick: () -> Unit = {}, + addDocLongClick: () -> Unit = {} +) { + Row( + modifier = modifier + .height(Height) + .wrapContentWidth() + .background( + shape = RoundedCornerShape(16.dp), + color = colorResource(id = R.color.home_screen_toolbar_button) + ) + /** + * Workaround for clicks through the bottom navigation menu. + */ + .noRippleClickable { }, + verticalAlignment = Alignment.CenterVertically + ) { + if (state is NavPanelState.Default) { + when (state.leftButtonState) { + is NavPanelState.LeftButtonState.AddMembers -> { + MenuItem( + modifier = Modifier + .width(72.dp) + .height(52.dp), + contentDescription = stringResource(id = R.string.main_navigation_content_desc_members_button), + res = BottomNavigationItem.ADD_MEMBERS.res, + onClick = onShareButtonClicked + ) + } + + is NavPanelState.LeftButtonState.Comment -> { + // TODO + } + + NavPanelState.LeftButtonState.ViewMembers -> { + MenuItem( + modifier = Modifier + .width(72.dp) + .height(52.dp), + contentDescription = stringResource(id = R.string.main_navigation_content_desc_members_button), + res = BottomNavigationItem.MEMBERS.res, + onClick = onShareButtonClicked + ) + } + } + } else { + MenuItem( + modifier = Modifier + .width(72.dp) + .height(52.dp), + contentDescription = stringResource(id = R.string.main_navigation_content_desc_members_button), + res = BottomNavigationItem.MEMBERS.res, + onClick = onShareButtonClicked + ) + } + MenuItem( + modifier = Modifier + .width(72.dp) + .height(52.dp), + contentDescription = stringResource(id = R.string.main_navigation_content_desc_search_button), + res = BottomNavigationItem.SEARCH.res, + onClick = searchClick + ) + MenuItem( + modifier = Modifier + .width(72.dp) + .height(52.dp) + .alpha( + if (state is NavPanelState.Default) { + if (state.isCreateObjectButtonEnabled) + FULL_ALPHA + else + DEFAULT_DISABLED_ALPHA + } else { + DEFAULT_DISABLED_ALPHA + } + ) + , + contentDescription = stringResource(id = R.string.main_navigation_content_desc_create_button), + res = BottomNavigationItem.ADD_DOC.res, + onClick = addDocClick, + onLongClick = addDocLongClick, + enabled = (state is NavPanelState.Default && state.isCreateObjectButtonEnabled) + ) + } +} + @Composable private fun MenuItem( modifier: Modifier, contentDescription: String, @DrawableRes res: Int, onClick: () -> Unit = {}, - onLongClick: () -> Unit = {} + onLongClick: () -> Unit = {}, + enabled: Boolean = true ) { val haptic = LocalHapticFeedback.current Image( @@ -123,80 +255,29 @@ private fun MenuItem( contentDescription = contentDescription, contentScale = ContentScale.Inside, modifier = modifier - .noRippleCombinedClickable( - onClick = onClick, - onLongClicked = { - haptic.performHapticFeedback( - HapticFeedbackType.LongPress - ) - onLongClick() - } - ) + .then( + if (enabled) { + Modifier + .noRippleCombinedClickable( + onClick = onClick, + onLongClicked = { + haptic.performHapticFeedback( + HapticFeedbackType.LongPress + ) + onLongClick() + } + ) + } else { + Modifier + } + ) ) } -@Composable -private fun ProfileMenuItem( - icon: ProfileIconView, - onClick: () -> Unit = {} -) { - when (icon) { - is ProfileIconView.Image -> { - Image( - painter = rememberAsyncImagePainter( - model = icon.url, - error = painterResource(id = R.drawable.ic_home_widget_space) - ), - contentDescription = "Custom image profile", - contentScale = ContentScale.Crop, - modifier = Modifier - .size(28.dp) - .clip(CircleShape) - .noRippleClickable { onClick() } - ) - } - - is ProfileIconView.Placeholder -> { - val name = icon.name - val nameFirstChar = if (name.isNullOrEmpty()) { - stringResource(id = R.string.account_default_name) - } else { - name.first().uppercaseChar().toString() - } - Box( - modifier = Modifier - .size(28.dp) - .clip(RoundedCornerShape(16.dp)) - .background(colorResource(id = R.color.shape_primary)) - .noRippleClickable { onClick() } - ) { - Text( - text = nameFirstChar, - style = MaterialTheme.typography.h3.copy( - color = colorResource(id = R.color.text_white), - fontSize = 12.sp - ), - modifier = Modifier.align(Alignment.Center) - ) - } - } - - else -> { - Box( - modifier = Modifier - .size(28.dp) - .clip(CircleShape) - .background(colorResource(id = R.color.shape_primary)) - .noRippleClickable { onClick() } - ) - } - } -} - - private enum class BottomNavigationItem(@DrawableRes val res: Int) { BACK(R.drawable.ic_nav_panel_back), MEMBERS(R.drawable.ic_nav_panel_members), + ADD_MEMBERS(R.drawable.ic_nav_panel_add_member), SEARCH(R.drawable.ic_nav_panel_search), ADD_DOC(R.drawable.ic_nav_panel_plus) } diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/toolbar/MainBottomToolbar.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/toolbar/MainBottomToolbar.kt index 91038da63e..9ca95d3ae4 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/toolbar/MainBottomToolbar.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/toolbar/MainBottomToolbar.kt @@ -6,8 +6,10 @@ import android.view.LayoutInflater import android.widget.LinearLayout import com.anytypeio.anytype.core_ui.databinding.WidgetMainBottomToolbarBinding import com.anytypeio.anytype.core_ui.reactive.clicks -import com.anytypeio.anytype.core_utils.ext.gone -import com.anytypeio.anytype.core_utils.ext.visible +import com.anytypeio.anytype.presentation.navigation.NavPanelState +import com.anytypeio.anytype.core_ui.R +import com.anytypeio.anytype.core_ui.common.DEFAULT_DISABLED_ALPHA +import com.anytypeio.anytype.core_ui.common.FULL_ALPHA class MainBottomToolbar @JvmOverloads constructor( context: Context, @@ -27,13 +29,55 @@ class MainBottomToolbar @JvmOverloads constructor( fun addDocClicks() = binding.btnAddDoc.clicks() fun shareClicks() = binding.btnShare.clicks() + fun setState(state: NavPanelState) { + when(state) { + is NavPanelState.Default -> { + setDefaultState(state) + } + NavPanelState.Init -> { + // Do nothing + } + } + } - fun setIsReadOnly(isReadOnly: Boolean) { - with(binding.btnAddDoc) { - if (isReadOnly) - gone() - else - visible() + private fun setDefaultState(state: NavPanelState.Default) { + setLeftButtonState(state) + setCreateButtonState(state) + } + + private fun setCreateButtonState(state: NavPanelState.Default) { + if (state.isCreateObjectButtonEnabled) { + binding.icAddDoc.alpha = FULL_ALPHA + binding.btnAddDoc.isEnabled = true + } else { + binding.icAddDoc.alpha = DEFAULT_DISABLED_ALPHA + binding.btnAddDoc.isEnabled = false + } + } + + private fun setLeftButtonState(state: NavPanelState.Default) { + when (val left = state.leftButtonState) { + is NavPanelState.LeftButtonState.AddMembers -> { + binding.icShare.setImageResource( + R.drawable.ic_nav_panel_add_member + ) + if (left.isActive) { + binding.icShare.alpha = FULL_ALPHA + } else { + binding.icShare.alpha = DEFAULT_DISABLED_ALPHA + } + } + + is NavPanelState.LeftButtonState.Comment -> { + + } + + NavPanelState.LeftButtonState.ViewMembers -> { + binding.icShare.setImageResource( + R.drawable.ic_nav_panel_add_member + ) + binding.icShare.alpha = FULL_ALPHA + } } } } \ No newline at end of file diff --git a/core-ui/src/main/res/drawable/ic_nav_panel_add_member.xml b/core-ui/src/main/res/drawable/ic_nav_panel_add_member.xml new file mode 100644 index 0000000000..a0394e3b38 --- /dev/null +++ b/core-ui/src/main/res/drawable/ic_nav_panel_add_member.xml @@ -0,0 +1,17 @@ + + + + + diff --git a/feature-all-content/src/main/java/com/anytypeio/anytype/feature_allcontent/ui/AllContentScreen.kt b/feature-all-content/src/main/java/com/anytypeio/anytype/feature_allcontent/ui/AllContentScreen.kt index a5b5c2ce08..ca9fb1b740 100644 --- a/feature-all-content/src/main/java/com/anytypeio/anytype/feature_allcontent/ui/AllContentScreen.kt +++ b/feature-all-content/src/main/java/com/anytypeio/anytype/feature_allcontent/ui/AllContentScreen.kt @@ -236,8 +236,6 @@ fun AllContentMainScreen( onGlobalSearchClicked = onGlobalSearchClicked, onAddDocClicked = onAddDocClicked, onCreateObjectLongClicked = onCreateObjectLongClicked, - onBackClicked = onBackClicked, - onBackLongClicked = onBackLongClicked, uiBottomMenu = uiBottomMenu, onShareButtonClicked = onShareButtonClicked ) @@ -340,16 +338,12 @@ fun BottomMenu( onGlobalSearchClicked: () -> Unit, onAddDocClicked: () -> Unit, onCreateObjectLongClicked: () -> Unit, - onBackClicked: () -> Unit, - onBackLongClicked: () -> Unit, onShareButtonClicked: () -> Unit ) { val isImeVisible = WindowInsets.ime.getBottom(LocalDensity.current) > 0 if (isImeVisible) return BottomNavigationMenu( modifier = modifier, - backClick = onBackClicked, - backLongClick = onBackLongClicked, searchClick = onGlobalSearchClicked, addDocClick = onAddDocClicked, addDocLongClick = onCreateObjectLongClicked, diff --git a/feature-date/src/main/java/com/anytypeio/anytype/feature_date/ui/MainScreen.kt b/feature-date/src/main/java/com/anytypeio/anytype/feature_date/ui/MainScreen.kt index 6b30e1a1d7..69f466dcb1 100644 --- a/feature-date/src/main/java/com/anytypeio/anytype/feature_date/ui/MainScreen.kt +++ b/feature-date/src/main/java/com/anytypeio/anytype/feature_date/ui/MainScreen.kt @@ -166,12 +166,6 @@ fun DateMainScreen( modifier = Modifier .align(Alignment.BottomCenter) .padding(bottom = 16.dp), - backClick = { - onDateEvent(DateEvent.NavigationWidget.OnBackClick) - }, - backLongClick = { - onDateEvent(DateEvent.NavigationWidget.OnBackLongClick) - }, searchClick = { onDateEvent(DateEvent.NavigationWidget.OnGlobalSearchClick) }, diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModel.kt index 100fc33e6a..3ced86e6e7 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModel.kt @@ -257,6 +257,7 @@ import com.anytypeio.anytype.presentation.editor.model.OnEditorDatePickerEvent.O import com.anytypeio.anytype.presentation.editor.model.OnEditorDatePickerEvent.OnTomorrowClick import com.anytypeio.anytype.presentation.extension.getFileDetailsForBlock import com.anytypeio.anytype.presentation.extension.getUrlForFileContent +import com.anytypeio.anytype.presentation.navigation.NavPanelState import com.anytypeio.anytype.presentation.objects.getCreateObjectParams import com.anytypeio.anytype.presentation.objects.getObjectTypeViewsForSBPage import com.anytypeio.anytype.presentation.objects.getProperType @@ -431,6 +432,8 @@ class EditorViewModel( */ val mentionDatePicker = MutableStateFlow(EditorDatePickerState.Hidden) + val navPanelState = permission.map { permission -> NavPanelState.fromPermission(permission) } + init { Timber.i("EditorViewModel, init") proceedWithObservingPermissions() diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/home/HomeScreenViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/home/HomeScreenViewModel.kt index 6e946b705c..d7c9fd67ba 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/home/HomeScreenViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/home/HomeScreenViewModel.kt @@ -89,6 +89,7 @@ import com.anytypeio.anytype.presentation.extension.sendReorderWidgetEvent import com.anytypeio.anytype.presentation.extension.sendSelectHomeTabEvent import com.anytypeio.anytype.presentation.home.Command.ChangeWidgetType.Companion.UNDEFINED_LAYOUT_CODE import com.anytypeio.anytype.presentation.navigation.DeepLinkToObjectDelegate +import com.anytypeio.anytype.presentation.navigation.NavPanelState import com.anytypeio.anytype.presentation.navigation.NavigationViewModel import com.anytypeio.anytype.presentation.objects.getCreateObjectParams import com.anytypeio.anytype.presentation.search.Subscriptions @@ -107,7 +108,6 @@ import com.anytypeio.anytype.presentation.widgets.DropDownMenuAction import com.anytypeio.anytype.presentation.widgets.LinkWidgetContainer import com.anytypeio.anytype.presentation.widgets.ListWidgetContainer import com.anytypeio.anytype.presentation.widgets.SpaceBinWidgetContainer -import com.anytypeio.anytype.presentation.widgets.SpaceChatWidgetContainer import com.anytypeio.anytype.presentation.widgets.SpaceWidgetContainer import com.anytypeio.anytype.presentation.widgets.TreePath import com.anytypeio.anytype.presentation.widgets.TreeWidgetBranchStateHolder @@ -186,7 +186,6 @@ class HomeScreenViewModel( private val analytics: Analytics, private val getWidgetSession: GetWidgetSession, private val saveWidgetSession: SaveWidgetSession, - private val spaceGradientProvider: SpaceGradientProvider, private val storeOfObjectTypes: StoreOfObjectTypes, private val objectWatcher: ObjectWatcher, private val spaceManager: SpaceManager, @@ -251,6 +250,8 @@ class HomeScreenViewModel( val hasEditAccess = userPermissions.map { it?.isOwnerOrEditor() == true } + val navPanelState = MutableStateFlow(NavPanelState.Init) + private val widgetObjectPipeline = spaceManager .observe() .distinctUntilChanged() @@ -361,6 +362,18 @@ class HomeScreenViewModel( proceedWithObservingDispatches() proceedWithSettingUpShortcuts() proceedWithViewStatePipeline() + proceedWithNavPanelState() + } + + private fun proceedWithNavPanelState() { + viewModelScope.launch { + userPermissions + .map { permission -> + NavPanelState.fromPermission(permission) + }.collect { + navPanelState.value = it + } + } } private fun proceedWithViewStatePipeline() { @@ -2261,7 +2274,6 @@ class HomeScreenViewModel( analytics = analytics, getWidgetSession = getWidgetSession, saveWidgetSession = saveWidgetSession, - spaceGradientProvider = spaceGradientProvider, storeOfObjectTypes = storeOfObjectTypes, storeOfRelations = storeOfRelations, objectWatcher = objectWatcher, diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/navigation/NavPanelState.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/navigation/NavPanelState.kt new file mode 100644 index 0000000000..409dcdf360 --- /dev/null +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/navigation/NavPanelState.kt @@ -0,0 +1,55 @@ +package com.anytypeio.anytype.presentation.navigation + +import com.anytypeio.anytype.core_models.multiplayer.SpaceMemberPermissions + +sealed class NavPanelState { + + data object Init : NavPanelState() + + data class Default( + val isCreateObjectButtonEnabled: Boolean, + val leftButtonState: LeftButtonState + ) : NavPanelState() + + sealed class LeftButtonState { + data object ViewMembers : LeftButtonState() + data class AddMembers(val isActive: Boolean): LeftButtonState() + data class Comment(val isActive: Boolean): LeftButtonState() + } + + companion object { + fun fromPermission(permission: SpaceMemberPermissions?) : NavPanelState { + return when(permission) { + SpaceMemberPermissions.READER -> { + Default( + isCreateObjectButtonEnabled = false, + leftButtonState = LeftButtonState.ViewMembers + ) + } + SpaceMemberPermissions.WRITER -> { + Default( + isCreateObjectButtonEnabled = true, + leftButtonState = LeftButtonState.ViewMembers + ) + } + SpaceMemberPermissions.OWNER -> { + Default( + isCreateObjectButtonEnabled = true, + leftButtonState = LeftButtonState.AddMembers( + isActive = true + ) + ) + } + SpaceMemberPermissions.NO_PERMISSIONS -> { + Default( + isCreateObjectButtonEnabled = false, + leftButtonState = LeftButtonState.ViewMembers + ) + } + else -> { + Init + } + } + } + } +} \ No newline at end of file diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/ObjectSetViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/ObjectSetViewModel.kt index 8780a2152d..fbefd671dd 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/ObjectSetViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/sets/ObjectSetViewModel.kt @@ -76,6 +76,7 @@ import com.anytypeio.anytype.presentation.navigation.AppNavigation import com.anytypeio.anytype.presentation.navigation.SupportNavigation import com.anytypeio.anytype.core_models.SupportedLayouts import com.anytypeio.anytype.core_models.TimeInMillis +import com.anytypeio.anytype.presentation.navigation.NavPanelState import com.anytypeio.anytype.presentation.objects.getCreateObjectParams import com.anytypeio.anytype.presentation.objects.isCreateObjectAllowed import com.anytypeio.anytype.presentation.objects.isTemplatesAllowed @@ -225,6 +226,8 @@ class ObjectSetViewModel( private val selectedTypeFlow: MutableStateFlow = MutableStateFlow(null) + val navPanelState = permission.map { permission -> NavPanelState.fromPermission(permission) } + init { Timber.i("ObjectSetViewModel, init") diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/widgets/collection/CollectionViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/widgets/collection/CollectionViewModel.kt index d2909059c9..a0af74f790 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/widgets/collection/CollectionViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/widgets/collection/CollectionViewModel.kt @@ -49,6 +49,7 @@ import com.anytypeio.anytype.presentation.extension.sendScreenHomeEvent import com.anytypeio.anytype.presentation.home.OpenObjectNavigation import com.anytypeio.anytype.presentation.home.navigation import com.anytypeio.anytype.presentation.navigation.DefaultObjectView +import com.anytypeio.anytype.presentation.navigation.NavPanelState import com.anytypeio.anytype.presentation.objects.ObjectAction import com.anytypeio.anytype.presentation.objects.getCreateObjectParams import com.anytypeio.anytype.presentation.objects.mapFileObjectToView @@ -119,6 +120,7 @@ class CollectionViewModel( init { Timber.i("CollectionViewModel, init, spaceId:${vmParams.spaceId.id}") proceedWithObservingPermissions() + proceedWithNavPanelState() val externalChannelEvents: Flow = spaceManager .observe() .flatMapLatest { config -> @@ -148,6 +150,8 @@ class CollectionViewModel( private var actionMode: ActionMode = ActionMode.Edit private var subscription: Subscription = Subscription.None + val navPanelState = MutableStateFlow(NavPanelState.Init) + val uiState: StateFlow> = combine(interactionMode, views, operationInProgress) { mode, views, operationInProgress -> Resultat.success( @@ -189,6 +193,17 @@ class CollectionViewModel( } } + private fun proceedWithNavPanelState() { + viewModelScope.launch { + permission + .map { permission -> + NavPanelState.fromPermission(permission) + }.collect { + navPanelState.value = it + } + } + } + private suspend fun objectTypes(): StateFlow> { val params = GetObjectTypes.Params( space = SpaceId(vmParams.spaceId.id), diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/home/HomeScreenViewModelTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/home/HomeScreenViewModelTest.kt index f501324e26..452465d588 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/home/HomeScreenViewModelTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/home/HomeScreenViewModelTest.kt @@ -197,9 +197,6 @@ class HomeScreenViewModelTest { @Mock lateinit var saveWidgetSession: SaveWidgetSession - @Mock - lateinit var spaceGradientProvider: SpaceGradientProvider - @Mock lateinit var getWidgetSession: GetWidgetSession @@ -3036,7 +3033,6 @@ class HomeScreenViewModelTest { analytics = analytics, getWidgetSession = getWidgetSession, saveWidgetSession = saveWidgetSession, - spaceGradientProvider = spaceGradientProvider, storeOfObjectTypes = storeOfObjectTypes, objectWatcher = objectWatcher, setWidgetActiveView = setWidgetActiveView,