mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-3279 Navigation | Fix | Nav panel fixes (#2032)
This commit is contained in:
parent
151e0a415e
commit
2cff1f68fe
17 changed files with 341 additions and 137 deletions
|
@ -851,13 +851,9 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(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)
|
||||
|
||||
|
|
|
@ -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<WidgetView>,
|
||||
|
@ -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
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
package com.anytypeio.anytype.core_ui.common
|
||||
|
||||
const val DEFAULT_DISABLED_ALPHA = 0.5f
|
||||
const val FULL_ALPHA = 1f
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
17
core-ui/src/main/res/drawable/ic_nav_panel_add_member.xml
Normal file
17
core-ui/src/main/res/drawable/ic_nav_panel_add_member.xml
Normal file
|
@ -0,0 +1,17 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="33dp"
|
||||
android:viewportWidth="32"
|
||||
android:viewportHeight="33">
|
||||
<path
|
||||
android:pathData="M10.25,10.813a3.75,4 0,1 0,7.5 0a3.75,4 0,1 0,-7.5 0z"
|
||||
android:fillColor="@color/glyph_active" />
|
||||
<path
|
||||
android:pathData="M16.826,24.313C16.605,23.687 16.484,23.014 16.484,22.313C16.484,20.482 17.304,18.843 18.597,17.742C17.293,16.841 15.709,16.313 14,16.313C10.064,16.313 6.788,19.115 6.084,22.821C5.93,23.635 6.616,24.313 7.445,24.313H16.826Z"
|
||||
android:fillColor="@color/glyph_active"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M22.484,26.813C24.978,26.813 27,24.791 27,22.297C27,19.803 24.978,17.781 22.484,17.781C19.99,17.781 17.969,19.803 17.969,22.297C17.969,24.791 19.99,26.813 22.484,26.813ZM21.984,20.047C21.984,19.771 22.208,19.547 22.484,19.547C22.76,19.547 22.984,19.771 22.984,20.047V21.797H24.734C25.01,21.797 25.234,22.021 25.234,22.297C25.234,22.573 25.01,22.797 24.734,22.797H22.984V24.547C22.984,24.823 22.76,25.047 22.484,25.047C22.208,25.047 21.984,24.823 21.984,24.547V22.797H20.234C19.958,22.797 19.734,22.573 19.734,22.297C19.734,22.021 19.958,21.797 20.234,21.797H21.984V20.047Z"
|
||||
android:fillColor="@color/glyph_active"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
},
|
||||
|
|
|
@ -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>(EditorDatePickerState.Hidden)
|
||||
|
||||
val navPanelState = permission.map { permission -> NavPanelState.fromPermission(permission) }
|
||||
|
||||
init {
|
||||
Timber.i("EditorViewModel, init")
|
||||
proceedWithObservingPermissions()
|
||||
|
|
|
@ -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>(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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<ObjectWrapper.Type?> = MutableStateFlow(null)
|
||||
|
||||
val navPanelState = permission.map { permission -> NavPanelState.fromPermission(permission) }
|
||||
|
||||
init {
|
||||
Timber.i("ObjectSetViewModel, init")
|
||||
|
||||
|
|
|
@ -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<Payload> = 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>(NavPanelState.Init)
|
||||
|
||||
val uiState: StateFlow<Resultat<CollectionUiState>> =
|
||||
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<List<ObjectWrapper.Type>> {
|
||||
val params = GetObjectTypes.Params(
|
||||
space = SpaceId(vmParams.spaceId.id),
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue