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:
parent
b27d725530
commit
113e572e32
4 changed files with 100 additions and 84 deletions
|
@ -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}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue