diff --git a/src/Umbraco.Web.UI.Client/examples/modal-routed/dashboard.element.ts b/src/Umbraco.Web.UI.Client/examples/modal-routed/dashboard.element.ts index 967a4a7a88..61c0f6862f 100644 --- a/src/Umbraco.Web.UI.Client/examples/modal-routed/dashboard.element.ts +++ b/src/Umbraco.Web.UI.Client/examples/modal-routed/dashboard.element.ts @@ -17,6 +17,7 @@ export class UmbDashboardElement extends UmbElementMixin(LitElement) { }, { path: '', + pathMatch: 'full', redirectTo: 'tab1', }, ]; diff --git a/src/Umbraco.Web.UI.Client/examples/modal-routed/modal/example-modal.element.ts b/src/Umbraco.Web.UI.Client/examples/modal-routed/modal/example-modal.element.ts index e1f0f5bdd4..45c0229e37 100644 --- a/src/Umbraco.Web.UI.Client/examples/modal-routed/modal/example-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/examples/modal-routed/modal/example-modal.element.ts @@ -17,6 +17,7 @@ export class UmbExampleModal extends UmbModalBaseElement { }, { path: '', + pathMatch: 'full', redirectTo: 'modalOverview', }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-main.element.ts b/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-main.element.ts index 9435f94a1b..0550e6c52c 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-main.element.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-main.element.ts @@ -63,8 +63,10 @@ export class UmbBackofficeMainElement extends UmbLitElement { if (newRoutes.length > 0) { newRoutes.push({ + path: '', + pathMatch: 'full', + awaitStability: true, redirectTo: newRoutes[0].path, - path: ``, }); newRoutes.push({ diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit.element.ts index 21205661e5..e9ce9d3152 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit.element.ts @@ -123,6 +123,7 @@ export class UmbBlockWorkspaceViewEditElement extends UmbLitElement implements U if (!this._hasRootGroups) { routes.push({ path: '', + pathMatch: 'full', redirectTo: routes[0]?.path, }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor.element.ts index 34d0e5d3a8..ec9b43034a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor.element.ts @@ -205,12 +205,14 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements }); routes.push({ path: '', + pathMatch: 'full', redirectTo: 'root', guards: [() => this.#processingTabId === undefined], }); } else { routes.push({ path: '', + pathMatch: 'full', redirectTo: routes[0]?.path, guards: [() => this.#processingTabId === undefined], }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/views/edit/content-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/views/edit/content-editor.element.ts index 6f9bb5f542..693808923e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/views/edit/content-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/views/edit/content-editor.element.ts @@ -109,6 +109,7 @@ export class UmbContentWorkspaceViewEditElement extends UmbLitElement implements if (routes.length !== 0) { routes.push({ path: '', + pathMatch: 'full', redirectTo: routes[0].path, }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/router/router-slot/model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/router/router-slot/model.ts index 72e669027c..4b9892946a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/router/router-slot/model.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/router/router-slot/model.ts @@ -75,6 +75,9 @@ export interface IRedirectRoute extends IRouteBase { // The paths the route should redirect to. Can either be relative or absolute. redirectTo: string; + // First redirect when the routes appears stable. Delaying the redirect so other routes get the change to resolve first. + awaitStability?: boolean; + // Whether the query should be preserved when redirecting. preserveQuery?: boolean; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/router/router-slot/router-slot.ts b/src/Umbraco.Web.UI.Client/src/packages/core/router/router-slot/router-slot.ts index 3f3a0b9a8d..eebcec1dea 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/router/router-slot/router-slot.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/router/router-slot/router-slot.ts @@ -314,6 +314,24 @@ export class RouterSlot extends HTMLElement implements IRouter } } + private getRedirectDelay() { + if ('connection' in navigator) { + const connection = + navigator.connection || (navigator as any).mozConnection || (navigator as any).webkitConnection; + + switch (connection.effectiveType) { + case 'slow-2g': + case '2g': + return 1200; + case '3g': + return 800; + case '4g': + return 200; + } + } + return 400; + } + /** * Loads a new path based on the routes. * Returns true if a navigation was made to a new page. @@ -387,6 +405,14 @@ export class RouterSlot extends HTMLElement implements IRouter // Redirect if necessary if (isRedirectRoute(route)) { cleanup(); + if (route.awaitStability === true) { + // await until browser is done loading, based on a guess: + const delay = this.getRedirectDelay(); + await new Promise((resolve) => setTimeout(resolve, delay)); + if (navigationInvalidated) { + return cancel(); + } + } handleRedirect(this, route); return false; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-editor.element.ts index 0f75fd2ac0..38a20c07f0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace-editor.element.ts @@ -79,6 +79,7 @@ export class UmbDocumentBlueprintWorkspaceEditorElement extends UmbLitElement { // Using first single view as the default route for now (hence the math below): routes.push({ path: '', + pathMatch: 'full', redirectTo: routes[variants.length * variants.length]?.path, }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/dashboard/media-dashboard.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/dashboard/media-dashboard.element.ts index 1012858562..3e5739daaa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/dashboard/media-dashboard.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/dashboard/media-dashboard.element.ts @@ -53,6 +53,7 @@ export class UmbMediaDashboardElement extends UmbLitElement { }, { path: '', + pathMatch: 'full', redirectTo: 'collection', }, { diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace-editor.element.ts index d7eaa87ced..92f0fc4701 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace-editor.element.ts @@ -79,6 +79,7 @@ export class UmbMediaWorkspaceEditorElement extends UmbLitElement { // Using first single view as the default route for now (hence the math below): routes.push({ path: '', + pathMatch: 'full', redirectTo: routes[variants.length * variants.length]?.path, }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace-editor.element.ts index 70aa290688..27e7c6651e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/member-workspace-editor.element.ts @@ -81,6 +81,7 @@ export class UmbMemberWorkspaceEditorElement extends UmbLitElement { // Using first single view as the default route for now (hence the math below): routes.push({ path: '', + pathMatch: 'full', redirectTo: routes[options.length * options.length]?.path, }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/packages/package-section/views/created/created-packages-section-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/packages/package-section/views/created/created-packages-section-view.element.ts index 7537effb3e..b132fc82f7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/packages/package-section/views/created/created-packages-section-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/packages/package-section/views/created/created-packages-section-view.element.ts @@ -54,6 +54,7 @@ export class UmbCreatedPackagesSectionViewElement extends UmbLitElement implemen routes.push({ path: '', + pathMatch: 'full', redirectTo: 'overview', }); routes.push({