From c4f3780c9d8abf59e894fd5ad695f07162275019 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Thu, 9 Dec 2021 15:47:50 +0000 Subject: [PATCH 1/3] fix(vue): do not unmount old tab when navigating back to tabs context --- .../vue/src/components/IonRouterOutlet.ts | 21 ++++++++++++++ packages/vue/test-app/tests/e2e/specs/tabs.js | 29 ++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/packages/vue/src/components/IonRouterOutlet.ts b/packages/vue/src/components/IonRouterOutlet.ts index e5053f7aa3a..57f23ae0486 100644 --- a/packages/vue/src/components/IonRouterOutlet.ts +++ b/packages/vue/src/components/IonRouterOutlet.ts @@ -14,6 +14,10 @@ import { AnimationBuilder, LIFECYCLE_DID_ENTER, LIFECYCLE_DID_LEAVE, LIFECYCLE_W import { matchedRouteKey, routeLocationKey, useRoute } from 'vue-router'; import { fireLifecycle, generateId, getConfig } from '../utils'; +const isViewVisible = (enteringEl: HTMLElement) => { + return !enteringEl.classList.contains('ion-page-hidden') && !enteringEl.classList.contains('ion-page-invisible'); +} + let viewDepthKey: InjectionKey<0> = Symbol(0); export const IonRouterOutlet = defineComponent({ name: 'IonRouterOutlet', @@ -231,6 +235,23 @@ export const IonRouterOutlet = defineComponent({ See https://ionicframework.com/docs/vue/navigation#ionpage for more information.`); } + /** + * If the entering view is already + * visible, then no transition is needed. + * This is most common when navigating + * from a tabs page to a non-tabs page + * and then back to the tabs page. + * Even when the tabs context navigated away, + * the inner tabs page was still active. + * This also avoids an issue where + * the previous tabs page is incorrectly + * unmounted since it would automatically + * unmount the previous view. + */ + if (isViewVisible(enteringEl)) { + return; + } + if (enteringViewItem === leavingViewItem) return; if (!leavingViewItem && prevRouteLastPathname) { diff --git a/packages/vue/test-app/tests/e2e/specs/tabs.js b/packages/vue/test-app/tests/e2e/specs/tabs.js index 376ebfa1a33..2657b8d56a9 100644 --- a/packages/vue/test-app/tests/e2e/specs/tabs.js +++ b/packages/vue/test-app/tests/e2e/specs/tabs.js @@ -307,7 +307,7 @@ describe('Tabs', () => { cy.url().should('include', '/tabs/tab1/child-one?key=value'); }); - // Verifies fix for https://github.com/ionic-team/ionic-framework/issues/23699 + // Verifies fix for https://github.com/ionic-team/ionic-framework/issues/24353 it('should handle clicking tab multiple times without query string', () => { cy.visit('http://localhost:8080/tabs/tab1'); @@ -329,6 +329,33 @@ describe('Tabs', () => { cy.ionPageVisible('tab2'); cy.ionPageHidden('tab1'); }); + + // Verifies fix for https://github.com/ionic-team/ionic-framework/issues/24332 + it('should not unmount tab 1 when leaving tabs context', () => { + cy.visit('http://localhost:8080/tabs'); + cy.ionPageVisible('tab1'); + + // Dynamically add tab 4 because tab 3 redirects to tab 1 + cy.get('#add-tab').click(); + + cy.get('ion-tab-button#tab-button-tab4').click(); + cy.ionPageHidden('tab1'); + cy.ionPageVisible('tab4'); + + cy.get('ion-tab-button#tab-button-tab2').click(); + cy.ionPageHidden('tab4'); + cy.ionPageVisible('tab2'); + + cy.get('[data-pageid="tab2"] #routing').click(); + cy.ionPageVisible('routing'); + cy.ionPageHidden('tabs'); + + cy.ionBackClick('routing'); + cy.ionPageDoesNotExist('routing'); + cy.ionPageVisible('tabs'); + cy.ionPageVisible('tab2'); + cy.ionPageHidden('tab1'); + }); }) describe('Tabs - Swipe to Go Back', () => { From 86b63c846041593fe250d0e591e27574626be1da Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Thu, 9 Dec 2021 16:09:23 +0000 Subject: [PATCH 2/3] chore(): move fix down for better coverage --- .../vue/src/components/IonRouterOutlet.ts | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/vue/src/components/IonRouterOutlet.ts b/packages/vue/src/components/IonRouterOutlet.ts index 57f23ae0486..68ac4cfc433 100644 --- a/packages/vue/src/components/IonRouterOutlet.ts +++ b/packages/vue/src/components/IonRouterOutlet.ts @@ -234,6 +234,11 @@ export const IonRouterOutlet = defineComponent({ See https://ionicframework.com/docs/vue/navigation#ionpage for more information.`); } + if (enteringViewItem === leavingViewItem) return; + + if (!leavingViewItem && prevRouteLastPathname) { + leavingViewItem = viewStacks.findViewItemByPathname(prevRouteLastPathname, id, usingDeprecatedRouteSetup); + } /** * If the entering view is already @@ -247,17 +252,17 @@ See https://ionicframework.com/docs/vue/navigation#ionpage for more information. * the previous tabs page is incorrectly * unmounted since it would automatically * unmount the previous view. + * + * This should also only apply to entering and + * leaving items in the same router outlet (i.e. + * Tab1 and Tab2), otherwise this will + * return early for swipe to go back when + * going from a non-tabs page to a tabs page. */ - if (isViewVisible(enteringEl)) { + if (isViewVisible(enteringEl) && !isViewVisible(leavingViewItem.ionPageElement)) { return; } - if (enteringViewItem === leavingViewItem) return; - - if (!leavingViewItem && prevRouteLastPathname) { - leavingViewItem = viewStacks.findViewItemByPathname(prevRouteLastPathname, id, usingDeprecatedRouteSetup); - } - fireLifecycle(enteringViewItem.vueComponent, enteringViewItem.vueComponentRef, LIFECYCLE_WILL_ENTER); if (leavingViewItem && enteringViewItem !== leavingViewItem) { From ef6eb07fbc9677d83786f60f816c97577a3bc935 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Thu, 9 Dec 2021 16:33:24 +0000 Subject: [PATCH 3/3] fix(): add undefined check --- packages/vue/src/components/IonRouterOutlet.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vue/src/components/IonRouterOutlet.ts b/packages/vue/src/components/IonRouterOutlet.ts index 68ac4cfc433..ff9a05a8644 100644 --- a/packages/vue/src/components/IonRouterOutlet.ts +++ b/packages/vue/src/components/IonRouterOutlet.ts @@ -259,7 +259,7 @@ See https://ionicframework.com/docs/vue/navigation#ionpage for more information. * return early for swipe to go back when * going from a non-tabs page to a tabs page. */ - if (isViewVisible(enteringEl) && !isViewVisible(leavingViewItem.ionPageElement)) { + if (isViewVisible(enteringEl) && leavingViewItem !== undefined && !isViewVisible(leavingViewItem.ionPageElement)) { return; }