router-vue-native
Version:
NativeScript Vue Router Extended for NativeScript Vue hybrid Apps.
237 lines • 8.24 kB
JavaScript
import { RouterGuardsService } from "./router-guards-service";
import { registerActionDispatcher } from "./router-dispatcher-service";
import routerMixin from "./router-mixin";
import RouterView from "./router-view";
export class RouterService {
constructor({ routes = [] }, { routeToCallback = null, routeBackCallback = null, routeBackFallbackPath = "", logger = null, frame = null, vm = null, }) {
this.routes = [];
this.history = [];
this.routerGuardsService = null;
this.defaultOptions = {
transition: {
duration: 100,
},
meta: {
props: {},
},
};
this.routes = routes;
this.routeToCallback = routeToCallback;
this.routeBackCallback = routeBackCallback;
this.routeBackFallbackPath = routeBackFallbackPath;
this.logger = logger || console.log;
this.vm = vm;
this.frame = frame;
this.routerGuardsService = new RouterGuardsService({
to: null,
from: null,
});
}
install(app) {
const router = this;
this.vm = app;
const globals = app.config.globalProperties;
globals.$routeTo = router.push.bind(router);
globals.$routeBack = router.back.bind(router);
globals.$router = router;
app.provide("$router", router);
if (app.mixin) {
app.mixin(routerMixin);
}
app.component("RouterView", RouterView);
registerActionDispatcher(router, app);
}
push(route, options = {}) {
this.navigateTo(route, options);
}
back(options = {}, emptyRouteFallbackPath = null) {
this.navigateBack(options, emptyRouteFallbackPath);
}
onError(callback) {
this.errorCallbacks.push(callback);
}
beforeEach(callback) {
this.routerGuardsService.addBeforeEach(callback);
}
beforeResolve(callback) {
this.routerGuardsService.addBeforeResolve(callback);
}
invokeBeforeResolve() {
const context = this.routerGuardsService.runBeforeResolve();
if (!this.performContextAction(context)) {
this.setNavigationState(false);
return false;
}
return true;
}
afterEach(callback) {
this.routerGuardsService.addAfterEach(callback);
this.setNavigationState(false);
}
invokeAfterEach() {
this.routerGuardsService.runAfterEach();
}
updateVm(vm) {
this.vm = vm;
}
getRoute(route) {
if (!route) {
return null;
}
let routePath = "";
if (typeof route === "string") {
routePath = route;
}
else if (typeof route === "object") {
routePath = route.name || route.path;
}
return (this.routes.find(({ path, name }) => path === routePath || name === routePath) || null);
}
getCurrentRoute() {
return this.getRoute(this.currentRoute);
}
setCurrentRoute(route) {
this.currentRoute = route;
if (this.vm.config.globalProperties.$route) {
this.vm.config.globalProperties.$route = Object.assign({}, this.vm.config.globalProperties.$route, route);
}
else {
this.vm.config.globalProperties.$route = route;
}
}
getNewRoute() {
return this.newRoute;
}
getPreviousRoute() {
const historyEntryNo = this.history.length - 1;
if (historyEntryNo < 0) {
return null;
}
if (!this.history[historyEntryNo]) {
return null;
}
return this.getRoute(this.history[historyEntryNo]);
}
setNavigationState(toggle) {
this.isNavigating = toggle;
if (!this.isNavigating) {
this.setNewRoute(null);
}
}
appendRouteHistory(routePath) {
this.history.push(routePath);
}
clearRouteHistory() {
this.history.splice(0);
}
isRouteAvailable(route) {
return Object.keys(this.getRoute(route) || {}).length > 0;
}
setNewRoute(route) {
this.newRoute = route;
}
isValidRoute(route) {
let logMessage = "";
if (!this.isRouteAvailable(route)) {
const routePath = typeof route === "object" && route && route.path
? route.path
: route.toString();
logMessage = `Route ${routePath} is missing`;
}
if (logMessage && this.logger) {
this.logger.warn("ROUTER", logMessage);
return false;
}
return true;
}
navigateTo(route, options = {
frame: "default",
}, isNavigatingBack = false) {
if (!this.vm) {
this.logger.error("ROUTER", "The router needs a Vue instance, this can be added in the createRoute method or use app.use(router)");
return;
}
if (!this.isValidRoute(route)) {
return;
}
const previousRoute = this.getCurrentRoute();
const newRoute = this.getRoute(route);
const routeOptions = Object.assign(Object.assign({}, this.defaultOptions), options);
routeOptions.props = routeOptions.props || {};
routeOptions.context = routeOptions.props;
newRoute.meta = newRoute.meta || {};
newRoute.meta.props = Object.assign(Object.assign(Object.assign({}, newRoute.meta), (newRoute.meta.props || {})), routeOptions.props);
this.setNavigationState(true);
this.setNewRoute(newRoute);
this.routerGuardsService.setRoutes(newRoute, previousRoute);
const context = this.routerGuardsService.runBeforeEach();
if (!this.performContextAction(context)) {
this.setNavigationState(false);
return;
}
if (this.vm.config.globalProperties.$modalPage) {
const modal = this.vm.config.globalProperties.$modalPage;
if (modal.instance && modal.data) {
modal.instance.onNavigatingFrom(modal.data);
}
this.vm.config.globalProperties.$modalPage = null;
}
if (isNavigatingBack) {
if (this.routeBackCallback) {
this.routeBackCallback(newRoute, routeOptions);
}
this.vm.config.globalProperties.$navigateBack(routeOptions);
}
else {
if (this.routeToCallback) {
this.routeToCallback(newRoute, routeOptions);
}
this.vm.config.globalProperties.$navigateTo(newRoute.component, routeOptions);
}
this.setCurrentRoute(newRoute);
if (routeOptions.clearHistory) {
this.clearRouteHistory();
}
if (!isNavigatingBack && previousRoute) {
this.appendRouteHistory(previousRoute.path);
}
if (isNavigatingBack && this.history.length > 0) {
this.history.pop();
}
}
navigateBack(options = {
frame: "default",
}, emptyRouteFallbackPath = null) {
var _a;
let newRoute = this.getPreviousRoute();
if (!newRoute || ((_a = this.frame.topmost()) === null || _a === void 0 ? void 0 : _a.backStack.length) < 1) {
const alternativePath = emptyRouteFallbackPath || this.routeBackFallbackPath;
if (alternativePath) {
newRoute = this.getRoute(alternativePath);
options.clearHistory = true;
console.log(newRoute, options);
this.navigateTo(newRoute, options);
}
if (!newRoute && this.logger) {
this.logger.warn("ROUTER", "No route to go back to");
}
return;
}
this.navigateTo(newRoute, options, true);
}
performContextAction(context) {
if (context === false) {
return false;
}
if (context instanceof Error) {
this.onError(context);
return false;
}
if (typeof context === "object" || typeof context === "string") {
this.navigateTo(context);
return false;
}
return true;
}
}
//# sourceMappingURL=router-service.js.map