1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00
jellyfin-web/src/components/appRouter.js

845 lines
25 KiB
JavaScript
Raw Normal View History

2022-04-13 16:38:19 -04:00
import { Events } from 'jellyfin-apiclient';
import { Action, createHashHistory } from 'history';
2020-08-16 20:24:45 +02:00
import { appHost } from './apphost';
2020-08-14 08:46:34 +02:00
import appSettings from '../scripts/settings/appSettings';
import { clearBackdrop, setBackdropTransparency } from './backdrop/backdrop';
2020-08-14 08:46:34 +02:00
import globalize from '../scripts/globalize';
import itemHelper from './itemHelper';
import loading from './loading/loading';
import viewManager from './viewManager/viewManager';
2022-04-10 02:22:13 -04:00
import Dashboard from '../utils/dashboard';
import ServerConnections from './ServerConnections';
import alert from './alert';
import reactControllerFactory from './reactControllerFactory';
2020-07-30 20:34:21 +02:00
2022-04-13 16:38:19 -04:00
const history = createHashHistory();
2020-07-30 20:34:21 +02:00
class AppRouter {
2022-04-13 16:38:19 -04:00
allRoutes = new Map();
2020-07-30 20:34:21 +02:00
backdropContainer;
backgroundContainer;
currentRouteInfo;
currentViewLoadRequest;
firstConnectionResult;
forcedLogoutMsg;
isDummyBackToHome;
msgTimeout;
2021-10-03 21:51:06 +03:00
promiseShow;
2020-07-30 20:34:21 +02:00
resolveOnNextShow;
2021-08-25 00:11:12 +03:00
previousRoute = {};
2020-07-30 20:34:21 +02:00
/**
* Pages of "no return" (when "Go back" should behave differently, probably quitting the application).
*/
startPages = ['home', 'login', 'selectserver'];
constructor() {
2021-09-21 22:26:09 +03:00
document.addEventListener('viewshow', () => this.onViewShow());
2020-07-30 20:34:21 +02:00
2022-04-13 16:38:19 -04:00
// TODO: Can this baseRoute logic be simplified?
2020-08-25 10:12:35 +09:00
this.baseRoute = window.location.href.split('?')[0].replace(this.getRequestFile(), '');
2020-07-30 20:34:21 +02:00
// support hashbang
this.baseRoute = this.baseRoute.split('#')[0];
if (this.baseRoute.endsWith('/') && !this.baseRoute.endsWith('://')) {
this.baseRoute = this.baseRoute.substring(0, this.baseRoute.length - 1);
}
}
2022-04-13 16:38:19 -04:00
addRoute(path, route) {
this.allRoutes.set(path, {
route,
handler: this.#getHandler(route)
});
2020-07-30 20:34:21 +02:00
}
showLocalLogin(serverId) {
2020-08-06 23:25:18 +02:00
Dashboard.navigate('login.html?serverid=' + serverId);
}
showVideoOsd() {
return Dashboard.navigate('video');
2020-07-30 20:34:21 +02:00
}
showSelectServer() {
Dashboard.navigate('selectserver.html');
2020-07-30 20:34:21 +02:00
}
showSettings() {
2020-08-06 23:25:18 +02:00
Dashboard.navigate('mypreferencesmenu.html');
2020-07-30 20:34:21 +02:00
}
showNowPlaying() {
2020-08-06 23:25:18 +02:00
this.show('queue');
2020-07-30 20:34:21 +02:00
}
beginConnectionWizard() {
clearBackdrop();
2020-07-31 21:35:01 +01:00
loading.show();
ServerConnections.connect({
2018-10-23 01:05:09 +03:00
enableAutoLogin: appSettings.enableAutoLogin()
2020-07-30 20:34:21 +02:00
}).then((result) => {
this.handleConnectionResult(result);
});
2018-10-23 01:05:09 +03:00
}
2021-10-03 21:51:06 +03:00
ready() {
return this.promiseShow || Promise.resolve();
2020-07-30 20:34:21 +02:00
}
2021-10-03 21:51:06 +03:00
async back() {
if (this.promiseShow) await this.promiseShow;
this.promiseShow = new Promise((resolve) => {
this.resolveOnNextShow = resolve;
2022-04-13 16:38:19 -04:00
history.back();
2021-10-03 21:51:06 +03:00
});
return this.promiseShow;
}
async show(path, options) {
if (this.promiseShow) await this.promiseShow;
2020-12-03 00:19:31 -05:00
// ensure the path does not start with '#!' since the router adds this
if (path.startsWith('#!')) {
path = path.substring(2);
}
2020-07-30 20:34:21 +02:00
if (path.indexOf('/') !== 0 && path.indexOf('://') === -1) {
path = '/' + path;
}
path = path.replace(this.baseUrl(), '');
if (this.currentRouteInfo && this.currentRouteInfo.path === path) {
// can't use this with home right now due to the back menu
if (this.currentRouteInfo.route.type !== 'home') {
loading.hide();
return Promise.resolve();
}
}
2021-10-03 21:51:06 +03:00
this.promiseShow = new Promise((resolve) => {
2020-07-30 20:34:21 +02:00
this.resolveOnNextShow = resolve;
2021-10-03 21:51:06 +03:00
// Schedule a call to return the promise
2022-04-13 16:38:19 -04:00
setTimeout(() => history.push(path, options), 0);
2020-07-30 20:34:21 +02:00
});
2021-10-03 21:51:06 +03:00
return this.promiseShow;
2020-07-30 20:34:21 +02:00
}
2021-10-03 21:51:06 +03:00
async showDirect(path) {
if (this.promiseShow) await this.promiseShow;
this.promiseShow = new Promise((resolve) => {
2020-07-30 20:34:21 +02:00
this.resolveOnNextShow = resolve;
2021-10-03 21:51:06 +03:00
// Schedule a call to return the promise
2022-04-13 16:38:19 -04:00
setTimeout(() => history.push(this.baseUrl() + path), 0);
2020-07-30 20:34:21 +02:00
});
2021-10-03 21:51:06 +03:00
return this.promiseShow;
2020-07-30 20:34:21 +02:00
}
2022-04-13 16:38:19 -04:00
#goToRoute({ location, action }) {
// Strip the leading "!" if present
const normalizedPath = location.pathname.replace(/^!/, '');
2022-04-19 23:33:51 -04:00
const route = this.allRoutes.get(normalizedPath);
if (route) {
console.debug('[appRouter] "%s" route found', normalizedPath, location, route);
route.handler({
// Recreate the default context used by page.js: https://github.com/visionmedia/page.js#context
path: normalizedPath + location.search,
pathname: normalizedPath,
querystring: location.search.replace(/^\?/, ''),
state: location.state,
// Custom context variables
isBack: action === Action.Pop
});
2022-04-13 16:38:19 -04:00
} else {
console.warn('[appRouter] "%s" route not found', normalizedPath, location);
}
}
start() {
2020-07-30 20:34:21 +02:00
loading.show();
this.initApiClients();
2020-09-08 02:05:02 -04:00
Events.on(appHost, 'resume', this.onAppResume);
2020-07-30 20:34:21 +02:00
ServerConnections.connect({
2020-07-30 20:34:21 +02:00
enableAutoLogin: appSettings.enableAutoLogin()
}).then((result) => {
this.firstConnectionResult = result;
2022-04-13 16:38:19 -04:00
// Handle the initial route
this.#goToRoute({ location: history.location });
// Handle route changes
history.listen(params => {
this.#goToRoute(params);
2020-07-30 20:34:21 +02:00
});
}).catch().then(() => {
loading.hide();
});
}
baseUrl() {
return this.baseRoute;
}
canGoBack() {
const curr = this.current();
if (!curr) {
return false;
}
if (!document.querySelector('.dialogContainer') && this.startPages.indexOf(curr.type) !== -1) {
return false;
}
2020-08-25 10:12:35 +09:00
return window.history.length > 1;
2020-07-30 20:34:21 +02:00
}
current() {
return this.currentRouteInfo ? this.currentRouteInfo.route : null;
}
invokeShortcut(id) {
if (id.indexOf('library-') === 0) {
id = id.replace('library-', '');
id = id.split('_');
this.showItem(id[0], id[1]);
} else if (id.indexOf('item-') === 0) {
id = id.replace('item-', '');
id = id.split('_');
this.showItem(id[0], id[1]);
} else {
id = id.split('_');
this.show(this.getRouteUrl(id[0], {
serverId: id[1]
}));
}
}
showItem(item, serverId, options) {
// TODO: Refactor this so it only gets items, not strings.
if (typeof (item) === 'string') {
const apiClient = serverId ? ServerConnections.getApiClient(serverId) : ServerConnections.currentApiClient();
2020-07-30 20:34:21 +02:00
apiClient.getItem(apiClient.getCurrentUserId(), item).then((itemObject) => {
this.showItem(itemObject, options);
});
} else {
if (arguments.length === 2) {
options = arguments[1];
}
const url = this.getRouteUrl(item, options);
this.show(url, {
item: item
});
}
}
/**
* Sets the backdrop, background, and document transparency
* @deprecated use Dashboard.setBackdropTransparency
*/
2020-07-30 20:34:21 +02:00
setTransparency(level) {
// TODO: Remove this after JMP is updated to not use this function
console.warn('Deprecated! Use Dashboard.setBackdropTransparency');
setBackdropTransparency(level);
2020-07-30 20:34:21 +02:00
}
handleConnectionResult(result) {
2018-10-23 01:05:09 +03:00
switch (result.State) {
case 'SignedIn':
2020-07-31 21:35:01 +01:00
loading.hide();
2020-10-18 20:00:39 +01:00
this.goHome();
break;
case 'ServerSignIn':
2020-07-30 20:34:21 +02:00
result.ApiClient.getPublicUsers().then((users) => {
if (users.length) {
2020-07-30 20:34:21 +02:00
this.showLocalLogin(result.Servers[0].Id);
} else {
2020-07-30 20:34:21 +02:00
this.showLocalLogin(result.Servers[0].Id, true);
}
});
2018-10-23 01:05:09 +03:00
break;
case 'ServerSelection':
2020-07-30 20:34:21 +02:00
this.showSelectServer();
2018-10-23 01:05:09 +03:00
break;
case 'ServerUpdateNeeded':
alert({
text: globalize.translate('ServerUpdateNeeded', 'https://github.com/jellyfin/jellyfin'),
html: globalize.translate('ServerUpdateNeeded', '<a href="https://github.com/jellyfin/jellyfin">https://github.com/jellyfin/jellyfin</a>')
}).then(() => {
this.showSelectServer();
});
break;
default:
2018-10-23 01:05:09 +03:00
break;
}
}
2020-07-30 20:34:21 +02:00
loadContentUrl(ctx, next, route, request) {
let url;
if (route.contentPath && typeof (route.contentPath) === 'function') {
url = route.contentPath(ctx.querystring);
} else {
url = route.contentPath || route.path;
}
if (ctx.querystring && route.enableContentQueryString) {
url += '?' + ctx.querystring;
}
let promise;
if (route.serverRequest) {
const apiClient = ServerConnections.currentApiClient();
url = apiClient.getUrl(`/web${url}`);
promise = apiClient.get(url);
} else {
promise = import(/* webpackChunkName: "[request]" */ `../controllers/${url}`);
}
promise.then((html) => {
2020-07-30 20:34:21 +02:00
this.loadContent(ctx, route, html, request);
});
2018-10-23 01:05:09 +03:00
}
2020-07-30 20:34:21 +02:00
handleRoute(ctx, next, route) {
this.authenticate(ctx, route, () => {
this.initRoute(ctx, next, route);
});
2018-10-23 01:05:09 +03:00
}
2020-07-30 20:34:21 +02:00
initRoute(ctx, next, route) {
const onInitComplete = (controllerFactory) => {
this.sendRouteToViewManager(ctx, next, route, controllerFactory);
2018-10-23 01:05:09 +03:00
};
if (route.pageComponent) {
onInitComplete(reactControllerFactory);
} else if (route.controller) {
2020-08-14 08:46:34 +02:00
import('../controllers/' + route.controller).then(onInitComplete);
} else {
onInitComplete();
}
2018-10-23 01:05:09 +03:00
}
2020-07-30 20:34:21 +02:00
cancelCurrentLoadRequest() {
const currentRequest = this.currentViewLoadRequest;
if (currentRequest) {
currentRequest.cancel = true;
}
2018-10-23 01:05:09 +03:00
}
2020-07-30 20:34:21 +02:00
sendRouteToViewManager(ctx, next, route, controllerFactory) {
if (this.isDummyBackToHome && route.type === 'home') {
this.isDummyBackToHome = false;
return;
}
2020-07-30 20:34:21 +02:00
this.cancelCurrentLoadRequest();
const isBackNav = ctx.isBack;
2020-07-30 20:34:21 +02:00
const currentRequest = {
url: this.baseUrl() + ctx.path,
transition: route.transition,
isBack: isBackNav,
state: ctx.state,
type: route.type,
fullscreen: route.fullscreen,
controllerFactory: controllerFactory,
options: {
pageComponent: route.pageComponent,
supportsThemeMedia: route.supportsThemeMedia || false,
enableMediaControl: route.enableMediaControl !== false
},
autoFocus: route.autoFocus
};
2020-07-30 20:34:21 +02:00
this.currentViewLoadRequest = currentRequest;
2020-07-30 20:34:21 +02:00
const onNewViewNeeded = () => {
if (typeof route.path === 'string') {
2020-07-30 20:34:21 +02:00
this.loadContentUrl(ctx, next, route, currentRequest);
} else {
next();
}
2018-10-23 01:05:09 +03:00
};
if (!isBackNav) {
onNewViewNeeded();
return;
}
2020-07-30 20:34:21 +02:00
viewManager.tryRestoreView(currentRequest, () => {
this.currentRouteInfo = {
2018-10-23 01:05:09 +03:00
route: route,
path: ctx.path
};
2020-07-30 20:34:21 +02:00
}).catch((result) => {
if (!result || !result.cancelled) {
onNewViewNeeded();
2018-10-23 01:05:09 +03:00
}
});
2018-10-23 01:05:09 +03:00
}
2021-09-21 22:26:09 +03:00
onViewShow() {
const resolve = this.resolveOnNextShow;
if (resolve) {
2021-10-03 21:51:06 +03:00
this.promiseShow = null;
2021-09-21 22:26:09 +03:00
this.resolveOnNextShow = null;
resolve();
}
}
2020-07-30 20:34:21 +02:00
onForcedLogoutMessageTimeout() {
const msg = this.forcedLogoutMsg;
this.forcedLogoutMsg = null;
if (msg) {
alert(msg);
}
2018-10-23 01:05:09 +03:00
}
2020-07-30 20:34:21 +02:00
showForcedLogoutMessage(msg) {
this.forcedLogoutMsg = msg;
if (this.msgTimeout) {
clearTimeout(this.msgTimeout);
}
2020-07-30 20:34:21 +02:00
this.msgTimeout = setTimeout(this.onForcedLogoutMessageTimeout, 100);
2018-10-23 01:05:09 +03:00
}
2020-07-30 20:34:21 +02:00
onRequestFail(e, data) {
const apiClient = this;
2021-03-29 20:51:41 +02:00
if (data.status === 403) {
2020-05-04 12:44:12 +02:00
if (data.errorCode === 'ParentalControl') {
2021-04-10 11:45:55 +02:00
const isCurrentAllowed = appRouter.currentRouteInfo ? (appRouter.currentRouteInfo.route.anonymous || appRouter.currentRouteInfo.route.startup) : true;
// Bounce to the login screen, but not if a password entry fails, obviously
if (!isCurrentAllowed) {
2021-04-10 11:45:55 +02:00
appRouter.showForcedLogoutMessage(globalize.translate('AccessRestrictedTryAgainLater'));
appRouter.showLocalLogin(apiClient.serverId());
}
}
2018-10-23 01:05:09 +03:00
}
}
2020-07-30 20:34:21 +02:00
normalizeImageOptions(options) {
let setQuality;
if (options.maxWidth || options.width || options.maxHeight || options.height || options.fillWidth || options.fillHeight) {
setQuality = true;
}
2020-07-16 17:25:36 +02:00
if (setQuality && !options.quality) {
2020-07-16 16:03:36 +02:00
options.quality = 90;
2018-10-23 01:05:09 +03:00
}
}
2020-07-30 20:34:21 +02:00
getMaxBandwidth() {
/* eslint-disable compat/compat */
2018-10-23 01:05:09 +03:00
if (navigator.connection) {
2020-07-30 20:34:21 +02:00
let max = navigator.connection.downlinkMax;
if (max && max > 0 && max < Number.POSITIVE_INFINITY) {
max /= 8;
max *= 1000000;
max *= 0.7;
2020-07-30 19:42:30 +02:00
return parseInt(max, 10);
}
2018-10-23 01:05:09 +03:00
}
/* eslint-enable compat/compat */
return null;
2018-10-23 01:05:09 +03:00
}
2020-07-30 20:34:21 +02:00
onApiClientCreated(e, newApiClient) {
newApiClient.normalizeImageOptions = this.normalizeImageOptions;
2021-02-27 23:30:14 -05:00
newApiClient.getMaxBandwidth = this.getMaxBandwidth;
2020-09-08 02:05:02 -04:00
Events.off(newApiClient, 'requestfail', this.onRequestFail);
Events.on(newApiClient, 'requestfail', this.onRequestFail);
2018-10-23 01:05:09 +03:00
}
2020-07-30 20:34:21 +02:00
initApiClient(apiClient, instance) {
instance.onApiClientCreated({}, apiClient);
2018-10-23 01:05:09 +03:00
}
2020-07-30 20:34:21 +02:00
initApiClients() {
ServerConnections.getApiClients().forEach((apiClient) => {
2020-07-30 20:34:21 +02:00
this.initApiClient(apiClient, this);
});
Events.on(ServerConnections, 'apiclientcreated', this.onApiClientCreated);
2018-10-23 01:05:09 +03:00
}
2020-07-30 20:34:21 +02:00
onAppResume() {
const apiClient = ServerConnections.currentApiClient();
if (apiClient) {
apiClient.ensureWebSocket();
}
2018-10-23 01:05:09 +03:00
}
2020-07-30 20:34:21 +02:00
authenticate(ctx, route, callback) {
const firstResult = this.firstConnectionResult;
this.firstConnectionResult = null;
2021-03-22 23:34:48 +03:00
if (firstResult) {
if (firstResult.State === 'ServerSignIn') {
const url = firstResult.ApiClient.serverAddress() + '/System/Info/Public';
fetch(url).then(response => {
if (!response.ok) return Promise.reject('fetch failed');
return response.json();
}).then(data => {
if (data !== null && data.StartupWizardCompleted === false) {
ServerConnections.setLocalApiClient(firstResult.ApiClient);
Dashboard.navigate('wizardstart.html');
} else {
this.handleConnectionResult(firstResult);
}
}).catch(error => {
console.error(error);
});
2020-11-07 15:16:39 +09:00
2021-03-22 23:34:48 +03:00
return;
} else if (firstResult.State !== 'SignedIn') {
this.handleConnectionResult(firstResult);
return;
}
}
const apiClient = ServerConnections.currentApiClient();
2020-07-30 20:34:21 +02:00
const pathname = ctx.pathname.toLowerCase();
2022-04-13 16:38:19 -04:00
console.debug('[appRouter] processing path request: ' + pathname);
2020-07-30 20:34:21 +02:00
const isCurrentRouteStartup = this.currentRouteInfo ? this.currentRouteInfo.route.startup : true;
const shouldExitApp = ctx.isBack && route.isDefaultRoute && isCurrentRouteStartup;
if (!shouldExitApp && (!apiClient || !apiClient.isLoggedIn()) && !route.anonymous) {
2022-04-13 16:38:19 -04:00
console.debug('[appRouter] route does not allow anonymous access: redirecting to login');
2020-07-30 20:34:21 +02:00
this.beginConnectionWizard();
return;
}
2018-10-23 01:05:09 +03:00
if (shouldExitApp) {
if (appHost.supports('exit')) {
appHost.exit();
}
return;
}
if (apiClient && apiClient.isLoggedIn()) {
2022-04-13 16:38:19 -04:00
console.debug('[appRouter] user is authenticated');
2019-03-24 12:15:13 +00:00
if (route.isDefaultRoute) {
2022-04-13 16:38:19 -04:00
console.debug('[appRouter] loading home page');
2020-10-18 20:00:39 +01:00
this.goHome();
return;
} else if (route.roles) {
2020-07-30 20:34:21 +02:00
this.validateRoles(apiClient, route.roles).then(() => {
callback();
2020-07-30 20:34:21 +02:00
}, this.beginConnectionWizard);
return;
2018-10-23 01:05:09 +03:00
}
}
2022-04-13 16:38:19 -04:00
console.debug('[appRouter] proceeding to page: ' + pathname);
callback();
2018-10-23 01:05:09 +03:00
}
2020-07-30 20:34:21 +02:00
validateRoles(apiClient, roles) {
return Promise.all(roles.split(',').map((role) => {
return this.validateRole(apiClient, role);
}));
2018-10-23 01:05:09 +03:00
}
2020-07-30 20:34:21 +02:00
validateRole(apiClient, role) {
if (role === 'admin') {
2020-07-30 20:34:21 +02:00
return apiClient.getCurrentUser().then((user) => {
if (user.Policy.IsAdministrator) {
return Promise.resolve();
}
return Promise.reject();
});
}
// Unknown role
return Promise.resolve();
2018-10-23 01:05:09 +03:00
}
2020-07-30 20:34:21 +02:00
loadContent(ctx, route, html, request) {
2020-07-18 09:21:15 +01:00
html = globalize.translateHtml(html, route.dictionary);
request.view = html;
viewManager.loadView(request);
2020-07-30 20:34:21 +02:00
this.currentRouteInfo = {
2018-10-23 01:05:09 +03:00
route: route,
path: ctx.path
};
ctx.handled = true;
2018-10-23 01:05:09 +03:00
}
2020-07-30 20:34:21 +02:00
getRequestFile() {
2020-08-25 10:12:35 +09:00
let path = window.location.pathname || '';
2020-07-30 20:34:21 +02:00
const index = path.lastIndexOf('/');
if (index !== -1) {
path = path.substring(index);
} else {
path = '/' + path;
}
if (!path || path === '/') {
path = '/index.html';
}
return path;
2018-10-23 01:05:09 +03:00
}
2022-04-13 16:38:19 -04:00
#getHandler(route) {
2020-07-30 20:34:21 +02:00
return (ctx, next) => {
2021-08-25 00:11:12 +03:00
const ignore = route.dummyRoute === true || this.previousRoute.dummyRoute === true;
this.previousRoute = route;
2021-09-21 22:26:09 +03:00
if (ignore) {
// Resolve 'show' promise
this.onViewShow();
return;
}
2021-08-25 00:11:12 +03:00
this.handleRoute(ctx, next, route);
2020-07-30 20:34:21 +02:00
};
2018-10-23 01:05:09 +03:00
}
2020-07-30 20:34:21 +02:00
showGuide() {
2020-08-06 23:25:18 +02:00
Dashboard.navigate('livetv.html?tab=1');
2018-10-23 01:05:09 +03:00
}
2020-07-30 20:34:21 +02:00
goHome() {
2020-08-06 23:25:18 +02:00
Dashboard.navigate('home.html');
2020-07-30 20:34:21 +02:00
}
2020-03-24 10:03:51 +03:00
2020-07-30 20:34:21 +02:00
showSearch() {
2020-08-06 23:25:18 +02:00
Dashboard.navigate('search.html');
2018-10-23 01:05:09 +03:00
}
2020-07-30 20:34:21 +02:00
showLiveTV() {
2020-08-06 23:25:18 +02:00
Dashboard.navigate('livetv.html');
2020-07-30 20:34:21 +02:00
}
2020-07-30 20:34:21 +02:00
showRecordedTV() {
2020-08-06 23:25:18 +02:00
Dashboard.navigate('livetv.html?tab=3');
2020-07-30 20:34:21 +02:00
}
2020-07-30 20:34:21 +02:00
showFavorites() {
2020-08-06 23:25:18 +02:00
Dashboard.navigate('home.html?tab=1');
2020-07-30 20:34:21 +02:00
}
2020-07-30 20:34:21 +02:00
getRouteUrl(item, options) {
if (!item) {
throw new Error('item cannot be null');
}
2020-07-30 20:34:21 +02:00
if (item.url) {
return item.url;
}
2018-10-23 01:05:09 +03:00
2020-07-30 20:34:21 +02:00
const context = options ? options.context : null;
const id = item.Id || item.ItemId;
2018-10-23 01:05:09 +03:00
2020-07-30 20:34:21 +02:00
if (!options) {
options = {};
}
2020-01-25 01:18:07 +03:00
2020-07-30 20:34:21 +02:00
let url;
// TODO: options will never be false. Replace condition with lodash's isEmpty()
const itemType = item.Type || (options ? options.itemType : null);
const serverId = item.ServerId || options.serverId;
if (item === 'settings') {
return '#!/mypreferencesmenu.html';
}
2020-07-30 20:34:21 +02:00
if (item === 'wizard') {
return '#!/wizardstart.html';
}
2020-07-24 19:02:25 +02:00
2020-07-30 20:34:21 +02:00
if (item === 'manageserver') {
return '#!/dashboard.html';
2020-07-30 20:34:21 +02:00
}
2020-07-30 20:34:21 +02:00
if (item === 'recordedtv') {
return '#!/livetv.html?tab=3&serverId=' + options.serverId;
2020-07-30 20:34:21 +02:00
}
2020-07-30 20:34:21 +02:00
if (item === 'nextup') {
return '#!/list.html?type=nextup&serverId=' + options.serverId;
}
2020-07-30 20:34:21 +02:00
if (item === 'list') {
let url = '#!/list.html?serverId=' + options.serverId + '&type=' + options.itemTypes;
2020-07-30 20:34:21 +02:00
if (options.isFavorite) {
url += '&IsFavorite=true';
}
2020-07-30 20:34:21 +02:00
return url;
}
2020-07-30 20:34:21 +02:00
if (item === 'livetv') {
if (options.section === 'programs') {
return '#!/livetv.html?tab=0&serverId=' + options.serverId;
2020-07-30 20:34:21 +02:00
}
if (options.section === 'guide') {
return '#!/livetv.html?tab=1&serverId=' + options.serverId;
2020-07-30 20:34:21 +02:00
}
2018-10-23 01:05:09 +03:00
2020-07-30 20:34:21 +02:00
if (options.section === 'movies') {
return '#!/list.html?type=Programs&IsMovie=true&serverId=' + options.serverId;
2020-07-30 20:34:21 +02:00
}
2020-07-30 20:34:21 +02:00
if (options.section === 'shows') {
return '#!/list.html?type=Programs&IsSeries=true&IsMovie=false&IsNews=false&serverId=' + options.serverId;
2020-07-30 20:34:21 +02:00
}
2018-10-23 01:05:09 +03:00
2020-07-30 20:34:21 +02:00
if (options.section === 'sports') {
return '#!/list.html?type=Programs&IsSports=true&serverId=' + options.serverId;
}
2020-07-30 20:34:21 +02:00
if (options.section === 'kids') {
return '#!/list.html?type=Programs&IsKids=true&serverId=' + options.serverId;
2020-07-30 20:34:21 +02:00
}
if (options.section === 'news') {
return '#!/list.html?type=Programs&IsNews=true&serverId=' + options.serverId;
2020-07-30 20:34:21 +02:00
}
if (options.section === 'onnow') {
return '#!/list.html?type=Programs&IsAiring=true&serverId=' + options.serverId;
2020-07-30 20:34:21 +02:00
}
2022-01-13 10:15:24 -05:00
if (options.section === 'channels') {
return '#!/livetv.html?tab=2&serverId=' + options.serverId;
}
2020-07-30 20:34:21 +02:00
if (options.section === 'dvrschedule') {
return '#!/livetv.html?tab=4&serverId=' + options.serverId;
2020-07-30 20:34:21 +02:00
}
if (options.section === 'seriesrecording') {
return '#!/livetv.html?tab=5&serverId=' + options.serverId;
2020-07-30 20:34:21 +02:00
}
return '#!/livetv.html?serverId=' + options.serverId;
2018-10-23 01:05:09 +03:00
}
2020-07-30 20:34:21 +02:00
if (itemType == 'SeriesTimer') {
return '#!/details?seriesTimerId=' + id + '&serverId=' + serverId;
2020-07-30 20:34:21 +02:00
}
2020-07-30 20:34:21 +02:00
if (item.CollectionType == 'livetv') {
return '#!/livetv.html';
2020-07-30 20:34:21 +02:00
}
2018-10-23 01:05:09 +03:00
2020-07-30 20:34:21 +02:00
if (item.Type === 'Genre') {
url = '#!/list.html?genreId=' + item.Id + '&serverId=' + serverId;
2020-07-30 20:34:21 +02:00
if (context === 'livetv') {
url += '&type=Programs';
}
if (options.parentId) {
url += '&parentId=' + options.parentId;
}
2018-10-23 01:05:09 +03:00
2020-07-30 20:34:21 +02:00
return url;
}
2020-07-30 20:34:21 +02:00
if (item.Type === 'MusicGenre') {
url = '#!/list.html?musicGenreId=' + item.Id + '&serverId=' + serverId;
2020-07-30 20:34:21 +02:00
if (options.parentId) {
url += '&parentId=' + options.parentId;
}
return url;
}
2020-07-30 20:34:21 +02:00
if (item.Type === 'Studio') {
url = '#!/list.html?studioId=' + item.Id + '&serverId=' + serverId;
2020-07-30 20:34:21 +02:00
if (options.parentId) {
url += '&parentId=' + options.parentId;
}
return url;
}
2018-10-23 01:05:09 +03:00
2020-07-30 20:34:21 +02:00
if (context !== 'folders' && !itemHelper.isLocalItem(item)) {
if (item.CollectionType == 'movies') {
url = '#!/movies.html?topParentId=' + item.Id;
2020-07-30 20:34:21 +02:00
if (options && options.section === 'latest') {
url += '&tab=1';
}
return url;
}
if (item.CollectionType == 'tvshows') {
url = '#!/tv.html?topParentId=' + item.Id;
2020-07-30 20:34:21 +02:00
if (options && options.section === 'latest') {
2021-01-02 00:23:43 -05:00
url += '&tab=1';
2020-07-30 20:34:21 +02:00
}
return url;
}
if (item.CollectionType == 'music') {
2021-01-02 00:23:43 -05:00
url = '#!/music.html?topParentId=' + item.Id;
if (options?.section === 'latest') {
url += '&tab=1';
}
return url;
2020-07-30 20:34:21 +02:00
}
}
2020-07-30 20:34:21 +02:00
const itemTypes = ['Playlist', 'TvChannel', 'Program', 'BoxSet', 'MusicAlbum', 'MusicGenre', 'Person', 'Recording', 'MusicArtist'];
2020-07-30 20:34:21 +02:00
if (itemTypes.indexOf(itemType) >= 0) {
return '#!/details?id=' + id + '&serverId=' + serverId;
2020-07-30 20:34:21 +02:00
}
2020-07-30 20:34:21 +02:00
const contextSuffix = context ? '&context=' + context : '';
2020-07-30 20:34:21 +02:00
if (itemType == 'Series' || itemType == 'Season' || itemType == 'Episode') {
return '#!/details?id=' + id + contextSuffix + '&serverId=' + serverId;
2020-07-30 20:34:21 +02:00
}
2020-07-30 20:34:21 +02:00
if (item.IsFolder) {
if (id) {
return '#!/list.html?parentId=' + id + '&serverId=' + serverId;
2020-07-30 20:34:21 +02:00
}
return '#';
}
2020-07-30 20:34:21 +02:00
return '#!/details?id=' + id + '&serverId=' + serverId;
2018-10-23 01:05:09 +03:00
}
2020-07-30 20:34:21 +02:00
}
2020-08-16 20:24:45 +02:00
export const appRouter = new AppRouter();
2020-10-18 20:00:39 +01:00
window.Emby = window.Emby || {};
window.Emby.Page = appRouter;