1
0
Fork 0
mirror of https://github.com/anyproto/anytype-kotlin.git synced 2025-06-08 05:47:05 +09:00

DROID-3281 Objects | Enhancement | Always show three-dots menu, but apply space member permissions - part 2 (#2023)

This commit is contained in:
Evgenii Kozlov 2025-01-22 22:38:32 +01:00 committed by Evgenii Kozlov
parent 21393f4ec3
commit 0114a4f968
15 changed files with 64 additions and 30 deletions

View file

@ -1009,6 +1009,7 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
isArchived = command.isArchived,
isFavorite = command.isFavorite,
isLocked = command.isLocked,
isReadOnly = command.isReadOnly,
fromName = getFrom(),
isTemplate = command.isTemplate
)

View file

@ -51,6 +51,7 @@ abstract class ObjectMenuBaseFragment :
private val isArchived get() = arg<Boolean>(IS_ARCHIVED_KEY)
private val isFavorite get() = arg<Boolean>(IS_FAVORITE_KEY)
private val isLocked get() = arg<Boolean>(IS_LOCKED_KEY)
private val isReadOnly get() = arg<Boolean>(IS_READ_ONLY_KEY)
private val isTemplate get() = argOrNull<Boolean>(IS_TEMPLATE_KEY)
private val fromName get() = argOrNull<String?>(FROM_NAME)
@ -106,7 +107,8 @@ abstract class ObjectMenuBaseFragment :
isArchived = isArchived,
isFavorite = isFavorite,
isLocked = isLocked,
isTemplate = isTemplate ?: false
isTemplate = isTemplate == true,
isReadOnly = isReadOnly
)
}
@ -354,6 +356,7 @@ abstract class ObjectMenuBaseFragment :
const val IS_ARCHIVED_KEY = "arg.doc-menu-bottom-sheet.is-archived"
const val IS_FAVORITE_KEY = "arg.doc-menu-bottom-sheet.is-favorite"
const val IS_LOCKED_KEY = "arg.doc-menu-bottom-sheet.is-locked"
const val IS_READ_ONLY_KEY = "arg.doc-menu-bottom-sheet.is-read-only"
const val FROM_NAME = "arg.doc-menu-bottom-sheet.from-name"
const val COMING_SOON_MSG = "Coming soon..."
const val IS_TEMPLATE_KEY = "arg.doc-menu-bottom-sheet.is-template"

View file

@ -55,7 +55,8 @@ class ObjectMenuFragment : ObjectMenuBaseFragment() {
isFavorite: Boolean,
isLocked: Boolean,
fromName: String?,
isTemplate: Boolean
isTemplate: Boolean,
isReadOnly: Boolean
) = bundleOf(
CTX_KEY to ctx,
SPACE_KEY to space,
@ -63,7 +64,8 @@ class ObjectMenuFragment : ObjectMenuBaseFragment() {
IS_FAVORITE_KEY to isFavorite,
IS_LOCKED_KEY to isLocked,
FROM_NAME to fromName,
IS_TEMPLATE_KEY to isTemplate
IS_TEMPLATE_KEY to isTemplate,
IS_READ_ONLY_KEY to isReadOnly
)
}
}

View file

@ -1001,7 +1001,8 @@ open class ObjectSetFragment :
ObjectMenuBaseFragment.IS_FAVORITE_KEY to command.isFavorite,
ObjectMenuBaseFragment.IS_LOCKED_KEY to false,
ObjectMenuBaseFragment.FROM_NAME to title.text.toString(),
ObjectMenuBaseFragment.IS_LOCKED_KEY to command.isLocked
ObjectMenuBaseFragment.IS_LOCKED_KEY to command.isReadOnly,
ObjectMenuBaseFragment.IS_READ_ONLY_KEY to command.isReadOnly
)
)
}

View file

@ -247,6 +247,7 @@ import com.anytypeio.anytype.presentation.objects.ObjectTypeView
import com.anytypeio.anytype.core_models.SupportedLayouts
import com.anytypeio.anytype.core_models.TimeInMillis
import com.anytypeio.anytype.core_models.TimeInSeconds
import com.anytypeio.anytype.core_models.multiplayer.SpaceMemberPermissions
import com.anytypeio.anytype.presentation.editor.ControlPanelMachine.Event.SAM.*
import com.anytypeio.anytype.presentation.editor.editor.Intent.Clipboard.*
import com.anytypeio.anytype.presentation.editor.editor.ext.isAllowedToShowTypesWidget
@ -1553,6 +1554,9 @@ class EditorViewModel(
sendToast("Space not found")
return
}
val isReadOnly = permission.value == null
|| permission.value == SpaceMemberPermissions.NO_PERMISSIONS
|| permission.value == SpaceMemberPermissions.READER
when {
isTemplate -> {
dispatch(
@ -1562,7 +1566,8 @@ class EditorViewModel(
isArchived = false,
isFavorite = false,
isLocked = false,
isTemplate = true
isTemplate = true,
isReadOnly = isReadOnly
)
)
}
@ -1573,7 +1578,8 @@ class EditorViewModel(
space = space,
isArchived = details[context]?.isArchived ?: false,
isFavorite = details[context]?.isFavorite ?: false,
isLocked = mode == EditorMode.Locked || mode == EditorMode.Read,
isLocked = mode == EditorMode.Locked,
isReadOnly = isReadOnly,
isTemplate = isObjectTemplate()
)
)

View file

@ -67,6 +67,7 @@ sealed class Command {
val isArchived: Boolean,
val isFavorite: Boolean,
val isLocked: Boolean,
val isReadOnly: Boolean,
val isTemplate: Boolean
) : Command()

View file

@ -33,5 +33,5 @@ interface ObjectMenuOptionsProvider {
}
}
fun provide(ctx: Id, isLocked: Boolean): Flow<Options>
fun provide(ctx: Id, isLocked: Boolean, isReadOnly: Boolean): Flow<Options>
}

View file

