diff --git a/app/src/main/java/com/anytypeio/anytype/di/feature/MainEntryDI.kt b/app/src/main/java/com/anytypeio/anytype/di/feature/MainEntryDI.kt index d75a229418..6629a9b244 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/feature/MainEntryDI.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/feature/MainEntryDI.kt @@ -1,6 +1,7 @@ package com.anytypeio.anytype.di.feature import com.anytypeio.anytype.analytics.base.Analytics +import com.anytypeio.anytype.core_utils.di.scope.PerDialog import com.anytypeio.anytype.core_utils.di.scope.PerScreen import com.anytypeio.anytype.domain.account.AccountStatusChannel import com.anytypeio.anytype.domain.account.AwaitAccountStartManager @@ -14,6 +15,8 @@ import com.anytypeio.anytype.domain.config.ConfigStorage import com.anytypeio.anytype.domain.config.UserSettingsRepository import com.anytypeio.anytype.domain.device.PathProvider import com.anytypeio.anytype.domain.misc.LocaleProvider +import com.anytypeio.anytype.domain.multiplayer.SpaceInviteResolver +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.notifications.SystemNotificationService import com.anytypeio.anytype.domain.platform.InitialParamsProvider import com.anytypeio.anytype.domain.subscriptions.GlobalSubscriptionManager @@ -22,6 +25,7 @@ import com.anytypeio.anytype.domain.wallpaper.ObserveWallpaper import com.anytypeio.anytype.domain.wallpaper.RestoreWallpaper import com.anytypeio.anytype.domain.wallpaper.WallpaperStore import com.anytypeio.anytype.domain.workspace.SpaceManager +import com.anytypeio.anytype.other.DefaultSpaceInviteResolver import com.anytypeio.anytype.presentation.main.MainViewModelFactory import com.anytypeio.anytype.presentation.membership.provider.MembershipProvider import com.anytypeio.anytype.presentation.navigation.DeepLinkToObjectDelegate @@ -70,7 +74,8 @@ object MainEntryModule { deepLinkToObjectDelegate: DeepLinkToObjectDelegate, awaitAccountStartManager: AwaitAccountStartManager, membershipProvider: MembershipProvider, - globalSubscriptionManager: GlobalSubscriptionManager + globalSubscriptionManager: GlobalSubscriptionManager, + spaceInviteResolver: SpaceInviteResolver ): MainViewModelFactory = MainViewModelFactory( resumeAccount = resumeAccount, analytics = analytics, @@ -87,7 +92,8 @@ object MainEntryModule { deepLinkToObjectDelegate = deepLinkToObjectDelegate, awaitAccountStartManager = awaitAccountStartManager, membershipProvider = membershipProvider, - globalSubscriptionManager = globalSubscriptionManager + globalSubscriptionManager = globalSubscriptionManager, + spaceInviteResolver = spaceInviteResolver ) @JvmStatic @@ -192,4 +198,9 @@ object MainEntryModule { fun provideDeepLinkToObjectDelegate( default: DeepLinkToObjectDelegate.Default ): DeepLinkToObjectDelegate = default + + @JvmStatic + @PerScreen + @Provides + fun provideSpaceInviteResolver(): SpaceInviteResolver = DefaultSpaceInviteResolver } \ No newline at end of file diff --git a/app/src/main/java/com/anytypeio/anytype/di/feature/ObjectMenuDI.kt b/app/src/main/java/com/anytypeio/anytype/di/feature/ObjectMenuDI.kt index 97a214e9b1..e232014272 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/feature/ObjectMenuDI.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/feature/ObjectMenuDI.kt @@ -15,6 +15,8 @@ import com.anytypeio.anytype.domain.dashboard.interactor.SetObjectListIsFavorite import com.anytypeio.anytype.domain.misc.DateProvider import com.anytypeio.anytype.domain.misc.DeepLinkResolver import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.multiplayer.GetSpaceInviteLink +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.`object`.DuplicateObject import com.anytypeio.anytype.domain.`object`.SetObjectDetails import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived @@ -119,7 +121,9 @@ object ObjectMenuModule { payloadDelegator: PayloadDelegator, setObjectListIsFavorite: SetObjectListIsFavorite, setObjectIsArchived: SetObjectListIsArchived, - fieldParser: FieldParser + fieldParser: FieldParser, + spaceViewSubscriptionContainer: SpaceViewSubscriptionContainer, + getSpaceInviteLink: GetSpaceInviteLink ): ObjectMenuViewModel.Factory = ObjectMenuViewModel.Factory( setObjectIsArchived = setObjectIsArchived, duplicateObject = duplicateObject, @@ -142,7 +146,9 @@ object ObjectMenuModule { analyticSpaceHelperDelegate = analyticSpaceHelperDelegate, payloadDelegator = payloadDelegator, setObjectListIsFavorite = setObjectListIsFavorite, - fieldParser = fieldParser + fieldParser = fieldParser, + getSpaceInviteLink = getSpaceInviteLink, + spaceViewSubscriptionContainer = spaceViewSubscriptionContainer ) @JvmStatic @@ -237,6 +243,8 @@ object ObjectSetMenuModule { setObjectListIsFavorite: SetObjectListIsFavorite, setObjectIsArchived: SetObjectListIsArchived, fieldParser: FieldParser, + getSpaceInviteLink: GetSpaceInviteLink, + spaceViewSubscriptionContainer: SpaceViewSubscriptionContainer ): ObjectSetMenuViewModel.Factory = ObjectSetMenuViewModel.Factory( setObjectListIsArchived = setObjectIsArchived, addBackLinkToObject = addBackLinkToObject, @@ -255,7 +263,9 @@ object ObjectSetMenuModule { analyticSpaceHelperDelegate = analyticSpaceHelperDelegate, payloadDelegator = payloadDelegator, setObjectListIsFavorite = setObjectListIsFavorite, - fieldParser = fieldParser + fieldParser = fieldParser, + getSpaceInviteLink = getSpaceInviteLink, + spaceViewSubscriptionContainer = spaceViewSubscriptionContainer ) @JvmStatic diff --git a/app/src/main/java/com/anytypeio/anytype/di/feature/home/HomescreenDI.kt b/app/src/main/java/com/anytypeio/anytype/di/feature/home/HomescreenDI.kt index 7320b467dc..9615103091 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/feature/home/HomescreenDI.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/feature/home/HomescreenDI.kt @@ -22,6 +22,7 @@ import com.anytypeio.anytype.domain.misc.AppActionManager 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.SpaceInviteResolver import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider import com.anytypeio.anytype.domain.`object`.GetObject @@ -38,6 +39,7 @@ import com.anytypeio.anytype.domain.search.SubscriptionEventChannel import com.anytypeio.anytype.domain.templates.GetTemplates import com.anytypeio.anytype.domain.workspace.NotificationsChannel import com.anytypeio.anytype.domain.workspace.SpaceManager +import com.anytypeio.anytype.other.DefaultSpaceInviteResolver import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate import com.anytypeio.anytype.presentation.common.PayloadDelegator import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider @@ -207,6 +209,11 @@ object HomeScreenModule { @PerScreen fun coverHashProvider() : CoverImageHashProvider = DefaultCoverImageHashProvider() + @JvmStatic + @PerScreen + @Provides + fun provideSpaceInviteResolver(): SpaceInviteResolver = DefaultSpaceInviteResolver + @Module interface Declarations { @PerScreen diff --git a/app/src/main/java/com/anytypeio/anytype/di/feature/vault/VaultDI.kt b/app/src/main/java/com/anytypeio/anytype/di/feature/vault/VaultDI.kt index e85e5c1c48..544693e81d 100644 --- a/app/src/main/java/com/anytypeio/anytype/di/feature/vault/VaultDI.kt +++ b/app/src/main/java/com/anytypeio/anytype/di/feature/vault/VaultDI.kt @@ -2,6 +2,7 @@ package com.anytypeio.anytype.di.feature.vault import androidx.lifecycle.ViewModelProvider import com.anytypeio.anytype.analytics.base.Analytics +import com.anytypeio.anytype.core_utils.di.scope.PerDialog import com.anytypeio.anytype.core_utils.di.scope.PerScreen import com.anytypeio.anytype.di.common.ComponentDependencies import com.anytypeio.anytype.domain.account.AwaitAccountStartManager @@ -12,15 +13,18 @@ import com.anytypeio.anytype.domain.config.UserSettingsRepository import com.anytypeio.anytype.domain.debugging.Logger import com.anytypeio.anytype.domain.misc.AppActionManager import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.multiplayer.SpaceInviteResolver import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider import com.anytypeio.anytype.domain.workspace.SpaceManager +import com.anytypeio.anytype.other.DefaultSpaceInviteResolver import com.anytypeio.anytype.presentation.navigation.DeepLinkToObjectDelegate import com.anytypeio.anytype.presentation.vault.VaultViewModel import com.anytypeio.anytype.ui.vault.VaultFragment import dagger.Binds import dagger.Component import dagger.Module +import dagger.Provides @Component( dependencies = [VaultComponentDependencies::class], @@ -56,6 +60,10 @@ object VaultModule { default: DeepLinkToObjectDelegate.Default ) : DeepLinkToObjectDelegate } + + @PerScreen + @Provides + fun provideSpaceInviteResolver() : SpaceInviteResolver = DefaultSpaceInviteResolver } interface VaultComponentDependencies : ComponentDependencies { diff --git a/app/src/main/java/com/anytypeio/anytype/other/Deeplinks.kt b/app/src/main/java/com/anytypeio/anytype/other/Deeplinks.kt index 2fbd504ebb..cc10d296a9 100644 --- a/app/src/main/java/com/anytypeio/anytype/other/Deeplinks.kt +++ b/app/src/main/java/com/anytypeio/anytype/other/Deeplinks.kt @@ -9,6 +9,8 @@ import com.anytypeio.anytype.domain.multiplayer.SpaceInviteResolver const val DEEP_LINK_PATTERN = "anytype://" +const val DEEP_LINK_INVITE_DOMAIN = "invite.any.coop" + /** * Regex pattern for matching */ @@ -25,6 +27,8 @@ const val MEMBERSHIP_PATH = "membership" const val TYPE_PARAM = "type" const val OBJECT_ID_PARAM = "objectId" const val SPACE_ID_PARAM = "spaceId" +const val CONTENT_ID_PARAM = "cid" +const val ENCRYPTION_KEY_PARAM = "key" const val SOURCE_PARAM = "source" const val TYPE_VALUE_EXPERIENCE = "experience" const val TIER_ID_PARAM = "tier" @@ -61,9 +65,19 @@ object DefaultDeepLinkResolver : DeepLinkResolver { val obj = uri.getQueryParameter(OBJECT_ID_PARAM) val space = uri.getQueryParameter(SPACE_ID_PARAM) if (!obj.isNullOrEmpty() && !space.isNullOrEmpty()) { + val cid = uri.getQueryParameter(CONTENT_ID_PARAM) + val key = uri.getQueryParameter(ENCRYPTION_KEY_PARAM) DeepLinkResolver.Action.DeepLinkToObject( obj = obj, - space = SpaceId(space) + space = SpaceId(space), + invite = if (!cid.isNullOrEmpty() && !key.isNullOrEmpty()) { + DeepLinkResolver.Action.DeepLinkToObject.Invite( + cid = cid, + key = key + ) + } else { + null + } ) } else { DeepLinkResolver.Action.Unknown @@ -82,6 +96,15 @@ object DefaultDeepLinkResolver : DeepLinkResolver { return "${DEEP_LINK_PATTERN}${OBJECT_PATH}?${OBJECT_ID_PARAM}=$obj&${SPACE_ID_PARAM}=${space.id}" } + override fun createObjectDeepLinkWithInvite( + obj: Id, + space: SpaceId, + invite: Id, + encryptionKey: String + ): Url { + return "${DEEP_LINK_PATTERN}${OBJECT_PATH}?${OBJECT_ID_PARAM}=$obj&${SPACE_ID_PARAM}=${space.id}&${DefaultSpaceInviteResolver.CONTENT_ID_KEY}=$invite&${DefaultSpaceInviteResolver.FILE_KEY_KEY}=$encryptionKey" + } + override fun isDeepLink(link: String): Boolean { return link.contains(defaultInviteRegex) || link.contains(DEEP_LINK_PATTERN) } @@ -112,8 +135,12 @@ object DefaultSpaceInviteResolver : SpaceInviteResolver { } } + override fun createInviteLink(contentId: String, encryptionKey: String) : String { + return "https://$DEEP_LINK_INVITE_DOMAIN/$contentId#$encryptionKey" + } + private const val CONTENT_INDEX = 1 private const val KEY_INDEX = 2 - private const val CONTENT_ID_KEY = "cid" - private const val FILE_KEY_KEY = "key" + const val CONTENT_ID_KEY = "cid" + const val FILE_KEY_KEY = "key" } \ No newline at end of file diff --git a/domain/src/main/java/com/anytypeio/anytype/domain/misc/DeepLinkResolver.kt b/domain/src/main/java/com/anytypeio/anytype/domain/misc/DeepLinkResolver.kt index 7e1cd90f7c..a1158c3077 100644 --- a/domain/src/main/java/com/anytypeio/anytype/domain/misc/DeepLinkResolver.kt +++ b/domain/src/main/java/com/anytypeio/anytype/domain/misc/DeepLinkResolver.kt @@ -11,6 +11,13 @@ interface DeepLinkResolver { fun createObjectDeepLink(obj: Id, space: SpaceId) : Url + fun createObjectDeepLinkWithInvite( + obj: Id, + space: SpaceId, + invite: Id, + encryptionKey: String + ) : Url + fun isDeepLink(link: String) : Boolean sealed class Action { @@ -21,8 +28,14 @@ interface DeepLinkResolver { data class Invite(val link: String) : Action() data class DeepLinkToObject( val obj: Id, - val space: SpaceId - ) : Action() + val space: SpaceId, + val invite: Invite? = null + ) : Action() { + data class Invite( + val cid: String, + val key: String + ) + } data class DeepLinkToMembership( val tierId: String? ) : Action() diff --git a/domain/src/main/java/com/anytypeio/anytype/domain/multiplayer/SpaceInviteResolver.kt b/domain/src/main/java/com/anytypeio/anytype/domain/multiplayer/SpaceInviteResolver.kt index 0f924c9644..100b708998 100644 --- a/domain/src/main/java/com/anytypeio/anytype/domain/multiplayer/SpaceInviteResolver.kt +++ b/domain/src/main/java/com/anytypeio/anytype/domain/multiplayer/SpaceInviteResolver.kt @@ -5,4 +5,5 @@ import com.anytypeio.anytype.core_models.Id interface SpaceInviteResolver { fun parseContentId(link: String) : Id? fun parseFileKey(link: String) : Id? + fun createInviteLink(contentId: String, encryptionKey: String) : String } \ No newline at end of file diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/home/HomeScreenViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/home/HomeScreenViewModel.kt index 1c319b3c02..4866039a1b 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/home/HomeScreenViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/home/HomeScreenViewModel.kt @@ -54,6 +54,7 @@ import com.anytypeio.anytype.domain.misc.DateProvider import com.anytypeio.anytype.domain.misc.DeepLinkResolver import com.anytypeio.anytype.domain.misc.Reducer import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.multiplayer.SpaceInviteResolver import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider import com.anytypeio.anytype.domain.`object`.GetObject import com.anytypeio.anytype.domain.`object`.OpenObject @@ -207,7 +208,8 @@ class HomeScreenViewModel( private val clearLastOpenedObject: ClearLastOpenedObject, private val spaceBinWidgetContainer: SpaceBinWidgetContainer, private val featureToggles: FeatureToggles, - private val fieldParser: FieldParser + private val fieldParser: FieldParser, + private val spaceInviteResolver: SpaceInviteResolver ) : NavigationViewModel(), Reducer, WidgetActiveViewStateHolder by widgetActiveViewStateHolder, @@ -1339,7 +1341,19 @@ class HomeScreenViewModel( ).collect { result -> when(result) { is DeepLinkToObjectDelegate.Result.Error -> { - commands.emit(Command.Deeplink.DeepLinkToObjectNotWorking) + val link = deeplink.invite + if (link != null) { + commands.emit( + Command.Deeplink.Invite( + link = spaceInviteResolver.createInviteLink( + contentId = link.cid, + encryptionKey = link.key + ) + ) + ) + } else { + commands.emit(Command.Deeplink.DeepLinkToObjectNotWorking) + } } is DeepLinkToObjectDelegate.Result.Success -> { proceedWithNavigation(result.obj.navigation()) @@ -2196,7 +2210,8 @@ class HomeScreenViewModel( private val clearLastOpenedObject: ClearLastOpenedObject, private val spaceBinWidgetContainer: SpaceBinWidgetContainer, private val featureToggles: FeatureToggles, - private val fieldParser: FieldParser + private val fieldParser: FieldParser, + private val spaceInviteResolver: SpaceInviteResolver ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create(modelClass: Class): T = HomeScreenViewModel( @@ -2248,7 +2263,8 @@ class HomeScreenViewModel( clearLastOpenedObject = clearLastOpenedObject, spaceBinWidgetContainer = spaceBinWidgetContainer, featureToggles = featureToggles, - fieldParser = fieldParser + fieldParser = fieldParser, + spaceInviteResolver = spaceInviteResolver ) as T } diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/main/MainViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/main/MainViewModel.kt index 92c0458ec7..e6ad05d42e 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/main/MainViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/main/MainViewModel.kt @@ -24,6 +24,7 @@ import com.anytypeio.anytype.domain.base.Interactor import com.anytypeio.anytype.domain.config.ConfigStorage import com.anytypeio.anytype.domain.misc.DeepLinkResolver import com.anytypeio.anytype.domain.misc.LocaleProvider +import com.anytypeio.anytype.domain.multiplayer.SpaceInviteResolver import com.anytypeio.anytype.domain.notifications.SystemNotificationService import com.anytypeio.anytype.domain.subscriptions.GlobalSubscriptionManager import com.anytypeio.anytype.domain.wallpaper.ObserveWallpaper @@ -62,7 +63,8 @@ class MainViewModel( private val deepLinkToObjectDelegate: DeepLinkToObjectDelegate, private val awaitAccountStartManager: AwaitAccountStartManager, private val membershipProvider: MembershipProvider, - private val globalSubscriptionManager: GlobalSubscriptionManager + private val globalSubscriptionManager: GlobalSubscriptionManager, + private val spaceInviteResolver: SpaceInviteResolver ) : ViewModel(), NotificationActionDelegate by notificationActionDelegate, DeepLinkToObjectDelegate by deepLinkToObjectDelegate { @@ -336,7 +338,19 @@ class MainViewModel( ) when (result) { is DeepLinkToObjectDelegate.Result.Error -> { - toasts.emit("Error: $result") + val link = deeplink.invite + if (link != null) { + commands.emit( + Command.Deeplink.Invite( + spaceInviteResolver.createInviteLink( + contentId = link.cid, + encryptionKey = link.key + ) + ) + ) + } else { + toasts.emit("Error: $result") + } } is DeepLinkToObjectDelegate.Result.Success -> { commands.emit( diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/main/MainViewModelFactory.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/main/MainViewModelFactory.kt index 2fad48824f..5a1340c7de 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/main/MainViewModelFactory.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/main/MainViewModelFactory.kt @@ -10,6 +10,7 @@ import com.anytypeio.anytype.domain.auth.interactor.Logout import com.anytypeio.anytype.domain.auth.interactor.ResumeAccount import com.anytypeio.anytype.domain.config.ConfigStorage import com.anytypeio.anytype.domain.misc.LocaleProvider +import com.anytypeio.anytype.domain.multiplayer.SpaceInviteResolver import com.anytypeio.anytype.domain.notifications.SystemNotificationService import com.anytypeio.anytype.domain.subscriptions.GlobalSubscriptionManager import com.anytypeio.anytype.domain.wallpaper.ObserveWallpaper @@ -36,7 +37,8 @@ class MainViewModelFactory @Inject constructor( private val deepLinkToObjectDelegate: DeepLinkToObjectDelegate, private val awaitAccountStartManager: AwaitAccountStartManager, private val membershipProvider: MembershipProvider, - private val globalSubscriptionManager: GlobalSubscriptionManager + private val globalSubscriptionManager: GlobalSubscriptionManager, + private val spaceInviteResolver: SpaceInviteResolver ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create( @@ -57,6 +59,7 @@ class MainViewModelFactory @Inject constructor( deepLinkToObjectDelegate = deepLinkToObjectDelegate, awaitAccountStartManager = awaitAccountStartManager, membershipProvider = membershipProvider, - globalSubscriptionManager = globalSubscriptionManager + globalSubscriptionManager = globalSubscriptionManager, + spaceInviteResolver = spaceInviteResolver ) as T } \ No newline at end of file diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/menu/ObjectMenuViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/menu/ObjectMenuViewModel.kt index 04b94f8b4e..163b7fd737 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/menu/ObjectMenuViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/menu/ObjectMenuViewModel.kt @@ -38,6 +38,9 @@ import com.anytypeio.anytype.presentation.extension.sendAnalyticsDefaultTemplate import com.anytypeio.anytype.presentation.objects.ObjectAction import com.anytypeio.anytype.core_models.SupportedLayouts.fileLayouts import com.anytypeio.anytype.core_models.SupportedLayouts.systemLayouts +import com.anytypeio.anytype.core_models.multiplayer.SpaceAccessType +import com.anytypeio.anytype.domain.multiplayer.GetSpaceInviteLink +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.presentation.objects.isTemplatesAllowed import com.anytypeio.anytype.presentation.util.Dispatcher import com.anytypeio.anytype.presentation.util.downloader.DebugGoroutinesShareDownloader @@ -69,7 +72,9 @@ class ObjectMenuViewModel( private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate, private val setObjectListIsFavorite: SetObjectListIsFavorite, private val setObjectIsArchived: SetObjectListIsArchived, - private val fieldParser: FieldParser + private val fieldParser: FieldParser, + private val spaceViewSubscriptionContainer: SpaceViewSubscriptionContainer, + private val getSpaceInviteLink: GetSpaceInviteLink ) : ObjectMenuViewModelBase( setObjectIsArchived = setObjectIsArchived, addBackLinkToObject = addBackLinkToObject, @@ -86,7 +91,10 @@ class ObjectMenuViewModel( analyticSpaceHelperDelegate = analyticSpaceHelperDelegate, payloadDelegator = payloadDelegator, setObjectListIsFavorite = setObjectListIsFavorite, - fieldParser = fieldParser + fieldParser = fieldParser, + spaceViewSubscriptionContainer = spaceViewSubscriptionContainer, + deepLinkResolver = deepLinkResolver, + getSpaceInviteLink = getSpaceInviteLink ) { init { @@ -276,11 +284,13 @@ class ObjectMenuViewModel( proceedWithLinkTo() } ObjectAction.COPY_LINK -> { - val deeplink = deepLinkResolver.createObjectDeepLink( - obj = ctx, - space = SpaceId(space) - ) - viewModelScope.launch { commands.emit(Command.ShareDeeplinkToObject(deeplink)) } + viewModelScope.launch { + val link = proceedWithGeneratingObjectLink( + space = SpaceId(space), + ctx = ctx + ) + commands.emit(Command.ShareDeeplinkToObject(link)) + } } ObjectAction.UNLOCK -> { proceedWithUpdatingLockStatus(ctx, false) @@ -479,7 +489,9 @@ class ObjectMenuViewModel( private val payloadDelegator: PayloadDelegator, private val setObjectListIsFavorite: SetObjectListIsFavorite, private val setObjectIsArchived: SetObjectListIsArchived, - private val fieldParser: FieldParser + private val fieldParser: FieldParser, + private val getSpaceInviteLink: GetSpaceInviteLink, + private val spaceViewSubscriptionContainer: SpaceViewSubscriptionContainer ) : ViewModelProvider.Factory { override fun create(modelClass: Class): T { return ObjectMenuViewModel( @@ -504,7 +516,9 @@ class ObjectMenuViewModel( analyticSpaceHelperDelegate = analyticSpaceHelperDelegate, payloadDelegator = payloadDelegator, setObjectListIsFavorite = setObjectListIsFavorite, - fieldParser = fieldParser + fieldParser = fieldParser, + getSpaceInviteLink = getSpaceInviteLink, + spaceViewSubscriptionContainer = spaceViewSubscriptionContainer ) as T } } diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/menu/ObjectMenuViewModelBase.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/menu/ObjectMenuViewModelBase.kt index 3d3a99236a..4839875414 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/menu/ObjectMenuViewModelBase.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/menu/ObjectMenuViewModelBase.kt @@ -11,11 +11,15 @@ import com.anytypeio.anytype.core_models.ObjectWrapper import com.anytypeio.anytype.core_models.Payload import com.anytypeio.anytype.core_models.WidgetLayout import com.anytypeio.anytype.core_models.isDataView +import com.anytypeio.anytype.core_models.multiplayer.SpaceAccessType import com.anytypeio.anytype.core_models.primitives.SpaceId import com.anytypeio.anytype.domain.base.fold import com.anytypeio.anytype.domain.collections.AddObjectToCollection import com.anytypeio.anytype.domain.dashboard.interactor.SetObjectListIsFavorite +import com.anytypeio.anytype.domain.misc.DeepLinkResolver import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.multiplayer.GetSpaceInviteLink +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.`object`.DuplicateObject import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived import com.anytypeio.anytype.domain.page.AddBackLinkToObject @@ -62,7 +66,10 @@ abstract class ObjectMenuViewModelBase( private val payloadDelegator: PayloadDelegator, private val setObjectListIsFavorite: SetObjectListIsFavorite, private val setObjectIsArchived: SetObjectListIsArchived, - private val fieldParser: FieldParser + private val fieldParser: FieldParser, + private val spaceViewSubscriptionContainer: SpaceViewSubscriptionContainer, + private val getSpaceInviteLink: GetSpaceInviteLink, + private val deepLinkResolver: DeepLinkResolver ) : BaseViewModel(), AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate { protected val jobs = mutableListOf() @@ -434,6 +441,34 @@ abstract class ObjectMenuViewModelBase( } } + suspend fun proceedWithGeneratingObjectLink( + space: SpaceId, + ctx: String + ): String { + val spaceView = spaceViewSubscriptionContainer.get(space) + return if (spaceView?.spaceAccessType == SpaceAccessType.SHARED) { + val link = getSpaceInviteLink.async(space).getOrNull() + if (link != null) { + deepLinkResolver.createObjectDeepLinkWithInvite( + obj = ctx, + space = space, + encryptionKey = link.fileKey, + invite = link.contentId + ) + } else { + deepLinkResolver.createObjectDeepLink( + obj = ctx, + space = space + ) + } + } else { + deepLinkResolver.createObjectDeepLink( + obj = ctx, + space = space + ) + } + } + sealed class Command { data object OpenObjectIcons : Command() data object OpenSetIcons : Command() diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/menu/ObjectSetMenuViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/menu/ObjectSetMenuViewModel.kt index b8833dc4f0..8a46fa7556 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/menu/ObjectSetMenuViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/objects/menu/ObjectSetMenuViewModel.kt @@ -13,6 +13,8 @@ import com.anytypeio.anytype.domain.collections.AddObjectToCollection import com.anytypeio.anytype.domain.dashboard.interactor.SetObjectListIsFavorite import com.anytypeio.anytype.domain.misc.DeepLinkResolver import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.multiplayer.GetSpaceInviteLink +import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.`object`.DuplicateObject import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived import com.anytypeio.anytype.domain.page.AddBackLinkToObject @@ -51,7 +53,9 @@ class ObjectSetMenuViewModel( private val deepLinkResolver: DeepLinkResolver, private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate, setObjectListIsFavorite: SetObjectListIsFavorite, - fieldParser: FieldParser + fieldParser: FieldParser, + spaceViewSubscriptionContainer: SpaceViewSubscriptionContainer, + getSpaceInviteLink: GetSpaceInviteLink ) : ObjectMenuViewModelBase( setObjectIsArchived = setObjectIsArchived, addBackLinkToObject = addBackLinkToObject, @@ -68,7 +72,10 @@ class ObjectSetMenuViewModel( analyticSpaceHelperDelegate = analyticSpaceHelperDelegate, payloadDelegator = payloadDelegator, setObjectListIsFavorite = setObjectListIsFavorite, - fieldParser = fieldParser + fieldParser = fieldParser, + deepLinkResolver = deepLinkResolver, + spaceViewSubscriptionContainer = spaceViewSubscriptionContainer, + getSpaceInviteLink = getSpaceInviteLink ) { init { @@ -94,7 +101,9 @@ class ObjectSetMenuViewModel( private val payloadDelegator: PayloadDelegator, private val setObjectListIsFavorite: SetObjectListIsFavorite, private val setObjectListIsArchived: SetObjectListIsArchived, - private val fieldParser: FieldParser + private val fieldParser: FieldParser, + private val spaceViewSubscriptionContainer: SpaceViewSubscriptionContainer, + private val getSpaceInviteLink: GetSpaceInviteLink ) : ViewModelProvider.Factory { override fun create(modelClass: Class): T { return ObjectSetMenuViewModel( @@ -115,7 +124,9 @@ class ObjectSetMenuViewModel( analyticSpaceHelperDelegate = analyticSpaceHelperDelegate, payloadDelegator = payloadDelegator, setObjectListIsFavorite = setObjectListIsFavorite, - fieldParser = fieldParser + fieldParser = fieldParser, + spaceViewSubscriptionContainer = spaceViewSubscriptionContainer, + getSpaceInviteLink = getSpaceInviteLink ) as T } } @@ -219,11 +230,13 @@ class ObjectSetMenuViewModel( proceedWithCreatingWidget(obj = wrapper) } ObjectAction.COPY_LINK -> { - val deeplink = deepLinkResolver.createObjectDeepLink( - obj = ctx, - space = SpaceId(space) - ) - viewModelScope.launch { commands.emit(Command.ShareDeeplinkToObject(deeplink)) } + viewModelScope.launch { + val link = proceedWithGeneratingObjectLink( + space = SpaceId(space), + ctx = ctx + ) + commands.emit(Command.ShareDeeplinkToObject(link)) + } } ObjectAction.MOVE_TO, ObjectAction.SEARCH_ON_PAGE, diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/vault/VaultViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/vault/VaultViewModel.kt index 401e4882f0..60bfff39d5 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/vault/VaultViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/vault/VaultViewModel.kt @@ -20,6 +20,7 @@ import com.anytypeio.anytype.domain.base.onSuccess import com.anytypeio.anytype.domain.misc.AppActionManager import com.anytypeio.anytype.domain.misc.DeepLinkResolver import com.anytypeio.anytype.domain.misc.UrlBuilder +import com.anytypeio.anytype.domain.multiplayer.SpaceInviteResolver import com.anytypeio.anytype.domain.multiplayer.SpaceViewSubscriptionContainer import com.anytypeio.anytype.domain.spaces.SaveCurrentSpace import com.anytypeio.anytype.domain.vault.GetVaultSettings @@ -60,7 +61,8 @@ class VaultViewModel( private val setVaultSpaceOrder: SetVaultSpaceOrder, private val analytics: Analytics, private val deepLinkToObjectDelegate: DeepLinkToObjectDelegate, - private val appActionManager: AppActionManager + private val appActionManager: AppActionManager, + private val spaceInviteResolver: SpaceInviteResolver ) : NavigationViewModel(), DeepLinkToObjectDelegate by deepLinkToObjectDelegate { val spaces = MutableStateFlow>(emptyList()) @@ -206,7 +208,19 @@ class VaultViewModel( ).collect { result -> when(result) { is DeepLinkToObjectDelegate.Result.Error -> { - commands.emit(Command.Deeplink.DeepLinkToObjectNotWorking) + val link = deeplink.invite + if (link != null) { + commands.emit( + Command.Deeplink.Invite( + link = spaceInviteResolver.createInviteLink( + contentId = link.cid, + encryptionKey = link.key + ) + ) + ) + } else { + commands.emit(Command.Deeplink.DeepLinkToObjectNotWorking) + } } is DeepLinkToObjectDelegate.Result.Success -> { proceedWithNavigation(result.obj.navigation()) @@ -304,7 +318,8 @@ class VaultViewModel( private val observeVaultSettings: ObserveVaultSettings, private val analytics: Analytics, private val deepLinkToObjectDelegate: DeepLinkToObjectDelegate, - private val appActionManager: AppActionManager + private val appActionManager: AppActionManager, + private val spaceInviteResolver: SpaceInviteResolver ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create( @@ -321,7 +336,8 @@ class VaultViewModel( observeVaultSettings = observeVaultSettings, analytics = analytics, deepLinkToObjectDelegate = deepLinkToObjectDelegate, - appActionManager = appActionManager + appActionManager = appActionManager, + spaceInviteResolver = spaceInviteResolver ) as T }