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

DROID-3294 Editor | Fix | Do not allow to navigate from link-to-object to object from different space (#2034)

This commit is contained in:
Evgenii Kozlov 2025-01-25 15:09:08 +01:00 committed by konstantiniiv
parent b27d725530
commit 113e572e32
4 changed files with 100 additions and 84 deletions

View file

@ -3231,55 +3231,65 @@ class EditorViewModel(
proceedWithClearingFocus()
val details = orchestrator.stores.details.current()
val wrapper = ObjectWrapper.Basic(map = details.details[target]?.map ?: emptyMap())
when (wrapper.layout) {
ObjectType.Layout.BASIC,
ObjectType.Layout.NOTE,
ObjectType.Layout.TODO,
ObjectType.Layout.BOOKMARK -> {
proceedWithOpeningObject(target = target)
}
in SupportedLayouts.fileLayouts -> {
proceedWithOpeningObject(target = target)
}
ObjectType.Layout.PROFILE -> {
val identity = wrapper.getValue<Id>(Relations.IDENTITY_PROFILE_LINK)
if (identity != null) {
proceedWithOpeningObject(target = identity)
} else {
if (wrapper.spaceId != vmParams.space.id) {
sendToast("Cannot open object from another space from here.")
} else {
when (wrapper.layout) {
ObjectType.Layout.BASIC,
ObjectType.Layout.NOTE,
ObjectType.Layout.TODO,
ObjectType.Layout.BOOKMARK -> {
proceedWithOpeningObject(target = target)
}
}
ObjectType.Layout.SET, ObjectType.Layout.COLLECTION -> {
val space = wrapper.spaceId
if (space != null) {
proceedWithOpeningDataViewObject(
target = target,
space = SpaceId(checkNotNull(wrapper.spaceId))
in SupportedLayouts.fileLayouts -> {
proceedWithOpeningObject(target = target)
}
ObjectType.Layout.PROFILE -> {
val identity = wrapper.getValue<Id>(Relations.IDENTITY_PROFILE_LINK)
if (identity != null) {
proceedWithOpeningObject(target = identity)
} else {
proceedWithOpeningObject(target = target)
}
}
ObjectType.Layout.SET, ObjectType.Layout.COLLECTION -> {
val space = wrapper.spaceId
if (space != null) {
proceedWithOpeningDataViewObject(
target = target,
space = SpaceId(checkNotNull(wrapper.spaceId))
)
}
}
ObjectType.Layout.DATE -> {
navigate(
EventWrapper(
OpenDateObject(
objectId = target,
space = vmParams.space.id
)
)
)
}
}
ObjectType.Layout.DATE -> {
navigate(
EventWrapper(
OpenDateObject(
objectId = target,
space = vmParams.space.id
ObjectType.Layout.PARTICIPANT -> {
navigate(
EventWrapper(
OpenParticipant(
objectId = target,
space = vmParams.space.id
)
)
)
)
}
ObjectType.Layout.PARTICIPANT -> {
navigate(
EventWrapper(
OpenParticipant(
objectId = target,
space = vmParams.space.id
)
)
)
}
else -> {
sendToast("Cannot open object with layout: ${wrapper.layout}")
}
else -> {
sendToast("Cannot open object with layout: ${wrapper.layout}")
}
}
}
}

View file

@ -117,25 +117,7 @@ class CollectionViewModel(
private val permission = MutableStateFlow(userPermissionProvider.get(vmParams.spaceId))
init {
Timber.i("CollectionViewModel, init, spaceId:${vmParams.spaceId.id}")
proceedWithObservingPermissions()
proceedWithNavPanelState()
val externalChannelEvents: Flow<Payload> = spaceManager
.observe()
.flatMapLatest { config ->
val params = InterceptEvents.Params(config.home)
interceptEvents.build(params).map {
Payload(
context = config.home,
events = it
)
}
}
val internalChannelEvents = objectPayloadDispatcher.flow()
payloads = merge(externalChannelEvents, internalChannelEvents)
}
val navPanelState = MutableStateFlow<NavPanelState>(NavPanelState.Init)
val commands = MutableSharedFlow<Command>()
@ -150,8 +132,6 @@ 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(
@ -183,6 +163,26 @@ class CollectionViewModel(
initialValue = Resultat.loading()
)
init {
Timber.i("CollectionViewModel, init, spaceId:${vmParams.spaceId.id}")
proceedWithObservingPermissions()
proceedWithNavPanelState()
val externalChannelEvents: Flow<Payload> = spaceManager
.observe()
.flatMapLatest { config ->
val params = InterceptEvents.Params(config.home)
interceptEvents.build(params).map {
Payload(
context = config.home,
events = it
)
}
}
val internalChannelEvents = objectPayloadDispatcher.flow()
payloads = merge(externalChannelEvents, internalChannelEvents)
}
private fun proceedWithObservingPermissions() {
viewModelScope.launch {
userPermissionProvider

View file

@ -284,7 +284,8 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
target to Block.Fields(
mapOf(
Relations.ID to target,
Relations.LAYOUT to ObjectType.Layout.BASIC.code.toDouble()
Relations.LAYOUT to ObjectType.Layout.BASIC.code.toDouble(),
Relations.SPACE_ID to defaultSpace
)
)
)

View file

@ -6,6 +6,9 @@ import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.domain.base.Either
import com.anytypeio.anytype.domain.base.ResultInteractor
import com.anytypeio.anytype.domain.base.Resultat
import com.anytypeio.anytype.domain.`object`.SetObjectDetails
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
import com.anytypeio.anytype.test_utils.MockDataFactory
@ -28,9 +31,8 @@ class ObjectSetRecordViewModelTest {
val coroutineTestRule = CoroutinesTestRule()
@Mock
lateinit var setObjectDetails: UpdateDetail
lateinit var setObjectDetails: SetObjectDetails
private val ctx: Id = MockDataFactory.randomUuid()
private val defaultSpace = MockDataFactory.randomUuid()
private val obj = ObjectWrapper.Basic(
mapOf(
@ -53,10 +55,11 @@ class ObjectSetRecordViewModelTest {
val input = MockDataFactory.randomString()
val params = UpdateDetail.Params(
target = obj.id,
key = Relations.NAME,
value = input
val params = SetObjectDetails.Params(
ctx = obj.id,
details = mapOf(
Relations.NAME to input
)
)
stubSetObjectDetails(params)
@ -70,7 +73,7 @@ class ObjectSetRecordViewModelTest {
)
verifyBlocking(setObjectDetails, times(1)) {
invoke(params)
async(params)
}
}
@ -81,10 +84,11 @@ class ObjectSetRecordViewModelTest {
val input = MockDataFactory.randomString()
val params = UpdateDetail.Params(
target = obj.id,
key = Relations.NAME,
value = input
val params = SetObjectDetails.Params(
ctx = obj.id,
details = mapOf(
Relations.NAME to input
)
)
stubSetObjectDetails(params)
@ -109,7 +113,7 @@ class ObjectSetRecordViewModelTest {
}
verifyBlocking(setObjectDetails, times(1)) {
invoke(params)
async(params)
}
}
@ -120,10 +124,11 @@ class ObjectSetRecordViewModelTest {
val emptyInput = ""
val params = UpdateDetail.Params(
target = obj.id,
key = Relations.NAME,
value = emptyInput
val params = SetObjectDetails.Params(
ctx = obj.id,
details = mapOf(
Relations.NAME to emptyInput
)
)
stubSetObjectDetails(params)
@ -155,7 +160,7 @@ class ObjectSetRecordViewModelTest {
)
private fun stubSetObjectDetails(
params: UpdateDetail.Params,
params: SetObjectDetails.Params,
payload: Payload = Payload(
context = MockDataFactory.randomUuid(),
events = emptyList()
@ -163,8 +168,8 @@ class ObjectSetRecordViewModelTest {
) {
setObjectDetails.stub {
onBlocking {
invoke(params)
} doReturn Either.Right(payload)
async(params)
} doReturn Resultat.Success(payload)
}
}
}