@ -31,9 +31,14 @@ class ObjectMenuOptionsProviderImpl(
ObjectWrapper.Basic(fields.map).layout
}
override fun provide(ctx: Id, isLocked: Boolean): Flow<Options> {
override fun provide(ctx: Id, isLocked: Boolean, isReadOnly: Boolean): Flow<Options> {
return combine(observeLayout(ctx), restrictions) { layout, restrictions ->
createOptions(layout, restrictions, isLocked)
createOptions(
layout = layout,
restrictions = restrictions,
isLocked = isLocked,
isReadOnly = isReadOnly
)
}
}
@ -41,10 +46,11 @@ class ObjectMenuOptionsProviderImpl(
layout: ObjectType.Layout?,
restrictions: List<ObjectRestriction>,
isLocked: Boolean,
isReadOnly: Boolean
): Options {
val hasIcon = !isLocked
val hasCover = !isLocked
val hasLayout = !isLocked && !restrictions.contains(ObjectRestriction.LAYOUT_CHANGE)
val hasIcon = !isLocked && !isReadOnly
val hasCover = !isLocked && !isReadOnly
val hasLayout = !isLocked && !restrictions.contains(ObjectRestriction.LAYOUT_CHANGE) && !isReadOnly
val options = if (layout != null) {
when (layout) {
ObjectType.Layout.PARTICIPANT -> Options.ALL.copy(
@ -72,7 +78,7 @@ class ObjectMenuOptionsProviderImpl(
hasCover = hasCover,
hasLayout = false,
hasDiagnosticsVisibility = true,
hasHistory = !isLocked
hasHistory = !isLocked && !isReadOnly
)
}
ObjectType.Layout.BASIC,
@ -82,7 +88,7 @@ class ObjectMenuOptionsProviderImpl(
hasCover = hasCover,
hasLayout = hasLayout,
hasDiagnosticsVisibility = true,
hasHistory = !isLocked
hasHistory = !isLocked && !isReadOnly
)
ObjectType.Layout.TODO -> Options(
hasIcon = false,
@ -90,7 +96,7 @@ class ObjectMenuOptionsProviderImpl(
hasLayout = hasLayout,
hasRelations = true,
hasDiagnosticsVisibility = true,
hasHistory = !isLocked
hasHistory = !isLocked && !isReadOnly
)
ObjectType.Layout.NOTE -> Options(
@ -99,7 +105,7 @@ class ObjectMenuOptionsProviderImpl(
hasLayout = hasLayout,
hasRelations = true,
hasDiagnosticsVisibility = true,
hasHistory = !isLocked
hasHistory = !isLocked && !isReadOnly
)
else -> Options.NONE.copy(
hasDiagnosticsVisibility = true

View file

@ -108,20 +108,20 @@ class ObjectMenuViewModel(
isArchived: Boolean,
isFavorite: Boolean,
isTemplate: Boolean,
isLocked: Boolean
isLocked: Boolean,
isReadOnly: Boolean
): List<ObjectAction> = buildList {
val wrapper = ObjectWrapper.Basic(storage.details.current().details[ctx]?.map.orEmpty())
val layout = wrapper.layout
if (isLocked) {
if (isReadOnly) {
add(ObjectAction.COPY_LINK)
add(ObjectAction.SEARCH_ON_PAGE)
if (layout in fileLayouts) {
add(ObjectAction.DOWNLOAD_FILE)
}
} else {
if (!isTemplate) {
if (isFavorite) {
add(ObjectAction.REMOVE_FROM_FAVOURITE)

View file

@ -111,18 +111,22 @@ abstract class ObjectMenuViewModelBase(
isFavorite: Boolean,
isArchived: Boolean,
isLocked: Boolean,
isTemplate: Boolean
isTemplate: Boolean,
isReadOnly: Boolean
) {
Timber.d("ObjectMenuViewModelBase, onStart, ctx:[$ctx], isFavorite:[$isFavorite], isArchived:[$isArchived], isLocked:[$isLocked]")
Timber.d("ObjectMenuViewModelBase, onStart, ctx:[$ctx], isFavorite:[$isFavorite], isArchived:[$isArchived], isLocked:[$isLocked], isReadOnly: [$isReadOnly]")
actions.value = buildActions(
ctx = ctx,
isArchived = isArchived,
isFavorite = isFavorite,
isTemplate = isTemplate,
isLocked = isLocked
isLocked = isLocked,
isReadOnly = isReadOnly
)
jobs += viewModelScope.launch {
menuOptionsProvider.provide(ctx, isLocked).collect(_options)
menuOptionsProvider
.provide(ctx = ctx, isLocked = isLocked, isReadOnly = isReadOnly)
.collect(_options)
}
}
@ -133,7 +137,8 @@ abstract class ObjectMenuViewModelBase(
isArchived: Boolean,
isFavorite: Boolean,
isTemplate: Boolean = false,
isLocked: Boolean
isLocked: Boolean,
isReadOnly: Boolean
): List<ObjectAction>
protected fun proceedWithRemovingFromFavorites(ctx: Id) {

View file

@ -180,9 +180,10 @@ class ObjectSetMenuViewModel(
isArchived: Boolean,
isFavorite: Boolean,
isTemplate: Boolean,
isLocked: Boolean
isLocked: Boolean,
isReadOnly: Boolean
): List<ObjectAction> = buildList {
if (!isLocked) {
if (!isReadOnly) {
if (isArchived) {
add(ObjectAction.RESTORE)
} else {

View file

@ -12,7 +12,7 @@ sealed class ObjectSetCommand {
val space: Id,
val isArchived: Boolean,
val isFavorite: Boolean,
val isLocked: Boolean
val isReadOnly: Boolean
) : Modal()
data class OpenSettings(

View file

@ -1252,7 +1252,7 @@ class ObjectSetViewModel(
space = space,
isArchived = state.details[vmParams.ctx]?.isArchived ?: false,
isFavorite = state.details[vmParams.ctx]?.isFavorite ?: false,
isLocked = !isOwnerOrEditor
isReadOnly = !isOwnerOrEditor
)
)
} else {

View file

@ -101,7 +101,8 @@ class EditorMenuTest : EditorPresentationTestSetup() {
isLocked = false,
isTemplate = false,
space = defaultSpace,
ctx = root
ctx = root,
isReadOnly = false
)
}
}
@ -156,6 +157,7 @@ class EditorMenuTest : EditorPresentationTestSetup() {
isArchived = false,
isFavorite = false,
isLocked = false,
isReadOnly = false,
isTemplate = false,
space = space,
ctx = root
@ -236,6 +238,7 @@ class EditorMenuTest : EditorPresentationTestSetup() {
value.peekContent() == Command.OpenDocumentMenu(
isFavorite = false,
isLocked = false,
isReadOnly = false,
isArchived = false,
isTemplate = false,
space = space,

View file

@ -119,9 +119,14 @@ class ObjectMenuOptionsProviderImplTest {
private fun assertOptions(
expected: ObjectMenuOptionsProvider.Options,
isLocked: Boolean = false,
isReadOnly: Boolean = false
) {
runTest {
provider.provide(objectId, isLocked).test {
provider.provide(
objectId,
isLocked = isLocked,
isReadOnly = isReadOnly
).test {
assertEquals(
expected = expected,
actual = awaitItem()