mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-15 09:34:19 +08:00
chore(vue-router): add eslint and prettier (#26636)
This commit is contained in:
@ -17,7 +17,7 @@ runs:
|
|||||||
path: ./packages/vue
|
path: ./packages/vue
|
||||||
filename: VueBuild.zip
|
filename: VueBuild.zip
|
||||||
- name: Install Vue Router Dependencies
|
- name: Install Vue Router Dependencies
|
||||||
run: npm install
|
run: npm ci
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: ./packages/vue-router
|
working-directory: ./packages/vue-router
|
||||||
- name: Sync
|
- name: Sync
|
||||||
|
26
packages/vue-router/.eslintrc.js
Normal file
26
packages/vue-router/.eslintrc.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
module.exports = {
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"es6": true,
|
||||||
|
"node": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:@typescript-eslint/recommended",
|
||||||
|
"@ionic/eslint-config/recommended"
|
||||||
|
],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"project": "tsconfig.json",
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
"@typescript-eslint",
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||||
|
"@typescript-eslint/no-non-null-assertion": "off",
|
||||||
|
"@typescript-eslint/prefer-optional-chain": "off",
|
||||||
|
"@typescript-eslint/ban-types": "off"
|
||||||
|
}
|
||||||
|
};
|
4078
packages/vue-router/package-lock.json
generated
4078
packages/vue-router/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,10 @@
|
|||||||
"description": "Vue Router integration for @ionic/vue",
|
"description": "Vue Router integration for @ionic/vue",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test.spec": "jest",
|
"test.spec": "jest",
|
||||||
"lint": "echo add linter",
|
"eslint": "eslint src",
|
||||||
|
"prettier": "prettier \"./src/**/*.{html,ts,tsx,js,jsx}\"",
|
||||||
|
"lint": "npm run eslint && npm run prettier -- --write --cache",
|
||||||
|
"lint.fix": "npm run eslint -- --fix && npm run prettier -- --write --cache",
|
||||||
"bundle": "rollup --config rollup.config.js",
|
"bundle": "rollup --config rollup.config.js",
|
||||||
"build": "npm run clean && npm run compile && npm run bundle",
|
"build": "npm run clean && npm run compile && npm run bundle",
|
||||||
"clean": "rimraf dist",
|
"clean": "rimraf dist",
|
||||||
@ -46,10 +49,16 @@
|
|||||||
"@ionic/vue": "^6.5.0"
|
"@ionic/vue": "^6.5.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@ionic/eslint-config": "^0.3.0",
|
||||||
|
"@ionic/prettier-config": "^2.0.0",
|
||||||
"@types/jest": "^28.1.1",
|
"@types/jest": "^28.1.1",
|
||||||
"@types/node": "^14.10.1",
|
"@types/node": "^14.10.1",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.48.2",
|
||||||
|
"@typescript-eslint/parser": "^5.48.2",
|
||||||
|
"eslint": "^7.32.0",
|
||||||
"jest": "^28.1.1",
|
"jest": "^28.1.1",
|
||||||
"jest-environment-jsdom": "^28.1.1",
|
"jest-environment-jsdom": "^28.1.1",
|
||||||
|
"prettier": "^2.8.3",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"rollup": "^2.32.1",
|
"rollup": "^2.32.1",
|
||||||
"ts-jest": "^28.0.5",
|
"ts-jest": "^28.0.5",
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import { App } from 'vue';
|
import type { App } from "vue";
|
||||||
import {
|
import {
|
||||||
createRouter as createVueRouter,
|
createRouter as createVueRouter,
|
||||||
createWebHistory as createVueWebHistory,
|
createWebHistory as createVueWebHistory,
|
||||||
createWebHashHistory as createVueWebHashHistory,
|
createWebHashHistory as createVueWebHashHistory,
|
||||||
createMemoryHistory as createVueMemoryHistory
|
createMemoryHistory as createVueMemoryHistory,
|
||||||
} from 'vue-router';
|
} from "vue-router";
|
||||||
import { createIonRouter } from './router';
|
|
||||||
import { createViewStacks } from './viewStacks';
|
import { createIonRouter } from "./router";
|
||||||
import { IonicVueRouterOptions } from './types';
|
import type { IonicVueRouterOptions } from "./types";
|
||||||
|
import { createViewStacks } from "./viewStacks";
|
||||||
|
|
||||||
export const createRouter = (opts: IonicVueRouterOptions) => {
|
export const createRouter = (opts: IonicVueRouterOptions) => {
|
||||||
const routerOptions = { ...opts };
|
const routerOptions = { ...opts };
|
||||||
@ -19,8 +20,8 @@ export const createRouter = (opts: IonicVueRouterOptions) => {
|
|||||||
|
|
||||||
const oldInstall = router.install.bind(router);
|
const oldInstall = router.install.bind(router);
|
||||||
router.install = (app: App) => {
|
router.install = (app: App) => {
|
||||||
app.provide('navManager', ionRouter);
|
app.provide("navManager", ionRouter);
|
||||||
app.provide('viewStacks', viewStacks);
|
app.provide("viewStacks", viewStacks);
|
||||||
|
|
||||||
oldInstall(app);
|
oldInstall(app);
|
||||||
};
|
};
|
||||||
@ -29,8 +30,10 @@ export const createRouter = (opts: IonicVueRouterOptions) => {
|
|||||||
router.isReady = () => oldIsReady();
|
router.isReady = () => oldIsReady();
|
||||||
|
|
||||||
return router;
|
return router;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const createWebHistory = (base?: string) => createVueWebHistory(base);
|
export const createWebHistory = (base?: string) => createVueWebHistory(base);
|
||||||
export const createWebHashHistory = (base?: string) => createVueWebHashHistory(base);
|
export const createWebHashHistory = (base?: string) =>
|
||||||
export const createMemoryHistory = (base?: string) => createVueMemoryHistory(base);
|
createVueWebHashHistory(base);
|
||||||
|
export const createMemoryHistory = (base?: string) =>
|
||||||
|
createVueMemoryHistory(base);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { RouteInfo } from './types';
|
import type { RouteInfo } from "./types";
|
||||||
|
|
||||||
export const createLocationHistory = () => {
|
export const createLocationHistory = () => {
|
||||||
const locationHistory: RouteInfo[] = [];
|
const locationHistory: RouteInfo[] = [];
|
||||||
@ -14,20 +14,22 @@ export const createLocationHistory = () => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (routeInfo.routerDirection === 'root') {
|
if (routeInfo.routerDirection === "root") {
|
||||||
clearHistory();
|
clearHistory();
|
||||||
addRoute(routeInfo);
|
addRoute(routeInfo);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const update = (routeInfo: RouteInfo) => {
|
const update = (routeInfo: RouteInfo) => {
|
||||||
const locationIndex = locationHistory.findIndex(x => x.id === routeInfo.id);
|
const locationIndex = locationHistory.findIndex(
|
||||||
|
(x) => x.id === routeInfo.id
|
||||||
|
);
|
||||||
if (locationIndex > -1) {
|
if (locationIndex > -1) {
|
||||||
locationHistory.splice(locationIndex, 1, routeInfo);
|
locationHistory.splice(locationIndex, 1, routeInfo);
|
||||||
}
|
}
|
||||||
const tabArray = tabsHistory[routeInfo.tab || ''];
|
const tabArray = tabsHistory[routeInfo.tab || ""];
|
||||||
if (tabArray) {
|
if (tabArray) {
|
||||||
const tabIndex = tabArray.findIndex(x => x.id === routeInfo.id);
|
const tabIndex = tabArray.findIndex((x) => x.id === routeInfo.id);
|
||||||
if (tabIndex > -1) {
|
if (tabIndex > -1) {
|
||||||
tabArray.splice(tabIndex, 1, routeInfo);
|
tabArray.splice(tabIndex, 1, routeInfo);
|
||||||
} else {
|
} else {
|
||||||
@ -36,7 +38,7 @@ export const createLocationHistory = () => {
|
|||||||
} else if (routeInfo.tab) {
|
} else if (routeInfo.tab) {
|
||||||
tabsHistory[routeInfo.tab] = [routeInfo];
|
tabsHistory[routeInfo.tab] = [routeInfo];
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const pop = (routeInfo: RouteInfo) => {
|
const pop = (routeInfo: RouteInfo) => {
|
||||||
const tabHistory = getTabsHistory(routeInfo.tab);
|
const tabHistory = getTabsHistory(routeInfo.tab);
|
||||||
@ -61,19 +63,22 @@ export const createLocationHistory = () => {
|
|||||||
// Replace with updated route
|
// Replace with updated route
|
||||||
locationHistory.pop();
|
locationHistory.pop();
|
||||||
locationHistory.push(routeInfo);
|
locationHistory.push(routeInfo);
|
||||||
}
|
};
|
||||||
|
|
||||||
const addRoute = (routeInfo: RouteInfo) => {
|
const addRoute = (routeInfo: RouteInfo) => {
|
||||||
const tabHistory = getTabsHistory(routeInfo.tab);
|
const tabHistory = getTabsHistory(routeInfo.tab);
|
||||||
if (tabHistory) {
|
if (tabHistory) {
|
||||||
// If the latest routeInfo is the same (going back and forth between tabs), replace it
|
// If the latest routeInfo is the same (going back and forth between tabs), replace it
|
||||||
if (tabHistory[tabHistory.length - 1] && tabHistory[tabHistory.length - 1].id === routeInfo.id) {
|
if (
|
||||||
|
tabHistory[tabHistory.length - 1] &&
|
||||||
|
tabHistory[tabHistory.length - 1].id === routeInfo.id
|
||||||
|
) {
|
||||||
tabHistory.pop();
|
tabHistory.pop();
|
||||||
}
|
}
|
||||||
tabHistory.push(routeInfo);
|
tabHistory.push(routeInfo);
|
||||||
}
|
}
|
||||||
locationHistory.push(routeInfo);
|
locationHistory.push(routeInfo);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wipes the location history arrays.
|
* Wipes the location history arrays.
|
||||||
@ -90,17 +95,21 @@ export const createLocationHistory = () => {
|
|||||||
* then there will not be any route index in
|
* then there will not be any route index in
|
||||||
* tabs either.
|
* tabs either.
|
||||||
*/
|
*/
|
||||||
const existingRouteIndex = locationHistory.findIndex(r => r.position === position);
|
const existingRouteIndex = locationHistory.findIndex(
|
||||||
|
(r) => r.position === position
|
||||||
|
);
|
||||||
if (existingRouteIndex === -1) return;
|
if (existingRouteIndex === -1) return;
|
||||||
|
|
||||||
locationHistory.splice(existingRouteIndex);
|
locationHistory.splice(existingRouteIndex);
|
||||||
|
|
||||||
const clearTabHistory = (tab: string) => {
|
const clearTabHistory = (tab: string) => {
|
||||||
const existingTabRouteIndex = tabsHistory[tab].findIndex(r => r.position === position);
|
const existingTabRouteIndex = tabsHistory[tab].findIndex(
|
||||||
|
(r) => r.position === position
|
||||||
|
);
|
||||||
if (existingTabRouteIndex === -1) return;
|
if (existingTabRouteIndex === -1) return;
|
||||||
|
|
||||||
tabsHistory[tab].splice(existingTabRouteIndex);
|
tabsHistory[tab].splice(existingTabRouteIndex);
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We also need to search the current tab
|
* We also need to search the current tab
|
||||||
@ -137,7 +146,7 @@ export const createLocationHistory = () => {
|
|||||||
|
|
||||||
locationHistory.length = 0;
|
locationHistory.length = 0;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
const getTabsHistory = (tab: string): RouteInfo[] => {
|
const getTabsHistory = (tab: string): RouteInfo[] => {
|
||||||
let history;
|
let history;
|
||||||
if (tab) {
|
if (tab) {
|
||||||
@ -148,7 +157,7 @@ export const createLocationHistory = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return history;
|
return history;
|
||||||
}
|
};
|
||||||
|
|
||||||
const size = () => locationHistory.length;
|
const size = () => locationHistory.length;
|
||||||
|
|
||||||
@ -166,7 +175,7 @@ export const createLocationHistory = () => {
|
|||||||
*/
|
*/
|
||||||
const index = currentHistory - initialHistory;
|
const index = currentHistory - initialHistory;
|
||||||
return locationHistory[index] || last();
|
return locationHistory[index] || last();
|
||||||
}
|
};
|
||||||
const last = () => locationHistory[locationHistory.length - 1];
|
const last = () => locationHistory[locationHistory.length - 1];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -177,9 +186,13 @@ export const createLocationHistory = () => {
|
|||||||
* the length of locationHistory, but that only worked since we were pruning
|
* the length of locationHistory, but that only worked since we were pruning
|
||||||
* the array.
|
* the array.
|
||||||
*/
|
*/
|
||||||
const canGoBack = (deep: number = 1, initialHistory: number, currentHistory: number) => {
|
const canGoBack = (
|
||||||
|
deep = 1,
|
||||||
|
initialHistory: number,
|
||||||
|
currentHistory: number
|
||||||
|
) => {
|
||||||
return currentHistory - deep >= initialHistory;
|
return currentHistory - deep >= initialHistory;
|
||||||
}
|
};
|
||||||
|
|
||||||
const getFirstRouteInfoForTab = (tab: string): RouteInfo | undefined => {
|
const getFirstRouteInfoForTab = (tab: string): RouteInfo | undefined => {
|
||||||
const tabHistory = getTabsHistory(tab);
|
const tabHistory = getTabsHistory(tab);
|
||||||
@ -187,7 +200,7 @@ export const createLocationHistory = () => {
|
|||||||
return tabHistory[0];
|
return tabHistory[0];
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
const getCurrentRouteInfoForTab = (tab: string): RouteInfo | undefined => {
|
const getCurrentRouteInfoForTab = (tab: string): RouteInfo | undefined => {
|
||||||
const tabHistory = getTabsHistory(tab);
|
const tabHistory = getTabsHistory(tab);
|
||||||
@ -195,7 +208,7 @@ export const createLocationHistory = () => {
|
|||||||
return tabHistory[tabHistory.length - 1];
|
return tabHistory[tabHistory.length - 1];
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds and returns the previous view based upon
|
* Finds and returns the previous view based upon
|
||||||
@ -207,7 +220,10 @@ export const createLocationHistory = () => {
|
|||||||
* do not modify the locationHistory stack so we would
|
* do not modify the locationHistory stack so we would
|
||||||
* not update pushedByRoute anyways.
|
* not update pushedByRoute anyways.
|
||||||
*/
|
*/
|
||||||
const findLastLocation = (routeInfo: RouteInfo, delta: number = -1): RouteInfo | undefined => {
|
const findLastLocation = (
|
||||||
|
routeInfo: RouteInfo,
|
||||||
|
delta = -1
|
||||||
|
): RouteInfo | undefined => {
|
||||||
const routeInfos = getTabsHistory(routeInfo.tab);
|
const routeInfos = getTabsHistory(routeInfo.tab);
|
||||||
if (routeInfos) {
|
if (routeInfos) {
|
||||||
if (delta < -1) {
|
if (delta < -1) {
|
||||||
@ -236,7 +252,7 @@ export const createLocationHistory = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
current,
|
current,
|
||||||
@ -248,6 +264,6 @@ export const createLocationHistory = () => {
|
|||||||
getFirstRouteInfoForTab,
|
getFirstRouteInfoForTab,
|
||||||
getCurrentRouteInfoForTab,
|
getCurrentRouteInfoForTab,
|
||||||
findLastLocation,
|
findLastLocation,
|
||||||
clearHistory
|
clearHistory,
|
||||||
}
|
};
|
||||||
}
|
};
|
||||||
|
@ -1,27 +1,35 @@
|
|||||||
import {
|
import type { AnimationBuilder } from "@ionic/vue";
|
||||||
parseQuery,
|
import type {
|
||||||
Router,
|
Router,
|
||||||
RouteLocationNormalized,
|
RouteLocationNormalized,
|
||||||
NavigationFailure,
|
NavigationFailure,
|
||||||
RouteLocationRaw
|
RouteLocationRaw,
|
||||||
} from 'vue-router';
|
} from "vue-router";
|
||||||
import { createLocationHistory } from './locationHistory';
|
import { parseQuery } from "vue-router";
|
||||||
import { generateId } from './utils';
|
|
||||||
import {
|
import { createLocationHistory } from "./locationHistory";
|
||||||
|
import type {
|
||||||
ExternalNavigationOptions,
|
ExternalNavigationOptions,
|
||||||
RouteInfo,
|
RouteInfo,
|
||||||
RouteParams,
|
RouteParams,
|
||||||
RouteAction,
|
RouteAction,
|
||||||
RouteDirection,
|
RouteDirection,
|
||||||
IonicVueRouterOptions,
|
IonicVueRouterOptions,
|
||||||
NavigationInformation
|
NavigationInformation,
|
||||||
} from './types';
|
} from "./types";
|
||||||
import { AnimationBuilder } from '@ionic/vue';
|
import { generateId } from "./utils";
|
||||||
|
|
||||||
// TODO(FW-2969): types
|
// TODO(FW-2969): types
|
||||||
|
|
||||||
export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) => {
|
export const createIonRouter = (
|
||||||
let currentNavigationInfo: NavigationInformation = { direction: undefined, action: undefined, delta: undefined };
|
opts: IonicVueRouterOptions,
|
||||||
|
router: Router
|
||||||
|
) => {
|
||||||
|
let currentNavigationInfo: NavigationInformation = {
|
||||||
|
direction: undefined,
|
||||||
|
action: undefined,
|
||||||
|
delta: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ionic Vue should only react to navigation
|
* Ionic Vue should only react to navigation
|
||||||
@ -32,7 +40,12 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
|||||||
* which is fired once navigation is confirmed
|
* which is fired once navigation is confirmed
|
||||||
* and any user guards have run.
|
* and any user guards have run.
|
||||||
*/
|
*/
|
||||||
router.afterEach((to: RouteLocationNormalized, _: RouteLocationNormalized, failure?: NavigationFailure) => {
|
router.afterEach(
|
||||||
|
(
|
||||||
|
to: RouteLocationNormalized,
|
||||||
|
_: RouteLocationNormalized,
|
||||||
|
failure?: NavigationFailure
|
||||||
|
) => {
|
||||||
if (failure) return;
|
if (failure) return;
|
||||||
|
|
||||||
const { direction, action, delta } = currentNavigationInfo;
|
const { direction, action, delta } = currentNavigationInfo;
|
||||||
@ -48,11 +61,16 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
|||||||
|
|
||||||
currentHistoryPosition = opts.history.state.position as number;
|
currentHistoryPosition = opts.history.state.position as number;
|
||||||
|
|
||||||
const replaceAction = opts.history.state.replaced ? 'replace' : undefined;
|
const replaceAction = opts.history.state.replaced ? "replace" : undefined;
|
||||||
handleHistoryChange(to, action || replaceAction, direction, delta);
|
handleHistoryChange(to, action || replaceAction, direction, delta);
|
||||||
|
|
||||||
currentNavigationInfo = { direction: undefined, action: undefined, delta: undefined };
|
currentNavigationInfo = {
|
||||||
});
|
direction: undefined,
|
||||||
|
action: undefined,
|
||||||
|
delta: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const locationHistory = createLocationHistory();
|
const locationHistory = createLocationHistory();
|
||||||
|
|
||||||
@ -68,15 +86,15 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
|||||||
let currentRouteInfo: RouteInfo;
|
let currentRouteInfo: RouteInfo;
|
||||||
let incomingRouteParams: RouteParams;
|
let incomingRouteParams: RouteParams;
|
||||||
|
|
||||||
let historyChangeListeners: any[] = [];
|
const historyChangeListeners: any[] = [];
|
||||||
|
|
||||||
if (typeof (document as any) !== 'undefined') {
|
if (typeof (document as any) !== "undefined") {
|
||||||
document.addEventListener('ionBackButton', (ev: Event) => {
|
document.addEventListener("ionBackButton", (ev: Event) => {
|
||||||
(ev as any).detail.register(0, (processNextHandler: () => void) => {
|
(ev as any).detail.register(0, (processNextHandler: () => void) => {
|
||||||
opts.history.go(-1);
|
opts.history.go(-1);
|
||||||
processNextHandler();
|
processNextHandler();
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
opts.history.listen((_: any, _x: any, info: any) => {
|
opts.history.listen((_: any, _x: any, info: any) => {
|
||||||
@ -99,38 +117,46 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
|||||||
* are considered "pop" actions, but when going forward
|
* are considered "pop" actions, but when going forward
|
||||||
* we want to make sure the forward animation is used.
|
* we want to make sure the forward animation is used.
|
||||||
*/
|
*/
|
||||||
action: (info.type === 'pop' && info.delta >= 1) ? 'push' : info.type,
|
action: info.type === "pop" && info.delta >= 1 ? "push" : info.type,
|
||||||
direction: info.direction === '' ? 'forward' : info.direction
|
direction: info.direction === "" ? "forward" : info.direction,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleNavigateBack = (defaultHref?: string, routerAnimation?: AnimationBuilder) => {
|
const handleNavigateBack = (
|
||||||
const routeInfo = locationHistory.current(initialHistoryPosition, currentHistoryPosition);
|
defaultHref?: string,
|
||||||
|
routerAnimation?: AnimationBuilder
|
||||||
|
) => {
|
||||||
|
const routeInfo = locationHistory.current(
|
||||||
|
initialHistoryPosition,
|
||||||
|
currentHistoryPosition
|
||||||
|
);
|
||||||
if (routeInfo && routeInfo.pushedByRoute) {
|
if (routeInfo && routeInfo.pushedByRoute) {
|
||||||
const prevInfo = locationHistory.findLastLocation(routeInfo);
|
const prevInfo = locationHistory.findLastLocation(routeInfo);
|
||||||
if (prevInfo) {
|
if (prevInfo) {
|
||||||
incomingRouteParams = { ...prevInfo, routerAction: 'pop', routerDirection: 'back', routerAnimation: routerAnimation || routeInfo.routerAnimation };
|
incomingRouteParams = {
|
||||||
|
...prevInfo,
|
||||||
|
routerAction: "pop",
|
||||||
|
routerDirection: "back",
|
||||||
|
routerAnimation: routerAnimation || routeInfo.routerAnimation,
|
||||||
|
};
|
||||||
if (
|
if (
|
||||||
routeInfo.lastPathname === routeInfo.pushedByRoute ||
|
routeInfo.lastPathname === routeInfo.pushedByRoute ||
|
||||||
(
|
|
||||||
/**
|
/**
|
||||||
* We need to exclude tab switches/tab
|
* We need to exclude tab switches/tab
|
||||||
* context changes here because tabbed
|
* context changes here because tabbed
|
||||||
* navigation is not linear, but router.back()
|
* navigation is not linear, but router.back()
|
||||||
* will go back in a linear fashion.
|
* will go back in a linear fashion.
|
||||||
*/
|
*/
|
||||||
prevInfo.pathname === routeInfo.pushedByRoute &&
|
(prevInfo.pathname === routeInfo.pushedByRoute &&
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tab info can be undefined or '' (empty string)
|
* Tab info can be undefined or '' (empty string)
|
||||||
* both are false-y values, so we can just use !.
|
* both are false-y values, so we can just use !.
|
||||||
*/
|
*/
|
||||||
!routeInfo.tab && !prevInfo.tab
|
!routeInfo.tab &&
|
||||||
)
|
!prevInfo.tab)
|
||||||
) {
|
) {
|
||||||
router.back();
|
router.back();
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When going back to a child page of a tab
|
* When going back to a child page of a tab
|
||||||
* after being on another tab, we need to use
|
* after being on another tab, we need to use
|
||||||
@ -160,22 +186,28 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
|||||||
router.go(prevInfo.position - routeInfo.position);
|
router.go(prevInfo.position - routeInfo.position);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
handleNavigate(defaultHref, 'pop', 'back');
|
handleNavigate(defaultHref, "pop", "back");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
handleNavigate(defaultHref, 'pop', 'back');
|
handleNavigate(defaultHref, "pop", "back");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleNavigate = (path: RouteLocationRaw, routerAction?: RouteAction, routerDirection?: RouteDirection, routerAnimation?: AnimationBuilder, tab?: string) => {
|
const handleNavigate = (
|
||||||
|
path: RouteLocationRaw,
|
||||||
|
routerAction?: RouteAction,
|
||||||
|
routerDirection?: RouteDirection,
|
||||||
|
routerAnimation?: AnimationBuilder,
|
||||||
|
tab?: string
|
||||||
|
) => {
|
||||||
setIncomingRouteParams(routerAction, routerDirection, routerAnimation, tab);
|
setIncomingRouteParams(routerAction, routerDirection, routerAnimation, tab);
|
||||||
|
|
||||||
if (routerAction === 'push') {
|
if (routerAction === "push") {
|
||||||
router.push(path);
|
router.push(path);
|
||||||
} else {
|
} else {
|
||||||
router.replace(path);
|
router.replace(path);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// TODO RouteLocationNormalized
|
// TODO RouteLocationNormalized
|
||||||
const handleHistoryChange = (
|
const handleHistoryChange = (
|
||||||
@ -186,17 +218,22 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
|||||||
) => {
|
) => {
|
||||||
let leavingLocationInfo: RouteInfo;
|
let leavingLocationInfo: RouteInfo;
|
||||||
if (incomingRouteParams) {
|
if (incomingRouteParams) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If we are replacing the state of a route
|
* If we are replacing the state of a route
|
||||||
* with another route, the "leaving" route
|
* with another route, the "leaving" route
|
||||||
* is at the same position in location history
|
* is at the same position in location history
|
||||||
* as where the replaced route will exist.
|
* as where the replaced route will exist.
|
||||||
*/
|
*/
|
||||||
if (incomingRouteParams.routerAction === 'replace') {
|
if (incomingRouteParams.routerAction === "replace") {
|
||||||
leavingLocationInfo = locationHistory.current(initialHistoryPosition, currentHistoryPosition);
|
leavingLocationInfo = locationHistory.current(
|
||||||
} else if (incomingRouteParams.routerAction === 'pop') {
|
initialHistoryPosition,
|
||||||
leavingLocationInfo = locationHistory.current(initialHistoryPosition, currentHistoryPosition + 1);
|
currentHistoryPosition
|
||||||
|
);
|
||||||
|
} else if (incomingRouteParams.routerAction === "pop") {
|
||||||
|
leavingLocationInfo = locationHistory.current(
|
||||||
|
initialHistoryPosition,
|
||||||
|
currentHistoryPosition + 1
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the Ionic Router action was "pop"
|
* If the Ionic Router action was "pop"
|
||||||
@ -233,7 +270,7 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
|||||||
* the past history and you can no longer go
|
* the past history and you can no longer go
|
||||||
* forward to /page2 or /page3.
|
* forward to /page2 or /page3.
|
||||||
*/
|
*/
|
||||||
if (action === 'replace') {
|
if (action === "replace") {
|
||||||
locationHistory.clearHistory();
|
locationHistory.clearHistory();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -249,8 +286,14 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
|||||||
* so we can grab the previous item in history relative
|
* so we can grab the previous item in history relative
|
||||||
* to where the history state currently is.
|
* to where the history state currently is.
|
||||||
*/
|
*/
|
||||||
const position = (incomingRouteParams.routerDirection === 'root') ? currentHistoryPosition : currentHistoryPosition - 1;
|
const position =
|
||||||
leavingLocationInfo = locationHistory.current(initialHistoryPosition, position);
|
incomingRouteParams.routerDirection === "root"
|
||||||
|
? currentHistoryPosition
|
||||||
|
: currentHistoryPosition - 1;
|
||||||
|
leavingLocationInfo = locationHistory.current(
|
||||||
|
initialHistoryPosition,
|
||||||
|
position
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
leavingLocationInfo = currentRouteInfo;
|
leavingLocationInfo = currentRouteInfo;
|
||||||
@ -258,42 +301,49 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
|||||||
|
|
||||||
if (!leavingLocationInfo) {
|
if (!leavingLocationInfo) {
|
||||||
leavingLocationInfo = {
|
leavingLocationInfo = {
|
||||||
pathname: '',
|
pathname: "",
|
||||||
search: ''
|
search: "",
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const leavingUrl = leavingLocationInfo.pathname + leavingLocationInfo.search;
|
const leavingUrl =
|
||||||
|
leavingLocationInfo.pathname + leavingLocationInfo.search;
|
||||||
if (leavingUrl !== location.fullPath) {
|
if (leavingUrl !== location.fullPath) {
|
||||||
if (!incomingRouteParams) {
|
if (!incomingRouteParams) {
|
||||||
if (action === 'replace') {
|
if (action === "replace") {
|
||||||
incomingRouteParams = {
|
incomingRouteParams = {
|
||||||
routerAction: 'replace',
|
routerAction: "replace",
|
||||||
routerDirection: 'none'
|
routerDirection: "none",
|
||||||
}
|
};
|
||||||
} else if (action === 'pop') {
|
} else if (action === "pop") {
|
||||||
const routeInfo = locationHistory.current(initialHistoryPosition, currentHistoryPosition - delta);
|
const routeInfo = locationHistory.current(
|
||||||
|
initialHistoryPosition,
|
||||||
|
currentHistoryPosition - delta
|
||||||
|
);
|
||||||
|
|
||||||
if (routeInfo && routeInfo.pushedByRoute) {
|
if (routeInfo && routeInfo.pushedByRoute) {
|
||||||
const prevRouteInfo = locationHistory.findLastLocation(routeInfo, delta);
|
const prevRouteInfo = locationHistory.findLastLocation(
|
||||||
|
routeInfo,
|
||||||
|
delta
|
||||||
|
);
|
||||||
incomingRouteParams = {
|
incomingRouteParams = {
|
||||||
...prevRouteInfo,
|
...prevRouteInfo,
|
||||||
routerAction: 'pop',
|
routerAction: "pop",
|
||||||
routerDirection: 'back'
|
routerDirection: "back",
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
incomingRouteParams = {
|
incomingRouteParams = {
|
||||||
routerAction: 'pop',
|
routerAction: "pop",
|
||||||
routerDirection: 'none'
|
routerDirection: "none",
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!incomingRouteParams) {
|
if (!incomingRouteParams) {
|
||||||
incomingRouteParams = {
|
incomingRouteParams = {
|
||||||
routerAction: 'push',
|
routerAction: "push",
|
||||||
routerDirection: direction || 'forward'
|
routerDirection: direction || "forward",
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,31 +351,39 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
|||||||
if (incomingRouteParams?.id) {
|
if (incomingRouteParams?.id) {
|
||||||
routeInfo = {
|
routeInfo = {
|
||||||
...incomingRouteParams,
|
...incomingRouteParams,
|
||||||
lastPathname: leavingLocationInfo.pathname
|
lastPathname: leavingLocationInfo.pathname,
|
||||||
}
|
};
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
const isPushed = incomingRouteParams.routerAction === 'push' && incomingRouteParams.routerDirection === 'forward';
|
const isPushed =
|
||||||
|
incomingRouteParams.routerAction === "push" &&
|
||||||
|
incomingRouteParams.routerDirection === "forward";
|
||||||
routeInfo = {
|
routeInfo = {
|
||||||
id: generateId('routeInfo'),
|
id: generateId("routeInfo"),
|
||||||
...incomingRouteParams,
|
...incomingRouteParams,
|
||||||
lastPathname: leavingLocationInfo.pathname,
|
lastPathname: leavingLocationInfo.pathname,
|
||||||
pathname: location.path,
|
pathname: location.path,
|
||||||
search: location.fullPath && location.fullPath.split('?')[1] || '',
|
search: (location.fullPath && location.fullPath.split("?")[1]) || "",
|
||||||
params: location.params && location.params,
|
params: location.params && location.params,
|
||||||
prevRouteLastPathname: leavingLocationInfo.lastPathname
|
prevRouteLastPathname: leavingLocationInfo.lastPathname,
|
||||||
}
|
};
|
||||||
|
|
||||||
if (isPushed) {
|
if (isPushed) {
|
||||||
routeInfo.pushedByRoute = (leavingLocationInfo.pathname !== '') ? leavingLocationInfo.pathname : undefined;
|
routeInfo.pushedByRoute =
|
||||||
} else if (routeInfo.routerAction === 'pop') {
|
leavingLocationInfo.pathname !== ""
|
||||||
|
? leavingLocationInfo.pathname
|
||||||
|
: undefined;
|
||||||
|
} else if (routeInfo.routerAction === "pop") {
|
||||||
const route = locationHistory.findLastLocation(routeInfo);
|
const route = locationHistory.findLastLocation(routeInfo);
|
||||||
routeInfo.pushedByRoute = route?.pushedByRoute;
|
routeInfo.pushedByRoute = route?.pushedByRoute;
|
||||||
} else if (routeInfo.routerAction === 'push' && routeInfo.tab !== leavingLocationInfo.tab) {
|
} else if (
|
||||||
const lastRoute = locationHistory.getCurrentRouteInfoForTab(routeInfo.tab);
|
routeInfo.routerAction === "push" &&
|
||||||
|
routeInfo.tab !== leavingLocationInfo.tab
|
||||||
|
) {
|
||||||
|
const lastRoute = locationHistory.getCurrentRouteInfoForTab(
|
||||||
|
routeInfo.tab
|
||||||
|
);
|
||||||
routeInfo.pushedByRoute = lastRoute?.pushedByRoute;
|
routeInfo.pushedByRoute = lastRoute?.pushedByRoute;
|
||||||
} else if (routeInfo.routerAction === 'replace') {
|
} else if (routeInfo.routerAction === "replace") {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When replacing a route, we want to make sure we select the current route
|
* When replacing a route, we want to make sure we select the current route
|
||||||
* that we are on, not the last route in the stack. The last route in the stack
|
* that we are on, not the last route in the stack. The last route in the stack
|
||||||
@ -337,7 +395,10 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
|||||||
* be replaced with /page3 even though /page2 is the last
|
* be replaced with /page3 even though /page2 is the last
|
||||||
* item in the stack/
|
* item in the stack/
|
||||||
*/
|
*/
|
||||||
const currentRouteInfo = locationHistory.current(initialHistoryPosition, currentHistoryPosition);
|
const currentRouteInfo = locationHistory.current(
|
||||||
|
initialHistoryPosition,
|
||||||
|
currentHistoryPosition
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If going from /home to /child, then replacing from
|
* If going from /home to /child, then replacing from
|
||||||
@ -345,15 +406,21 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
|||||||
* say that /home was pushed by /home which is not correct.
|
* say that /home was pushed by /home which is not correct.
|
||||||
*/
|
*/
|
||||||
const currentPushedBy = currentRouteInfo?.pushedByRoute;
|
const currentPushedBy = currentRouteInfo?.pushedByRoute;
|
||||||
const pushedByRoute = (currentPushedBy !== undefined && currentPushedBy !== routeInfo.pathname) ? currentPushedBy : routeInfo.pushedByRoute;
|
const pushedByRoute =
|
||||||
|
currentPushedBy !== undefined &&
|
||||||
|
currentPushedBy !== routeInfo.pathname
|
||||||
|
? currentPushedBy
|
||||||
|
: routeInfo.pushedByRoute;
|
||||||
|
|
||||||
routeInfo.lastPathname = currentRouteInfo?.pathname || routeInfo.lastPathname;
|
routeInfo.lastPathname =
|
||||||
|
currentRouteInfo?.pathname || routeInfo.lastPathname;
|
||||||
routeInfo.pushedByRoute = pushedByRoute;
|
routeInfo.pushedByRoute = pushedByRoute;
|
||||||
routeInfo.routerDirection = currentRouteInfo?.routerDirection || routeInfo.routerDirection;
|
routeInfo.routerDirection =
|
||||||
routeInfo.routerAnimation = currentRouteInfo?.routerAnimation || routeInfo.routerAnimation;
|
currentRouteInfo?.routerDirection || routeInfo.routerDirection;
|
||||||
|
routeInfo.routerAnimation =
|
||||||
|
currentRouteInfo?.routerAnimation || routeInfo.routerAnimation;
|
||||||
routeInfo.prevRouteLastPathname = currentRouteInfo?.lastPathname;
|
routeInfo.prevRouteLastPathname = currentRouteInfo?.lastPathname;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
routeInfo.position = currentHistoryPosition;
|
routeInfo.position = currentHistoryPosition;
|
||||||
@ -379,7 +446,8 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
|||||||
* we want to make sure we exclude that
|
* we want to make sure we exclude that
|
||||||
* action by ensuring historySize > 0.
|
* action by ensuring historySize > 0.
|
||||||
*/
|
*/
|
||||||
const isReplacing = historySize === historyDiff && historySize > 0 && action === 'replace';
|
const isReplacing =
|
||||||
|
historySize === historyDiff && historySize > 0 && action === "replace";
|
||||||
if (historySize > historyDiff || isReplacing) {
|
if (historySize > historyDiff || isReplacing) {
|
||||||
/**
|
/**
|
||||||
* When navigating back through the history,
|
* When navigating back through the history,
|
||||||
@ -400,7 +468,8 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(routeInfo.routerAction === 'push' || routeInfo.routerAction === 'replace') &&
|
(routeInfo.routerAction === "push" ||
|
||||||
|
routeInfo.routerAction === "replace") &&
|
||||||
delta === undefined
|
delta === undefined
|
||||||
) {
|
) {
|
||||||
locationHistory.clearHistory(routeInfo);
|
locationHistory.clearHistory(routeInfo);
|
||||||
@ -422,20 +491,25 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
|||||||
currentRouteInfo = routeInfo;
|
currentRouteInfo = routeInfo;
|
||||||
}
|
}
|
||||||
incomingRouteParams = undefined;
|
incomingRouteParams = undefined;
|
||||||
historyChangeListeners.forEach(cb => cb(currentRouteInfo));
|
historyChangeListeners.forEach((cb) => cb(currentRouteInfo));
|
||||||
}
|
};
|
||||||
|
|
||||||
const getCurrentRouteInfo = () => currentRouteInfo;
|
const getCurrentRouteInfo = () => currentRouteInfo;
|
||||||
|
|
||||||
const canGoBack = (deep: number = 1) => locationHistory.canGoBack(deep, initialHistoryPosition, currentHistoryPosition);
|
const canGoBack = (deep = 1) =>
|
||||||
|
locationHistory.canGoBack(
|
||||||
|
deep,
|
||||||
|
initialHistoryPosition,
|
||||||
|
currentHistoryPosition
|
||||||
|
);
|
||||||
|
|
||||||
const navigate = (navigationOptions: ExternalNavigationOptions) => {
|
const navigate = (navigationOptions: ExternalNavigationOptions) => {
|
||||||
const { routerAnimation, routerDirection, routerLink } = navigationOptions;
|
const { routerAnimation, routerDirection, routerLink } = navigationOptions;
|
||||||
|
|
||||||
setIncomingRouteParams('push', routerDirection, routerAnimation);
|
setIncomingRouteParams("push", routerDirection, routerAnimation);
|
||||||
|
|
||||||
router.push(routerLink);
|
router.push(routerLink);
|
||||||
}
|
};
|
||||||
|
|
||||||
const resetTab = (tab: string) => {
|
const resetTab = (tab: string) => {
|
||||||
/**
|
/**
|
||||||
@ -454,21 +528,21 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
|||||||
if (routeInfo) {
|
if (routeInfo) {
|
||||||
router.go(routeInfo.position - currentHistoryPosition);
|
router.go(routeInfo.position - currentHistoryPosition);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const changeTab = (tab: string, path?: string) => {
|
const changeTab = (tab: string, path?: string) => {
|
||||||
if (!path) return;
|
if (!path) return;
|
||||||
|
|
||||||
const routeInfo = locationHistory.getCurrentRouteInfoForTab(tab);
|
const routeInfo = locationHistory.getCurrentRouteInfoForTab(tab);
|
||||||
const [pathname] = path.split('?');
|
const [pathname] = path.split("?");
|
||||||
|
|
||||||
if (routeInfo) {
|
if (routeInfo) {
|
||||||
incomingRouteParams = {
|
incomingRouteParams = {
|
||||||
...incomingRouteParams,
|
...incomingRouteParams,
|
||||||
routerAction: 'push',
|
routerAction: "push",
|
||||||
routerDirection: 'none',
|
routerDirection: "none",
|
||||||
tab
|
tab,
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When going back to a tab
|
* When going back to a tab
|
||||||
@ -478,15 +552,17 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
|||||||
* tab you are on.
|
* tab you are on.
|
||||||
*/
|
*/
|
||||||
if (routeInfo.pathname === pathname) {
|
if (routeInfo.pathname === pathname) {
|
||||||
router.push({ path: routeInfo.pathname, query: parseQuery(routeInfo.search) });
|
router.push({
|
||||||
|
path: routeInfo.pathname,
|
||||||
|
query: parseQuery(routeInfo.search),
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
router.push({ path: pathname, query: parseQuery(routeInfo.search) });
|
router.push({ path: pathname, query: parseQuery(routeInfo.search) });
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
handleNavigate(pathname, "push", "none", undefined, tab);
|
||||||
}
|
}
|
||||||
else {
|
};
|
||||||
handleNavigate(pathname, 'push', 'none', undefined, tab);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is invoked by the IonTabs component
|
* This method is invoked by the IonTabs component
|
||||||
@ -506,7 +582,12 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
|||||||
* in the locationHistory stack. As a result,
|
* in the locationHistory stack. As a result,
|
||||||
* we cannot use locationHistory.last() here.
|
* we cannot use locationHistory.last() here.
|
||||||
*/
|
*/
|
||||||
const ri = { ...locationHistory.current(initialHistoryPosition, currentHistoryPosition) };
|
const ri = {
|
||||||
|
...locationHistory.current(
|
||||||
|
initialHistoryPosition,
|
||||||
|
currentHistoryPosition
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* handleHistoryChange is tabs-agnostic by design.
|
* handleHistoryChange is tabs-agnostic by design.
|
||||||
@ -559,34 +640,42 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
|||||||
ri.pushedByRoute = undefined;
|
ri.pushedByRoute = undefined;
|
||||||
locationHistory.update(ri);
|
locationHistory.update(ri);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const registerHistoryChangeListener = (cb: any) => {
|
const registerHistoryChangeListener = (cb: any) => {
|
||||||
historyChangeListeners.push(cb);
|
historyChangeListeners.push(cb);
|
||||||
}
|
};
|
||||||
|
|
||||||
const setIncomingRouteParams = (routerAction: RouteAction = 'push', routerDirection: RouteDirection = 'forward', routerAnimation?: AnimationBuilder, tab?: string) => {
|
const setIncomingRouteParams = (
|
||||||
|
routerAction: RouteAction = "push",
|
||||||
|
routerDirection: RouteDirection = "forward",
|
||||||
|
routerAnimation?: AnimationBuilder,
|
||||||
|
tab?: string
|
||||||
|
) => {
|
||||||
incomingRouteParams = {
|
incomingRouteParams = {
|
||||||
routerAction,
|
routerAction,
|
||||||
routerDirection,
|
routerDirection,
|
||||||
routerAnimation,
|
routerAnimation,
|
||||||
tab
|
tab,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
const goBack = (routerAnimation?: AnimationBuilder) => {
|
const goBack = (routerAnimation?: AnimationBuilder) => {
|
||||||
setIncomingRouteParams('pop', 'back', routerAnimation);
|
setIncomingRouteParams("pop", "back", routerAnimation);
|
||||||
router.back()
|
router.back();
|
||||||
};
|
};
|
||||||
|
|
||||||
const goForward = (routerAnimation?: AnimationBuilder) => {
|
const goForward = (routerAnimation?: AnimationBuilder) => {
|
||||||
setIncomingRouteParams('push', 'forward', routerAnimation);
|
setIncomingRouteParams("push", "forward", routerAnimation);
|
||||||
router.forward();
|
router.forward();
|
||||||
}
|
};
|
||||||
|
|
||||||
const getLeavingRouteInfo = () => {
|
const getLeavingRouteInfo = () => {
|
||||||
return locationHistory.current(initialHistoryPosition, currentHistoryPosition);
|
return locationHistory.current(
|
||||||
}
|
initialHistoryPosition,
|
||||||
|
currentHistoryPosition
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
handleNavigate,
|
handleNavigate,
|
||||||
@ -600,6 +689,6 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
|||||||
changeTab,
|
changeTab,
|
||||||
registerHistoryChangeListener,
|
registerHistoryChangeListener,
|
||||||
goBack,
|
goBack,
|
||||||
goForward
|
goForward,
|
||||||
}
|
};
|
||||||
}
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { AnimationBuilder } from '@ionic/vue';
|
import type { AnimationBuilder } from "@ionic/vue";
|
||||||
import { RouteLocationMatched, RouterOptions } from 'vue-router';
|
import type { Ref } from "vue";
|
||||||
import { Ref } from 'vue';
|
import type { RouteLocationMatched, RouterOptions } from "vue-router";
|
||||||
|
|
||||||
// TODO(FW-2969): types
|
// TODO(FW-2969): types
|
||||||
|
|
||||||
@ -56,8 +56,8 @@ export interface RouteParams {
|
|||||||
id?: string;
|
id?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RouteAction = 'push' | 'pop' | 'replace';
|
export type RouteAction = "push" | "pop" | "replace";
|
||||||
export type RouteDirection = 'forward' | 'back' | 'root' | 'none';
|
export type RouteDirection = "forward" | "back" | "root" | "none";
|
||||||
|
|
||||||
export interface ViewItem {
|
export interface ViewItem {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const ids: { [k: string]: number } = { main: 0 };
|
const ids: { [k: string]: number } = { main: 0 };
|
||||||
|
|
||||||
export const generateId = (type = 'main') => {
|
export const generateId = (type = "main") => {
|
||||||
const id = (ids[type] ?? 0) + 1;
|
const id = (ids[type] ?? 0) + 1;
|
||||||
ids[type] = id;
|
ids[type] = id;
|
||||||
return (id).toString();
|
return id.toString();
|
||||||
};
|
};
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
import { generateId } from './utils';
|
import { shallowRef } from "vue";
|
||||||
import { RouteInfo,
|
import type { RouteLocationMatched, Router } from "vue-router";
|
||||||
ViewItem,
|
|
||||||
ViewStacks,
|
import type { RouteInfo, ViewItem, ViewStacks } from "./types";
|
||||||
} from './types';
|
import { generateId } from "./utils";
|
||||||
import { RouteLocationMatched, Router } from 'vue-router';
|
|
||||||
import { shallowRef } from 'vue';
|
|
||||||
|
|
||||||
export const createViewStacks = (router: Router) => {
|
export const createViewStacks = (router: Router) => {
|
||||||
let viewStacks: ViewStacks = {};
|
const viewStacks: ViewStacks = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of active stacks.
|
* Returns the number of active stacks.
|
||||||
@ -20,11 +18,11 @@ export const createViewStacks = (router: Router) => {
|
|||||||
|
|
||||||
const clear = (outletId: number) => {
|
const clear = (outletId: number) => {
|
||||||
delete viewStacks[outletId];
|
delete viewStacks[outletId];
|
||||||
}
|
};
|
||||||
|
|
||||||
const getViewStack = (outletId: number) => {
|
const getViewStack = (outletId: number) => {
|
||||||
return viewStacks[outletId];
|
return viewStacks[outletId];
|
||||||
}
|
};
|
||||||
|
|
||||||
const registerIonPage = (viewItem: ViewItem, ionPage: HTMLElement) => {
|
const registerIonPage = (viewItem: ViewItem, ionPage: HTMLElement) => {
|
||||||
viewItem.ionPageElement = ionPage;
|
viewItem.ionPageElement = ionPage;
|
||||||
@ -36,45 +34,57 @@ export const createViewStacks = (router: Router) => {
|
|||||||
* and will not run route guards that
|
* and will not run route guards that
|
||||||
* are written in the component.
|
* are written in the component.
|
||||||
*/
|
*/
|
||||||
viewItem.matchedRoute.instances = { default: viewItem.vueComponentRef.value };
|
viewItem.matchedRoute.instances = {
|
||||||
}
|
default: viewItem.vueComponentRef.value,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const findViewItemByRouteInfo = (routeInfo: RouteInfo, outletId?: number) => {
|
const findViewItemByRouteInfo = (routeInfo: RouteInfo, outletId?: number) => {
|
||||||
return findViewItemByPath(routeInfo.pathname, outletId, false);
|
return findViewItemByPath(routeInfo.pathname, outletId, false);
|
||||||
}
|
};
|
||||||
|
|
||||||
const findLeavingViewItemByRouteInfo = (routeInfo: RouteInfo, outletId?: number, mustBeIonRoute: boolean = true) => {
|
const findLeavingViewItemByRouteInfo = (
|
||||||
|
routeInfo: RouteInfo,
|
||||||
|
outletId?: number,
|
||||||
|
mustBeIonRoute = true
|
||||||
|
) => {
|
||||||
return findViewItemByPath(routeInfo.lastPathname, outletId, mustBeIonRoute);
|
return findViewItemByPath(routeInfo.lastPathname, outletId, mustBeIonRoute);
|
||||||
}
|
};
|
||||||
|
|
||||||
const findViewItemByPathname = (pathname: string, outletId?: number) => {
|
const findViewItemByPathname = (pathname: string, outletId?: number) => {
|
||||||
return findViewItemByPath(pathname, outletId, false);
|
return findViewItemByPath(pathname, outletId, false);
|
||||||
}
|
};
|
||||||
|
|
||||||
const findViewItemInStack = (path: string, stack: ViewItem[]): ViewItem | undefined => {
|
const findViewItemInStack = (
|
||||||
|
path: string,
|
||||||
|
stack: ViewItem[]
|
||||||
|
): ViewItem | undefined => {
|
||||||
return stack.find((viewItem: ViewItem) => {
|
return stack.find((viewItem: ViewItem) => {
|
||||||
if (viewItem.pathname === path) {
|
if (viewItem.pathname === path) {
|
||||||
return viewItem;
|
return viewItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
const findViewItemByPath = (path: string, outletId?: number, mustBeIonRoute: boolean = false): ViewItem | undefined => {
|
const findViewItemByPath = (
|
||||||
|
path: string,
|
||||||
|
outletId?: number,
|
||||||
|
mustBeIonRoute = false
|
||||||
|
): ViewItem | undefined => {
|
||||||
const matchView = (viewItem: ViewItem) => {
|
const matchView = (viewItem: ViewItem) => {
|
||||||
if (
|
if ((mustBeIonRoute && !viewItem.ionRoute) || path === "") {
|
||||||
(mustBeIonRoute && !viewItem.ionRoute) ||
|
|
||||||
path === ''
|
|
||||||
) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const resolvedPath = router.resolve(path);
|
const resolvedPath = router.resolve(path);
|
||||||
const findMatchedRoute = resolvedPath.matched.find((matchedRoute: RouteLocationMatched) => matchedRoute === viewItem.matchedRoute);
|
const findMatchedRoute = resolvedPath.matched.find(
|
||||||
|
(matchedRoute: RouteLocationMatched) =>
|
||||||
|
matchedRoute === viewItem.matchedRoute
|
||||||
|
);
|
||||||
|
|
||||||
if (findMatchedRoute) {
|
if (findMatchedRoute) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* /page/1 and /page/2 should not match
|
* /page/1 and /page/2 should not match
|
||||||
* to the same view item otherwise there will
|
* to the same view item otherwise there will
|
||||||
@ -83,7 +93,7 @@ export const createViewStacks = (router: Router) => {
|
|||||||
* so the page 2 params are properly passed
|
* so the page 2 params are properly passed
|
||||||
* to the developer's app.
|
* to the developer's app.
|
||||||
*/
|
*/
|
||||||
const hasParameter = findMatchedRoute.path.includes(':');
|
const hasParameter = findMatchedRoute.path.includes(":");
|
||||||
if (hasParameter && path !== viewItem.pathname) {
|
if (hasParameter && path !== viewItem.pathname) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -92,16 +102,18 @@ export const createViewStacks = (router: Router) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
if (outletId) {
|
if (outletId) {
|
||||||
const stack = viewStacks[outletId];
|
const stack = viewStacks[outletId];
|
||||||
if (!stack) return undefined;
|
if (!stack) return undefined;
|
||||||
|
|
||||||
const match = (router) ? stack.find(matchView) : findViewItemInStack(path, stack)
|
const match = router
|
||||||
|
? stack.find(matchView)
|
||||||
|
: findViewItemInStack(path, stack);
|
||||||
if (match) return match;
|
if (match) return match;
|
||||||
} else {
|
} else {
|
||||||
for (let outletId in viewStacks) {
|
for (const outletId in viewStacks) {
|
||||||
const stack = viewStacks[outletId];
|
const stack = viewStacks[outletId];
|
||||||
const viewItem = findViewItemInStack(path, stack);
|
const viewItem = findViewItemInStack(path, stack);
|
||||||
if (viewItem) {
|
if (viewItem) {
|
||||||
@ -111,12 +123,18 @@ export const createViewStacks = (router: Router) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
// TODO(FW-2969): type
|
// TODO(FW-2969): type
|
||||||
const createViewItem = (outletId: number, vueComponent: any, matchedRoute: RouteLocationMatched, routeInfo: RouteInfo, ionPage?: HTMLElement): ViewItem => {
|
const createViewItem = (
|
||||||
|
outletId: number,
|
||||||
|
vueComponent: any,
|
||||||
|
matchedRoute: RouteLocationMatched,
|
||||||
|
routeInfo: RouteInfo,
|
||||||
|
ionPage?: HTMLElement
|
||||||
|
): ViewItem => {
|
||||||
return {
|
return {
|
||||||
id: generateId('viewItem'),
|
id: generateId("viewItem"),
|
||||||
pathname: routeInfo.pathname,
|
pathname: routeInfo.pathname,
|
||||||
outletId,
|
outletId,
|
||||||
matchedRoute,
|
matchedRoute,
|
||||||
@ -127,9 +145,9 @@ export const createViewStacks = (router: Router) => {
|
|||||||
mount: false,
|
mount: false,
|
||||||
exact: routeInfo.pathname === matchedRoute.path,
|
exact: routeInfo.pathname === matchedRoute.path,
|
||||||
params: routeInfo.params,
|
params: routeInfo.params,
|
||||||
vueComponentData: {}
|
vueComponentData: {},
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
const add = (viewItem: ViewItem): void => {
|
const add = (viewItem: ViewItem): void => {
|
||||||
const { outletId } = viewItem;
|
const { outletId } = viewItem;
|
||||||
@ -138,25 +156,29 @@ export const createViewStacks = (router: Router) => {
|
|||||||
} else {
|
} else {
|
||||||
viewStacks[outletId].push(viewItem);
|
viewStacks[outletId].push(viewItem);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const remove = (viewItem: ViewItem, outletId?: number): void => {
|
const remove = (viewItem: ViewItem, outletId?: number): void => {
|
||||||
if (!outletId) { throw Error('outletId required') }
|
if (!outletId) {
|
||||||
|
throw Error("outletId required");
|
||||||
|
}
|
||||||
|
|
||||||
const viewStack = viewStacks[outletId];
|
const viewStack = viewStacks[outletId];
|
||||||
if (viewStack) {
|
if (viewStack) {
|
||||||
viewStacks[outletId] = viewStack.filter(item => item.id !== viewItem.id);
|
viewStacks[outletId] = viewStack.filter(
|
||||||
}
|
(item) => item.id !== viewItem.id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const getChildrenToRender = (outletId: number): ViewItem[] => {
|
const getChildrenToRender = (outletId: number): ViewItem[] => {
|
||||||
const viewStack = viewStacks[outletId];
|
const viewStack = viewStacks[outletId];
|
||||||
if (viewStack) {
|
if (viewStack) {
|
||||||
const components = viewStacks[outletId].filter(v => v.mount);
|
const components = viewStacks[outletId].filter((v) => v.mount);
|
||||||
return components;
|
return components;
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When navigating backwards, we need to clean up and
|
* When navigating backwards, we need to clean up and
|
||||||
@ -165,11 +187,15 @@ export const createViewStacks = (router: Router) => {
|
|||||||
* important when using router.go and stepping back
|
* important when using router.go and stepping back
|
||||||
* multiple pages at a time.
|
* multiple pages at a time.
|
||||||
*/
|
*/
|
||||||
const unmountLeavingViews = (outletId: number, viewItem: ViewItem, delta: number = 1) => {
|
const unmountLeavingViews = (
|
||||||
|
outletId: number,
|
||||||
|
viewItem: ViewItem,
|
||||||
|
delta = 1
|
||||||
|
) => {
|
||||||
const viewStack = viewStacks[outletId];
|
const viewStack = viewStacks[outletId];
|
||||||
if (!viewStack) return;
|
if (!viewStack) return;
|
||||||
|
|
||||||
const startIndex = viewStack.findIndex(v => v === viewItem);
|
const startIndex = viewStack.findIndex((v) => v === viewItem);
|
||||||
|
|
||||||
for (let i = startIndex + 1; i < startIndex - delta; i++) {
|
for (let i = startIndex + 1; i < startIndex - delta; i++) {
|
||||||
const viewItem = viewStack[i];
|
const viewItem = viewStack[i];
|
||||||
@ -178,7 +204,7 @@ export const createViewStacks = (router: Router) => {
|
|||||||
viewItem.ionRoute = false;
|
viewItem.ionRoute = false;
|
||||||
viewItem.matchedRoute.instances = {};
|
viewItem.matchedRoute.instances = {};
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When navigating forward it is possible for
|
* When navigating forward it is possible for
|
||||||
@ -198,16 +224,20 @@ export const createViewStacks = (router: Router) => {
|
|||||||
* to go back to /page2 and /home, so we need both pages mounted
|
* to go back to /page2 and /home, so we need both pages mounted
|
||||||
* in the DOM.
|
* in the DOM.
|
||||||
*/
|
*/
|
||||||
const mountIntermediaryViews = (outletId: number, viewItem: ViewItem, delta: number = 1) => {
|
const mountIntermediaryViews = (
|
||||||
|
outletId: number,
|
||||||
|
viewItem: ViewItem,
|
||||||
|
delta = 1
|
||||||
|
) => {
|
||||||
const viewStack = viewStacks[outletId];
|
const viewStack = viewStacks[outletId];
|
||||||
if (!viewStack) return;
|
if (!viewStack) return;
|
||||||
|
|
||||||
const startIndex = viewStack.findIndex(v => v === viewItem);
|
const startIndex = viewStack.findIndex((v) => v === viewItem);
|
||||||
|
|
||||||
for (let i = startIndex + 1; i < startIndex + delta; i++) {
|
for (let i = startIndex + 1; i < startIndex + delta; i++) {
|
||||||
viewStack[i].mount = true;
|
viewStack[i].mount = true;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
unmountLeavingViews,
|
unmountLeavingViews,
|
||||||
@ -222,6 +252,6 @@ export const createViewStacks = (router: Router) => {
|
|||||||
remove,
|
remove,
|
||||||
registerIonPage,
|
registerIonPage,
|
||||||
getViewStack,
|
getViewStack,
|
||||||
size
|
size,
|
||||||
}
|
};
|
||||||
}
|
};
|
||||||
|
Reference in New Issue
Block a user