mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-2644 Sync Status | Editor + sets implementation (#1422)
This commit is contained in:
parent
ad96048321
commit
e67704f7f2
63 changed files with 1289 additions and 605 deletions
|
@ -61,10 +61,8 @@ import com.anytypeio.anytype.domain.launch.GetDefaultObjectType
|
|||
import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
|
||||
import com.anytypeio.anytype.domain.networkmode.GetNetworkMode
|
||||
import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection
|
||||
import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet
|
||||
import com.anytypeio.anytype.domain.`object`.SetObjectInternalFlags
|
||||
import com.anytypeio.anytype.domain.`object`.UpdateDetail
|
||||
import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes
|
||||
import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations
|
||||
|
@ -83,8 +81,6 @@ import com.anytypeio.anytype.domain.relations.AddRelationToObject
|
|||
import com.anytypeio.anytype.domain.relations.SetRelationKey
|
||||
import com.anytypeio.anytype.domain.search.SearchObjects
|
||||
import com.anytypeio.anytype.domain.sets.FindObjectSetForType
|
||||
import com.anytypeio.anytype.domain.status.InterceptThreadStatus
|
||||
import com.anytypeio.anytype.domain.status.ThreadStatusChannel
|
||||
import com.anytypeio.anytype.domain.table.CreateTable
|
||||
import com.anytypeio.anytype.domain.table.FillTableRow
|
||||
import com.anytypeio.anytype.domain.templates.ApplyTemplate
|
||||
|
@ -111,6 +107,7 @@ import com.anytypeio.anytype.presentation.editor.render.DefaultBlockViewRenderer
|
|||
import com.anytypeio.anytype.presentation.editor.selection.SelectionStateHolder
|
||||
import com.anytypeio.anytype.presentation.editor.toggle.ToggleStateHolder
|
||||
import com.anytypeio.anytype.presentation.search.ObjectSearchConstants
|
||||
import com.anytypeio.anytype.presentation.sync.SpaceSyncAndP2PStatusProvider
|
||||
import com.anytypeio.anytype.presentation.templates.ObjectTypeTemplatesContainer
|
||||
import com.anytypeio.anytype.presentation.util.CopyFileToCacheDirectory
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
|
@ -206,7 +203,6 @@ open class EditorTestSetup {
|
|||
lateinit var applyTemplate: ApplyTemplate
|
||||
|
||||
lateinit var createObjectAsMentionOrLink: CreateObjectAsMentionOrLink
|
||||
lateinit var interceptThreadStatus: InterceptThreadStatus
|
||||
|
||||
lateinit var setDocCoverImage: SetDocCoverImage
|
||||
lateinit var setDocImageIcon: SetDocumentImageIcon
|
||||
|
@ -260,9 +256,6 @@ open class EditorTestSetup {
|
|||
@Mock
|
||||
lateinit var analytics: Analytics
|
||||
|
||||
@Mock
|
||||
lateinit var threadStatusChannel: ThreadStatusChannel
|
||||
|
||||
@Mock
|
||||
lateinit var createTable: CreateTable
|
||||
|
||||
|
@ -278,9 +271,6 @@ open class EditorTestSetup {
|
|||
@Mock
|
||||
lateinit var fileLimitsEventChannel: FileLimitsEventChannel
|
||||
|
||||
@Mock
|
||||
lateinit var setObjectInternalFlags: SetObjectInternalFlags
|
||||
|
||||
@Mock
|
||||
lateinit var spaceManager: SpaceManager
|
||||
|
||||
|
@ -290,15 +280,15 @@ open class EditorTestSetup {
|
|||
@Mock
|
||||
lateinit var templatesContainer: ObjectTypeTemplatesContainer
|
||||
|
||||
@Mock
|
||||
lateinit var getNetworkMode: GetNetworkMode
|
||||
|
||||
@Mock
|
||||
lateinit var permissions: UserPermissionProvider
|
||||
|
||||
@Mock
|
||||
lateinit var analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
|
||||
|
||||
@Mock
|
||||
lateinit var spaceSyncAndP2PStatusProvider: SpaceSyncAndP2PStatusProvider
|
||||
|
||||
lateinit var interceptFileLimitEvents: InterceptFileLimitEvents
|
||||
|
||||
lateinit var addRelationToObject: AddRelationToObject
|
||||
|
@ -351,7 +341,6 @@ open class EditorTestSetup {
|
|||
spaceManager = spaceManager
|
||||
)
|
||||
getSearchObjects = SearchObjects(repo)
|
||||
interceptThreadStatus = InterceptThreadStatus(channel = threadStatusChannel)
|
||||
downloadUnsplashImage = DownloadUnsplashImage(unsplashRepository)
|
||||
clearBlockContent = ClearBlockContent(repo)
|
||||
clearBlockStyle = ClearBlockStyle(repo)
|
||||
|
@ -473,7 +462,6 @@ open class EditorTestSetup {
|
|||
spaceManager = spaceManager
|
||||
),
|
||||
createObjectAsMentionOrLink = createObjectAsMentionOrLink,
|
||||
interceptThreadStatus = interceptThreadStatus,
|
||||
analytics = analytics,
|
||||
dispatcher = Dispatcher.Default(),
|
||||
updateDetail = updateDetail,
|
||||
|
@ -502,13 +490,13 @@ open class EditorTestSetup {
|
|||
templatesContainer = templatesContainer,
|
||||
storelessSubscriptionContainer = storelessSubscriptionContainer,
|
||||
dispatchers = appCoroutineDispatchers,
|
||||
getNetworkMode = getNetworkMode,
|
||||
params = EditorViewModel.Params(
|
||||
ctx = root,
|
||||
space = SpaceId(defaultSpace)
|
||||
),
|
||||
permissions = permissions,
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
|
||||
syncStatusProvider = spaceSyncAndP2PStatusProvider
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -522,11 +510,9 @@ open class EditorTestSetup {
|
|||
}
|
||||
}
|
||||
|
||||
fun stubInterceptThreadStatus(
|
||||
params: InterceptThreadStatus.Params = InterceptThreadStatus.Params(ctx = root)
|
||||
) {
|
||||
interceptThreadStatus.stub {
|
||||
onBlocking { build(params) } doReturn emptyFlow()
|
||||
fun stubInterceptThreadStatus() {
|
||||
spaceSyncAndP2PStatusProvider.stub {
|
||||
onBlocking { observe() } doReturn emptyFlow()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,8 +49,6 @@ import com.anytypeio.anytype.domain.search.DataViewSubscriptionContainer
|
|||
import com.anytypeio.anytype.domain.search.SubscriptionEventChannel
|
||||
import com.anytypeio.anytype.domain.sets.OpenObjectSet
|
||||
import com.anytypeio.anytype.domain.sets.SetQueryToObjectSet
|
||||
import com.anytypeio.anytype.domain.status.InterceptThreadStatus
|
||||
import com.anytypeio.anytype.domain.status.ThreadStatusChannel
|
||||
import com.anytypeio.anytype.domain.templates.CreateTemplate
|
||||
import com.anytypeio.anytype.domain.templates.GetTemplates
|
||||
import com.anytypeio.anytype.domain.unsplash.DownloadUnsplashImage
|
||||
|
@ -69,6 +67,7 @@ import com.anytypeio.anytype.presentation.sets.ObjectSetViewModelFactory
|
|||
import com.anytypeio.anytype.presentation.sets.state.DefaultObjectStateReducer
|
||||
import com.anytypeio.anytype.presentation.sets.subscription.DefaultDataViewSubscription
|
||||
import com.anytypeio.anytype.presentation.sets.viewer.ViewerDelegate
|
||||
import com.anytypeio.anytype.presentation.sync.SpaceSyncAndP2PStatusProvider
|
||||
import com.anytypeio.anytype.presentation.templates.ObjectTypeTemplatesContainer
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
import com.anytypeio.anytype.presentation.widgets.collection.DateProviderImpl
|
||||
|
@ -90,7 +89,6 @@ abstract class TestObjectSetSetup {
|
|||
private lateinit var updateText: UpdateText
|
||||
private lateinit var createDataViewObject: CreateDataViewObject
|
||||
private lateinit var closeBlock: CloseBlock
|
||||
private lateinit var interceptThreadStatus: InterceptThreadStatus
|
||||
private lateinit var setDocCoverImage: SetDocCoverImage
|
||||
private lateinit var downloadUnsplashImage: DownloadUnsplashImage
|
||||
private lateinit var setDataViewQuery: SetDataViewQuery
|
||||
|
@ -125,7 +123,7 @@ abstract class TestObjectSetSetup {
|
|||
@Mock
|
||||
lateinit var interceptEvents: InterceptEvents
|
||||
@Mock
|
||||
lateinit var threadStatusChannel: ThreadStatusChannel
|
||||
lateinit var spaceSyncAndP2PStatusProvider: SpaceSyncAndP2PStatusProvider
|
||||
@Mock
|
||||
lateinit var subscriptionEventChannel: SubscriptionEventChannel
|
||||
@Mock
|
||||
|
@ -249,7 +247,6 @@ abstract class TestObjectSetSetup {
|
|||
)
|
||||
setObjectDetails = UpdateDetail(repo)
|
||||
updateDataViewViewer = UpdateDataViewViewer(repo, dispatchers)
|
||||
interceptThreadStatus = InterceptThreadStatus(channel = threadStatusChannel)
|
||||
closeBlock = CloseBlock(repo, dispatchers)
|
||||
urlBuilder = UrlBuilder(gateway)
|
||||
downloadUnsplashImage = DownloadUnsplashImage(unsplashRepo)
|
||||
|
@ -270,7 +267,6 @@ abstract class TestObjectSetSetup {
|
|||
openObjectSet = openObjectSet,
|
||||
closeBlock = closeBlock,
|
||||
interceptEvents = interceptEvents,
|
||||
interceptThreadStatus = interceptThreadStatus,
|
||||
createDataViewObject = createDataViewObject,
|
||||
setObjectDetails = setObjectDetails,
|
||||
updateText = updateText,
|
||||
|
@ -283,7 +279,6 @@ abstract class TestObjectSetSetup {
|
|||
setDocCoverImage = setDocCoverImage,
|
||||
delegator = delegator,
|
||||
createObject = createObject,
|
||||
cancelSearchSubscription = cancelSearchSubscription,
|
||||
paginator = paginator,
|
||||
database = database,
|
||||
dataViewSubscriptionContainer = dataViewSubscriptionContainer,
|
||||
|
@ -304,14 +299,14 @@ abstract class TestObjectSetSetup {
|
|||
getObjectTypes = getObjectTypes,
|
||||
storelessSubscriptionContainer = storelessSubscriptionContainer,
|
||||
dispatchers = appCoroutineDispatchers,
|
||||
getNetworkMode = getNetworkMode,
|
||||
dateProvider = dateProvider,
|
||||
params = ObjectSetViewModel.Params(
|
||||
ctx = ctx,
|
||||
space = SpaceId(defaultSpace)
|
||||
),
|
||||
permissions = permissions,
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
|
||||
spaceSyncAndP2PStatusProvider = spaceSyncAndP2PStatusProvider,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -322,8 +317,8 @@ abstract class TestObjectSetSetup {
|
|||
}
|
||||
|
||||
fun stubInterceptThreadStatus() {
|
||||
threadStatusChannel.stub {
|
||||
onBlocking { observe(any()) } doReturn emptyFlow()
|
||||
spaceSyncAndP2PStatusProvider.stub {
|
||||
onBlocking { observe() } doReturn emptyFlow()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
package com.anytypeio.anytype.app
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import com.anytypeio.anytype.BuildConfig
|
||||
import com.anytypeio.anytype.core_utils.tools.FeatureToggles
|
||||
import com.anytypeio.anytype.device.BuildProvider
|
||||
import javax.inject.Inject
|
||||
|
||||
class DefaultFeatureToggles @Inject constructor(
|
||||
private val context: Context,
|
||||
@TogglePrefs private val prefs: SharedPreferences,
|
||||
private val buildProvider: BuildProvider
|
||||
buildProvider: BuildProvider
|
||||
) : FeatureToggles {
|
||||
|
||||
override val isLogFromGoProcess =
|
||||
|
@ -18,8 +14,6 @@ class DefaultFeatureToggles @Inject constructor(
|
|||
|
||||
override val isLogMiddlewareInteraction = BuildConfig.LOG_MW_INTERACTION && buildProvider.isDebug()
|
||||
|
||||
override val excludeThreadStatusLogging: Boolean = true
|
||||
|
||||
override val isLogEditorViewModelEvents =
|
||||
BuildConfig.LOG_EDITOR_VIEWMODEL_EVENTS && buildProvider.isDebug()
|
||||
|
||||
|
|
|
@ -54,8 +54,8 @@ import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon
|
|||
import com.anytypeio.anytype.domain.launch.GetDefaultObjectType
|
||||
import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.multiplayer.ActiveSpaceMemberSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
|
||||
import com.anytypeio.anytype.domain.networkmode.GetNetworkMode
|
||||
import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection
|
||||
import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet
|
||||
import com.anytypeio.anytype.domain.`object`.DuplicateObject
|
||||
|
@ -79,8 +79,6 @@ import com.anytypeio.anytype.domain.relations.AddRelationToObject
|
|||
import com.anytypeio.anytype.domain.relations.SetRelationKey
|
||||
import com.anytypeio.anytype.domain.search.SearchObjects
|
||||
import com.anytypeio.anytype.domain.sets.FindObjectSetForType
|
||||
import com.anytypeio.anytype.domain.status.InterceptThreadStatus
|
||||
import com.anytypeio.anytype.domain.status.ThreadStatusChannel
|
||||
import com.anytypeio.anytype.domain.table.CreateTable
|
||||
import com.anytypeio.anytype.domain.table.CreateTableColumn
|
||||
import com.anytypeio.anytype.domain.table.CreateTableRow
|
||||
|
@ -99,7 +97,9 @@ import com.anytypeio.anytype.domain.unsplash.DownloadUnsplashImage
|
|||
import com.anytypeio.anytype.domain.unsplash.UnsplashRepository
|
||||
import com.anytypeio.anytype.domain.workspace.FileLimitsEventChannel
|
||||
import com.anytypeio.anytype.domain.workspace.InterceptFileLimitEvents
|
||||
import com.anytypeio.anytype.domain.workspace.P2PStatusChannel
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceSyncStatusChannel
|
||||
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
|
||||
import com.anytypeio.anytype.presentation.common.Action
|
||||
import com.anytypeio.anytype.presentation.common.Delegator
|
||||
|
@ -124,6 +124,7 @@ import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProv
|
|||
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider.Companion.INTRINSIC_PROVIDER_TYPE
|
||||
import com.anytypeio.anytype.presentation.relations.providers.ObjectValueProvider
|
||||
import com.anytypeio.anytype.presentation.relations.providers.RelationListProvider
|
||||
import com.anytypeio.anytype.presentation.sync.SpaceSyncAndP2PStatusProvider
|
||||
import com.anytypeio.anytype.presentation.templates.ObjectTypeTemplatesContainer
|
||||
import com.anytypeio.anytype.presentation.util.CopyFileToCacheDirectory
|
||||
import com.anytypeio.anytype.presentation.util.DefaultCopyFileToCacheDirectory
|
||||
|
@ -251,7 +252,6 @@ object EditorSessionModule {
|
|||
openPage: OpenPage,
|
||||
closePage: CloseBlock,
|
||||
interceptEvents: InterceptEvents,
|
||||
interceptThreadStatus: InterceptThreadStatus,
|
||||
updateLinkMarks: UpdateLinkMarks,
|
||||
removeLinkMark: RemoveLinkMark,
|
||||
createObjectSet: CreateObjectSet,
|
||||
|
@ -288,8 +288,8 @@ object EditorSessionModule {
|
|||
templatesContainer: ObjectTypeTemplatesContainer,
|
||||
storelessSubscriptionContainer: StorelessSubscriptionContainer,
|
||||
dispatchers: AppCoroutineDispatchers,
|
||||
getNetworkMode: GetNetworkMode,
|
||||
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
|
||||
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
|
||||
syncStatusProvider: SpaceSyncAndP2PStatusProvider
|
||||
): EditorViewModelFactory = EditorViewModelFactory(
|
||||
params = params,
|
||||
permissions = permissions,
|
||||
|
@ -298,7 +298,6 @@ object EditorSessionModule {
|
|||
createBlockLinkWithObject = createBlockLinkWithObject,
|
||||
createObjectAsMentionOrLink = createObjectAsMentionOrLink,
|
||||
interceptEvents = interceptEvents,
|
||||
interceptThreadStatus = interceptThreadStatus,
|
||||
updateLinkMarks = updateLinkMarks,
|
||||
removeLinkMark = removeLinkMark,
|
||||
documentEventReducer = documentExternalEventReducer,
|
||||
|
@ -333,8 +332,8 @@ object EditorSessionModule {
|
|||
templatesContainer = templatesContainer,
|
||||
dispatchers = dispatchers,
|
||||
storelessSubscriptionContainer = storelessSubscriptionContainer,
|
||||
getNetworkMode = getNetworkMode,
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
|
||||
syncStatusProvider = syncStatusProvider
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
|
@ -561,16 +560,6 @@ object EditorUseCaseModule {
|
|||
context = Dispatchers.IO
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun providesInterceptThreadStatusUseCase(
|
||||
channel: ThreadStatusChannel
|
||||
): InterceptThreadStatus = InterceptThreadStatus(
|
||||
channel = channel,
|
||||
context = Dispatchers.IO
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
|
@ -1207,6 +1196,18 @@ object EditorUseCaseModule {
|
|||
spaceManager = spaceManager
|
||||
)
|
||||
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideSpaceSyncStatusProvider(
|
||||
activeSpace: ActiveSpaceMemberSubscriptionContainer,
|
||||
syncChannel: SpaceSyncStatusChannel,
|
||||
p2PStatusChannel: P2PStatusChannel
|
||||
): SpaceSyncAndP2PStatusProvider = SpaceSyncAndP2PStatusProvider.Impl(
|
||||
activeSpace = activeSpace,
|
||||
spaceSyncStatusChannel = syncChannel,
|
||||
p2PStatusChannel = p2PStatusChannel
|
||||
)
|
||||
|
||||
@Module
|
||||
interface Bindings {
|
||||
|
||||
|
|
|
@ -36,8 +36,8 @@ import com.anytypeio.anytype.domain.launch.GetDefaultObjectType
|
|||
import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.misc.DateProvider
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.multiplayer.ActiveSpaceMemberSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
|
||||
import com.anytypeio.anytype.domain.networkmode.GetNetworkMode
|
||||
import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection
|
||||
import com.anytypeio.anytype.domain.`object`.DuplicateObject
|
||||
import com.anytypeio.anytype.domain.`object`.DuplicateObjects
|
||||
|
@ -60,13 +60,13 @@ import com.anytypeio.anytype.domain.search.SearchObjects
|
|||
import com.anytypeio.anytype.domain.search.SubscriptionEventChannel
|
||||
import com.anytypeio.anytype.domain.sets.OpenObjectSet
|
||||
import com.anytypeio.anytype.domain.sets.SetQueryToObjectSet
|
||||
import com.anytypeio.anytype.domain.status.InterceptThreadStatus
|
||||
import com.anytypeio.anytype.domain.status.ThreadStatusChannel
|
||||
import com.anytypeio.anytype.domain.templates.CreateTemplate
|
||||
import com.anytypeio.anytype.domain.templates.GetTemplates
|
||||
import com.anytypeio.anytype.domain.unsplash.DownloadUnsplashImage
|
||||
import com.anytypeio.anytype.domain.unsplash.UnsplashRepository
|
||||
import com.anytypeio.anytype.domain.workspace.P2PStatusChannel
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceSyncStatusChannel
|
||||
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
|
||||
import com.anytypeio.anytype.presentation.common.Action
|
||||
import com.anytypeio.anytype.presentation.common.Delegator
|
||||
|
@ -94,6 +94,7 @@ import com.anytypeio.anytype.presentation.sets.subscription.DataViewSubscription
|
|||
import com.anytypeio.anytype.presentation.sets.subscription.DefaultDataViewSubscription
|
||||
import com.anytypeio.anytype.presentation.sets.viewer.DefaultViewerDelegate
|
||||
import com.anytypeio.anytype.presentation.sets.viewer.ViewerDelegate
|
||||
import com.anytypeio.anytype.presentation.sync.SpaceSyncAndP2PStatusProvider
|
||||
import com.anytypeio.anytype.presentation.templates.ObjectTypeTemplatesContainer
|
||||
import com.anytypeio.anytype.presentation.util.CopyFileToCacheDirectory
|
||||
import com.anytypeio.anytype.presentation.util.DefaultCopyFileToCacheDirectory
|
||||
|
@ -212,7 +213,6 @@ object ObjectSetModule {
|
|||
setObjectDetails: UpdateDetail,
|
||||
updateText: UpdateText,
|
||||
interceptEvents: InterceptEvents,
|
||||
interceptThreadStatus: InterceptThreadStatus,
|
||||
createDataViewObject: CreateDataViewObject,
|
||||
createObject: CreateObject,
|
||||
dispatcher: Dispatcher<Payload>,
|
||||
|
@ -224,7 +224,6 @@ object ObjectSetModule {
|
|||
downloadUnsplashImage: DownloadUnsplashImage,
|
||||
setDocCoverImage: SetDocCoverImage,
|
||||
dataViewSubscriptionContainer: DataViewSubscriptionContainer,
|
||||
cancelSearchSubscription: CancelSearchSubscription,
|
||||
setQueryToObjectSet: SetQueryToObjectSet,
|
||||
database: ObjectSetDatabase,
|
||||
paginator: ObjectSetPaginator,
|
||||
|
@ -244,10 +243,10 @@ object ObjectSetModule {
|
|||
spaceManager: SpaceManager,
|
||||
storelessSubscriptionContainer: StorelessSubscriptionContainer,
|
||||
dispatchers: AppCoroutineDispatchers,
|
||||
getNetworkMode: GetNetworkMode,
|
||||
dateProvider: DateProvider,
|
||||
permissions: UserPermissionProvider,
|
||||
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
|
||||
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
|
||||
spaceSyncAndP2PStatusProvider: SpaceSyncAndP2PStatusProvider
|
||||
): ObjectSetViewModelFactory = ObjectSetViewModelFactory(
|
||||
params = params,
|
||||
openObjectSet = openObjectSet,
|
||||
|
@ -256,7 +255,6 @@ object ObjectSetModule {
|
|||
createDataViewObject = createDataViewObject,
|
||||
updateText = updateText,
|
||||
interceptEvents = interceptEvents,
|
||||
interceptThreadStatus = interceptThreadStatus,
|
||||
dispatcher = dispatcher,
|
||||
delegator = delegator,
|
||||
coverImageHashProvider = coverImageHashProvider,
|
||||
|
@ -267,7 +265,6 @@ object ObjectSetModule {
|
|||
setDocCoverImage = setDocCoverImage,
|
||||
createObject = createObject,
|
||||
dataViewSubscriptionContainer = dataViewSubscriptionContainer,
|
||||
cancelSearchSubscription = cancelSearchSubscription,
|
||||
setQueryToObjectSet = setQueryToObjectSet,
|
||||
database = database,
|
||||
paginator = paginator,
|
||||
|
@ -287,10 +284,10 @@ object ObjectSetModule {
|
|||
createTemplate = createTemplate,
|
||||
storelessSubscriptionContainer = storelessSubscriptionContainer,
|
||||
dispatchers = dispatchers,
|
||||
getNetworkMode = getNetworkMode,
|
||||
dateProvider = dateProvider,
|
||||
permissions = permissions,
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
|
||||
spaceSyncAndP2PStatusProvider = spaceSyncAndP2PStatusProvider
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
|
@ -372,15 +369,6 @@ object ObjectSetModule {
|
|||
context = Dispatchers.IO
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideInterceptThreadStatus(
|
||||
channel: ThreadStatusChannel
|
||||
): InterceptThreadStatus = InterceptThreadStatus(
|
||||
channel = channel
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
|
@ -723,6 +711,18 @@ object ObjectSetModule {
|
|||
analytics = analytics,
|
||||
dispatcher = dispatcher
|
||||
)
|
||||
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideSpaceSyncStatusProvider(
|
||||
activeSpace: ActiveSpaceMemberSubscriptionContainer,
|
||||
syncChannel: SpaceSyncStatusChannel,
|
||||
p2PStatusChannel: P2PStatusChannel
|
||||
): SpaceSyncAndP2PStatusProvider = SpaceSyncAndP2PStatusProvider.Impl(
|
||||
activeSpace = activeSpace,
|
||||
spaceSyncStatusChannel = syncChannel,
|
||||
p2PStatusChannel = p2PStatusChannel
|
||||
)
|
||||
}
|
||||
|
||||
data class DefaultComponentParam(
|
||||
|
|
|
@ -9,12 +9,9 @@ import com.anytypeio.anytype.data.auth.event.FileLimitsDataChannel
|
|||
import com.anytypeio.anytype.data.auth.event.FileLimitsRemoteChannel
|
||||
import com.anytypeio.anytype.data.auth.event.SubscriptionDataChannel
|
||||
import com.anytypeio.anytype.data.auth.event.SubscriptionEventRemoteChannel
|
||||
import com.anytypeio.anytype.data.auth.status.ThreadStatusDataChannel
|
||||
import com.anytypeio.anytype.data.auth.status.ThreadStatusRemoteChannel
|
||||
import com.anytypeio.anytype.domain.account.AccountStatusChannel
|
||||
import com.anytypeio.anytype.domain.event.interactor.EventChannel
|
||||
import com.anytypeio.anytype.domain.search.SubscriptionEventChannel
|
||||
import com.anytypeio.anytype.domain.status.ThreadStatusChannel
|
||||
import com.anytypeio.anytype.domain.workspace.FileLimitsEventChannel
|
||||
import com.anytypeio.anytype.middleware.EventProxy
|
||||
import com.anytypeio.anytype.middleware.interactor.AccountStatusMiddlewareChannel
|
||||
|
@ -22,7 +19,6 @@ import com.anytypeio.anytype.middleware.interactor.EventHandler
|
|||
import com.anytypeio.anytype.middleware.interactor.FileLimitsMiddlewareChannel
|
||||
import com.anytypeio.anytype.middleware.interactor.MiddlewareEventChannel
|
||||
import com.anytypeio.anytype.middleware.interactor.MiddlewareSubscriptionEventChannel
|
||||
import com.anytypeio.anytype.middleware.interactor.ThreadStatusMiddlewareChannel
|
||||
import com.anytypeio.anytype.presentation.common.PayloadDelegator
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
|
@ -54,27 +50,6 @@ object EventModule {
|
|||
featureToggles: FeatureToggles
|
||||
): EventRemoteChannel = MiddlewareEventChannel(events = proxy, featureToggles = featureToggles)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideThreadStatusChannel(
|
||||
channel: ThreadStatusDataChannel
|
||||
): ThreadStatusChannel = channel
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideThreadStatusDataChannel(
|
||||
remote: ThreadStatusRemoteChannel
|
||||
): ThreadStatusDataChannel = ThreadStatusDataChannel(remote)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideThreadStatusRemoteChannel(
|
||||
proxy: EventProxy
|
||||
): ThreadStatusRemoteChannel = ThreadStatusMiddlewareChannel(events = proxy)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@Singleton
|
||||
|
|
|
@ -1,11 +1,20 @@
|
|||
package com.anytypeio.anytype.di.main
|
||||
|
||||
import com.anytypeio.anytype.data.auth.status.P2PStatusDataChannel
|
||||
import com.anytypeio.anytype.data.auth.status.P2PStatusRemoteChannel
|
||||
import com.anytypeio.anytype.data.auth.status.SpaceStatusDataChannel
|
||||
import com.anytypeio.anytype.data.auth.status.SpaceStatusRemoteChannel
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
import com.anytypeio.anytype.domain.config.ConfigStorage
|
||||
import com.anytypeio.anytype.domain.debugging.Logger
|
||||
import com.anytypeio.anytype.domain.workspace.P2PStatusChannel
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceSyncStatusChannel
|
||||
import com.anytypeio.anytype.domain.workspace.WorkspaceManager
|
||||
import com.anytypeio.anytype.middleware.EventProxy
|
||||
import com.anytypeio.anytype.middleware.interactor.P2PStatusRemoteChannelImpl
|
||||
import com.anytypeio.anytype.middleware.interactor.SpaceSyncStatusRemoteChannelImpl
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import javax.inject.Singleton
|
||||
|
@ -14,7 +23,7 @@ import javax.inject.Singleton
|
|||
object WorkspaceModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
fun manager() : WorkspaceManager = WorkspaceManager.DefaultWorkspaceManager()
|
||||
fun manager(): WorkspaceManager = WorkspaceManager.DefaultWorkspaceManager()
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
|
@ -23,10 +32,37 @@ object WorkspaceModule {
|
|||
dispatchers: AppCoroutineDispatchers,
|
||||
configStorage: ConfigStorage,
|
||||
logger: Logger
|
||||
) : SpaceManager = SpaceManager.Impl(
|
||||
): SpaceManager = SpaceManager.Impl(
|
||||
dispatchers = dispatchers,
|
||||
repo = repo,
|
||||
configStorage = configStorage,
|
||||
logger = logger
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideSyncStatusRemoteChannel(
|
||||
proxy: EventProxy
|
||||
): SpaceStatusRemoteChannel = SpaceSyncStatusRemoteChannelImpl(events = proxy)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun spaceSyncStatusChannel(
|
||||
channel: SpaceStatusRemoteChannel
|
||||
): SpaceSyncStatusChannel = SpaceStatusDataChannel(channel)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@Singleton
|
||||
fun p2pStatusRemoteChannel(
|
||||
proxy: EventProxy
|
||||
): P2PStatusRemoteChannel = P2PStatusRemoteChannelImpl(events = proxy)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@Singleton
|
||||
fun p2pStatusChannel(
|
||||
channel: P2PStatusRemoteChannel
|
||||
): P2PStatusChannel = P2PStatusDataChannel(channel)
|
||||
}
|
|
@ -57,8 +57,6 @@ import com.anytypeio.anytype.core_models.primitives.SpaceId
|
|||
import com.anytypeio.anytype.core_ui.extensions.addTextFromSelectedStart
|
||||
import com.anytypeio.anytype.core_ui.extensions.color
|
||||
import com.anytypeio.anytype.core_ui.extensions.cursorYBottomCoordinate
|
||||
import com.anytypeio.anytype.core_ui.extensions.getLabelText
|
||||
import com.anytypeio.anytype.core_ui.extensions.getToastMsg
|
||||
import com.anytypeio.anytype.core_ui.features.editor.BlockAdapter
|
||||
import com.anytypeio.anytype.core_ui.features.editor.DragAndDropAdapterDelegate
|
||||
import com.anytypeio.anytype.core_ui.features.editor.scrollandmove.DefaultScrollAndMoveTargetDescriptor
|
||||
|
@ -67,6 +65,7 @@ import com.anytypeio.anytype.core_ui.features.editor.scrollandmove.ScrollAndMove
|
|||
import com.anytypeio.anytype.core_ui.menu.ObjectTypePopupMenu
|
||||
import com.anytypeio.anytype.core_ui.reactive.clicks
|
||||
import com.anytypeio.anytype.core_ui.reactive.longClicks
|
||||
import com.anytypeio.anytype.core_ui.syncstatus.SpaceSyncStatusScreen
|
||||
import com.anytypeio.anytype.core_ui.tools.ClipboardInterceptor
|
||||
import com.anytypeio.anytype.core_ui.tools.EditorHeaderOverlayDetector
|
||||
import com.anytypeio.anytype.core_ui.tools.LastItemBottomOffsetDecorator
|
||||
|
@ -126,7 +125,7 @@ import com.anytypeio.anytype.presentation.editor.model.EditorFooter
|
|||
import com.anytypeio.anytype.presentation.editor.template.SelectTemplateViewState
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectIcon
|
||||
import com.anytypeio.anytype.presentation.relations.value.tagstatus.RelationContext
|
||||
import com.anytypeio.anytype.presentation.sync.SyncStatusView
|
||||
import com.anytypeio.anytype.presentation.sync.SpaceSyncAndP2PStatusState
|
||||
import com.anytypeio.anytype.ui.alert.AlertUpdateAppFragment
|
||||
import com.anytypeio.anytype.ui.base.NavigationFragment
|
||||
import com.anytypeio.anytype.ui.base.navigation
|
||||
|
@ -393,9 +392,6 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
|
|||
) { isHeaderOverlaid ->
|
||||
if (isHeaderOverlaid) {
|
||||
binding.topToolbar.setBackgroundColor(0)
|
||||
binding.topToolbar.statusText.animate().alpha(1f)
|
||||
.setDuration(DEFAULT_TOOLBAR_ANIM_DURATION)
|
||||
.start()
|
||||
binding.topToolbar.container.animate().alpha(0f)
|
||||
.setDuration(DEFAULT_TOOLBAR_ANIM_DURATION)
|
||||
.start()
|
||||
|
@ -409,9 +405,6 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
|
|||
}
|
||||
} else {
|
||||
binding.topToolbar.setBackgroundColor(requireContext().color(R.color.defaultCanvasColor))
|
||||
binding.topToolbar.statusText.animate().alpha(0f)
|
||||
.setDuration(DEFAULT_TOOLBAR_ANIM_DURATION)
|
||||
.start()
|
||||
binding.topToolbar.container.animate().alpha(1f)
|
||||
.setDuration(DEFAULT_TOOLBAR_ANIM_DURATION)
|
||||
.start()
|
||||
|
@ -746,6 +739,17 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
|
|||
}
|
||||
}
|
||||
|
||||
binding.syncStatusWidget.apply {
|
||||
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
|
||||
setContent {
|
||||
SpaceSyncStatusScreen(
|
||||
uiState = vm.syncStatusWidget.collectAsStateWithLifecycle().value,
|
||||
onDismiss = vm::onSyncWidgetDismiss,
|
||||
scope = lifecycleScope
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
BottomSheetBehavior.from(binding.styleToolbarMain).state = BottomSheetBehavior.STATE_HIDDEN
|
||||
BottomSheetBehavior.from(binding.styleToolbarOther).state = BottomSheetBehavior.STATE_HIDDEN
|
||||
BottomSheetBehavior.from(binding.styleToolbarColors).state =
|
||||
|
@ -810,13 +814,7 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
|
|||
}
|
||||
.launchIn(lifecycleScope)
|
||||
|
||||
vm.syncStatus.onEach { status -> bindSyncStatus(status) }.launchIn(lifecycleScope)
|
||||
vm.isSyncStatusVisible.onEach { isSyncStatusVisible ->
|
||||
if (isSyncStatusVisible)
|
||||
binding.topToolbar.findViewById<ViewGroup>(R.id.statusContainer).visible()
|
||||
else
|
||||
binding.topToolbar.findViewById<ViewGroup>(R.id.statusContainer).invisible()
|
||||
}.launchIn(lifecycleScope)
|
||||
vm.spaceSyncStatus.onEach { status -> bindSyncStatus(status) }.launchIn(lifecycleScope)
|
||||
|
||||
vm.isUndoEnabled.onEach {
|
||||
// TODO
|
||||
|
@ -866,18 +864,16 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
|
|||
}
|
||||
}
|
||||
|
||||
private fun bindSyncStatus(status: SyncStatusView?) {
|
||||
private fun bindSyncStatus(status: SpaceSyncAndP2PStatusState) {
|
||||
binding.topToolbar.status.bind(status)
|
||||
if (status == null) {
|
||||
if (status is SpaceSyncAndP2PStatusState.Initial) {
|
||||
binding.topToolbar.hideStatusContainer()
|
||||
} else {
|
||||
binding.topToolbar.showStatusContainer()
|
||||
}
|
||||
val tvStatus = binding.topToolbar.statusText
|
||||
binding.topToolbar.statusContainer.setOnClickListener {
|
||||
toast(status.getToastMsg(requireContext()))
|
||||
binding.topToolbar.status.setOnClickListener {
|
||||
vm.onSyncStatusBadgeClicked()
|
||||
}
|
||||
tvStatus.text = status?.getLabelText(requireContext())
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
|
|
@ -45,8 +45,6 @@ import com.anytypeio.anytype.core_models.Id
|
|||
import com.anytypeio.anytype.core_models.Key
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
import com.anytypeio.anytype.core_ui.extensions.getLabelText
|
||||
import com.anytypeio.anytype.core_ui.extensions.getToastMsg
|
||||
import com.anytypeio.anytype.core_ui.extensions.setEmojiOrNull
|
||||
import com.anytypeio.anytype.core_ui.features.dataview.ViewerGridAdapter
|
||||
import com.anytypeio.anytype.core_ui.features.dataview.ViewerGridHeaderAdapter
|
||||
|
@ -56,6 +54,7 @@ import com.anytypeio.anytype.core_ui.reactive.clicks
|
|||
import com.anytypeio.anytype.core_ui.reactive.editorActionEvents
|
||||
import com.anytypeio.anytype.core_ui.reactive.longClicks
|
||||
import com.anytypeio.anytype.core_ui.reactive.touches
|
||||
import com.anytypeio.anytype.core_ui.syncstatus.SpaceSyncStatusScreen
|
||||
import com.anytypeio.anytype.core_ui.tools.DefaultTextWatcher
|
||||
import com.anytypeio.anytype.core_ui.views.ButtonPrimarySmallIcon
|
||||
import com.anytypeio.anytype.core_ui.widgets.FeaturedRelationGroupWidget
|
||||
|
@ -101,7 +100,7 @@ import com.anytypeio.anytype.presentation.sets.ViewerLayoutWidgetUi
|
|||
import com.anytypeio.anytype.presentation.sets.ViewersWidgetUi
|
||||
import com.anytypeio.anytype.presentation.sets.isVisible
|
||||
import com.anytypeio.anytype.presentation.sets.model.Viewer
|
||||
import com.anytypeio.anytype.presentation.sync.SyncStatusView
|
||||
import com.anytypeio.anytype.presentation.sync.SpaceSyncAndP2PStatusState
|
||||
import com.anytypeio.anytype.ui.base.NavigationFragment
|
||||
import com.anytypeio.anytype.ui.editor.cover.SelectCoverObjectSetFragment
|
||||
import com.anytypeio.anytype.ui.editor.modals.IconPickerFragmentBase
|
||||
|
@ -446,6 +445,17 @@ open class ObjectSetFragment :
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
binding.syncStatusWidget.apply {
|
||||
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
|
||||
setContent {
|
||||
SpaceSyncStatusScreen(
|
||||
uiState = vm.syncStatusWidget.collectAsStateWithLifecycle().value,
|
||||
onDismiss = vm::onSyncWidgetDismiss,
|
||||
scope = lifecycleScope
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupWindowInsetAnimation() {
|
||||
|
@ -524,7 +534,6 @@ open class ObjectSetFragment :
|
|||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
vm.navigation.observe(viewLifecycleOwner, navObserver)
|
||||
lifecycleScope.subscribe(vm.status) { setStatus(it) }
|
||||
lifecycleScope.subscribe(vm.isCustomizeViewPanelVisible) { isCustomizeViewPanelVisible ->
|
||||
if (isCustomizeViewPanelVisible) showBottomPanel() else hideBottomPanel()
|
||||
}
|
||||
|
@ -539,12 +548,10 @@ open class ObjectSetFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun setStatus(status: SyncStatusView?) {
|
||||
private fun setStatus(status: SpaceSyncAndP2PStatusState?) {
|
||||
binding.topToolbar.root.findViewById<StatusBadgeWidget>(R.id.statusBadge).bind(status)
|
||||
val tvStatus = binding.topToolbar.root.findViewById<TextView>(R.id.tvStatus)
|
||||
tvStatus.text = status?.getLabelText(requireContext())
|
||||
topToolbarStatusContainer.setOnClickListener {
|
||||
toast(status.getToastMsg(requireContext()))
|
||||
vm.onSyncStatusBadgeClicked()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1319,6 +1326,8 @@ open class ObjectSetFragment :
|
|||
}
|
||||
jobs += lifecycleScope.subscribe(vm.toasts) { toast(it) }
|
||||
|
||||
jobs += lifecycleScope.subscribe(vm.spaceSyncStatus) { setStatus(it) }
|
||||
|
||||
subscribe(vm.icon) { icon ->
|
||||
binding.bottomToolbar.bind(icon)
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ class EditorTemplateFragment : EditorFragment() {
|
|||
topMargin = dimen(R.dimen.default_toolbar_height)
|
||||
}
|
||||
binding.topToolbar.title.text = getString(R.string.templates_menu_edit)
|
||||
binding.topToolbar.statusContainer.hide()
|
||||
binding.topToolbar.status.hide()
|
||||
} else {
|
||||
binding.topToolbar.hide()
|
||||
}
|
||||
|
|
|
@ -299,4 +299,10 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|center_horizontal" />
|
||||
|
||||
<androidx.compose.ui.platform.ComposeView
|
||||
android:id="@+id/syncStatusWidget"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|center_horizontal" />
|
||||
|
||||
</FrameLayout>
|
|
@ -188,4 +188,12 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
|
||||
<androidx.compose.ui.platform.ComposeView
|
||||
android:id="@+id/syncStatusWidget"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.motion.widget.MotionLayout>
|
|
@ -97,6 +97,12 @@
|
|||
app:applyMotionScene="false"
|
||||
app:visibilityMode="ignore"/>
|
||||
</Constraint>
|
||||
<Constraint
|
||||
android:id="@id/syncStatusWidget">
|
||||
<PropertySet
|
||||
app:applyMotionScene="false"
|
||||
app:visibilityMode="ignore"/>
|
||||
</Constraint>
|
||||
</ConstraintSet>
|
||||
|
||||
<ConstraintSet android:id="@+id/end">
|
||||
|
@ -185,6 +191,12 @@
|
|||
app:applyMotionScene="false"
|
||||
app:visibilityMode="ignore"/>
|
||||
</Constraint>
|
||||
<Constraint
|
||||
android:id="@id/syncStatusWidget">
|
||||
<PropertySet
|
||||
app:applyMotionScene="false"
|
||||
app:visibilityMode="ignore"/>
|
||||
</Constraint>
|
||||
</ConstraintSet>
|
||||
|
||||
</MotionScene>
|
|
@ -1,10 +0,0 @@
|
|||
package com.anytypeio.anytype.core_models
|
||||
|
||||
enum class SyncStatus {
|
||||
UNKNOWN,
|
||||
OFFLINE,
|
||||
SYNCING,
|
||||
SYNCED,
|
||||
FAILED,
|
||||
INCOMPATIBLE_VERSION
|
||||
}
|
|
@ -60,13 +60,16 @@ sealed class SpaceInviteError : Exception() {
|
|||
class InvalidInvite : SpaceInviteError()
|
||||
}
|
||||
|
||||
data class SpaceSyncUpdate(
|
||||
val id: String,
|
||||
val status: SpaceSyncStatus,
|
||||
val network: SpaceSyncNetwork,
|
||||
val error: SpaceSyncError?,
|
||||
val syncingObjectsCounter: Long
|
||||
)
|
||||
sealed class SpaceSyncUpdate {
|
||||
data object Initial : SpaceSyncUpdate()
|
||||
data class Update(
|
||||
val id: String,
|
||||
val status: SpaceSyncStatus,
|
||||
val network: SpaceSyncNetwork,
|
||||
val error: SpaceSyncError,
|
||||
val syncingObjectsCounter: Long
|
||||
) : SpaceSyncUpdate()
|
||||
}
|
||||
|
||||
enum class SpaceSyncStatus {
|
||||
SYNCED,
|
||||
|
@ -88,11 +91,14 @@ enum class SpaceSyncError {
|
|||
NETWORK_ERROR
|
||||
}
|
||||
|
||||
data class P2PStatusUpdate(
|
||||
val spaceId: String,
|
||||
val status: P2PStatus,
|
||||
val devicesCounter: Long
|
||||
)
|
||||
sealed class P2PStatusUpdate {
|
||||
data object Initial : P2PStatusUpdate()
|
||||
data class Update(
|
||||
val spaceId: String,
|
||||
val status: P2PStatus,
|
||||
val devicesCounter: Long
|
||||
) : P2PStatusUpdate()
|
||||
}
|
||||
|
||||
enum class P2PStatus {
|
||||
NOT_CONNECTED,
|
||||
|
|
|
@ -13,7 +13,6 @@ import com.anytypeio.anytype.core_ui.R
|
|||
import com.anytypeio.anytype.core_utils.const.MimeTypes
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectLayoutView
|
||||
import com.anytypeio.anytype.presentation.sets.model.ColumnView
|
||||
import com.anytypeio.anytype.presentation.sync.SyncStatusView
|
||||
|
||||
fun Context.drawable(
|
||||
@DrawableRes id: Int
|
||||
|
@ -293,30 +292,4 @@ fun RelationFormat.getPrettyName(): Int = when (this) {
|
|||
RelationFormat.OBJECT -> R.string.relation_format_object
|
||||
RelationFormat.RELATIONS -> R.string.relation_format_relation
|
||||
RelationFormat.UNDEFINED -> R.string.undefined
|
||||
}
|
||||
|
||||
fun SyncStatusView?.getLabelText(context: Context): String = when (this) {
|
||||
SyncStatusView.Unknown -> context.getString(R.string.sync_status_unknown)
|
||||
SyncStatusView.Offline -> context.getString(R.string.sync_status_offline)
|
||||
SyncStatusView.Syncing -> context.getString(R.string.sync_status_syncing)
|
||||
SyncStatusView.Failed -> context.getString(R.string.sync_status_failed)
|
||||
SyncStatusView.IncompatibleVersion -> context.getString(R.string.sync_status_incompatible)
|
||||
SyncStatusView.Synced.LocalOnly -> context.getString(R.string.sync_status_local_only)
|
||||
SyncStatusView.Synced.AnyNetwork -> context.getString(R.string.sync_status_synced)
|
||||
SyncStatusView.Synced.SelfHostedNetwork -> context.getString(R.string.sync_status_synced)
|
||||
SyncStatusView.Synced.StagingNetwork -> context.getString(R.string.sync_status_synced)
|
||||
else -> ""
|
||||
}
|
||||
|
||||
fun SyncStatusView?.getToastMsg(context: Context): String = when (this) {
|
||||
SyncStatusView.Failed -> context.getString(R.string.sync_status_toast_failed)
|
||||
SyncStatusView.IncompatibleVersion -> context.getString(R.string.sync_status_toast_incompatible)
|
||||
SyncStatusView.Offline -> context.getString(R.string.sync_status_toast_offline)
|
||||
SyncStatusView.Synced.AnyNetwork -> context.getString(R.string.sync_status_toast_synced)
|
||||
SyncStatusView.Synced.LocalOnly -> context.getString(R.string.sync_status_toast_synced_local)
|
||||
SyncStatusView.Synced.SelfHostedNetwork -> context.getString(R.string.sync_status_toast_synced_self_hosted)
|
||||
SyncStatusView.Synced.StagingNetwork -> context.getString(R.string.sync_status_toast_synced_staging)
|
||||
SyncStatusView.Syncing -> context.getString(R.string.sync_status_toast_syncing)
|
||||
SyncStatusView.Unknown -> context.getString(R.string.sync_status_toast_unknown)
|
||||
else -> ""
|
||||
}
|
|
@ -0,0 +1,543 @@
|
|||
package com.anytypeio.anytype.core_ui.syncstatus
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.slideInVertically
|
||||
import androidx.compose.animation.slideOutVertically
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.gestures.Orientation
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.material.CircularProgressIndicator
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.FractionalThreshold
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.rememberSwipeableState
|
||||
import androidx.compose.material.swipeable
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.ElevatedCard
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.anytypeio.anytype.core_models.multiplayer.P2PStatus
|
||||
import com.anytypeio.anytype.core_models.multiplayer.P2PStatusUpdate
|
||||
import com.anytypeio.anytype.core_models.multiplayer.SpaceSyncError
|
||||
import com.anytypeio.anytype.core_models.multiplayer.SpaceSyncNetwork
|
||||
import com.anytypeio.anytype.core_models.multiplayer.SpaceSyncStatus
|
||||
import com.anytypeio.anytype.core_models.multiplayer.SpaceSyncUpdate
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.foundation.Divider
|
||||
import com.anytypeio.anytype.core_ui.views.BodyRegular
|
||||
import com.anytypeio.anytype.core_ui.views.Relations3
|
||||
import com.anytypeio.anytype.core_ui.views.Title2
|
||||
import com.anytypeio.anytype.core_ui.widgets.DragStates
|
||||
import com.anytypeio.anytype.presentation.sync.SyncStatusWidgetState
|
||||
import kotlin.math.roundToInt
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
fun SpaceSyncStatusScreen(
|
||||
uiState: SyncStatusWidgetState,
|
||||
onDismiss: () -> Unit,
|
||||
scope: CoroutineScope
|
||||
) {
|
||||
val isVisible = uiState is SyncStatusWidgetState.Success || uiState is SyncStatusWidgetState.Error
|
||||
|
||||
val swappableState = rememberSwipeableState(DragStates.VISIBLE)
|
||||
if (swappableState.isAnimationRunning && swappableState.targetValue == DragStates.DISMISSED) {
|
||||
DisposableEffect(Unit) {
|
||||
onDispose {
|
||||
onDismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isVisible) {
|
||||
DisposableEffect(Unit) {
|
||||
onDispose {
|
||||
scope.launch { swappableState.snapTo(DragStates.VISIBLE) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val sizePx = with(LocalDensity.current) { LocalConfiguration.current.screenHeightDp.dp.toPx() }
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = isVisible,
|
||||
enter = slideInVertically { it },
|
||||
exit = slideOutVertically { it },
|
||||
modifier = Modifier
|
||||
.swipeable(
|
||||
state = swappableState,
|
||||
orientation = Orientation.Vertical,
|
||||
anchors = mapOf(0f to DragStates.VISIBLE, sizePx to DragStates.DISMISSED),
|
||||
thresholds = { _, _ -> FractionalThreshold(0.3f) })
|
||||
.offset { IntOffset(0, swappableState.offset.value.roundToInt()) }
|
||||
) {
|
||||
ElevatedCard(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.padding(start = 8.dp, end = 8.dp, bottom = 10.dp),
|
||||
colors = CardDefaults.cardColors(
|
||||
containerColor = colorResource(id = R.color.background_secondary)
|
||||
),
|
||||
elevation = CardDefaults.elevatedCardElevation(
|
||||
defaultElevation = 16.dp
|
||||
)
|
||||
) {
|
||||
when (uiState) {
|
||||
is SyncStatusWidgetState.Error -> ErrorState()
|
||||
SyncStatusWidgetState.Hidden -> LoadingState()
|
||||
is SyncStatusWidgetState.Success -> SuccessState(
|
||||
spaceSyncUpdate = uiState.spaceSyncUpdate,
|
||||
p2pStatus = uiState.p2PStatusUpdate
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class MenuVisibilityState(val fraction: Float) { Hidden(0f), Visible(1f) }
|
||||
|
||||
@Composable
|
||||
private fun ColumnScope.LoadingState() {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier
|
||||
.size(24.dp)
|
||||
.padding(bottom = 16.dp)
|
||||
.align(Alignment.CenterHorizontally),
|
||||
color = colorResource(R.color.shape_secondary)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ColumnScope.ErrorState() {
|
||||
Text(
|
||||
text = stringResource(id = R.string.sync_status_get_error),
|
||||
style = BodyRegular,
|
||||
color = colorResource(R.color.palette_dark_red),
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.align(Alignment.CenterHorizontally)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SuccessState(spaceSyncUpdate: SpaceSyncUpdate, p2pStatus: P2PStatusUpdate) {
|
||||
if (spaceSyncUpdate is SpaceSyncUpdate.Update) {
|
||||
SpaceSyncStatusItem(spaceSyncUpdate)
|
||||
}
|
||||
Divider()
|
||||
if (p2pStatus is P2PStatusUpdate.Update) {
|
||||
P2PStatusItem(p2pStatus)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun P2PStatusItem(
|
||||
p2pStatus: P2PStatusUpdate.Update
|
||||
) {
|
||||
val networkCardSettings = getP2PCardSettings(p2pStatus = p2pStatus)
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(72.dp)
|
||||
.padding(horizontal = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.wrapContentSize(),
|
||||
painter = networkCardSettings.icon,
|
||||
contentDescription = "p2p status icon",
|
||||
alpha = networkCardSettings.alpha
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 12.dp)
|
||||
) {
|
||||
Text(
|
||||
text = networkCardSettings.mainText,
|
||||
style = Title2,
|
||||
color = colorResource(R.color.text_primary)
|
||||
)
|
||||
if (networkCardSettings.secondaryText != null) {
|
||||
Text(
|
||||
text = networkCardSettings.secondaryText,
|
||||
style = Relations3,
|
||||
color = colorResource(R.color.text_secondary)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SpaceSyncStatusItem(
|
||||
spaceSyncUpdate: SpaceSyncUpdate.Update
|
||||
) {
|
||||
val networkCardSettings = getNetworkCardSettings(
|
||||
syncStatus = spaceSyncUpdate.status,
|
||||
network = spaceSyncUpdate.network,
|
||||
error = spaceSyncUpdate.error,
|
||||
syncingObjectsCounter = spaceSyncUpdate.syncingObjectsCounter
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(72.dp)
|
||||
.padding(horizontal = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.wrapContentSize(),
|
||||
painter = networkCardSettings.icon,
|
||||
contentDescription = "dfas",
|
||||
alpha = networkCardSettings.alpha
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 12.dp)
|
||||
) {
|
||||
Text(
|
||||
text = networkCardSettings.mainText,
|
||||
style = Title2,
|
||||
color = colorResource(R.color.text_primary)
|
||||
)
|
||||
if (networkCardSettings.secondaryText != null) {
|
||||
Text(
|
||||
text = networkCardSettings.secondaryText,
|
||||
style = Relations3,
|
||||
color = colorResource(R.color.text_secondary)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun getP2PCardSettings(
|
||||
p2pStatus: P2PStatusUpdate.Update
|
||||
): CardSettings {
|
||||
return when (p2pStatus.status) {
|
||||
P2PStatus.NOT_CONNECTED -> {
|
||||
CardSettings(
|
||||
icon = painterResource(R.drawable.ic_sync_p2p_default),
|
||||
mainText = stringResource(id = R.string.sync_status_p2p_connecting),
|
||||
)
|
||||
}
|
||||
|
||||
P2PStatus.NOT_POSSIBLE -> {
|
||||
CardSettings(
|
||||
icon = painterResource(R.drawable.ic_sync_p2p_error),
|
||||
mainText = stringResource(id = R.string.sync_status_p2p),
|
||||
secondaryText = stringResource(id = R.string.sync_status_p2p_disabled)
|
||||
)
|
||||
}
|
||||
|
||||
P2PStatus.CONNECTED -> {
|
||||
CardSettings(
|
||||
icon = painterResource(R.drawable.ic_sync_p2p_connected),
|
||||
mainText = stringResource(id = R.string.sync_status_p2p),
|
||||
secondaryText = pluralStringResource(
|
||||
id = R.plurals.sync_status_p2p_devices,
|
||||
count = p2pStatus.devicesCounter.toInt(),
|
||||
formatArgs = arrayOf(p2pStatus.devicesCounter.toInt())
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun getNetworkCardSettings(
|
||||
syncStatus: SpaceSyncStatus,
|
||||
network: SpaceSyncNetwork,
|
||||
error: SpaceSyncError,
|
||||
syncingObjectsCounter: Long
|
||||
): CardSettings {
|
||||
return when (network) {
|
||||
SpaceSyncNetwork.ANYTYPE -> when (syncStatus) {
|
||||
SpaceSyncStatus.SYNCED -> {
|
||||
CardSettings(
|
||||
icon = painterResource(R.drawable.ic_sync_net_connected),
|
||||
mainText = stringResource(id = R.string.sync_status_anytype_network),
|
||||
secondaryText = stringResource(id = R.string.sync_status_anytype_end_to_end)
|
||||
)
|
||||
}
|
||||
|
||||
SpaceSyncStatus.SYNCING -> {
|
||||
CardSettings(
|
||||
icon = painterResource(R.drawable.ic_sync_net_connected),
|
||||
alpha = 0.5f,
|
||||
withAnimation = true,
|
||||
mainText = stringResource(id = R.string.sync_status_anytype_network),
|
||||
secondaryText = pluralStringResource(
|
||||
id = R.plurals.sync_status_network_items,
|
||||
count = syncingObjectsCounter.toInt(),
|
||||
formatArgs = arrayOf(syncingObjectsCounter.toInt())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
SpaceSyncStatus.ERROR -> {
|
||||
val errorText = getErrorText(error)
|
||||
CardSettings(
|
||||
icon = painterResource(R.drawable.ic_sync_net_error),
|
||||
mainText = stringResource(id = R.string.sync_status_anytype_network),
|
||||
secondaryText = stringResource(id = errorText)
|
||||
)
|
||||
}
|
||||
|
||||
SpaceSyncStatus.OFFLINE -> {
|
||||
CardSettings(
|
||||
icon = painterResource(R.drawable.ic_sync_net_default),
|
||||
mainText = stringResource(id = R.string.sync_status_anytype_network),
|
||||
secondaryText = stringResource(id = R.string.sync_status_anytype_network_no_connecting)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
SpaceSyncNetwork.SELF_HOST -> {
|
||||
when (syncStatus) {
|
||||
SpaceSyncStatus.SYNCED -> {
|
||||
CardSettings(
|
||||
icon = painterResource(R.drawable.ic_sync_self_connected),
|
||||
mainText = stringResource(id = R.string.sync_status_self_host),
|
||||
secondaryText = stringResource(id = R.string.sync_status_self_host_synced)
|
||||
)
|
||||
}
|
||||
|
||||
SpaceSyncStatus.SYNCING -> {
|
||||
CardSettings(
|
||||
icon = painterResource(R.drawable.ic_sync_self_connected),
|
||||
alpha = 0.5f,
|
||||
withAnimation = true,
|
||||
mainText = stringResource(id = R.string.sync_status_self_host),
|
||||
secondaryText = pluralStringResource(
|
||||
id = R.plurals.sync_status_self_host_syncing,
|
||||
count = syncingObjectsCounter.toInt(),
|
||||
formatArgs = arrayOf(syncingObjectsCounter.toInt())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
SpaceSyncStatus.ERROR -> {
|
||||
val errorText = getErrorText(error)
|
||||
CardSettings(
|
||||
icon = painterResource(R.drawable.ic_sync_self_error),
|
||||
mainText = stringResource(id = R.string.sync_status_self_host),
|
||||
secondaryText = stringResource(id = errorText)
|
||||
)
|
||||
}
|
||||
|
||||
SpaceSyncStatus.OFFLINE -> {
|
||||
CardSettings(
|
||||
icon = painterResource(R.drawable.ic_sync_self_default),
|
||||
mainText = stringResource(id = R.string.sync_status_self_host),
|
||||
secondaryText = stringResource(id = R.string.sync_status_anytype_network_no_connecting)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SpaceSyncNetwork.LOCAL_ONLY -> {
|
||||
CardSettings(
|
||||
icon = painterResource(R.drawable.ic_sync_local_only),
|
||||
mainText = stringResource(id = R.string.sync_status_local_only_title),
|
||||
secondaryText = stringResource(id = R.string.sync_status_data_backup)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getErrorText(error: SpaceSyncError): Int {
|
||||
return when (error) {
|
||||
SpaceSyncError.NULL -> R.string.sync_status_unrecognized
|
||||
SpaceSyncError.STORAGE_LIMIT_EXCEED -> R.string.sync_status_storage_limit_exceed
|
||||
SpaceSyncError.INCOMPATIBLE_VERSION -> R.string.sync_status_incompatible_version
|
||||
SpaceSyncError.NETWORK_ERROR -> R.string.sync_status_network_error
|
||||
}
|
||||
}
|
||||
|
||||
private data class CardSettings(
|
||||
val icon: Painter,
|
||||
val alpha: Float = 1f,
|
||||
val withAnimation: Boolean = false,
|
||||
val mainText: String,
|
||||
val secondaryText: String? = null
|
||||
)
|
||||
|
||||
@Preview(name = "AnytypeNetworkSynced", showBackground = true)
|
||||
@Composable
|
||||
fun SpaceSyncStatusPreview1() {
|
||||
val spaceSyncUpdate = SpaceSyncUpdate.Update(
|
||||
id = "1",
|
||||
status = SpaceSyncStatus.SYNCED,
|
||||
network = SpaceSyncNetwork.ANYTYPE,
|
||||
error = SpaceSyncError.NULL,
|
||||
syncingObjectsCounter = 0
|
||||
)
|
||||
SpaceSyncStatusItem(spaceSyncUpdate = spaceSyncUpdate)
|
||||
}
|
||||
|
||||
@Preview(name = "AnytypeNetworkSyncing", showBackground = true)
|
||||
@Composable
|
||||
fun SpaceSyncStatusPreview2() {
|
||||
val spaceSyncUpdate = SpaceSyncUpdate.Update(
|
||||
id = "1",
|
||||
status = SpaceSyncStatus.SYNCING,
|
||||
network = SpaceSyncNetwork.ANYTYPE,
|
||||
error = SpaceSyncError.NULL,
|
||||
syncingObjectsCounter = 2
|
||||
)
|
||||
SpaceSyncStatusItem(spaceSyncUpdate = spaceSyncUpdate)
|
||||
}
|
||||
|
||||
@Preview(name = "AnytypeNetworkError", showBackground = true)
|
||||
@Composable
|
||||
fun SpaceSyncStatusPreview3() {
|
||||
val spaceSyncUpdate = SpaceSyncUpdate.Update(
|
||||
id = "1",
|
||||
status = SpaceSyncStatus.ERROR,
|
||||
network = SpaceSyncNetwork.ANYTYPE,
|
||||
error = SpaceSyncError.NETWORK_ERROR,
|
||||
syncingObjectsCounter = 0
|
||||
)
|
||||
SpaceSyncStatusItem(spaceSyncUpdate = spaceSyncUpdate)
|
||||
}
|
||||
|
||||
@Preview(name = "AnytypeNetworkOffline", showBackground = true)
|
||||
@Composable
|
||||
fun SpaceSyncStatusPreview4() {
|
||||
val spaceSyncUpdate = SpaceSyncUpdate.Update(
|
||||
id = "1",
|
||||
status = SpaceSyncStatus.OFFLINE,
|
||||
network = SpaceSyncNetwork.ANYTYPE,
|
||||
error = SpaceSyncError.NULL,
|
||||
syncingObjectsCounter = 0
|
||||
)
|
||||
SpaceSyncStatusItem(spaceSyncUpdate = spaceSyncUpdate)
|
||||
}
|
||||
|
||||
@Preview(name = "SelfHostSynced", showBackground = true)
|
||||
@Composable
|
||||
fun SpaceSyncStatusPreview5() {
|
||||
val spaceSyncUpdate = SpaceSyncUpdate.Update(
|
||||
id = "1",
|
||||
status = SpaceSyncStatus.SYNCED,
|
||||
network = SpaceSyncNetwork.SELF_HOST,
|
||||
error = SpaceSyncError.NULL,
|
||||
syncingObjectsCounter = 0
|
||||
)
|
||||
SpaceSyncStatusItem(spaceSyncUpdate = spaceSyncUpdate)
|
||||
}
|
||||
|
||||
@Preview(name = "SelfHostSyncing", showBackground = true)
|
||||
@Composable
|
||||
fun SpaceSyncStatusPreview6() {
|
||||
val spaceSyncUpdate = SpaceSyncUpdate.Update(
|
||||
id = "1",
|
||||
status = SpaceSyncStatus.SYNCING,
|
||||
network = SpaceSyncNetwork.SELF_HOST,
|
||||
error = SpaceSyncError.NULL,
|
||||
syncingObjectsCounter = 2
|
||||
)
|
||||
SpaceSyncStatusItem(spaceSyncUpdate = spaceSyncUpdate)
|
||||
}
|
||||
|
||||
@Preview(name = "SelfHostError", showBackground = true)
|
||||
@Composable
|
||||
fun SpaceSyncStatusPreview7() {
|
||||
val spaceSyncUpdate = SpaceSyncUpdate.Update(
|
||||
id = "1",
|
||||
status = SpaceSyncStatus.ERROR,
|
||||
network = SpaceSyncNetwork.SELF_HOST,
|
||||
error = SpaceSyncError.NETWORK_ERROR,
|
||||
syncingObjectsCounter = 0
|
||||
)
|
||||
SpaceSyncStatusItem(spaceSyncUpdate = spaceSyncUpdate)
|
||||
}
|
||||
|
||||
@Preview(name = "SelfHostOffline", showBackground = true)
|
||||
@Composable
|
||||
fun SpaceSyncStatusPreview8() {
|
||||
val spaceSyncUpdate = SpaceSyncUpdate.Update(
|
||||
id = "1",
|
||||
status = SpaceSyncStatus.OFFLINE,
|
||||
network = SpaceSyncNetwork.SELF_HOST,
|
||||
error = SpaceSyncError.NULL,
|
||||
syncingObjectsCounter = 0
|
||||
)
|
||||
SpaceSyncStatusItem(spaceSyncUpdate = spaceSyncUpdate)
|
||||
}
|
||||
|
||||
@Preview(name = "LocalOnly", showBackground = true)
|
||||
@Composable
|
||||
fun SpaceSyncStatusPreview9() {
|
||||
val spaceSyncUpdate = SpaceSyncUpdate.Update(
|
||||
id = "1",
|
||||
status = SpaceSyncStatus.SYNCING,
|
||||
network = SpaceSyncNetwork.LOCAL_ONLY,
|
||||
error = SpaceSyncError.NULL,
|
||||
syncingObjectsCounter = 0
|
||||
)
|
||||
SpaceSyncStatusItem(spaceSyncUpdate = spaceSyncUpdate)
|
||||
}
|
||||
|
||||
@Preview(name = "P2PNotConnected", showBackground = true)
|
||||
@Composable
|
||||
fun SpaceSyncStatusPreview10() {
|
||||
val p2pStatus = P2PStatusUpdate.Update(
|
||||
status = P2PStatus.NOT_CONNECTED,
|
||||
devicesCounter = 0,
|
||||
spaceId = "1"
|
||||
)
|
||||
P2PStatusItem(p2pStatus = p2pStatus)
|
||||
}
|
||||
|
||||
@Preview(name = "P2PNotPossible", showBackground = true)
|
||||
@Composable
|
||||
fun SpaceSyncStatusPreview11() {
|
||||
val p2pStatus = P2PStatusUpdate.Update(
|
||||
status = P2PStatus.NOT_POSSIBLE,
|
||||
devicesCounter = 0,
|
||||
spaceId = "1"
|
||||
)
|
||||
P2PStatusItem(p2pStatus = p2pStatus)
|
||||
}
|
||||
|
||||
@Preview(name = "P2PConnected", showBackground = true)
|
||||
@Composable
|
||||
fun SpaceSyncStatusPreview12() {
|
||||
val p2pStatus = P2PStatusUpdate.Update(
|
||||
status = P2PStatus.CONNECTED,
|
||||
devicesCounter = 3,
|
||||
spaceId = "1"
|
||||
)
|
||||
P2PStatusItem(p2pStatus = p2pStatus)
|
||||
}
|
|
@ -2,46 +2,69 @@ package com.anytypeio.anytype.core_ui.widgets
|
|||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import androidx.appcompat.widget.AppCompatImageView
|
||||
import com.anytypeio.anytype.core_models.multiplayer.SpaceSyncError
|
||||
import com.anytypeio.anytype.core_models.multiplayer.SpaceSyncStatus
|
||||
import com.anytypeio.anytype.core_models.multiplayer.SpaceSyncUpdate
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.extensions.color
|
||||
import com.anytypeio.anytype.core_ui.extensions.tint
|
||||
import com.anytypeio.anytype.core_utils.ext.gone
|
||||
import com.anytypeio.anytype.core_utils.ext.visible
|
||||
import com.anytypeio.anytype.presentation.sync.SyncStatusView
|
||||
import com.anytypeio.anytype.presentation.sync.SpaceSyncAndP2PStatusState
|
||||
|
||||
class StatusBadgeWidget @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null
|
||||
) : View(context, attrs) {
|
||||
) : AppCompatImageView(context, attrs) {
|
||||
|
||||
init {
|
||||
setBackgroundResource(R.drawable.circle_solid_default)
|
||||
tint(color = context.color(R.color.palette_dark_grey))
|
||||
}
|
||||
|
||||
fun bind(status: SyncStatusView?) {
|
||||
fun bind(status: SpaceSyncAndP2PStatusState?) {
|
||||
when (status) {
|
||||
SyncStatusView.Failed,
|
||||
SyncStatusView.IncompatibleVersion -> {
|
||||
is SpaceSyncAndP2PStatusState.Error -> {
|
||||
visible()
|
||||
tint(color = context.color(R.color.palette_system_red))
|
||||
setImageResource(R.drawable.ic_sync_error_10)
|
||||
}
|
||||
SyncStatusView.Syncing -> {
|
||||
visible()
|
||||
tint(color = context.color(R.color.palette_system_amber_100))
|
||||
}
|
||||
SyncStatusView.Unknown, SyncStatusView.Offline, null -> {
|
||||
SpaceSyncAndP2PStatusState.Initial -> {
|
||||
gone()
|
||||
}
|
||||
SyncStatusView.Synced.LocalOnly -> {
|
||||
gone()
|
||||
is SpaceSyncAndP2PStatusState.Success -> {
|
||||
when (val spaceSyncUpdate = status.spaceSyncUpdate) {
|
||||
is SpaceSyncUpdate.Update -> {
|
||||
val error = spaceSyncUpdate.error
|
||||
if (error != SpaceSyncError.NULL) {
|
||||
visible()
|
||||
setImageResource(R.drawable.ic_sync_error_10)
|
||||
} else {
|
||||
return when (spaceSyncUpdate.status) {
|
||||
SpaceSyncStatus.SYNCED -> {
|
||||
visible()
|
||||
setImageResource(R.drawable.ic_synced_10)
|
||||
}
|
||||
|
||||
SpaceSyncStatus.SYNCING -> {
|
||||
visible()
|
||||
setImageResource(R.drawable.ic_syncing)
|
||||
}
|
||||
|
||||
SpaceSyncStatus.ERROR -> {
|
||||
visible()
|
||||
setImageResource(R.drawable.ic_sync_error_10)
|
||||
}
|
||||
|
||||
SpaceSyncStatus.OFFLINE -> {
|
||||
visible()
|
||||
setImageResource(R.drawable.ic_sync_grey_10)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SpaceSyncUpdate.Initial -> {
|
||||
gone()
|
||||
}
|
||||
}
|
||||
}
|
||||
SyncStatusView.Synced.AnyNetwork,
|
||||
SyncStatusView.Synced.SelfHostedNetwork,
|
||||
SyncStatusView.Synced.StagingNetwork -> {
|
||||
visible()
|
||||
tint(color = context.color(R.color.palette_system_green))
|
||||
|
||||
null -> {
|
||||
gone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,8 +26,6 @@ class ObjectTopToolbar @JvmOverloads constructor(
|
|||
)
|
||||
|
||||
val status: StatusBadgeWidget get() = binding.statusBadge
|
||||
val statusText: TextView get() = binding.tvStatus
|
||||
val statusContainer: ViewGroup get() = binding.statusContainer
|
||||
val menu: View get() = binding.threeDotsButton
|
||||
val container: ViewGroup get() = binding.titleContainer
|
||||
val title: TextView get() = binding.tvTopToolbarTitle
|
||||
|
@ -44,22 +42,20 @@ class ObjectTopToolbar @JvmOverloads constructor(
|
|||
if (overCover) {
|
||||
menu.setBackgroundResource(R.drawable.rect_object_menu_button_default)
|
||||
ivThreeDots.imageTintList = ColorStateList.valueOf(Color.WHITE)
|
||||
statusContainer.setBackgroundResource(R.drawable.rect_object_menu_button_default)
|
||||
statusText.setTextColor(Color.WHITE)
|
||||
statusBadge.setBackgroundResource(R.drawable.rect_object_menu_button_default)
|
||||
} else {
|
||||
menu.background = null
|
||||
ivThreeDots.imageTintList = null
|
||||
statusContainer.background = null
|
||||
statusText.setTextColor(context.getColor(R.color.default_status_text_color))
|
||||
statusBadge.background = null
|
||||
}
|
||||
}
|
||||
|
||||
fun hideStatusContainer() {
|
||||
binding.statusContainer.alpha = 0f
|
||||
binding.statusBadge.alpha = 0f
|
||||
}
|
||||
|
||||
fun showStatusContainer() {
|
||||
binding.statusContainer.animate().alpha(1f).setDuration(300).start()
|
||||
binding.statusBadge.animate().alpha(1f).setDuration(300).start()
|
||||
}
|
||||
|
||||
fun setIsLocked(isLocked: Boolean) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<solid android:color="@color/orange" />
|
||||
<size
|
||||
android:width="10dp"
|
||||
android:height="10dp" />
|
||||
</shape>
|
9
core-ui/src/main/res/drawable/ic_sync_error_10.xml
Normal file
9
core-ui/src/main/res/drawable/ic_sync_error_10.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="10dp"
|
||||
android:height="10dp"
|
||||
android:viewportWidth="10"
|
||||
android:viewportHeight="10">
|
||||
<path
|
||||
android:pathData="M5,5m-5,0a5,5 0,1 1,10 0a5,5 0,1 1,-10 0"
|
||||
android:fillColor="#F55522"/>
|
||||
</vector>
|
9
core-ui/src/main/res/drawable/ic_sync_grey_10.xml
Normal file
9
core-ui/src/main/res/drawable/ic_sync_grey_10.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="10dp"
|
||||
android:height="10dp"
|
||||
android:viewportWidth="10"
|
||||
android:viewportHeight="10">
|
||||
<path
|
||||
android:pathData="M5,5m-5,0a5,5 0,1 1,10 0a5,5 0,1 1,-10 0"
|
||||
android:fillColor="#A7A7A7"/>
|
||||
</vector>
|
13
core-ui/src/main/res/drawable/ic_sync_local_only.xml
Normal file
13
core-ui/src/main/res/drawable/ic_sync_local_only.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:pathData="M24,0L24,0A24,24 0,0 1,48 24L48,24A24,24 0,0 1,24 48L24,48A24,24 0,0 1,0 24L0,24A24,24 0,0 1,24 0z"
|
||||
android:fillColor="@color/shape_secondary"/>
|
||||
<path
|
||||
android:pathData="M17,16.5C17,15.119 18.119,14 19.5,14H29.5C30.881,14 32,15.119 32,16.5V31.5C32,32.881 30.881,34 29.5,34H19.5C18.119,34 17,32.881 17,31.5V16.5ZM19.5,15C18.672,15 18,15.672 18,16.5V31.5C18,32.328 18.672,33 19.5,33H29.5C30.328,33 31,32.328 31,31.5V16.5C31,15.672 30.328,15 29.5,15H19.5ZM22.5,17.25C22.5,16.836 22.836,16.5 23.25,16.5H25.75C26.164,16.5 26.5,16.836 26.5,17.25C26.5,17.664 26.164,18 25.75,18H23.25C22.836,18 22.5,17.664 22.5,17.25ZM21.25,30C20.836,30 20.5,30.336 20.5,30.75C20.5,31.164 20.836,31.5 21.25,31.5H27.75C28.164,31.5 28.5,31.164 28.5,30.75C28.5,30.336 28.164,30 27.75,30H21.25Z"
|
||||
android:fillColor="@color/glyph_active"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
19
core-ui/src/main/res/drawable/ic_sync_net_connected.xml
Normal file
19
core-ui/src/main/res/drawable/ic_sync_net_connected.xml
Normal file
|
@ -0,0 +1,19 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:pathData="M24,0L24,0A24,24 0,0 1,48 24L48,24A24,24 0,0 1,24 48L24,48A24,24 0,0 1,0 24L0,24A24,24 0,0 1,24 0z"
|
||||
android:fillColor="@color/palette_light_lime"/>
|
||||
<path
|
||||
android:pathData="M20.5,16L20.5,16A0.5,0.5 0,0 1,21 16.5L21,19.5A0.5,0.5 0,0 1,20.5 20L20.5,20A0.5,0.5 0,0 1,20 19.5L20,16.5A0.5,0.5 0,0 1,20.5 16z"
|
||||
android:fillColor="@color/palette_dark_lime"/>
|
||||
<path
|
||||
android:pathData="M27.5,16L27.5,16A0.5,0.5 0,0 1,28 16.5L28,19.5A0.5,0.5 0,0 1,27.5 20L27.5,20A0.5,0.5 0,0 1,27 19.5L27,16.5A0.5,0.5 0,0 1,27.5 16z"
|
||||
android:fillColor="@color/palette_dark_lime"/>
|
||||
<path
|
||||
android:pathData="M16.667,25C17.035,25 17.329,25.3 17.376,25.665C17.753,28.574 20.575,30.833 24,30.833C27.425,30.833 30.247,28.574 30.624,25.665C30.671,25.3 30.965,25 31.333,25C31.701,25 32.004,25.3 31.964,25.666C31.581,29.219 28.162,32 24,32C19.838,32 16.419,29.219 16.036,25.666C15.996,25.3 16.299,25 16.667,25Z"
|
||||
android:fillColor="@color/palette_dark_lime"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
21
core-ui/src/main/res/drawable/ic_sync_net_default.xml
Normal file
21
core-ui/src/main/res/drawable/ic_sync_net_default.xml
Normal file
|
@ -0,0 +1,21 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:pathData="M24,0L24,0A24,24 0,0 1,48 24L48,24A24,24 0,0 1,24 48L24,48A24,24 0,0 1,0 24L0,24A24,24 0,0 1,24 0z"
|
||||
android:fillColor="@color/shape_secondary"/>
|
||||
<path
|
||||
android:pathData="M20.5,16L20.5,16A0.5,0.5 0,0 1,21 16.5L21,19.5A0.5,0.5 0,0 1,20.5 20L20.5,20A0.5,0.5 0,0 1,20 19.5L20,16.5A0.5,0.5 0,0 1,20.5 16z"
|
||||
android:fillColor="@color/glyph_active"/>
|
||||
<path
|
||||
android:pathData="M27.5,16L27.5,16A0.5,0.5 0,0 1,28 16.5L28,19.5A0.5,0.5 0,0 1,27.5 20L27.5,20A0.5,0.5 0,0 1,27 19.5L27,16.5A0.5,0.5 0,0 1,27.5 16z"
|
||||
android:fillColor="@color/glyph_active"/>
|
||||
<path
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M16,29H32"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="@color/glyph_active"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
21
core-ui/src/main/res/drawable/ic_sync_net_error.xml
Normal file
21
core-ui/src/main/res/drawable/ic_sync_net_error.xml
Normal file
|
@ -0,0 +1,21 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:pathData="M24,0L24,0A24,24 0,0 1,48 24L48,24A24,24 0,0 1,24 48L24,48A24,24 0,0 1,0 24L0,24A24,24 0,0 1,24 0z"
|
||||
android:fillColor="@color/palette_light_red"/>
|
||||
<path
|
||||
android:pathData="M20.5,16L20.5,16A0.5,0.5 0,0 1,21 16.5L21,19.5A0.5,0.5 0,0 1,20.5 20L20.5,20A0.5,0.5 0,0 1,20 19.5L20,16.5A0.5,0.5 0,0 1,20.5 16z"
|
||||
android:fillColor="@color/palette_system_red"/>
|
||||
<path
|
||||
android:pathData="M27.5,16L27.5,16A0.5,0.5 0,0 1,28 16.5L28,19.5A0.5,0.5 0,0 1,27.5 20L27.5,20A0.5,0.5 0,0 1,27 19.5L27,16.5A0.5,0.5 0,0 1,27.5 16z"
|
||||
android:fillColor="@color/palette_system_red"/>
|
||||
<path
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M16,30L31.912,28.327"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="@color/palette_system_red"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
21
core-ui/src/main/res/drawable/ic_sync_offline.xml
Normal file
21
core-ui/src/main/res/drawable/ic_sync_offline.xml
Normal file
|
@ -0,0 +1,21 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:pathData="M24,0L24,0A24,24 0,0 1,48 24L48,24A24,24 0,0 1,24 48L24,48A24,24 0,0 1,0 24L0,24A24,24 0,0 1,24 0z"
|
||||
android:fillColor="@color/shape_secondary"/>
|
||||
<path
|
||||
android:pathData="M20.5,16L20.5,16A0.5,0.5 0,0 1,21 16.5L21,19.5A0.5,0.5 0,0 1,20.5 20L20.5,20A0.5,0.5 0,0 1,20 19.5L20,16.5A0.5,0.5 0,0 1,20.5 16z"
|
||||
android:fillColor="@color/glyph_active"/>
|
||||
<path
|
||||
android:pathData="M27.5,16L27.5,16A0.5,0.5 0,0 1,28 16.5L28,19.5A0.5,0.5 0,0 1,27.5 20L27.5,20A0.5,0.5 0,0 1,27 19.5L27,16.5A0.5,0.5 0,0 1,27.5 16z"
|
||||
android:fillColor="@color/glyph_active"/>
|
||||
<path
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M16,29H32"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="@color/glyph_active"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
13
core-ui/src/main/res/drawable/ic_sync_p2p_connected.xml
Normal file
13
core-ui/src/main/res/drawable/ic_sync_p2p_connected.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:pathData="M24,0L24,0A24,24 0,0 1,48 24L48,24A24,24 0,0 1,24 48L24,48A24,24 0,0 1,0 24L0,24A24,24 0,0 1,24 0z"
|
||||
android:fillColor="@color/palette_light_lime"/>
|
||||
<path
|
||||
android:pathData="M26,18C26,19.105 25.105,20 24,20C22.895,20 22,19.105 22,18C22,16.895 22.895,16 24,16C25.105,16 26,16.895 26,18ZM27,18C27,19.657 25.657,21 24,21C22.343,21 21,19.657 21,18C21,16.343 22.343,15 24,15C25.657,15 27,16.343 27,18ZM26,30C26,31.105 25.105,32 24,32C22.895,32 22,31.105 22,30C22,28.895 22.895,28 24,28C25.105,28 26,28.895 26,30ZM27,30C27,31.657 25.657,33 24,33C22.343,33 21,31.657 21,30C21,28.343 22.343,27 24,27C25.657,27 27,28.343 27,30ZM18,26C19.105,26 20,25.105 20,24C20,22.895 19.105,22 18,22C16.895,22 16,22.895 16,24C16,25.105 16.895,26 18,26ZM18,27C19.657,27 21,25.657 21,24C21,22.343 19.657,21 18,21C16.343,21 15,22.343 15,24C15,25.657 16.343,27 18,27ZM32,24C32,25.105 31.105,26 30,26C28.895,26 28,25.105 28,24C28,22.895 28.895,22 30,22C31.105,22 32,22.895 32,24ZM33,24C33,25.657 31.657,27 30,27C28.343,27 27,25.657 27,24C27,22.343 28.343,21 30,21C31.657,21 33,22.343 33,24Z"
|
||||
android:fillColor="@color/palette_dark_lime"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
13
core-ui/src/main/res/drawable/ic_sync_p2p_default.xml
Normal file
13
core-ui/src/main/res/drawable/ic_sync_p2p_default.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:pathData="M24,0L24,0A24,24 0,0 1,48 24L48,24A24,24 0,0 1,24 48L24,48A24,24 0,0 1,0 24L0,24A24,24 0,0 1,24 0z"
|
||||
android:fillColor="@color/shape_secondary"/>
|
||||
<path
|
||||
android:pathData="M26,18C26,19.105 25.105,20 24,20C22.895,20 22,19.105 22,18C22,16.895 22.895,16 24,16C25.105,16 26,16.895 26,18ZM27,18C27,19.657 25.657,21 24,21C22.343,21 21,19.657 21,18C21,16.343 22.343,15 24,15C25.657,15 27,16.343 27,18ZM26,30C26,31.105 25.105,32 24,32C22.895,32 22,31.105 22,30C22,28.895 22.895,28 24,28C25.105,28 26,28.895 26,30ZM27,30C27,31.657 25.657,33 24,33C22.343,33 21,31.657 21,30C21,28.343 22.343,27 24,27C25.657,27 27,28.343 27,30ZM18,26C19.105,26 20,25.105 20,24C20,22.895 19.105,22 18,22C16.895,22 16,22.895 16,24C16,25.105 16.895,26 18,26ZM18,27C19.657,27 21,25.657 21,24C21,22.343 19.657,21 18,21C16.343,21 15,22.343 15,24C15,25.657 16.343,27 18,27ZM32,24C32,25.105 31.105,26 30,26C28.895,26 28,25.105 28,24C28,22.895 28.895,22 30,22C31.105,22 32,22.895 32,24ZM33,24C33,25.657 31.657,27 30,27C28.343,27 27,25.657 27,24C27,22.343 28.343,21 30,21C31.657,21 33,22.343 33,24Z"
|
||||
android:fillColor="@color/glyph_active"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
13
core-ui/src/main/res/drawable/ic_sync_p2p_error.xml
Normal file
13
core-ui/src/main/res/drawable/ic_sync_p2p_error.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:pathData="M24,0L24,0A24,24 0,0 1,48 24L48,24A24,24 0,0 1,24 48L24,48A24,24 0,0 1,0 24L0,24A24,24 0,0 1,24 0z"
|
||||
android:fillColor="@color/palette_light_red"/>
|
||||
<path
|
||||
android:pathData="M26,18C26,19.105 25.105,20 24,20C22.895,20 22,19.105 22,18C22,16.895 22.895,16 24,16C25.105,16 26,16.895 26,18ZM27,18C27,19.657 25.657,21 24,21C22.343,21 21,19.657 21,18C21,16.343 22.343,15 24,15C25.657,15 27,16.343 27,18ZM26,30C26,31.105 25.105,32 24,32C22.895,32 22,31.105 22,30C22,28.895 22.895,28 24,28C25.105,28 26,28.895 26,30ZM27,30C27,31.657 25.657,33 24,33C22.343,33 21,31.657 21,30C21,28.343 22.343,27 24,27C25.657,27 27,28.343 27,30ZM18,26C19.105,26 20,25.105 20,24C20,22.895 19.105,22 18,22C16.895,22 16,22.895 16,24C16,25.105 16.895,26 18,26ZM18,27C19.657,27 21,25.657 21,24C21,22.343 19.657,21 18,21C16.343,21 15,22.343 15,24C15,25.657 16.343,27 18,27ZM32,24C32,25.105 31.105,26 30,26C28.895,26 28,25.105 28,24C28,22.895 28.895,22 30,22C31.105,22 32,22.895 32,24ZM33,24C33,25.657 31.657,27 30,27C28.343,27 27,25.657 27,24C27,22.343 28.343,21 30,21C31.657,21 33,22.343 33,24Z"
|
||||
android:fillColor="@color/palette_dark_red"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
13
core-ui/src/main/res/drawable/ic_sync_self_connected.xml
Normal file
13
core-ui/src/main/res/drawable/ic_sync_self_connected.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:pathData="M24,0L24,0A24,24 0,0 1,48 24L48,24A24,24 0,0 1,24 48L24,48A24,24 0,0 1,0 24L0,24A24,24 0,0 1,24 0z"
|
||||
android:fillColor="@color/palette_light_lime"/>
|
||||
<path
|
||||
android:pathData="M17,15.5C15.619,15.5 14.5,16.619 14.5,18V21C14.5,22.381 15.619,23.5 17,23.5H31C32.381,23.5 33.5,22.381 33.5,21V18C33.5,16.619 32.381,15.5 31,15.5H17ZM15.5,18C15.5,17.172 16.172,16.5 17,16.5H31C31.828,16.5 32.5,17.172 32.5,18V21C32.5,21.828 31.828,22.5 31,22.5H17C16.172,22.5 15.5,21.828 15.5,21V18ZM17,24.5C15.619,24.5 14.5,25.619 14.5,27V30C14.5,31.381 15.619,32.5 17,32.5H31C32.381,32.5 33.5,31.381 33.5,30V27C33.5,25.619 32.381,24.5 31,24.5H17ZM15.5,27C15.5,26.172 16.172,25.5 17,25.5H31C31.828,25.5 32.5,26.172 32.5,27V30C32.5,30.828 31.828,31.5 31,31.5H17C16.172,31.5 15.5,30.828 15.5,30V27ZM17,19.5C17,18.672 17.672,18 18.5,18C19.328,18 20,18.672 20,19.5C20,20.328 19.328,21 18.5,21C17.672,21 17,20.328 17,19.5ZM18.5,27C17.672,27 17,27.672 17,28.5C17,29.328 17.672,30 18.5,30C19.328,30 20,29.328 20,28.5C20,27.672 19.328,27 18.5,27Z"
|
||||
android:fillColor="@color/palette_dark_lime"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
13
core-ui/src/main/res/drawable/ic_sync_self_default.xml
Normal file
13
core-ui/src/main/res/drawable/ic_sync_self_default.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:pathData="M24,0L24,0A24,24 0,0 1,48 24L48,24A24,24 0,0 1,24 48L24,48A24,24 0,0 1,0 24L0,24A24,24 0,0 1,24 0z"
|
||||
android:fillColor="@color/shape_secondary"/>
|
||||
<path
|
||||
android:pathData="M17,15.5C15.619,15.5 14.5,16.619 14.5,18V21C14.5,22.381 15.619,23.5 17,23.5H31C32.381,23.5 33.5,22.381 33.5,21V18C33.5,16.619 32.381,15.5 31,15.5H17ZM15.5,18C15.5,17.172 16.172,16.5 17,16.5H31C31.828,16.5 32.5,17.172 32.5,18V21C32.5,21.828 31.828,22.5 31,22.5H17C16.172,22.5 15.5,21.828 15.5,21V18ZM17,24.5C15.619,24.5 14.5,25.619 14.5,27V30C14.5,31.381 15.619,32.5 17,32.5H31C32.381,32.5 33.5,31.381 33.5,30V27C33.5,25.619 32.381,24.5 31,24.5H17ZM15.5,27C15.5,26.172 16.172,25.5 17,25.5H31C31.828,25.5 32.5,26.172 32.5,27V30C32.5,30.828 31.828,31.5 31,31.5H17C16.172,31.5 15.5,30.828 15.5,30V27ZM17,19.5C17,18.672 17.672,18 18.5,18C19.328,18 20,18.672 20,19.5C20,20.328 19.328,21 18.5,21C17.672,21 17,20.328 17,19.5ZM18.5,27C17.672,27 17,27.672 17,28.5C17,29.328 17.672,30 18.5,30C19.328,30 20,29.328 20,28.5C20,27.672 19.328,27 18.5,27Z"
|
||||
android:fillColor="@color/glyph_active"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
13
core-ui/src/main/res/drawable/ic_sync_self_error.xml
Normal file
13
core-ui/src/main/res/drawable/ic_sync_self_error.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
<path
|
||||
android:pathData="M24,0L24,0A24,24 0,0 1,48 24L48,24A24,24 0,0 1,24 48L24,48A24,24 0,0 1,0 24L0,24A24,24 0,0 1,24 0z"
|
||||
android:fillColor="@color/palette_light_red"/>
|
||||
<path
|
||||
android:pathData="M17,15.5C15.619,15.5 14.5,16.619 14.5,18V21C14.5,22.381 15.619,23.5 17,23.5H31C32.381,23.5 33.5,22.381 33.5,21V18C33.5,16.619 32.381,15.5 31,15.5H17ZM15.5,18C15.5,17.172 16.172,16.5 17,16.5H31C31.828,16.5 32.5,17.172 32.5,18V21C32.5,21.828 31.828,22.5 31,22.5H17C16.172,22.5 15.5,21.828 15.5,21V18ZM17,24.5C15.619,24.5 14.5,25.619 14.5,27V30C14.5,31.381 15.619,32.5 17,32.5H31C32.381,32.5 33.5,31.381 33.5,30V27C33.5,25.619 32.381,24.5 31,24.5H17ZM15.5,27C15.5,26.172 16.172,25.5 17,25.5H31C31.828,25.5 32.5,26.172 32.5,27V30C32.5,30.828 31.828,31.5 31,31.5H17C16.172,31.5 15.5,30.828 15.5,30V27ZM17,19.5C17,18.672 17.672,18 18.5,18C19.328,18 20,18.672 20,19.5C20,20.328 19.328,21 18.5,21C17.672,21 17,20.328 17,19.5ZM18.5,27C17.672,27 17,27.672 17,28.5C17,29.328 17.672,30 18.5,30C19.328,30 20,29.328 20,28.5C20,27.672 19.328,27 18.5,27Z"
|
||||
android:fillColor="@color/palette_dark_red"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
9
core-ui/src/main/res/drawable/ic_synced_10.xml
Normal file
9
core-ui/src/main/res/drawable/ic_synced_10.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="10dp"
|
||||
android:height="10dp"
|
||||
android:viewportWidth="10"
|
||||
android:viewportHeight="10">
|
||||
<path
|
||||
android:pathData="M5,5m-5,0a5,5 0,1 1,10 0a5,5 0,1 1,-10 0"
|
||||
android:fillColor="#5DD400"/>
|
||||
</vector>
|
19
core-ui/src/main/res/drawable/ic_syncing.xml
Normal file
19
core-ui/src/main/res/drawable/ic_syncing.xml
Normal file
|
@ -0,0 +1,19 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="20">
|
||||
<path
|
||||
android:pathData="M10,10m-10,0a10,10 0,1 1,20 0a10,10 0,1 1,-20 0"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="@color/palette_system_green"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M10,10m-7,0a7,7 0,1 1,14 0a7,7 0,1 1,-14 0"
|
||||
android:strokeAlpha="0.4"
|
||||
android:fillColor="@color/palette_system_green"
|
||||
android:fillAlpha="0.4"/>
|
||||
<path
|
||||
android:pathData="M10,10m-4,0a4,4 0,1 1,8 0a4,4 0,1 1,-8 0"
|
||||
android:fillColor="@color/palette_system_green"/>
|
||||
</vector>
|
|
@ -5,7 +5,7 @@
|
|||
<shape
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="7dp" />
|
||||
<solid android:color="#59000000" />
|
||||
<solid android:color="#26000000" />
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
|
@ -3,40 +3,16 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/statusContainer"
|
||||
android:layout_width="wrap_content"
|
||||
<com.anytypeio.anytype.core_ui.widgets.StatusBadgeWidget
|
||||
android:id="@+id/statusBadge"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="10dp"
|
||||
android:paddingStart="10dp"
|
||||
android:paddingEnd="10dp">
|
||||
|
||||
<com.anytypeio.anytype.core_ui.widgets.StatusBadgeWidget
|
||||
android:id="@+id/statusBadge"
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="10dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:backgroundTint="@color/orange" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvStatus"
|
||||
style="@style/TextView.UXStyle.Captions.1.Regular"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="6dp"
|
||||
android:textColor="@color/text_secondary"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/statusBadge"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_goneMarginStart="0dp"
|
||||
tools:text="Syncing" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
android:scaleType="center"
|
||||
android:layout_marginStart="12dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -10,8 +10,6 @@ interface FeatureToggles {
|
|||
|
||||
val isConciseLogging: Boolean
|
||||
|
||||
val excludeThreadStatusLogging: Boolean
|
||||
|
||||
val isLogEditorViewModelEvents: Boolean
|
||||
|
||||
val isLogEditorControlPanelMachine: Boolean
|
||||
|
|
|
@ -6,14 +6,14 @@ import com.anytypeio.anytype.domain.workspace.P2PStatusChannel
|
|||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface P2PStatusRemoteChannel {
|
||||
fun observe(activeSpaceId: Id): Flow<List<P2PStatusUpdate>>
|
||||
fun observe(activeSpaceId: Id): Flow<P2PStatusUpdate>
|
||||
}
|
||||
|
||||
class P2PStatusDataChannel(
|
||||
private val channel: P2PStatusRemoteChannel
|
||||
) : P2PStatusChannel {
|
||||
|
||||
override fun observe(activeSpaceId: Id): Flow<List<P2PStatusUpdate>> {
|
||||
override fun observe(activeSpaceId: Id): Flow<P2PStatusUpdate> {
|
||||
return channel.observe(activeSpaceId)
|
||||
}
|
||||
}
|
|
@ -6,14 +6,14 @@ import com.anytypeio.anytype.domain.workspace.SpaceSyncStatusChannel
|
|||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface SpaceStatusRemoteChannel {
|
||||
fun observe(activeSpaceId: String): Flow<List<SpaceSyncUpdate>>
|
||||
fun observe(activeSpaceId: String): Flow<SpaceSyncUpdate>
|
||||
}
|
||||
|
||||
class SpaceStatusDataChannel(
|
||||
private val channel: SpaceStatusRemoteChannel
|
||||
) : SpaceSyncStatusChannel {
|
||||
|
||||
override fun observe(activeSpaceId: Id): Flow<List<SpaceSyncUpdate>> {
|
||||
override fun observe(activeSpaceId: Id): Flow<SpaceSyncUpdate> {
|
||||
return channel.observe(activeSpaceId)
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package com.anytypeio.anytype.data.auth.status
|
||||
|
||||
import com.anytypeio.anytype.core_models.SyncStatus
|
||||
import com.anytypeio.anytype.domain.status.ThreadStatusChannel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
class ThreadStatusDataChannel(
|
||||
private val remote: ThreadStatusRemoteChannel,
|
||||
) : ThreadStatusChannel {
|
||||
|
||||
override fun observe(ctx: String): Flow<SyncStatus> {
|
||||
return remote.observe(ctx)
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package com.anytypeio.anytype.data.auth.status
|
||||
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.SyncStatus
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface ThreadStatusRemoteChannel {
|
||||
fun observe(ctx: Id): Flow<SyncStatus>
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package com.anytypeio.anytype.domain.status
|
||||
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.SyncStatus
|
||||
import com.anytypeio.anytype.domain.base.FlowUseCase
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class InterceptThreadStatus(
|
||||
private val context: CoroutineContext = Dispatchers.IO,
|
||||
private val channel: ThreadStatusChannel,
|
||||
) : FlowUseCase<SyncStatus, InterceptThreadStatus.Params>() {
|
||||
|
||||
override fun build(params: Params?): Flow<SyncStatus> {
|
||||
checkNotNull(params) { "Params are required for this use-case." }
|
||||
return channel.observe(params.ctx).flowOn(context)
|
||||
}
|
||||
|
||||
data class Params(val ctx: Id)
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
package com.anytypeio.anytype.domain.status
|
||||
|
||||
import com.anytypeio.anytype.core_models.Hash
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
|
||||
data class SyncAccount(
|
||||
val id: Id,
|
||||
val name: String,
|
||||
val image: Hash,
|
||||
val isOnline: Boolean,
|
||||
val lastPulled: Int,
|
||||
val lastEdited: Int,
|
||||
val devices: List<Device>,
|
||||
) {
|
||||
data class Device(
|
||||
val name: String,
|
||||
val isOnline: Boolean,
|
||||
val lastPulled: Int,
|
||||
val lastEdited: Int,
|
||||
)
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
package com.anytypeio.anytype.domain.status
|
||||
|
||||
import com.anytypeio.anytype.core_models.SyncStatus
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface ThreadStatusChannel {
|
||||
fun observe(ctx: String): Flow<SyncStatus>
|
||||
}
|
|
@ -5,5 +5,5 @@ import com.anytypeio.anytype.core_models.multiplayer.P2PStatusUpdate
|
|||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface P2PStatusChannel {
|
||||
fun observe(activeSpaceId: Id): Flow<List<P2PStatusUpdate>>
|
||||
fun observe(activeSpaceId: Id): Flow<P2PStatusUpdate>
|
||||
}
|
|
@ -5,5 +5,5 @@ import com.anytypeio.anytype.core_models.multiplayer.SpaceSyncUpdate
|
|||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface SpaceSyncStatusChannel {
|
||||
fun observe(activeSpaceId: Id): Flow<List<SpaceSyncUpdate>>
|
||||
fun observe(activeSpaceId: Id): Flow<SpaceSyncUpdate>
|
||||
}
|
|
@ -1698,4 +1698,39 @@ Please provide specific details of your needs here.</string>
|
|||
<string name="sort_empty_values_top">On top</string>
|
||||
<string name="widget_view_see_all_objects">See all objects</string>
|
||||
|
||||
<string name="sync_status_get_error">Error getting sync status</string>
|
||||
|
||||
<string name="sync_status_local_only_title">Local Only</string>
|
||||
<string name="sync_status_data_backup">Data backup is disabled</string>
|
||||
|
||||
<string name="sync_status_self_host">Self Host</string>
|
||||
<string name="sync_status_self_host_synced">Synced</string>
|
||||
<plurals name="sync_status_self_host_syncing">
|
||||
<item quantity="one">%1$d item syncing</item>
|
||||
<item quantity="other">%1$d items syncing...</item>
|
||||
</plurals>
|
||||
|
||||
<string name="sync_status_p2p">P2P Connection</string>
|
||||
<plurals name="sync_status_p2p_devices">
|
||||
<item quantity="one">%1$d device connected</item>
|
||||
<item quantity="other">%1$d devices connected</item>
|
||||
</plurals>
|
||||
<string name="sync_status_p2p_connecting">P2P Connecting...</string>
|
||||
<string name="sync_status_p2p_disabled">Disabled</string>
|
||||
<string name="sync_status_p2p_restricted">Restricted. Check device settings.</string>
|
||||
|
||||
<string name="sync_status_anytype_network">Anytype Network</string>
|
||||
<string name="sync_status_anytype_end_to_end">End-to-end encrypted</string>
|
||||
<plurals name="sync_status_network_items">
|
||||
<item quantity="one">%1$d item syncing...</item>
|
||||
<item quantity="other">%1$d items syncing...</item>
|
||||
</plurals>
|
||||
<string name="sync_status_anytype_network_connecting">Network Connecting...</string>
|
||||
<string name="sync_status_anytype_network_no_connecting">No connection</string>
|
||||
|
||||
<string name="sync_status_storage_limit_exceed">Storage limit reached</string>
|
||||
<string name="sync_status_incompatible_version">Incompatible version</string>
|
||||
<string name="sync_status_network_error">No access to the space</string>
|
||||
<string name="sync_status_unrecognized">Unrecognized error</string>
|
||||
|
||||
</resources>
|
|
@ -57,7 +57,7 @@ class MiddlewareEventChannel(
|
|||
blockDataviewIsCollectionSet != null -> true
|
||||
blockSetWidget != null -> true
|
||||
else -> false.also {
|
||||
if (featureToggles.isLogMiddlewareInteraction && threadStatus == null)
|
||||
if (featureToggles.isLogMiddlewareInteraction)
|
||||
Timber.w("Ignored event: $this")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package com.anytypeio.anytype.middleware.interactor
|
||||
|
||||
import anytype.Event
|
||||
import com.anytypeio.anytype.core_utils.tools.FeatureToggles
|
||||
import com.google.gson.Gson
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -33,16 +31,7 @@ interface MiddlewareProtobufLogger {
|
|||
|
||||
override fun logEvent(any: Any) {
|
||||
if (featureToggles.isLogMiddlewareInteraction) {
|
||||
if (featureToggles.excludeThreadStatusLogging) {
|
||||
if (any is Event && containsOnlyThreadStatusEvents(any)) {
|
||||
// Do nothing.
|
||||
} else {
|
||||
Timber.d("event -> ${any.toLogMessage()}")
|
||||
}
|
||||
} else {
|
||||
Timber.d("event -> ${any.toLogMessage()}")
|
||||
}
|
||||
|
||||
Timber.d("event -> ${any.toLogMessage()}")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,11 +44,5 @@ interface MiddlewareProtobufLogger {
|
|||
}"
|
||||
}
|
||||
}
|
||||
|
||||
private fun containsOnlyThreadStatusEvents(event: Event) : Boolean {
|
||||
return event.messages.all { msg ->
|
||||
msg.threadStatus != null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,31 +6,24 @@ import com.anytypeio.anytype.data.auth.status.P2PStatusRemoteChannel
|
|||
import com.anytypeio.anytype.middleware.EventProxy
|
||||
import com.anytypeio.anytype.middleware.mappers.toCoreModel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
|
||||
class P2PStatusRemoteChannelImpl(private val events: EventProxy) : P2PStatusRemoteChannel {
|
||||
|
||||
override fun observe(activeSpaceId: Id): Flow<List<P2PStatusUpdate>> {
|
||||
return events.flow().mapNotNull { emission ->
|
||||
emission.messages.mapNotNull { message ->
|
||||
when {
|
||||
message.p2pStatusUpdate != null -> {
|
||||
val event = message.p2pStatusUpdate
|
||||
checkNotNull(event)
|
||||
if (event.spaceId == activeSpaceId) {
|
||||
P2PStatusUpdate(
|
||||
spaceId = event.spaceId,
|
||||
status = event.status.toCoreModel(),
|
||||
devicesCounter = event.devicesCounter
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
override fun observe(activeSpaceId: Id): Flow<P2PStatusUpdate> {
|
||||
return events.flow()
|
||||
.mapNotNull { emission ->
|
||||
emission.messages.lastOrNull()?.p2pStatusUpdate
|
||||
}
|
||||
.filter { event -> event.spaceId == activeSpaceId }
|
||||
.map { event ->
|
||||
P2PStatusUpdate.Update(
|
||||
spaceId = event.spaceId,
|
||||
status = event.status.toCoreModel(),
|
||||
devicesCounter = event.devicesCounter
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,33 +6,26 @@ import com.anytypeio.anytype.data.auth.status.SpaceStatusRemoteChannel
|
|||
import com.anytypeio.anytype.middleware.EventProxy
|
||||
import com.anytypeio.anytype.middleware.mappers.toCoreModel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
|
||||
class SpaceSyncStatusRemoteChannelImpl(private val events: EventProxy) : SpaceStatusRemoteChannel {
|
||||
|
||||
override fun observe(activeSpaceId: Id): Flow<List<SpaceSyncUpdate>> {
|
||||
return events.flow().mapNotNull { emission ->
|
||||
emission.messages.mapNotNull { message ->
|
||||
when {
|
||||
message.spaceSyncStatusUpdate != null -> {
|
||||
val event = message.spaceSyncStatusUpdate
|
||||
checkNotNull(event)
|
||||
if (event.id == activeSpaceId) {
|
||||
SpaceSyncUpdate(
|
||||
id = event.id,
|
||||
status = event.status.toCoreModel(),
|
||||
network = event.network.toCoreModel(),
|
||||
error = event.error.toCoreModel(),
|
||||
syncingObjectsCounter = event.syncingObjectsCounter
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
override fun observe(activeSpaceId: Id): Flow<SpaceSyncUpdate> {
|
||||
return events.flow()
|
||||
.mapNotNull { emission ->
|
||||
emission.messages.lastOrNull()?.spaceSyncStatusUpdate
|
||||
}
|
||||
.filter { event -> event.id == activeSpaceId }
|
||||
.map { event ->
|
||||
SpaceSyncUpdate.Update(
|
||||
id = event.id,
|
||||
status = event.status.toCoreModel(),
|
||||
network = event.network.toCoreModel(),
|
||||
error = event.error.toCoreModel(),
|
||||
syncingObjectsCounter = event.syncingObjectsCounter
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
package com.anytypeio.anytype.middleware.interactor
|
||||
|
||||
import com.anytypeio.anytype.core_models.SyncStatus
|
||||
import com.anytypeio.anytype.data.auth.status.ThreadStatusRemoteChannel
|
||||
import com.anytypeio.anytype.middleware.EventProxy
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.mapLatest
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import anytype.Event.Status.Thread.SyncStatus as MSyncStatus
|
||||
|
||||
class ThreadStatusMiddlewareChannel(
|
||||
private val events: EventProxy,
|
||||
) : ThreadStatusRemoteChannel {
|
||||
|
||||
override fun observe(ctx: String): Flow<SyncStatus> = events.flow()
|
||||
.filter { it.contextId == ctx }
|
||||
.mapNotNull { emission ->
|
||||
emission
|
||||
.messages
|
||||
.lastOrNull { it.threadStatus != null }
|
||||
?.threadStatus
|
||||
?.summary
|
||||
?.status
|
||||
}
|
||||
.mapLatest { status ->
|
||||
when (status) {
|
||||
MSyncStatus.Unknown -> SyncStatus.UNKNOWN
|
||||
MSyncStatus.Offline -> SyncStatus.OFFLINE
|
||||
MSyncStatus.Syncing -> SyncStatus.SYNCING
|
||||
MSyncStatus.Synced -> SyncStatus.SYNCED
|
||||
MSyncStatus.Failed -> SyncStatus.FAILED
|
||||
MSyncStatus.IncompatibleVersion -> SyncStatus.INCOMPATIBLE_VERSION
|
||||
}
|
||||
}
|
||||
}
|
|
@ -97,7 +97,6 @@ import com.anytypeio.anytype.domain.page.OpenPage
|
|||
import com.anytypeio.anytype.domain.relations.AddRelationToObject
|
||||
import com.anytypeio.anytype.domain.search.SearchObjects
|
||||
import com.anytypeio.anytype.domain.sets.FindObjectSetForType
|
||||
import com.anytypeio.anytype.domain.status.InterceptThreadStatus
|
||||
import com.anytypeio.anytype.domain.templates.ApplyTemplate
|
||||
import com.anytypeio.anytype.domain.unsplash.DownloadUnsplashImage
|
||||
import com.anytypeio.anytype.domain.workspace.InterceptFileLimitEvents
|
||||
|
@ -251,8 +250,11 @@ import com.anytypeio.anytype.presentation.relations.getObjectRelations
|
|||
import com.anytypeio.anytype.presentation.relations.views
|
||||
import com.anytypeio.anytype.presentation.search.ObjectSearchConstants
|
||||
import com.anytypeio.anytype.presentation.search.ObjectSearchViewModel
|
||||
import com.anytypeio.anytype.presentation.sync.SyncStatusView
|
||||
import com.anytypeio.anytype.presentation.sync.toView
|
||||
import com.anytypeio.anytype.presentation.sync.SpaceSyncAndP2PStatusProvider
|
||||
import com.anytypeio.anytype.presentation.sync.SpaceSyncAndP2PStatusState
|
||||
import com.anytypeio.anytype.presentation.sync.SyncStatusWidgetState
|
||||
import com.anytypeio.anytype.presentation.sync.toSyncStatusWidgetState
|
||||
import com.anytypeio.anytype.presentation.sync.updateStatus
|
||||
import com.anytypeio.anytype.presentation.templates.ObjectTypeTemplatesContainer
|
||||
import com.anytypeio.anytype.presentation.util.CopyFileStatus
|
||||
import com.anytypeio.anytype.presentation.util.CopyFileToCacheDirectory
|
||||
|
@ -291,7 +293,6 @@ class EditorViewModel(
|
|||
private val createBlockLinkWithObject: CreateBlockLinkWithObject,
|
||||
private val createObjectAsMentionOrLink: CreateObjectAsMentionOrLink,
|
||||
private val interceptEvents: InterceptEvents,
|
||||
private val interceptThreadStatus: InterceptThreadStatus,
|
||||
private val updateLinkMarks: UpdateLinkMarks,
|
||||
private val removeLinkMark: RemoveLinkMark,
|
||||
private val reducer: StateReducer<List<Block>, Event>,
|
||||
|
@ -326,8 +327,8 @@ class EditorViewModel(
|
|||
private val templatesContainer: ObjectTypeTemplatesContainer,
|
||||
private val storelessSubscriptionContainer: StorelessSubscriptionContainer,
|
||||
private val dispatchers: AppCoroutineDispatchers,
|
||||
private val getNetworkMode: GetNetworkMode,
|
||||
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
|
||||
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
|
||||
private val spaceSyncAndP2PStatusProvider: SpaceSyncAndP2PStatusProvider
|
||||
) : ViewStateViewModel<ViewState>(),
|
||||
PickerListener,
|
||||
SupportNavigation<EventWrapper<AppNavigation.Command>>,
|
||||
|
@ -341,9 +342,6 @@ class EditorViewModel(
|
|||
|
||||
val actions = MutableStateFlow(ActionItemType.defaultSorting)
|
||||
|
||||
val isSyncStatusVisible = MutableStateFlow(true)
|
||||
val syncStatus = MutableStateFlow<SyncStatusView?>(null)
|
||||
|
||||
val icon = MutableStateFlow<ProfileIconView>(ProfileIconView.Loading)
|
||||
|
||||
val isUndoEnabled = MutableStateFlow(false)
|
||||
|
@ -1054,18 +1052,7 @@ class EditorViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
jobs += viewModelScope.launch {
|
||||
val networkMode = getNetworkMode.run(Unit).networkMode
|
||||
interceptThreadStatus
|
||||
.build(InterceptThreadStatus.Params(context))
|
||||
.collect { status ->
|
||||
val statusView = status.toView(
|
||||
networkId = spaceManager.getConfig(space = vmParams.space)?.network,
|
||||
networkMode = networkMode
|
||||
)
|
||||
syncStatus.value = statusView
|
||||
}
|
||||
}
|
||||
proceedWithCollectingSyncStatus()
|
||||
|
||||
jobs += viewModelScope.launch {
|
||||
dispatcher
|
||||
|
@ -1092,9 +1079,6 @@ class EditorViewModel(
|
|||
orchestrator.proxies.payloads.send(result.data)
|
||||
result.data.events.forEach { event ->
|
||||
if (event is Event.Command.ShowObject) {
|
||||
if (event.details.details[context]?.type?.contains(ObjectTypeIds.FILE) == true) {
|
||||
isSyncStatusVisible.value = false
|
||||
}
|
||||
sendAnalyticsObjectShowEvent(
|
||||
analytics = analytics,
|
||||
startTime = startTime,
|
||||
|
@ -7353,6 +7337,31 @@ class EditorViewModel(
|
|||
return mode == EditorMode.Locked || objRestrictions.contains(ObjectRestriction.DETAILS)
|
||||
}
|
||||
|
||||
//region SYNC STATUS
|
||||
val spaceSyncStatus = MutableStateFlow<SpaceSyncAndP2PStatusState>(SpaceSyncAndP2PStatusState.Initial)
|
||||
val syncStatusWidget = MutableStateFlow<SyncStatusWidgetState>(SyncStatusWidgetState.Hidden)
|
||||
|
||||
fun onSyncStatusBadgeClicked() {
|
||||
Timber.d("onSyncStatusBadgeClicked, ")
|
||||
syncStatusWidget.value = spaceSyncStatus.value.toSyncStatusWidgetState()
|
||||
}
|
||||
|
||||
private fun proceedWithCollectingSyncStatus() {
|
||||
jobs += viewModelScope.launch {
|
||||
spaceSyncAndP2PStatusProvider
|
||||
.observe()
|
||||
.collect { syncAndP2pState ->
|
||||
spaceSyncStatus.value = syncAndP2pState
|
||||
syncStatusWidget.value = syncStatusWidget.value.updateStatus(syncAndP2pState)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onSyncWidgetDismiss() {
|
||||
syncStatusWidget.value = SyncStatusWidgetState.Hidden
|
||||
}
|
||||
//endregion
|
||||
|
||||
data class Params(
|
||||
val ctx: Id,
|
||||
val space: SpaceId
|
||||
|
|
|
@ -20,7 +20,6 @@ import com.anytypeio.anytype.domain.launch.GetDefaultObjectType
|
|||
import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
|
||||
import com.anytypeio.anytype.domain.networkmode.GetNetworkMode
|
||||
import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection
|
||||
import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet
|
||||
import com.anytypeio.anytype.domain.`object`.UpdateDetail
|
||||
|
@ -34,7 +33,6 @@ import com.anytypeio.anytype.domain.page.OpenPage
|
|||
import com.anytypeio.anytype.domain.relations.AddRelationToObject
|
||||
import com.anytypeio.anytype.domain.search.SearchObjects
|
||||
import com.anytypeio.anytype.domain.sets.FindObjectSetForType
|
||||
import com.anytypeio.anytype.domain.status.InterceptThreadStatus
|
||||
import com.anytypeio.anytype.domain.templates.ApplyTemplate
|
||||
import com.anytypeio.anytype.domain.unsplash.DownloadUnsplashImage
|
||||
import com.anytypeio.anytype.domain.workspace.InterceptFileLimitEvents
|
||||
|
@ -46,6 +44,7 @@ import com.anytypeio.anytype.presentation.common.StateReducer
|
|||
import com.anytypeio.anytype.presentation.editor.editor.Orchestrator
|
||||
import com.anytypeio.anytype.presentation.editor.editor.table.EditorTableDelegate
|
||||
import com.anytypeio.anytype.presentation.editor.render.DefaultBlockViewRenderer
|
||||
import com.anytypeio.anytype.presentation.sync.SpaceSyncAndP2PStatusProvider
|
||||
import com.anytypeio.anytype.presentation.templates.ObjectTypeTemplatesContainer
|
||||
import com.anytypeio.anytype.presentation.util.CopyFileToCacheDirectory
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
|
@ -60,7 +59,6 @@ open class EditorViewModelFactory @Inject constructor(
|
|||
private val createBlockLinkWithObject: CreateBlockLinkWithObject,
|
||||
private val createObjectAsMentionOrLink: CreateObjectAsMentionOrLink,
|
||||
private val interceptEvents: InterceptEvents,
|
||||
private val interceptThreadStatus: InterceptThreadStatus,
|
||||
private val updateLinkMarks: UpdateLinkMarks,
|
||||
private val removeLinkMark: RemoveLinkMark,
|
||||
private val documentEventReducer: StateReducer<List<Block>, Event>,
|
||||
|
@ -94,8 +92,8 @@ open class EditorViewModelFactory @Inject constructor(
|
|||
private val templatesContainer: ObjectTypeTemplatesContainer,
|
||||
private val storelessSubscriptionContainer: StorelessSubscriptionContainer,
|
||||
private val dispatchers: AppCoroutineDispatchers,
|
||||
private val getNetworkMode: GetNetworkMode,
|
||||
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
|
||||
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
|
||||
private val syncStatusProvider: SpaceSyncAndP2PStatusProvider
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
@ -108,7 +106,6 @@ open class EditorViewModelFactory @Inject constructor(
|
|||
createBlockLinkWithObject = createBlockLinkWithObject,
|
||||
createObjectAsMentionOrLink = createObjectAsMentionOrLink,
|
||||
interceptEvents = interceptEvents,
|
||||
interceptThreadStatus = interceptThreadStatus,
|
||||
updateLinkMarks = updateLinkMarks,
|
||||
removeLinkMark = removeLinkMark,
|
||||
reducer = documentEventReducer,
|
||||
|
@ -143,8 +140,8 @@ open class EditorViewModelFactory @Inject constructor(
|
|||
templatesContainer = templatesContainer,
|
||||
dispatchers = dispatchers,
|
||||
storelessSubscriptionContainer = storelessSubscriptionContainer,
|
||||
getNetworkMode = getNetworkMode,
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
|
||||
spaceSyncAndP2PStatusProvider = syncStatusProvider
|
||||
) as T
|
||||
}
|
||||
}
|
|
@ -43,7 +43,6 @@ import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
|
|||
import com.anytypeio.anytype.domain.misc.DateProvider
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
|
||||
import com.anytypeio.anytype.domain.networkmode.GetNetworkMode
|
||||
import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection
|
||||
import com.anytypeio.anytype.domain.`object`.DuplicateObjects
|
||||
import com.anytypeio.anytype.domain.`object`.UpdateDetail
|
||||
|
@ -53,12 +52,10 @@ import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
|
|||
import com.anytypeio.anytype.domain.objects.StoreOfRelations
|
||||
import com.anytypeio.anytype.domain.page.CloseBlock
|
||||
import com.anytypeio.anytype.domain.page.CreateObject
|
||||
import com.anytypeio.anytype.domain.search.CancelSearchSubscription
|
||||
import com.anytypeio.anytype.domain.search.DataViewState
|
||||
import com.anytypeio.anytype.domain.search.DataViewSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.sets.OpenObjectSet
|
||||
import com.anytypeio.anytype.domain.sets.SetQueryToObjectSet
|
||||
import com.anytypeio.anytype.domain.status.InterceptThreadStatus
|
||||
import com.anytypeio.anytype.domain.templates.CreateTemplate
|
||||
import com.anytypeio.anytype.domain.unsplash.DownloadUnsplashImage
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
|
@ -98,8 +95,11 @@ import com.anytypeio.anytype.presentation.sets.subscription.DefaultDataViewSubsc
|
|||
import com.anytypeio.anytype.presentation.sets.viewer.ViewerDelegate
|
||||
import com.anytypeio.anytype.presentation.sets.viewer.ViewerEvent
|
||||
import com.anytypeio.anytype.presentation.sets.viewer.ViewerView
|
||||
import com.anytypeio.anytype.presentation.sync.SyncStatusView
|
||||
import com.anytypeio.anytype.presentation.sync.toView
|
||||
import com.anytypeio.anytype.presentation.sync.SpaceSyncAndP2PStatusProvider
|
||||
import com.anytypeio.anytype.presentation.sync.SpaceSyncAndP2PStatusState
|
||||
import com.anytypeio.anytype.presentation.sync.SyncStatusWidgetState
|
||||
import com.anytypeio.anytype.presentation.sync.toSyncStatusWidgetState
|
||||
import com.anytypeio.anytype.presentation.sync.updateStatus
|
||||
import com.anytypeio.anytype.presentation.templates.ObjectTypeTemplatesContainer
|
||||
import com.anytypeio.anytype.presentation.templates.TemplateMenuClick
|
||||
import com.anytypeio.anytype.presentation.templates.TemplateObjectTypeView
|
||||
|
@ -148,7 +148,6 @@ class ObjectSetViewModel(
|
|||
private val setDocCoverImage: SetDocCoverImage,
|
||||
private val updateText: UpdateText,
|
||||
private val interceptEvents: InterceptEvents,
|
||||
private val interceptThreadStatus: InterceptThreadStatus,
|
||||
private val dispatcher: Dispatcher<Payload>,
|
||||
private val delegator: Delegator<Action>,
|
||||
private val urlBuilder: UrlBuilder,
|
||||
|
@ -158,7 +157,6 @@ class ObjectSetViewModel(
|
|||
private val createDataViewObject: CreateDataViewObject,
|
||||
private val createObject: CreateObject,
|
||||
private val dataViewSubscriptionContainer: DataViewSubscriptionContainer,
|
||||
private val cancelSearchSubscription: CancelSearchSubscription,
|
||||
private val setQueryToObjectSet: SetQueryToObjectSet,
|
||||
private val paginator: ObjectSetPaginator,
|
||||
private val storeOfRelations: StoreOfRelations,
|
||||
|
@ -177,9 +175,9 @@ class ObjectSetViewModel(
|
|||
private val createTemplate: CreateTemplate,
|
||||
private val storelessSubscriptionContainer: StorelessSubscriptionContainer,
|
||||
private val dispatchers: AppCoroutineDispatchers,
|
||||
private val getNetworkMode: GetNetworkMode,
|
||||
private val dateProvider: DateProvider,
|
||||
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
|
||||
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
|
||||
private val spaceSyncAndP2PStatusProvider: SpaceSyncAndP2PStatusProvider
|
||||
) : ViewModel(), SupportNavigation<EventWrapper<AppNavigation.Command>>,
|
||||
ViewerDelegate by viewerDelegate,
|
||||
AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate
|
||||
|
@ -191,7 +189,6 @@ class ObjectSetViewModel(
|
|||
|
||||
private val isOwnerOrEditor get() = permission.value?.isOwnerOrEditor() == true
|
||||
|
||||
val status = MutableStateFlow<SyncStatusView?>(null)
|
||||
val error = MutableStateFlow<String?>(null)
|
||||
|
||||
val featured = MutableStateFlow<BlockView.FeaturedRelation?>(null)
|
||||
|
@ -455,9 +452,9 @@ class ObjectSetViewModel(
|
|||
session.currentViewerId.value = view
|
||||
}
|
||||
subscribeToEvents(ctx = ctx)
|
||||
subscribeToThreadStatus(ctx = ctx)
|
||||
proceedWithOpeningCurrentObject(ctx = ctx)
|
||||
proceedWithObservingProfileIcon()
|
||||
proceedWithObservingSyncStatus()
|
||||
}
|
||||
|
||||
private fun subscribeToEvents(ctx: Id) {
|
||||
|
@ -468,21 +465,6 @@ class ObjectSetViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
private fun subscribeToThreadStatus(ctx: Id) {
|
||||
jobs += viewModelScope.launch {
|
||||
val networkMode = getNetworkMode.run(Unit).networkMode
|
||||
interceptThreadStatus
|
||||
.build(InterceptThreadStatus.Params(ctx))
|
||||
.collect {
|
||||
val statusView = it.toView(
|
||||
networkId = spaceManager.getConfig(vmParams.space)?.network,
|
||||
networkMode = networkMode
|
||||
)
|
||||
status.value = statusView
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
private fun subscribeToObjectState() {
|
||||
Timber.d("subscribeToObjectState, ctx:[$context]")
|
||||
|
@ -2830,6 +2812,31 @@ class ObjectSetViewModel(
|
|||
}
|
||||
//endregion
|
||||
|
||||
//region SYNC STATUS
|
||||
val spaceSyncStatus = MutableStateFlow<SpaceSyncAndP2PStatusState>(SpaceSyncAndP2PStatusState.Initial)
|
||||
val syncStatusWidget = MutableStateFlow<SyncStatusWidgetState>(SyncStatusWidgetState.Hidden)
|
||||
|
||||
fun onSyncStatusBadgeClicked() {
|
||||
Timber.d("onSyncStatusBadgeClicked, ")
|
||||
syncStatusWidget.value = spaceSyncStatus.value.toSyncStatusWidgetState()
|
||||
}
|
||||
|
||||
private fun proceedWithObservingSyncStatus() {
|
||||
jobs += viewModelScope.launch {
|
||||
spaceSyncAndP2PStatusProvider
|
||||
.observe()
|
||||
.collect { syncAndP2pState ->
|
||||
spaceSyncStatus.value = syncAndP2pState
|
||||
syncStatusWidget.value = syncStatusWidget.value.updateStatus(syncAndP2pState)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onSyncWidgetDismiss() {
|
||||
syncStatusWidget.value = SyncStatusWidgetState.Hidden
|
||||
}
|
||||
//endregion
|
||||
|
||||
companion object {
|
||||
const val NOT_ALLOWED = "Not allowed for this set"
|
||||
const val NOT_ALLOWED_CELL = "Not allowed for this cell"
|
||||
|
|
|
@ -15,7 +15,6 @@ import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
|
|||
import com.anytypeio.anytype.domain.misc.DateProvider
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
|
||||
import com.anytypeio.anytype.domain.networkmode.GetNetworkMode
|
||||
import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection
|
||||
import com.anytypeio.anytype.domain.`object`.DuplicateObjects
|
||||
import com.anytypeio.anytype.domain.`object`.UpdateDetail
|
||||
|
@ -25,11 +24,9 @@ import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
|
|||
import com.anytypeio.anytype.domain.objects.StoreOfRelations
|
||||
import com.anytypeio.anytype.domain.page.CloseBlock
|
||||
import com.anytypeio.anytype.domain.page.CreateObject
|
||||
import com.anytypeio.anytype.domain.search.CancelSearchSubscription
|
||||
import com.anytypeio.anytype.domain.search.DataViewSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.sets.OpenObjectSet
|
||||
import com.anytypeio.anytype.domain.sets.SetQueryToObjectSet
|
||||
import com.anytypeio.anytype.domain.status.InterceptThreadStatus
|
||||
import com.anytypeio.anytype.domain.templates.CreateTemplate
|
||||
import com.anytypeio.anytype.domain.unsplash.DownloadUnsplashImage
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
|
@ -40,6 +37,7 @@ import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider
|
|||
import com.anytypeio.anytype.presentation.sets.state.ObjectStateReducer
|
||||
import com.anytypeio.anytype.presentation.sets.subscription.DataViewSubscription
|
||||
import com.anytypeio.anytype.presentation.sets.viewer.ViewerDelegate
|
||||
import com.anytypeio.anytype.presentation.sync.SpaceSyncAndP2PStatusProvider
|
||||
import com.anytypeio.anytype.presentation.templates.ObjectTypeTemplatesContainer
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
|
||||
|
@ -54,7 +52,6 @@ class ObjectSetViewModelFactory(
|
|||
private val setDocCoverImage: SetDocCoverImage,
|
||||
private val updateText: UpdateText,
|
||||
private val interceptEvents: InterceptEvents,
|
||||
private val interceptThreadStatus: InterceptThreadStatus,
|
||||
private val dispatcher: Dispatcher<Payload>,
|
||||
private val delegator: Delegator<Action>,
|
||||
private val coverImageHashProvider: CoverImageHashProvider,
|
||||
|
@ -63,7 +60,6 @@ class ObjectSetViewModelFactory(
|
|||
private val analytics: Analytics,
|
||||
private val createObject: CreateObject,
|
||||
private val dataViewSubscriptionContainer: DataViewSubscriptionContainer,
|
||||
private val cancelSearchSubscription: CancelSearchSubscription,
|
||||
private val setQueryToObjectSet: SetQueryToObjectSet,
|
||||
private val database: ObjectSetDatabase,
|
||||
private val paginator: ObjectSetPaginator,
|
||||
|
@ -83,9 +79,9 @@ class ObjectSetViewModelFactory(
|
|||
private val spaceManager: SpaceManager,
|
||||
private val storelessSubscriptionContainer: StorelessSubscriptionContainer,
|
||||
private val dispatchers: AppCoroutineDispatchers,
|
||||
private val getNetworkMode: GetNetworkMode,
|
||||
private val dateProvider: DateProvider,
|
||||
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
|
||||
private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
|
||||
private val spaceSyncAndP2PStatusProvider: SpaceSyncAndP2PStatusProvider
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
|
@ -100,7 +96,6 @@ class ObjectSetViewModelFactory(
|
|||
downloadUnsplashImage = downloadUnsplashImage,
|
||||
updateText = updateText,
|
||||
interceptEvents = interceptEvents,
|
||||
interceptThreadStatus = interceptThreadStatus,
|
||||
dispatcher = dispatcher,
|
||||
delegator = delegator,
|
||||
coverImageHashProvider = coverImageHashProvider,
|
||||
|
@ -109,7 +104,6 @@ class ObjectSetViewModelFactory(
|
|||
analytics = analytics,
|
||||
createObject = createObject,
|
||||
dataViewSubscriptionContainer = dataViewSubscriptionContainer,
|
||||
cancelSearchSubscription = cancelSearchSubscription,
|
||||
setQueryToObjectSet = setQueryToObjectSet,
|
||||
database = database,
|
||||
paginator = paginator,
|
||||
|
@ -129,9 +123,9 @@ class ObjectSetViewModelFactory(
|
|||
createTemplate = createTemplate,
|
||||
dispatchers = dispatchers,
|
||||
storelessSubscriptionContainer = storelessSubscriptionContainer,
|
||||
getNetworkMode = getNetworkMode,
|
||||
dateProvider = dateProvider,
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
|
||||
spaceSyncAndP2PStatusProvider = spaceSyncAndP2PStatusProvider,
|
||||
) as T
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
package com.anytypeio.anytype.presentation.sync
|
||||
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.multiplayer.P2PStatusUpdate
|
||||
import com.anytypeio.anytype.core_models.multiplayer.SpaceSyncUpdate
|
||||
import com.anytypeio.anytype.domain.multiplayer.ActiveSpaceMemberSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.workspace.P2PStatusChannel
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceSyncStatusChannel
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
|
||||
interface SpaceSyncAndP2PStatusProvider {
|
||||
|
||||
suspend fun observe(): Flow<SpaceSyncAndP2PStatusState>
|
||||
|
||||
class Impl @Inject constructor(
|
||||
private val activeSpace: ActiveSpaceMemberSubscriptionContainer,
|
||||
private val spaceSyncStatusChannel: SpaceSyncStatusChannel,
|
||||
private val p2PStatusChannel: P2PStatusChannel
|
||||
) : SpaceSyncAndP2PStatusProvider {
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override suspend fun observe(): Flow<SpaceSyncAndP2PStatusState> {
|
||||
return activeSpace
|
||||
.observe()
|
||||
.flatMapLatest { activeSpace ->
|
||||
when (activeSpace) {
|
||||
is ActiveSpaceMemberSubscriptionContainer.Store.Data -> {
|
||||
observeSpaceSyncStatus(spaceId = activeSpace.config.space)
|
||||
}
|
||||
|
||||
ActiveSpaceMemberSubscriptionContainer.Store.Empty -> {
|
||||
emptyFlow()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun observeSpaceSyncStatus(spaceId: Id): Flow<SpaceSyncAndP2PStatusState> {
|
||||
val syncFlow =
|
||||
spaceSyncStatusChannel.observe(spaceId).onStart { emit(SpaceSyncUpdate.Initial) }
|
||||
val p2pFlow =
|
||||
p2PStatusChannel.observe(spaceId).onStart { emit(P2PStatusUpdate.Initial) }
|
||||
|
||||
return combine(syncFlow, p2pFlow) { syncStatus, p2PStatus ->
|
||||
if (syncStatus is SpaceSyncUpdate.Initial && p2PStatus is P2PStatusUpdate.Initial) {
|
||||
SpaceSyncAndP2PStatusState.Initial
|
||||
} else {
|
||||
SpaceSyncAndP2PStatusState.Success(
|
||||
spaceSyncUpdate = syncStatus,
|
||||
p2PStatusUpdate = p2PStatus
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class SpaceSyncAndP2PStatusState {
|
||||
data object Initial : SpaceSyncAndP2PStatusState()
|
||||
data class Error(val message: String) : SpaceSyncAndP2PStatusState()
|
||||
data class Success(
|
||||
val spaceSyncUpdate: SpaceSyncUpdate,
|
||||
val p2PStatusUpdate: P2PStatusUpdate
|
||||
) : SpaceSyncAndP2PStatusState()
|
||||
}
|
||||
|
||||
fun SyncStatusWidgetState.updateStatus(newState: SpaceSyncAndP2PStatusState): SyncStatusWidgetState {
|
||||
return when (this) {
|
||||
is SyncStatusWidgetState.Error -> {
|
||||
newState.toSyncStatusWidgetState()
|
||||
}
|
||||
|
||||
SyncStatusWidgetState.Hidden -> SyncStatusWidgetState.Hidden
|
||||
is SyncStatusWidgetState.Success -> {
|
||||
newState.toSyncStatusWidgetState()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun SpaceSyncAndP2PStatusState.toSyncStatusWidgetState(): SyncStatusWidgetState {
|
||||
return when (this) {
|
||||
is SpaceSyncAndP2PStatusState.Error -> {
|
||||
SyncStatusWidgetState.Error(message = message)
|
||||
}
|
||||
|
||||
SpaceSyncAndP2PStatusState.Initial -> {
|
||||
SyncStatusWidgetState.Hidden
|
||||
}
|
||||
|
||||
is SpaceSyncAndP2PStatusState.Success -> {
|
||||
SyncStatusWidgetState.Success(
|
||||
spaceSyncUpdate = spaceSyncUpdate,
|
||||
p2PStatusUpdate = p2PStatusUpdate
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class SyncStatusWidgetState {
|
||||
data object Hidden : SyncStatusWidgetState()
|
||||
data class Error(val message: String) : SyncStatusWidgetState()
|
||||
data class Success(
|
||||
val spaceSyncUpdate: SpaceSyncUpdate,
|
||||
val p2PStatusUpdate: P2PStatusUpdate
|
||||
) : SyncStatusWidgetState()
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
package com.anytypeio.anytype.presentation.sync
|
||||
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.NetworkMode
|
||||
import com.anytypeio.anytype.core_models.SyncStatus
|
||||
import com.anytypeio.anytype.core_models.NetworkModeConst.NODE_STAGING_ID
|
||||
|
||||
sealed class SyncStatusView {
|
||||
object Unknown : SyncStatusView()
|
||||
object Offline : SyncStatusView()
|
||||
object Syncing : SyncStatusView()
|
||||
sealed class Synced : SyncStatusView() {
|
||||
object AnyNetwork : Synced()
|
||||
object StagingNetwork : Synced()
|
||||
object LocalOnly : Synced()
|
||||
object SelfHostedNetwork : Synced()
|
||||
}
|
||||
object Failed : SyncStatusView()
|
||||
object IncompatibleVersion : SyncStatusView()
|
||||
}
|
||||
|
||||
fun SyncStatus.toView(networkId: Id?, networkMode: NetworkMode): SyncStatusView {
|
||||
return when (this) {
|
||||
SyncStatus.UNKNOWN -> {
|
||||
when (networkMode) {
|
||||
NetworkMode.LOCAL -> SyncStatusView.Synced.LocalOnly
|
||||
else -> SyncStatusView.Unknown
|
||||
}
|
||||
}
|
||||
SyncStatus.OFFLINE -> SyncStatusView.Offline
|
||||
SyncStatus.SYNCING -> SyncStatusView.Syncing
|
||||
SyncStatus.SYNCED -> {
|
||||
networkMode.syncedStatusToView(networkId)
|
||||
}
|
||||
SyncStatus.FAILED -> SyncStatusView.Failed
|
||||
SyncStatus.INCOMPATIBLE_VERSION -> SyncStatusView.IncompatibleVersion
|
||||
}
|
||||
}
|
||||
|
||||
fun NetworkMode.syncedStatusToView(networkId: String?): SyncStatusView {
|
||||
when (this) {
|
||||
NetworkMode.DEFAULT -> return SyncStatusView.Synced.AnyNetwork
|
||||
NetworkMode.LOCAL -> {
|
||||
return if (networkId.isNullOrEmpty()) {
|
||||
SyncStatusView.Synced.LocalOnly
|
||||
} else {
|
||||
SyncStatusView.Unknown
|
||||
}
|
||||
}
|
||||
NetworkMode.CUSTOM -> {
|
||||
return if (networkId == NODE_STAGING_ID) {
|
||||
SyncStatusView.Synced.StagingNetwork
|
||||
} else {
|
||||
SyncStatusView.Synced.SelfHostedNetwork
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -81,7 +81,6 @@ class CollectionCreateAndAddObjectTest: ObjectSetViewModelTestSetup() {
|
|||
closeBlock = closeBlock,
|
||||
updateText = updateText,
|
||||
interceptEvents = interceptEvents,
|
||||
interceptThreadStatus = interceptThreadStatus,
|
||||
createDataViewObject = CreateDataViewObject(
|
||||
repo = repo,
|
||||
spaceManager = spaceManager,
|
||||
|
@ -98,7 +97,6 @@ class CollectionCreateAndAddObjectTest: ObjectSetViewModelTestSetup() {
|
|||
createObject = createObject,
|
||||
setObjectDetails = setObjectDetails,
|
||||
paginator = paginator,
|
||||
cancelSearchSubscription = cancelSearchSubscription,
|
||||
database = database,
|
||||
dataViewSubscriptionContainer = dataViewSubscriptionContainer,
|
||||
storeOfRelations = storeOfRelations,
|
||||
|
@ -118,14 +116,14 @@ class CollectionCreateAndAddObjectTest: ObjectSetViewModelTestSetup() {
|
|||
getObjectTypes = getObjectTypes,
|
||||
storelessSubscriptionContainer = storelessSubscriptionContainer,
|
||||
dispatchers = dispatchers,
|
||||
getNetworkMode = getNetworkMode,
|
||||
dateProvider = dateProvider,
|
||||
vmParams = ObjectSetViewModel.Params(
|
||||
ctx = root,
|
||||
space = SpaceId(defaultSpace)
|
||||
),
|
||||
permissions = permissions,
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
|
||||
spaceSyncAndP2PStatusProvider = spaceSyncAndP2PStatusProvider
|
||||
)
|
||||
stubNetworkMode()
|
||||
stubObservePermissions()
|
||||
|
|
|
@ -87,7 +87,6 @@ import com.anytypeio.anytype.domain.relations.AddRelationToObject
|
|||
import com.anytypeio.anytype.domain.relations.SetRelationKey
|
||||
import com.anytypeio.anytype.domain.search.SearchObjects
|
||||
import com.anytypeio.anytype.domain.sets.FindObjectSetForType
|
||||
import com.anytypeio.anytype.domain.status.InterceptThreadStatus
|
||||
import com.anytypeio.anytype.domain.table.CreateTable
|
||||
import com.anytypeio.anytype.domain.table.FillTableRow
|
||||
import com.anytypeio.anytype.domain.templates.ApplyTemplate
|
||||
|
@ -120,6 +119,7 @@ import com.anytypeio.anytype.presentation.editor.render.parseThemeBackgroundColo
|
|||
import com.anytypeio.anytype.presentation.editor.selection.SelectionStateHolder
|
||||
import com.anytypeio.anytype.presentation.editor.toggle.ToggleStateHolder
|
||||
import com.anytypeio.anytype.presentation.navigation.AppNavigation
|
||||
import com.anytypeio.anytype.presentation.sync.SpaceSyncAndP2PStatusProvider
|
||||
import com.anytypeio.anytype.presentation.templates.ObjectTypeTemplatesContainer
|
||||
import com.anytypeio.anytype.presentation.util.CopyFileToCacheDirectory
|
||||
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
|
||||
|
@ -185,9 +185,6 @@ open class EditorViewModelTest {
|
|||
@Mock
|
||||
lateinit var interceptEvents: InterceptEvents
|
||||
|
||||
@Mock
|
||||
lateinit var interceptThreadStatus: InterceptThreadStatus
|
||||
|
||||
@Mock
|
||||
lateinit var createBlock: CreateBlock
|
||||
|
||||
|
@ -320,9 +317,6 @@ open class EditorViewModelTest {
|
|||
@Mock
|
||||
lateinit var copyFileToCacheDirectory: CopyFileToCacheDirectory
|
||||
|
||||
@Mock
|
||||
lateinit var getTemplates: GetTemplates
|
||||
|
||||
@Mock
|
||||
lateinit var applyTemplate: ApplyTemplate
|
||||
|
||||
|
@ -364,6 +358,9 @@ open class EditorViewModelTest {
|
|||
@Mock
|
||||
lateinit var permissions: UserPermissionProvider
|
||||
|
||||
@Mock
|
||||
lateinit var spaceSyncAndP2PStatusProvider: SpaceSyncAndP2PStatusProvider
|
||||
|
||||
lateinit var vm: EditorViewModel
|
||||
|
||||
private lateinit var builder: UrlBuilder
|
||||
|
@ -3739,8 +3736,8 @@ open class EditorViewModelTest {
|
|||
}
|
||||
|
||||
fun stubInterceptThreadStatus() {
|
||||
interceptThreadStatus.stub {
|
||||
onBlocking { build(any()) } doReturn emptyFlow()
|
||||
spaceSyncAndP2PStatusProvider.stub {
|
||||
onBlocking { observe() } doReturn emptyFlow()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3868,7 +3865,6 @@ open class EditorViewModelTest {
|
|||
createBlockLinkWithObject = createBlockLinkWithObject,
|
||||
createObjectAsMentionOrLink = createObjectAsMentionOrLink,
|
||||
interceptEvents = interceptEvents,
|
||||
interceptThreadStatus = interceptThreadStatus,
|
||||
updateLinkMarks = updateLinkMark,
|
||||
removeLinkMark = removeLinkMark,
|
||||
reducer = DocumentExternalEventReducer(),
|
||||
|
@ -3953,13 +3949,13 @@ open class EditorViewModelTest {
|
|||
templatesContainer = templatesContainer,
|
||||
storelessSubscriptionContainer = storelessSubscriptionContainer,
|
||||
dispatchers = dispatchers,
|
||||
getNetworkMode = getNetworkMode,
|
||||
vmParams = EditorViewModel.Params(
|
||||
ctx = root,
|
||||
space = spaceId
|
||||
),
|
||||
permissions = permissions,
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
|
||||
spaceSyncAndP2PStatusProvider = spaceSyncAndP2PStatusProvider
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,6 @@ import com.anytypeio.anytype.domain.relations.AddRelationToObject
|
|||
import com.anytypeio.anytype.domain.relations.SetRelationKey
|
||||
import com.anytypeio.anytype.domain.search.SearchObjects
|
||||
import com.anytypeio.anytype.domain.sets.FindObjectSetForType
|
||||
import com.anytypeio.anytype.domain.status.InterceptThreadStatus
|
||||
import com.anytypeio.anytype.domain.table.CreateTable
|
||||
import com.anytypeio.anytype.domain.table.CreateTableColumn
|
||||
import com.anytypeio.anytype.domain.table.CreateTableRow
|
||||
|
@ -112,6 +111,7 @@ import com.anytypeio.anytype.presentation.editor.render.DefaultBlockViewRenderer
|
|||
import com.anytypeio.anytype.presentation.editor.selection.SelectionStateHolder
|
||||
import com.anytypeio.anytype.presentation.editor.toggle.ToggleStateHolder
|
||||
import com.anytypeio.anytype.presentation.home.UserPermissionProviderStub
|
||||
import com.anytypeio.anytype.presentation.sync.SpaceSyncAndP2PStatusProvider
|
||||
import com.anytypeio.anytype.presentation.templates.ObjectTypeTemplatesContainer
|
||||
import com.anytypeio.anytype.presentation.util.CopyFileToCacheDirectory
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
|
@ -142,9 +142,6 @@ open class EditorPresentationTestSetup {
|
|||
@Mock
|
||||
lateinit var interceptEvents: InterceptEvents
|
||||
|
||||
@Mock
|
||||
lateinit var interceptThreadStatus: InterceptThreadStatus
|
||||
|
||||
@Mock
|
||||
lateinit var createBlock: CreateBlock
|
||||
|
||||
|
@ -352,9 +349,6 @@ open class EditorPresentationTestSetup {
|
|||
@Mock
|
||||
lateinit var getObjectTypes: GetObjectTypes
|
||||
|
||||
@Mock
|
||||
lateinit var fileLimitsEventChannel: FileLimitsEventChannel
|
||||
|
||||
@Mock
|
||||
lateinit var interceptFileLimitEvents: InterceptFileLimitEvents
|
||||
|
||||
|
@ -373,6 +367,9 @@ open class EditorPresentationTestSetup {
|
|||
@Mock
|
||||
lateinit var getNetworkMode: GetNetworkMode
|
||||
|
||||
@Mock
|
||||
lateinit var spaceSyncAndP2PStatusProvider: SpaceSyncAndP2PStatusProvider
|
||||
|
||||
var permissions: UserPermissionProvider = UserPermissionProviderStub()
|
||||
|
||||
open fun buildViewModel(urlBuilder: UrlBuilder = builder): EditorViewModel {
|
||||
|
@ -451,7 +448,6 @@ open class EditorPresentationTestSetup {
|
|||
createBlockLinkWithObject = createBlockLinkWithObject,
|
||||
createObjectAsMentionOrLink = createObjectAsMentionOrLink,
|
||||
interceptEvents = interceptEvents,
|
||||
interceptThreadStatus = interceptThreadStatus,
|
||||
updateLinkMarks = updateLinkMark,
|
||||
removeLinkMark = removeLinkMark,
|
||||
reducer = DocumentExternalEventReducer(),
|
||||
|
@ -492,13 +488,13 @@ open class EditorPresentationTestSetup {
|
|||
templatesContainer = templatesContainer,
|
||||
storelessSubscriptionContainer = storelessSubscriptionContainer,
|
||||
dispatchers = dispatchers,
|
||||
getNetworkMode = getNetworkMode,
|
||||
vmParams = EditorViewModel.Params(
|
||||
ctx = root,
|
||||
space = SpaceId(defaultSpace)
|
||||
),
|
||||
permissions = permissions,
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
|
||||
spaceSyncAndP2PStatusProvider = spaceSyncAndP2PStatusProvider
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -569,8 +565,8 @@ open class EditorPresentationTestSetup {
|
|||
}
|
||||
|
||||
fun stubInterceptThreadStatus() {
|
||||
interceptThreadStatus.stub {
|
||||
onBlocking { build(any()) } doReturn emptyFlow()
|
||||
spaceSyncAndP2PStatusProvider.stub {
|
||||
onBlocking { observe() } doReturn emptyFlow()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,6 @@ import com.anytypeio.anytype.domain.search.DataViewSubscriptionContainer
|
|||
import com.anytypeio.anytype.domain.search.SubscriptionEventChannel
|
||||
import com.anytypeio.anytype.domain.sets.OpenObjectSet
|
||||
import com.anytypeio.anytype.domain.sets.SetQueryToObjectSet
|
||||
import com.anytypeio.anytype.domain.status.InterceptThreadStatus
|
||||
import com.anytypeio.anytype.domain.templates.CreateTemplate
|
||||
import com.anytypeio.anytype.domain.unsplash.DownloadUnsplashImage
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
|
@ -82,6 +81,7 @@ import com.anytypeio.anytype.presentation.sets.subscription.DataViewSubscription
|
|||
import com.anytypeio.anytype.presentation.sets.subscription.DefaultDataViewSubscription
|
||||
import com.anytypeio.anytype.presentation.sets.updateFormatForSubscription
|
||||
import com.anytypeio.anytype.presentation.sets.viewer.ViewerDelegate
|
||||
import com.anytypeio.anytype.presentation.sync.SpaceSyncAndP2PStatusProvider
|
||||
import com.anytypeio.anytype.presentation.templates.ObjectTypeTemplatesContainer
|
||||
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
|
@ -131,9 +131,6 @@ open class ObjectSetViewModelTestSetup {
|
|||
@Mock
|
||||
lateinit var interceptEvents: InterceptEvents
|
||||
|
||||
@Mock
|
||||
lateinit var interceptThreadStatus: InterceptThreadStatus
|
||||
|
||||
@Mock
|
||||
lateinit var gateway: Gateway
|
||||
|
||||
|
@ -210,6 +207,9 @@ open class ObjectSetViewModelTestSetup {
|
|||
@Mock
|
||||
lateinit var analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
|
||||
|
||||
@Mock
|
||||
lateinit var spaceSyncAndP2PStatusProvider: SpaceSyncAndP2PStatusProvider
|
||||
|
||||
var permissions: UserPermissionProvider = UserPermissionProviderStub()
|
||||
|
||||
lateinit var spaceConfig: Config
|
||||
|
@ -262,7 +262,6 @@ open class ObjectSetViewModelTestSetup {
|
|||
closeBlock = closeBlock,
|
||||
updateText = updateText,
|
||||
interceptEvents = interceptEvents,
|
||||
interceptThreadStatus = interceptThreadStatus,
|
||||
createDataViewObject = createDataViewObject,
|
||||
dispatcher = dispatcher,
|
||||
delegator = delegator,
|
||||
|
@ -275,7 +274,6 @@ open class ObjectSetViewModelTestSetup {
|
|||
createObject = createObject,
|
||||
setObjectDetails = setObjectDetails,
|
||||
paginator = paginator,
|
||||
cancelSearchSubscription = cancelSearchSubscription,
|
||||
database = database,
|
||||
dataViewSubscriptionContainer = dataViewSubscriptionContainer,
|
||||
storeOfRelations = storeOfRelations,
|
||||
|
@ -295,14 +293,14 @@ open class ObjectSetViewModelTestSetup {
|
|||
getObjectTypes = getObjectTypes,
|
||||
storelessSubscriptionContainer = storelessSubscriptionContainer,
|
||||
dispatchers = dispatchers,
|
||||
getNetworkMode = getNetworkMode,
|
||||
dateProvider = DateProviderImpl(),
|
||||
vmParams = ObjectSetViewModel.Params(
|
||||
ctx = root,
|
||||
space = SpaceId(defaultSpace)
|
||||
),
|
||||
permissions = permissions,
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
|
||||
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
|
||||
spaceSyncAndP2PStatusProvider = spaceSyncAndP2PStatusProvider
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -315,11 +313,9 @@ open class ObjectSetViewModelTestSetup {
|
|||
}
|
||||
}
|
||||
|
||||
fun stubInterceptThreadStatus(
|
||||
params: InterceptThreadStatus.Params = InterceptThreadStatus.Params(ctx = root)
|
||||
) {
|
||||
interceptThreadStatus.stub {
|
||||
onBlocking { build(params) } doReturn emptyFlow()
|
||||
fun stubInterceptThreadStatus() {
|
||||
spaceSyncAndP2PStatusProvider.stub {
|
||||
onBlocking { observe() } doReturn emptyFlow()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue