Files
ionic-framework/packages/vue-router/src/locationHistory.ts
2020-09-15 09:54:35 -04:00

159 lines
4.2 KiB
TypeScript

import { RouteInfo } from './types';
export const createLocationHistory = () => {
const locationHistory: RouteInfo[] = [];
const tabsHistory: { [k: string]: RouteInfo[] } = {};
const add = (routeInfo: RouteInfo) => {
switch (routeInfo.routerAction) {
case "replace":
replaceRoute(routeInfo);
break;
case "pop":
pop(routeInfo);
break;
default:
addRoute(routeInfo);
break;
}
if (routeInfo.routerDirection === 'root') {
clearHistory();
addRoute(routeInfo);
}
}
const update = (routeInfo: RouteInfo) => {
const locationIndex = locationHistory.findIndex(x => x.id === routeInfo.id);
if (locationIndex > -1) {
locationHistory.splice(locationIndex, 1, routeInfo);
}
const tabArray = tabsHistory[routeInfo.tab || ''];
if (tabArray) {
const tabIndex = tabArray.findIndex(x => x.id === routeInfo.id);
if (tabIndex > -1) {
tabArray.splice(tabIndex, 1, routeInfo);
} else {
tabArray.push(routeInfo);
}
} else if (routeInfo.tab) {
tabsHistory[routeInfo.tab] = [routeInfo];
}
}
const replaceRoute = (routeInfo: RouteInfo) => {
const routeInfos = getTabsHistory(routeInfo.tab);
routeInfos && routeInfos.pop();
locationHistory.pop();
addRoute(routeInfo);
}
const pop = (routeInfo: RouteInfo) => {
const tabHistory = getTabsHistory(routeInfo.tab);
let ri;
if (tabHistory) {
// Pop all routes until we are back
ri = tabHistory[tabHistory.length - 1];
while (ri && ri.id !== routeInfo.id) {
tabHistory.pop();
ri = tabHistory[tabHistory.length - 1];
}
// Replace with updated route
tabHistory.pop();
tabHistory.push(routeInfo);
}
ri = locationHistory[locationHistory.length - 1];
while (ri && ri.id !== routeInfo.id) {
locationHistory.pop();
ri = locationHistory[locationHistory.length - 1];
}
// Replace with updated route
locationHistory.pop();
locationHistory.push(routeInfo);
}
const addRoute = (routeInfo: RouteInfo) => {
const tabHistory = getTabsHistory(routeInfo.tab);
if (tabHistory) {
// 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) {
tabHistory.pop();
}
tabHistory.push(routeInfo);
}
locationHistory.push(routeInfo);
}
const clearHistory = () => {
locationHistory.length = 0;
Object.keys(tabsHistory).forEach(key => {
tabsHistory[key] = [];
});
}
const getTabsHistory = (tab: string): RouteInfo[] => {
let history;
if (tab) {
history = tabsHistory[tab];
if (!history) {
history = tabsHistory[tab] = [];
}
}
return history;
}
const previous = () => locationHistory[locationHistory.length - 2] || current();
const current = () => locationHistory[locationHistory.length - 1];
const canGoBack = (deep: number = 1) => locationHistory.length > deep;
const getFirstRouteInfoForTab = (tab: string): RouteInfo | undefined => {
const tabHistory = getTabsHistory(tab);
if (tabHistory) {
return tabHistory[0];
}
return undefined;
}
const getCurrentRouteInfoForTab = (tab: string): RouteInfo | undefined => {
const tabHistory = getTabsHistory(tab);
if (tabHistory) {
return tabHistory[tabHistory.length - 1];
}
return undefined;
}
const findLastLocation = (routeInfo: RouteInfo): RouteInfo | undefined => {
const routeInfos = getTabsHistory(routeInfo.tab);
if (routeInfos) {
for (let i = routeInfos.length - 2; i >= 0; i--) {
const ri = routeInfos[i];
if (ri) {
if (ri.pathname === routeInfo.pushedByRoute) {
return ri;
}
}
}
}
for (let i = locationHistory.length - 2; i >= 0; i--) {
const ri = locationHistory[i];
if (ri) {
if (ri.pathname === routeInfo.pushedByRoute) {
return ri;
}
}
}
return undefined;
}
return {
current,
previous,
add,
canGoBack,
update,
getFirstRouteInfoForTab,
getCurrentRouteInfoForTab,
findLastLocation
}
}