diff --git a/Explorer/Assets/DCL/ExplorePanel/BackpackDeepLinkOpener.cs b/Explorer/Assets/DCL/ExplorePanel/BackpackDeepLinkOpener.cs new file mode 100644 index 00000000000..d6a74d06c12 --- /dev/null +++ b/Explorer/Assets/DCL/ExplorePanel/BackpackDeepLinkOpener.cs @@ -0,0 +1,24 @@ +using Cysharp.Threading.Tasks; +using DCL.Diagnostics; +using DCL.RealmNavigation; +using DCL.UI; +using MVC; +using System; +using System.Threading; + +namespace DCL.ExplorePanel +{ + public static class BackpackDeepLinkOpener + { + public static async UniTaskVoid OpenBackpackWhenLandedAsync(IMVCManager mvcManager, ILoadingStatus loadingStatus, CancellationToken ct) + { + try + { + await UniTask.WaitUntil(() => loadingStatus.CurrentStage.Value == LoadingStatus.LoadingStage.Completed, cancellationToken: ct); + await mvcManager.ShowAsync(ExplorePanelController.IssueCommand(new ExplorePanelParameter(ExploreSections.Backpack)), ct); + } + catch (OperationCanceledException) { } + catch (Exception e) { ReportHub.LogException(e, ReportCategory.UI); } + } + } +} diff --git a/Explorer/Assets/DCL/ExplorePanel/BackpackDeepLinkOpener.cs.meta b/Explorer/Assets/DCL/ExplorePanel/BackpackDeepLinkOpener.cs.meta new file mode 100644 index 00000000000..dd607b8b71b --- /dev/null +++ b/Explorer/Assets/DCL/ExplorePanel/BackpackDeepLinkOpener.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cd49ae39a64a4ea5ab42d313e801cead +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Explorer/Assets/DCL/Infrastructure/Global/AppArgs/AppArgsFlags.cs b/Explorer/Assets/DCL/Infrastructure/Global/AppArgs/AppArgsFlags.cs index 9c3992f08c3..3fadae5145b 100644 --- a/Explorer/Assets/DCL/Infrastructure/Global/AppArgs/AppArgsFlags.cs +++ b/Explorer/Assets/DCL/Infrastructure/Global/AppArgs/AppArgsFlags.cs @@ -32,6 +32,8 @@ public static class AppArgsFlags /// public const string COMMUNITY = "community"; + public const string FORCE_OPEN_BACKPACK = "force-open-backpack"; + // The opaque identity id delivered by the auth website's signin deep link (decentraland://?signin={identityId}). public const string SIGNIN = "signin"; diff --git a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/DynamicWorldContainer.cs b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/DynamicWorldContainer.cs index 91ff480e4d4..08c2cbc3238 100644 --- a/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/DynamicWorldContainer.cs +++ b/Explorer/Assets/DCL/Infrastructure/Global/Dynamic/DynamicWorldContainer.cs @@ -463,7 +463,7 @@ await MapRendererContainer // Deep link listening stays alive in every mode so browser sign-in can complete; local scene // development only opts out of navigation routing (teleports would break the scene under test). - var deepLinkHandleImplementation = new DeepLinkHandle(dynamicWorldParams.StartParcel, chatContainer.ChatTeleporter, ct, communitiesDataService, bootstrapContainer.DeeplinkSigninIdentityId, + var deepLinkHandleImplementation = new DeepLinkHandle(dynamicWorldParams.StartParcel, chatContainer.ChatTeleporter, ct, communitiesDataService, uiShellContainer.MvcManager, staticContainer.LoadingStatus, bootstrapContainer.DeeplinkSigninIdentityId, bootstrapContainer.DeeplinkLoginAwaitingSigninRequestId, routeNavigationDeepLinks: !appArgs.HasFlag(AppArgsFlags.LOCAL_SCENE)); deepLinkHandleImplementation.StartListenForDeepLinksAsync(ct).Forget(); diff --git a/Explorer/Assets/DCL/MarketplaceCredits/MarketplaceCreditsMenuController.cs b/Explorer/Assets/DCL/MarketplaceCredits/MarketplaceCreditsMenuController.cs index c4f6065ccc0..7286de4ee96 100644 --- a/Explorer/Assets/DCL/MarketplaceCredits/MarketplaceCreditsMenuController.cs +++ b/Explorer/Assets/DCL/MarketplaceCredits/MarketplaceCreditsMenuController.cs @@ -335,8 +335,9 @@ private async UniTaskVoid CheckForSidebarButtonStateAsync(CancellationToken ct) if (!creditsProgramProgressResponse.HasUserStartedProgram() || TrySetAsShownThisWeek(creditsProgramProgressResponse)) { - // Open the Marketplace Credits panel by default when the user didn't start the program and has landed in Genesis City. - await UniTask.WaitUntil(() => loadingStatus.CurrentStage.Value == LoadingStatus.LoadingStage.Completed && realmData.IsGenesis(), cancellationToken: ct); + // Open the Marketplace Credits panel by default when the user didn't start the program and has landed in Genesis City, + // holding off while any other popup or fullscreen view is on screen (e.g. the backpack opened via force-open-backpack). + await UniTask.WaitUntil(() => loadingStatus.CurrentStage.Value == LoadingStatus.LoadingStage.Completed && realmData.IsGenesis() && !mvcManager.IsAnyModalViewShowing(), cancellationToken: ct); await mvcManager.ShowAsync(MarketplaceCreditsMenuController.IssueCommand(new Params(isOpenedFromNotification: false)), ct); } diff --git a/Explorer/Assets/DCL/PluginSystem/Global/ExplorePanelPlugin.cs b/Explorer/Assets/DCL/PluginSystem/Global/ExplorePanelPlugin.cs index 9b6d493c6ae..958be7b2895 100644 --- a/Explorer/Assets/DCL/PluginSystem/Global/ExplorePanelPlugin.cs +++ b/Explorer/Assets/DCL/PluginSystem/Global/ExplorePanelPlugin.cs @@ -622,6 +622,9 @@ public async UniTask InitializeAsync(ExplorePanelSettings settings, Cancellation if (isCommunitiesFeatureEnabled) dclInput.Shortcuts.Communities.performed += OnInputShortcutsCommunitiesPerformed; + + if (appArgs.HasFlag(AppArgsFlags.FORCE_OPEN_BACKPACK)) + BackpackDeepLinkOpener.OpenBackpackWhenLandedAsync(mvcManager, loadingStatus, ct).Forget(); } private async UniTask> InitializePlaceElementsPoolAsync(SearchResultPanelView view, CancellationToken ct) diff --git a/Explorer/Assets/DCL/RuntimeDeepLink/DeepLinkHandleImplementation.cs b/Explorer/Assets/DCL/RuntimeDeepLink/DeepLinkHandleImplementation.cs index bff5fda641b..5cd3ba6ccf7 100644 --- a/Explorer/Assets/DCL/RuntimeDeepLink/DeepLinkHandleImplementation.cs +++ b/Explorer/Assets/DCL/RuntimeDeepLink/DeepLinkHandleImplementation.cs @@ -2,10 +2,12 @@ using Cysharp.Threading.Tasks; using DCL.Chat.Commands; using DCL.Communities; +using DCL.ExplorePanel; using DCL.Diagnostics; using DCL.RealmNavigation; using DCL.Utilities; using Global.AppArgs; +using MVC; using System.Threading; using UnityEngine; @@ -17,17 +19,21 @@ public class DeepLinkHandle : IDeepLinkHandle private readonly ChatTeleporter chatTeleporter; private readonly CancellationToken token; private readonly CommunityDataService communityDataService; + private readonly IMVCManager mvcManager; + private readonly ILoadingStatus loadingStatus; private readonly ReactiveProperty deeplinkSigninIdentityId; private readonly IReadonlyReactiveProperty loginAwaitingSigninRequestId; private readonly bool routeNavigationDeepLinks; - public DeepLinkHandle(StartParcel startParcel, ChatTeleporter chatTeleporter, CancellationToken token, CommunityDataService communityDataService, ReactiveProperty deeplinkSigninIdentityId, + public DeepLinkHandle(StartParcel startParcel, ChatTeleporter chatTeleporter, CancellationToken token, CommunityDataService communityDataService, IMVCManager mvcManager, ILoadingStatus loadingStatus, ReactiveProperty deeplinkSigninIdentityId, IReadonlyReactiveProperty loginAwaitingSigninRequestId, bool routeNavigationDeepLinks) { this.startParcel = startParcel; this.chatTeleporter = chatTeleporter; this.token = token; this.communityDataService = communityDataService; + this.mvcManager = mvcManager; + this.loadingStatus = loadingStatus; this.deeplinkSigninIdentityId = deeplinkSigninIdentityId; this.loginAwaitingSigninRequestId = loginAwaitingSigninRequestId; this.routeNavigationDeepLinks = routeNavigationDeepLinks; @@ -90,6 +96,12 @@ public DeepLinkHandleResult HandleDeepLink(DeepLink deeplink) handled = true; } + if (deeplink.ValueOf(AppArgsFlags.FORCE_OPEN_BACKPACK) != null) + { + BackpackDeepLinkOpener.OpenBackpackWhenLandedAsync(mvcManager, loadingStatus, token).Forget(); + handled = true; + } + return handled ? DeepLinkHandleResult.CONSUMED : DeepLinkHandleResult.NO_MATCHES; } diff --git a/docs/app-arguments.md b/docs/app-arguments.md index 139655e3de4..7f8f6938688 100644 --- a/docs/app-arguments.md +++ b/docs/app-arguments.md @@ -252,6 +252,21 @@ More detailed instructions on how to test can be found in the description of rel --- +## UI Flags + +### `force-open-backpack` +**Description:** Automatically opens the Backpack panel once the user lands in the world (after authentication and the loading screen). Presence-only: any value triggers it. Also works when a deep link reaches an already-running client — the Backpack opens immediately (or once loading completes). + +**Usage:** +```bash +--force-open-backpack +``` +``` +decentraland://?force-open-backpack=true +``` + +--- + ## Performance & Caching Flags ### `disable-disk-cache`