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

DROID-3001 App | Tech | Refactoring - provide space (#1764)

This commit is contained in:
Evgenii Kozlov 2024-11-05 11:30:56 +01:00 committed by Evgenii Kozlov
parent 3536f4535b
commit d60a10f115
30 changed files with 351 additions and 132 deletions

View file

@ -332,7 +332,7 @@ abstract class TestObjectSetSetup {
relations: List<Relation> = emptyList()
) {
repo.stub {
onBlocking { openObjectSet(ctx) } doReturn Result.Success(
onBlocking { openObjectSet(ctx, SpaceId(defaultSpace)) } doReturn Result.Success(
Payload(
context = ctx,
events = listOf(
@ -355,7 +355,7 @@ abstract class TestObjectSetSetup {
relations: List<Relation> = emptyList()
) {
repo.stub {
onBlocking { openObjectSet(ctx) } doReturn Result.Success(
onBlocking { openObjectSet(ctx, SpaceId(defaultSpace)) } doReturn Result.Success(
Payload(
context = ctx,
events = listOf(

View file

@ -12,10 +12,12 @@ import androidx.recyclerview.widget.LinearLayoutManager
import com.anytypeio.anytype.R
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Url
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_ui.features.editor.BlockAdapter
import com.anytypeio.anytype.core_ui.features.editor.DragAndDropAdapterDelegate
import com.anytypeio.anytype.core_ui.tools.ClipboardInterceptor
import com.anytypeio.anytype.core_utils.ext.arg
import com.anytypeio.anytype.core_utils.ext.argOrNull
import com.anytypeio.anytype.core_utils.ext.subscribe
import com.anytypeio.anytype.core_utils.ui.BaseFragment
import com.anytypeio.anytype.databinding.FragmentTemplateBinding
@ -27,7 +29,8 @@ import javax.inject.Inject
class TemplateFragment : BaseFragment<FragmentTemplateBinding>(R.layout.fragment_template),
ClipboardInterceptor, View.OnDragListener {
private val ctx: String get() = arg(CTX_KEY)
private val ctx: Id get() = arg(CTX_KEY)
private val space: Id get() = arg<Id>(SPACE_KEY)
@Inject
lateinit var factory: TemplateViewModel.Factory
@ -80,7 +83,7 @@ class TemplateFragment : BaseFragment<FragmentTemplateBinding>(R.layout.fragment
override fun onStart() {
super.onStart()
vm.onStart(ctx)
vm.onStart(ctx = ctx, space = SpaceId(space))
}
override fun onResume() {
@ -110,10 +113,14 @@ class TemplateFragment : BaseFragment<FragmentTemplateBinding>(R.layout.fragment
override fun onDrag(v: View?, event: DragEvent?) = false
companion object {
fun new(ctx: Id) = TemplateFragment().apply {
arguments = bundleOf(CTX_KEY to ctx)
fun new(ctx: Id, space: SpaceId) = TemplateFragment().apply {
arguments = bundleOf(
CTX_KEY to ctx,
SPACE_KEY to space.id
)
}
const val CTX_KEY = "arg.template.ctx"
private const val CTX_KEY = "arg.template.ctx"
private const val SPACE_KEY = "arg.template.space"
}
}

View file

@ -36,6 +36,7 @@ import com.anytypeio.anytype.core_models.membership.MembershipTierData
import com.anytypeio.anytype.core_models.multiplayer.SpaceInviteLink
import com.anytypeio.anytype.core_models.multiplayer.SpaceInviteView
import com.anytypeio.anytype.core_models.multiplayer.SpaceMemberPermissions
import com.anytypeio.anytype.core_models.primitives.Space
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.data.auth.exception.AnytypeNeedsUpgradeException
import com.anytypeio.anytype.data.auth.exception.NotFoundObjectException
@ -55,40 +56,41 @@ class BlockDataRepository(
private val logger: Logger
) : BlockRepository {
override suspend fun openObject(id: Id): ObjectView = remote.openObject(id = id)
override suspend fun getObject(id: Id): ObjectView = remote.getObject(id = id)
override suspend fun openObject(id: Id, space: SpaceId): ObjectView = remote.openObject(id = id, space = space)
override suspend fun getObject(id: Id, space: SpaceId): ObjectView = remote.getObject(id = id, space = space)
override suspend fun openObjectPreview(id: Id): Result<Payload> = try {
Result.Success(remote.openObjectPreview(id))
override suspend fun openObjectPreview(id: Id, space: SpaceId): Result<Payload> = try {
Result.Success(remote.openObjectPreview(id = id, space = space))
} catch (e: AnytypeNeedsUpgradeException) {
Result.Failure(Error.BackwardCompatibility)
} catch (e: NotFoundObjectException) {
Result.Failure(Error.NotFoundObject)
}
override suspend fun openPage(id: String): Result<Payload> = try {
Result.Success(remote.openPage(id))
override suspend fun openPage(id: String, space: SpaceId): Result<Payload> = try {
Result.Success(
remote.openPage(
id = id,
space = space
)
)
} catch (e: AnytypeNeedsUpgradeException) {
Result.Failure(Error.BackwardCompatibility)
} catch (e: NotFoundObjectException) {
Result.Failure(Error.NotFoundObject)
}
override suspend fun openProfile(id: String): Payload =
remote.openProfile(id)
override suspend fun openProfile(id: String, space: SpaceId): Payload =
remote.openProfile(id = id, space = space)
override suspend fun openObjectSet(id: String): Result<Payload> = try {
Result.Success(remote.openObjectSet(id))
override suspend fun openObjectSet(id: String, space: SpaceId): Result<Payload> = try {
Result.Success(remote.openObjectSet(id = id, space = space))
} catch (e: AnytypeNeedsUpgradeException) {
Result.Failure(Error.BackwardCompatibility)
} catch (e: NotFoundObjectException) {
Result.Failure(Error.NotFoundObject)
}
override suspend fun closeDashboard(id: String) {
remote.closeDashboard(id)
}
override suspend fun updateAlignment(
command: Command.UpdateAlignment
): Payload = remote.updateAlignment(command)
@ -103,8 +105,8 @@ class BlockDataRepository(
command: Command.CreateBlockLinkWithObject
): CreateBlockLinkWithObjectResult = remote.createBlockLinkWithObject(command)
override suspend fun closePage(id: String) {
remote.closePage(id)
override suspend fun closePage(id: String, space: Space) {
remote.closePage(id = id, space = space)
}
override suspend fun updateDocumentTitle(

View file

@ -36,6 +36,7 @@ import com.anytypeio.anytype.core_models.membership.MembershipTierData
import com.anytypeio.anytype.core_models.multiplayer.SpaceInviteLink
import com.anytypeio.anytype.core_models.multiplayer.SpaceInviteView
import com.anytypeio.anytype.core_models.multiplayer.SpaceMemberPermissions
import com.anytypeio.anytype.core_models.primitives.Space
import com.anytypeio.anytype.core_models.primitives.SpaceId
interface BlockRemote {
@ -64,15 +65,14 @@ interface BlockRemote {
command: Command.CreateBlockLinkWithObject
): CreateBlockLinkWithObjectResult
suspend fun openObject(id: Id): ObjectView
suspend fun getObject(id: Id): ObjectView
suspend fun openObject(id: Id, space: SpaceId): ObjectView
suspend fun getObject(id: Id, space: SpaceId): ObjectView
suspend fun openPage(id: String): Payload
suspend fun openProfile(id: String): Payload
suspend fun openObjectSet(id: String): Payload
suspend fun openObjectPreview(id: Id): Payload
suspend fun closePage(id: String)
suspend fun closeDashboard(id: String)
suspend fun openPage(id: String, space: SpaceId): Payload
suspend fun openProfile(id: String, space: SpaceId): Payload
suspend fun openObjectSet(id: String, space: SpaceId): Payload
suspend fun openObjectPreview(id: Id, space: SpaceId): Payload
suspend fun closePage(id: String, space: Space)
suspend fun setDocumentEmojiIcon(command: Command.SetDocumentEmojiIcon): Payload
suspend fun setDocumentImageIcon(command: Command.SetDocumentImageIcon): Payload
suspend fun setDocumentCoverColor(ctx: String, color: String): Payload

View file

@ -36,6 +36,7 @@ import com.anytypeio.anytype.core_models.membership.MembershipTierData
import com.anytypeio.anytype.core_models.multiplayer.SpaceInviteLink
import com.anytypeio.anytype.core_models.multiplayer.SpaceInviteView
import com.anytypeio.anytype.core_models.multiplayer.SpaceMemberPermissions
import com.anytypeio.anytype.core_models.primitives.Space
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.domain.base.Result
import com.anytypeio.anytype.domain.block.interactor.sets.CreateObjectSet
@ -104,20 +105,19 @@ interface BlockRepository {
suspend fun setRelationKey(command: Command.SetRelationKey): Payload
suspend fun openObject(id: Id) : ObjectView
suspend fun getObject(id: Id) : ObjectView
suspend fun openObject(id: Id, space: SpaceId) : ObjectView
suspend fun getObject(id: Id, space: SpaceId) : ObjectView
@Deprecated("To be deleted")
suspend fun openObjectPreview(id: Id): Result<Payload>
suspend fun openObjectPreview(id: Id, space: SpaceId): Result<Payload>
@Deprecated("To be deleted")
suspend fun openPage(id: String): Result<Payload>
suspend fun openPage(id: String, space: SpaceId): Result<Payload>
@Deprecated("To be deleted")
suspend fun openProfile(id: String): Payload
suspend fun openProfile(id: String, space: SpaceId): Payload
@Deprecated("To be deleted")
suspend fun openObjectSet(id: String): Result<Payload>
suspend fun openObjectSet(id: String, space: SpaceId): Result<Payload>
suspend fun closePage(id: String)
suspend fun closeDashboard(id: String)
suspend fun closePage(id: String, space: Space)
/**
* Upload media or file block by path or url.

View file

@ -2,6 +2,7 @@ package com.anytypeio.anytype.domain.`object`
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectView
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.base.ResultInteractor
import com.anytypeio.anytype.domain.block.repo.BlockRepository
@ -13,6 +14,14 @@ import com.anytypeio.anytype.domain.block.repo.BlockRepository
class GetObject(
private val repo: BlockRepository,
dispatchers: AppCoroutineDispatchers
) : ResultInteractor<Id, ObjectView>(dispatchers.io) {
override suspend fun doWork(params: Id): ObjectView = repo.getObject(params)
) : ResultInteractor<GetObject.Params, ObjectView>(dispatchers.io) {
override suspend fun doWork(params: Params): ObjectView = repo.getObject(
id = params.target,
space = params.space
)
data class Params(
val target: Id,
val space: SpaceId
)
}

View file

@ -16,7 +16,10 @@ class OpenObject @Inject constructor(
dispatchers: AppCoroutineDispatchers
) : ResultInteractor<OpenObject.Params, ObjectView>(dispatchers.io) {
override suspend fun doWork(params: Params) = repo.openObject(params.obj).also {
override suspend fun doWork(params: Params) = repo.openObject(
id = params.obj,
space = params.spaceId
).also {
if (params.saveAsLastOpened) {
val obj = ObjectWrapper.Basic(it.details[params.obj].orEmpty())
val space = obj.spaceId
@ -29,7 +32,7 @@ class OpenObject @Inject constructor(
}
else {
val givenSpace = params.spaceId
if (givenSpace != null && givenSpace.id.isNotEmpty()) {
if (givenSpace.id.isNotEmpty()) {
settings.clearLastOpenedObject(
SpaceId(givenSpace.id)
)
@ -40,6 +43,6 @@ class OpenObject @Inject constructor(
data class Params(
val obj: Id,
val saveAsLastOpened: Boolean = true,
val spaceId: SpaceId? = null
val spaceId: SpaceId
)
}

View file

@ -3,6 +3,7 @@ package com.anytypeio.anytype.domain.objects
import com.anytypeio.anytype.core_models.Event
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectView
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.event.interactor.EventChannel
import javax.inject.Inject
@ -16,17 +17,17 @@ class ObjectWatcher @Inject constructor(
private val events: EventChannel,
private val reducer: Reducer
) {
fun watch(target: Id): Flow<ObjectView> = flow {
fun watch(target: Id, space: SpaceId): Flow<ObjectView> = flow {
emitAll(
events.observeEvents(context = target).scan(
initial = repo.openObject(target),
initial = repo.openObject(id = target, space = space),
operation = reducer
)
)
}
suspend fun unwatch(target: Id) {
repo.closePage(target)
suspend fun unwatch(target: Id, space: SpaceId) {
repo.closePage(id = target, space = space)
}
interface Reducer : (ObjectView, List<Event>) -> ObjectView

View file

@ -55,7 +55,7 @@ class AddBackLinkToObject(
)
)
closeBlock.run(params.objectToPlaceLink)
closeBlock.run(CloseBlock.Params(params.objectToPlaceLink, params.spaceId))
return ObjectWrapper.Basic(objectDetails)
}

View file

@ -1,19 +1,29 @@
package com.anytypeio.anytype.domain.page
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.base.ResultInteractor
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import javax.inject.Inject
/**
* Use-case for closing a smart block by id.
*/
open class CloseBlock(
open class CloseBlock @Inject constructor(
private val repo: BlockRepository,
dispatchers: AppCoroutineDispatchers
) : ResultInteractor<Id, Unit>(dispatchers.io) {
) : ResultInteractor<CloseBlock.Params, Unit>(dispatchers.io) {
override suspend fun doWork(params: Id) {
repo.closePage(params)
override suspend fun doWork(params: Params) {
repo.closePage(
id = params.target,
space = params.space
)
}
data class Params(
val target: Id,
val space: SpaceId
)
}

View file

@ -18,7 +18,10 @@ open class OpenPage @Inject constructor(
) : ResultInteractor<OpenPage.Params, Result<Payload>>(dispatchers.io) {
override suspend fun doWork(params: Params): Result<Payload> {
return repo.openPage(params.obj).also {
return repo.openPage(
id = params.obj,
space = params.space
).also {
if (params.saveAsLastOpened) {
settings.setLastOpenedObject(
id = params.obj,

View file

@ -15,7 +15,10 @@ class OpenObjectSet(
) : BaseUseCase<Result<Payload>, OpenObjectSet.Params>() {
override suspend fun run(params: Params) = safe {
repo.openObjectSet(params.obj).also {
repo.openObjectSet(
id = params.obj,
space = params.space
).also {
settings.setLastOpenedObject(
id = params.obj,
space = params.space

View file

@ -2,6 +2,7 @@ package com.anytypeio.anytype.domain.templates
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.base.Result
import com.anytypeio.anytype.domain.base.ResultInteractor
@ -20,11 +21,16 @@ class OpenTemplate(
) : ResultInteractor<Params, Result<Payload>>(dispatchers.io) {
override suspend fun doWork(params: Params): Result<Payload> {
return withContext(dispatchers.io) { repo.openObjectPreview(params.id) }
return withContext(dispatchers.io) {
repo.openObjectPreview(
id = params.id,
space = params.space
)
}
}
/**
* @property [id] id of the template object.
*/
class Params(val id: Id)
class Params(val id: Id, val space: SpaceId)
}

View file

@ -24,6 +24,7 @@ interface SpaceManager {
fun getConfig(): Config?
fun getConfig(space: SpaceId) : Config?
fun observe() : Flow<Config>
fun observe(space: SpaceId): Flow<Config>
fun state(): Flow<State>
fun clear()
@ -80,6 +81,12 @@ interface SpaceManager {
}
}
override fun observe(space: SpaceId): Flow<Config> {
return currentSpace.mapNotNull {
info[space.id]
}
}
override fun state(): Flow<State> {
return currentSpace.map { space ->
if (space == NO_SPACE) {

View file

@ -37,6 +37,7 @@ import com.anytypeio.anytype.core_models.membership.MembershipTierData
import com.anytypeio.anytype.core_models.multiplayer.SpaceInviteLink
import com.anytypeio.anytype.core_models.multiplayer.SpaceInviteView
import com.anytypeio.anytype.core_models.multiplayer.SpaceMemberPermissions
import com.anytypeio.anytype.core_models.primitives.Space
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.data.auth.repo.block.BlockRemote
import com.anytypeio.anytype.middleware.interactor.Middleware
@ -46,20 +47,28 @@ class BlockMiddleware(
private val middleware: Middleware
) : BlockRemote {
override suspend fun closeDashboard(id: String) {
middleware.objectClose(id)
}
override suspend fun openObject(id: Id, space: SpaceId): ObjectView = middleware.objectOpen(id = id, space = space)
override suspend fun getObject(id: Id, space: SpaceId): ObjectView = middleware.objectShow(id = id, space = space)
override suspend fun openObject(id: Id): ObjectView = middleware.objectOpen(id = id)
override suspend fun getObject(id: Id): ObjectView = middleware.objectShow(id = id)
override suspend fun openPage(id: String, space: SpaceId): Payload = middleware.objectOpenOld(
id = id,
space = space
)
override suspend fun openProfile(id: String, space: SpaceId): Payload = middleware.objectOpenOld(
id = id,
space = space
)
override suspend fun openObjectSet(id: String, space: SpaceId): Payload = middleware.objectOpenOld(
id = id,
space = space
)
override suspend fun openObjectPreview(id: Id, space: SpaceId): Payload = middleware.objectShowOld(
id = id,
space = space
)
override suspend fun openPage(id: String): Payload = middleware.objectOpenOld(id)
override suspend fun openProfile(id: String): Payload = middleware.objectOpenOld(id)
override suspend fun openObjectSet(id: String): Payload = middleware.objectOpenOld(id)
override suspend fun openObjectPreview(id: Id): Payload = middleware.objectShowOld(id)
override suspend fun closePage(id: String) {
middleware.objectClose(id)
override suspend fun closePage(id: String, space: Space) {
middleware.objectClose(id = id, space = space)
}
override suspend fun updateDocumentTitle(command: Command.UpdateTitle) {

View file

@ -43,6 +43,7 @@ import com.anytypeio.anytype.core_models.membership.MembershipTierData
import com.anytypeio.anytype.core_models.multiplayer.SpaceInviteLink
import com.anytypeio.anytype.core_models.multiplayer.SpaceInviteView
import com.anytypeio.anytype.core_models.multiplayer.SpaceMemberPermissions
import com.anytypeio.anytype.core_models.primitives.Space
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_utils.tools.ThreadInfo
import com.anytypeio.anytype.middleware.BuildConfig
@ -848,8 +849,8 @@ class Middleware @Inject constructor(
}
@Throws(Exception::class)
fun objectClose(id: String) {
val request = Rpc.Object.Close.Request(objectId = id)
fun objectClose(id: String, space: Space) {
val request = Rpc.Object.Close.Request(objectId = id, spaceId = space.id)
logRequestIfDebug(request)
val (response, time) = measureTimedValue { service.objectClose(request) }
logResponseIfDebug(response, time)
@ -1091,8 +1092,8 @@ class Middleware @Inject constructor(
}
@Throws(Exception::class)
fun objectOpenOld(id: String): Payload {
val request = Rpc.Object.Open.Request(objectId = id)
fun objectOpenOld(id: String, space: SpaceId): Payload {
val request = Rpc.Object.Open.Request(objectId = id, spaceId = space.id)
logRequestIfDebug(request)
val (response, time) = measureTimedValue { service.objectOpen(request) }
logResponseIfDebug(response, time)
@ -1102,8 +1103,8 @@ class Middleware @Inject constructor(
}
@Throws(Exception::class)
fun objectOpen(id: String): ObjectView {
val request = Rpc.Object.Open.Request(objectId = id)
fun objectOpen(id: String, space: SpaceId): ObjectView {
val request = Rpc.Object.Open.Request(objectId = id, spaceId = space.id)
logRequestIfDebug(request)
val (response, time) = measureTimedValue { service.objectOpen(request) }
logResponseIfDebug(response, time)
@ -1531,8 +1532,8 @@ class Middleware @Inject constructor(
}
@Throws(Exception::class)
fun objectShowOld(id: String): Payload {
val request = Rpc.Object.Show.Request(objectId = id)
fun objectShowOld(id: String, space: SpaceId): Payload {
val request = Rpc.Object.Show.Request(objectId = id, spaceId = space.id)
logRequestIfDebug(request)
val (response, time) = measureTimedValue { service.objectShow(request) }
logResponseIfDebug(response, time)
@ -1541,8 +1542,8 @@ class Middleware @Inject constructor(
}
@Throws(Exception::class)
fun objectShow(id: String): ObjectView {
val request = Rpc.Object.Show.Request(objectId = id)
fun objectShow(id: String, space: SpaceId): ObjectView {
val request = Rpc.Object.Show.Request(objectId = id, spaceId = space.id)
logRequestIfDebug(request)
val (response, time) = measureTimedValue { service.objectShow(request) }
logResponseIfDebug(response, time)

View file

@ -1228,7 +1228,12 @@ class EditorViewModel(
Session.IDLE -> navigate(EventWrapper(AppNavigation.Command.Exit))
Session.OPEN -> {
viewModelScope.launch {
closePage.async(context).fold(
closePage.async(
CloseBlock.Params(
vmParams.ctx,
vmParams.space
)
).fold(
onSuccess = { navigate(EventWrapper(AppNavigation.Command.Exit)) },
onFailure = {
Timber.e(it, "Error while closing document: $context")
@ -1247,7 +1252,12 @@ class EditorViewModel(
private fun exitDashboard() {
viewModelScope.launch {
clearLastOpenedObject(ClearLastOpenedObject.Params(vmParams.space))
closePage.async(context).fold(
closePage.async(
CloseBlock.Params(
vmParams.ctx,
vmParams.space
)
).fold(
onSuccess = { navigateToDesktop() },
onFailure = {
Timber.e(it, "Error while closing this page: $context")
@ -4386,7 +4396,12 @@ class EditorViewModel(
fun proceedWithOpeningObject(target: Id) {
viewModelScope.launch {
closePage.async(context).fold(
closePage.async(
CloseBlock.Params(
vmParams.ctx,
vmParams.space
)
).fold(
onFailure = {
Timber.e(it, "Error while closing object")
navigate(EventWrapper(
@ -4404,7 +4419,12 @@ class EditorViewModel(
private fun proceedWithCloseCurrentAndOpenObject(obj: ObjectWrapper.Basic) {
jobs += viewModelScope.launch {
closePage.async(context).fold(
closePage.async(
CloseBlock.Params(
vmParams.ctx,
vmParams.space
)
).fold(
onSuccess = { proceedWithOpeningObject(obj) },
onFailure = {
Timber.e(it, "Error while closing object: $context")
@ -4454,7 +4474,12 @@ class EditorViewModel(
isPopUpToDashboard: Boolean = false
) {
viewModelScope.launch {
closePage.async(vmParams.ctx).fold(
closePage.async(
CloseBlock.Params(
vmParams.ctx,
vmParams.space
)
).fold(
onFailure = {
Timber.e(it, "Error while closing object")
navigate(

View file

@ -27,6 +27,7 @@ import com.anytypeio.anytype.core_models.WidgetSession
import com.anytypeio.anytype.core_models.ext.process
import com.anytypeio.anytype.core_models.isDataView
import com.anytypeio.anytype.core_models.multiplayer.SpaceMemberPermissions
import com.anytypeio.anytype.core_models.primitives.Space
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_models.primitives.TypeKey
import com.anytypeio.anytype.core_utils.ext.cancel
@ -238,7 +239,7 @@ class HomeScreenViewModel(
private val widgetObjectPipelineJobs = mutableListOf<Job>()
private val openWidgetObjectsHistory : MutableSet<Id> = LinkedHashSet()
private val openWidgetObjectsHistory : MutableSet<OpenObjectHistoryItem> = LinkedHashSet()
private val userPermissions = MutableStateFlow<SpaceMemberPermissions?>(null)
@ -265,14 +266,24 @@ class HomeScreenViewModel(
unsubscribe(subscriptions)
}
mutex.withLock {
val closed = mutableSetOf<Id>()
openWidgetObjectsHistory.forEach { previouslyOpenedWidgetObject ->
val closed = mutableSetOf<OpenObjectHistoryItem>()
openWidgetObjectsHistory.forEach { (previouslyOpenedWidgetObject, space) ->
if (previouslyOpenedWidgetObject != newConfig.widgets) {
closeObject
.async(params = previouslyOpenedWidgetObject)
.async(
CloseBlock.Params(
target = previouslyOpenedWidgetObject,
space = space
)
)
.fold(
onSuccess = {
closed.add(previouslyOpenedWidgetObject)
closed.add(
OpenObjectHistoryItem(
obj = previouslyOpenedWidgetObject,
space = space
)
)
},
onFailure = {
Timber.e(it, "Error while closing object from history: $previouslyOpenedWidgetObject")
@ -299,7 +310,14 @@ class HomeScreenViewModel(
onSuccess = { objectView ->
onSessionStarted().also {
viewModelScope.launch {
mutex.withLock { openWidgetObjectsHistory.add(objectView.root) }
mutex.withLock {
openWidgetObjectsHistory.add(
OpenObjectHistoryItem(
obj = objectView.root,
space = SpaceId(config.space)
)
)
}
}
}
},
@ -591,7 +609,10 @@ class HomeScreenViewModel(
}
}
private suspend fun proceedWithClosingWidgetObject(widgetObject: Id) {
private suspend fun proceedWithClosingWidgetObject(
widgetObject: Id,
space: SpaceId
) {
saveWidgetSession.async(
SaveWidgetSession.Params(
WidgetSession(
@ -613,7 +634,12 @@ class HomeScreenViewModel(
}
if (subscriptions.isNotEmpty()) unsubscribe(subscriptions)
closeObject.stream(widgetObject).collect { status ->
closeObject.stream(
CloseBlock.Params(
target = widgetObject,
space = space
)
).collect { status ->
status.fold(
onFailure = {
Timber.e(it, "Error while closing widget object")
@ -1691,9 +1717,14 @@ class HomeScreenViewModel(
fun onBackClicked() {
viewModelScope.launch {
openWidgetObjectsHistory.forEach { obj ->
openWidgetObjectsHistory.forEach { (obj, space) ->
closeObject
.async(obj)
.async(
CloseBlock.Params(
target = obj,
space = space
)
)
.onSuccess {
Timber.d("Closed object from widget object session history: $obj")
}
@ -1726,7 +1757,10 @@ class HomeScreenViewModel(
unsubscriber.unsubscribe(listOf(HOME_SCREEN_PROFILE_OBJECT_SUBSCRIPTION))
val config = spaceManager.getConfig()
if (config != null) {
proceedWithClosingWidgetObject(widgetObject = config.widgets)
proceedWithClosingWidgetObject(
widgetObject = config.widgets,
space = SpaceId(config.space)
)
}
jobs.cancel()
widgetObjectPipelineJobs.cancel()
@ -1897,7 +1931,12 @@ class HomeScreenViewModel(
if (target != null) {
val widgetSource = target.source
if (widgetSource is Widget.Source.Default) {
getObject.async(params = target.source.id).fold(
getObject.async(
params = GetObject.Params(
target = target.source.id,
space = SpaceId(target.config.space)
)
).fold(
onSuccess = { obj ->
val dv = obj.blocks.find { it.content is DV }?.content as? DV
val viewer = if (view.isNullOrEmpty())
@ -2211,6 +2250,11 @@ sealed class InteractionMode {
data object ReadOnly: InteractionMode()
}
data class OpenObjectHistoryItem(
val obj: Id,
val space: Space
)
sealed class Command {
/**

View file

@ -808,7 +808,12 @@ class ObjectSetViewModel(
private fun proceedWithClosingAndExit() {
viewModelScope.launch {
closeBlock.async(context).fold(
closeBlock.async(
CloseBlock.Params(
target = vmParams.ctx,
space = vmParams.space
)
).fold(
onSuccess = { dispatch(AppNavigation.Command.Exit) },
onFailure = {
Timber.e(it, "Error while closing object set: $context").also {
@ -1416,7 +1421,12 @@ class ObjectSetViewModel(
target = target,
space = space
)
closeBlock.async(context).fold(
closeBlock.async(
CloseBlock.Params(
target = vmParams.ctx,
space = vmParams.space
)
).fold(
onSuccess = { navigate(EventWrapper(navigateCommand)) },
onFailure = {
Timber.e(it, "Error while closing object set: $context")
@ -1447,7 +1457,12 @@ class ObjectSetViewModel(
}
isCustomizeViewPanelVisible.value = false
jobs += viewModelScope.launch {
closeBlock.async(context).fold(
closeBlock.async(
CloseBlock.Params(
target = vmParams.ctx,
space = vmParams.space
)
).fold(
onSuccess = {
navigate(
EventWrapper(
@ -1503,7 +1518,12 @@ class ObjectSetViewModel(
space = space
)
ObjectType.Layout.SET, ObjectType.Layout.COLLECTION -> {
closeBlock.async(context).fold(
closeBlock.async(
CloseBlock.Params(
target = vmParams.ctx,
space = vmParams.space
)
).fold(
onSuccess = {
navigate(
EventWrapper(
@ -1575,7 +1595,12 @@ class ObjectSetViewModel(
fun onHomeButtonClicked() {
viewModelScope.launch {
clearLastOpenedObject(ClearLastOpenedObject.Params(vmParams.space))
closeBlock.async(context).fold(
closeBlock.async(
CloseBlock.Params(
target = vmParams.ctx,
space = vmParams.space
)
).fold(
onSuccess = { dispatch(AppNavigation.Command.ExitToVault) },
onFailure = {
Timber.e(it, "Error while closing object set: $context").also {

View file

@ -6,6 +6,7 @@ import androidx.lifecycle.viewModelScope
import com.anytypeio.anytype.core_models.Event
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ext.asMap
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.base.Result
import com.anytypeio.anytype.domain.templates.OpenTemplate
@ -31,9 +32,9 @@ class TemplateViewModel(
val state = MutableStateFlow<List<BlockView>>(emptyList())
fun onStart(ctx: Id) {
fun onStart(ctx: Id, space: SpaceId) {
viewModelScope.launch {
state.value = openTemplate.asFlow(OpenTemplate.Params(ctx))
state.value = openTemplate.asFlow(OpenTemplate.Params(id = ctx, space = space))
.map { result ->
when(result) {
is Result.Failure -> {

View file

@ -135,7 +135,12 @@ class DataViewListWidgetContainer(
if (source.obj.layout == ObjectType.Layout.SET && source.obj.setOf.isEmpty()) {
flowOf(defaultEmptyState())
} else {
val obj = getObject.run(widget.source.id)
val obj = getObject.run(
GetObject.Params(
target = widget.source.id,
space = SpaceId(widget.config.space)
)
)
val dv = obj.blocks.find { it.content is DV }?.content
val target = if (dv is DV) {
dv.viewers.find { it.id == view } ?: dv.viewers.firstOrNull()

View file

@ -82,7 +82,7 @@ class ListWidgetContainer(
BundledWidgetSourceIds.FAVORITE -> {
// Objects from favorites have custom sorting logic.
objectWatcher
.watch(widget.config.home)
.watch(target = widget.config.home, space = SpaceId(widget.config.space))
.map { obj -> obj.orderOfRootObjects(obj.root) }
.catch {
Timber.e(it)

View file

@ -163,7 +163,10 @@ class TreeWidgetContainer(
return when (widget.source.id) {
BundledWidgetSourceIds.FAVORITE -> {
objectWatcher
.watch(widget.config.home)
.watch(
target = widget.config.home,
space = SpaceId(widget.config.space)
)
.map { obj -> obj.orderOfRootObjects(obj.root) }
.catch { emit(emptyMap()) }
.flatMapLatest { order ->

View file

@ -360,11 +360,19 @@ class CollectionViewModel(
container.subscribe(buildSearchParams()),
queryFlow(),
objectTypes(),
spaceManager.observe().flatMapLatest { config ->
openObject
.asFlow(OpenObject.Params(config.home, false))
.flatMapLatest { obj -> payloads.scan(obj) { s, p -> reduce(s, p) } }
}
spaceManager
.observe(vmParams.spaceId)
.flatMapLatest { config ->
openObject
.asFlow(
OpenObject.Params(
obj = config.home,
spaceId = vmParams.spaceId,
saveAsLastOpened = false
)
)
.flatMapLatest { obj -> payloads.scan(obj) { s, p -> reduce(s, p) } }
}
) { objs, query, types, favorotiesObj ->
val result = prepareFavorites(favorotiesObj, objs, query, types)
if (result.isEmpty() && query.isNotEmpty())

View file

@ -9,6 +9,7 @@ import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_models.primitives.TypeKey
import com.anytypeio.anytype.domain.base.Resultat
import com.anytypeio.anytype.domain.dataview.interactor.CreateDataViewObject
import com.anytypeio.anytype.domain.page.CloseBlock
import com.anytypeio.anytype.presentation.sets.ObjectSetViewModel
import com.anytypeio.anytype.presentation.sets.main.ObjectSetViewModelTestSetup
import com.anytypeio.anytype.presentation.sets.state.ObjectState
@ -98,7 +99,9 @@ class ObjectCreateTest : ObjectSetViewModelTestSetup() {
prefilled = emptyMap()
)
)
doReturn(Resultat.success(Unit)).`when`(closeBlock).async(mockObjectSet.root)
doReturn(Resultat.success(Unit)).`when`(closeBlock).async(
CloseBlock.Params(mockObjectSet.root, SpaceId(defaultSpace))
)
// TESTING
proceedWithStartingViewModel()
@ -120,7 +123,9 @@ class ObjectCreateTest : ObjectSetViewModelTestSetup() {
)
}
verifyBlocking(closeBlock, times(1)) { async(mockObjectSet.root) }
verifyBlocking(closeBlock, times(1)) {
async(CloseBlock.Params(mockObjectSet.root, SpaceId(defaultSpace)))
}
}
@Test
@ -168,7 +173,9 @@ class ObjectCreateTest : ObjectSetViewModelTestSetup() {
prefilled = emptyMap()
)
)
doReturn(Resultat.success(Unit)).`when`(closeBlock).async(mockObjectSet.root)
doReturn(Resultat.success(Unit)).`when`(closeBlock).async(
CloseBlock.Params(mockObjectSet.root, SpaceId(defaultSpace))
)
// TESTING
proceedWithStartingViewModel()
@ -261,7 +268,9 @@ class ObjectCreateTest : ObjectSetViewModelTestSetup() {
prefilled = emptyMap()
)
)
doReturn(Resultat.success(Unit)).`when`(closeBlock).async(mockObjectSet.root)
doReturn(Resultat.success(Unit)).`when`(closeBlock).async(
CloseBlock.Params(mockObjectSet.root, SpaceId(defaultSpace))
)
// TESTING
proceedWithStartingViewModel()
@ -344,7 +353,9 @@ class ObjectCreateTest : ObjectSetViewModelTestSetup() {
prefilled = emptyMap()
)
)
doReturn(Resultat.success(Unit)).`when`(closeBlock).async(objectCollection.root)
doReturn(Resultat.success(Unit)).`when`(closeBlock).async(
CloseBlock.Params(objectCollection.root, SpaceId(defaultSpace))
)
// TESTING
proceedWithStartingViewModel()

View file

@ -2831,7 +2831,7 @@ open class EditorViewModelTest {
vm.proceedWithExitingBack()
verify(closePage, times(1)).async(
params = eq(root)
params = eq(CloseBlock.Params(root, SpaceId(defaultSpace)))
)
}
@ -3662,7 +3662,7 @@ open class EditorViewModelTest {
) {
closePage.stub {
onBlocking { if (context == null) async(any()) else async(root) } doReturn Resultat.success(
onBlocking { if (context == null) async(any()) else async(CloseBlock.Params(root, SpaceId(defaultSpace))) } doReturn Resultat.success(
Unit
)
}

View file

@ -1,6 +1,8 @@
package com.anytypeio.anytype.presentation.editor.editor
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.domain.page.CloseBlock
import com.anytypeio.anytype.presentation.MockTypicalDocumentFactory
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
import kotlin.test.assertFalse
@ -64,6 +66,6 @@ class EditorBackButtonTest : EditorPresentationTestSetup() {
assertTrue(stateBackPressed?.styleTextToolbar?.isVisible == false)
verifyBlocking(closePage, times(1)) { async(root) }
verifyBlocking(closePage, times(1)) { async(CloseBlock.Params(root, SpaceId(defaultSpace))) }
}
}

View file

@ -3,7 +3,9 @@ package com.anytypeio.anytype.presentation.editor.editor
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.ext.content
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.domain.block.interactor.UpdateText
import com.anytypeio.anytype.domain.page.CloseBlock
import com.anytypeio.anytype.presentation.editor.EditorViewModel
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
@ -123,7 +125,7 @@ class EditorTextUpdateTest : EditorPresentationTestSetup() {
target = block.id
)
)
inOrder.verify(closePage, times(1)).async(root)
inOrder.verify(closePage, times(1)).async(CloseBlock.Params(root, SpaceId(defaultSpace)))
}
// RELEASING PENDING COROUTINES
@ -198,7 +200,7 @@ class EditorTextUpdateTest : EditorPresentationTestSetup() {
vm.onHomeButtonClicked()
verifyBlocking(closePage, times(1)) {
async(root)
async(CloseBlock.Params(root, SpaceId(defaultSpace)))
}
verifyNoMoreInteractions(updateText)
@ -269,7 +271,7 @@ class EditorTextUpdateTest : EditorPresentationTestSetup() {
)
)
inOrder.verify(closePage, times(1)).async(
root
CloseBlock.Params(root, SpaceId(defaultSpace))
)
}
@ -345,7 +347,7 @@ class EditorTextUpdateTest : EditorPresentationTestSetup() {
vm.onSystemBackPressed(false)
verifyBlocking(closePage, times(1)) {
async(root)
async(CloseBlock.Params(root, SpaceId(defaultSpace)))
}
verifyNoMoreInteractions(updateText)

View file

@ -1638,7 +1638,7 @@ class HomeScreenViewModelTest {
} doReturn Unit
}
given(objectWatcher.watch(any())).willReturn(flowOf())
given(objectWatcher.watch(defaultSpaceConfig.home, SpaceId(defaultSpaceConfig.space))).willReturn(flowOf())
given(storelessSubscriptionContainer.subscribe(any<StoreSearchParams>())).willReturn(flowOf())
given(storelessSubscriptionContainer.subscribe(any<StoreSearchByIdsParams>())).willReturn(
flowOf()
@ -1675,7 +1675,12 @@ class HomeScreenViewModelTest {
)
}
verify(closeObject, times(1)).async(params = WIDGET_OBJECT_ID)
verify(closeObject, times(1)).async(
params = CloseBlock.Params(
WIDGET_OBJECT_ID,
SpaceId(defaultSpaceConfig.space)
)
)
}
@Test
@ -1886,7 +1891,12 @@ class HomeScreenViewModelTest {
)
}
verify(closeObject, times(1)).async(params = WIDGET_OBJECT_ID)
verify(closeObject, times(1)).async(
params = CloseBlock.Params(
WIDGET_OBJECT_ID,
SpaceId(defaultSpaceConfig.space)
)
)
}
@Test
@ -2465,7 +2475,12 @@ class HomeScreenViewModelTest {
thirdWidget is WidgetView.SetOfObjects && thirdWidget.tabs.first().isSelected
}
verifyBlocking(getObject, times(1)) {
run(params = currentWidgetSourceObject.id)
run(
params = GetObject.Params(
currentWidgetSourceObject.id,
SpaceId(defaultSpaceConfig.space)
)
)
}
verify(storelessSubscriptionContainer, times(1)).subscribe(
StoreSearchByIdsParams(
@ -2651,7 +2666,12 @@ class HomeScreenViewModelTest {
) {
getObject.stub {
onBlocking {
run(givenObjectView.root)
run(
GetObject.Params(
givenObjectView.root,
SpaceId(defaultSpaceConfig.space)
)
)
} doReturn givenObjectView
}
}
@ -2660,14 +2680,20 @@ class HomeScreenViewModelTest {
closeObject.stub {
onBlocking {
stream(
params = WIDGET_OBJECT_ID
params = CloseBlock.Params(
WIDGET_OBJECT_ID,
SpaceId(defaultSpaceConfig.space)
)
)
} doReturn flowOf(Resultat.Loading(), Resultat.Success(Unit))
}
closeObject.stub {
onBlocking {
async(
params = WIDGET_OBJECT_ID
params = CloseBlock.Params(
WIDGET_OBJECT_ID,
SpaceId(defaultSpaceConfig.space)
)
)
} doReturn Resultat.success(Unit)
}
@ -2736,7 +2762,7 @@ class HomeScreenViewModelTest {
) {
objectWatcher.stub {
on {
watch(defaultSpaceConfig.home)
watch(defaultSpaceConfig.home, SpaceId(defaultSpaceConfig.space))
} doReturn flowOf(objectView)
}
}

View file

@ -5,6 +5,7 @@ import com.anytypeio.anytype.core_models.ObjectType
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.domain.page.CloseBlock
import com.anytypeio.anytype.presentation.collections.MockSet
import com.anytypeio.anytype.presentation.objects.ObjectIcon
import com.anytypeio.anytype.presentation.objects.SupportedLayouts
@ -213,7 +214,12 @@ class ObjectSetNavigationTest : ObjectSetViewModelTestSetup() {
// CHECK CLOSE BLOCK COMMAND
advanceUntilIdle()
verifyBlocking(closeBlock, times(1)) {
async(mockObjectSet.root)
async(
CloseBlock.Params(
mockObjectSet.root,
SpaceId(defaultSpace)
)
)
}
}
}