mirror of
https://github.com/jellyfin/jellyfin-web.git
synced 2024-11-17 19:08:18 -07:00
Merge pull request #3620 from thornbill/update-dialog-routing
Update dialog history handling
This commit is contained in:
commit
1dbbb4c65d
@ -11,7 +11,7 @@ import ServerConnections from './ServerConnections';
|
||||
import alert from './alert';
|
||||
import reactControllerFactory from './reactControllerFactory';
|
||||
|
||||
const history = createHashHistory();
|
||||
export const history = createHashHistory();
|
||||
|
||||
/**
|
||||
* Page types of "no return" (when "Go back" should behave differently, probably quitting the application).
|
||||
@ -20,14 +20,13 @@ const START_PAGE_TYPES = ['home', 'login', 'selectserver'];
|
||||
|
||||
class AppRouter {
|
||||
allRoutes = new Map();
|
||||
currentRouteInfo;
|
||||
currentRouteInfo = { route: {} };
|
||||
currentViewLoadRequest;
|
||||
firstConnectionResult;
|
||||
forcedLogoutMsg;
|
||||
msgTimeout;
|
||||
promiseShow;
|
||||
resolveOnNextShow;
|
||||
previousRoute = {};
|
||||
|
||||
constructor() {
|
||||
document.addEventListener('viewshow', () => this.onViewShow());
|
||||
@ -482,9 +481,9 @@ class AppRouter {
|
||||
|
||||
#getHandler(route) {
|
||||
return (ctx, next) => {
|
||||
const ignore = route.dummyRoute === true || this.previousRoute.dummyRoute === true;
|
||||
this.previousRoute = route;
|
||||
const ignore = ctx.path === this.currentRouteInfo.path;
|
||||
if (ignore) {
|
||||
console.debug('[appRouter] path did not change, ignoring route change');
|
||||
// Resolve 'show' promise
|
||||
this.onViewShow();
|
||||
return;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { appRouter } from '../appRouter';
|
||||
import { history } from '../appRouter';
|
||||
import focusManager from '../focusManager';
|
||||
import browser from '../../scripts/browser';
|
||||
import layoutManager from '../layoutManager';
|
||||
@ -39,7 +39,7 @@ import '../../assets/css/scrollstyles.scss';
|
||||
try {
|
||||
parentNode.removeChild(elem);
|
||||
} catch (err) {
|
||||
console.error('error removing dialog element: ' + err);
|
||||
console.error('[dialogHelper] error removing dialog element: ' + err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -49,26 +49,26 @@ import '../../assets/css/scrollstyles.scss';
|
||||
self.originalUrl = window.location.href;
|
||||
const activeElement = document.activeElement;
|
||||
let removeScrollLockOnClose = false;
|
||||
let unlisten;
|
||||
|
||||
function onHashChange() {
|
||||
const isBack = self.originalUrl === window.location.href;
|
||||
function onHashChange({ location }) {
|
||||
const dialogs = location.state?.dialogs || [];
|
||||
const shouldClose = !dialogs.includes(hash);
|
||||
|
||||
if (isBack || !isOpened(dlg)) {
|
||||
window.removeEventListener('popstate', onHashChange);
|
||||
if ((shouldClose || !isOpened(dlg)) && unlisten) {
|
||||
unlisten();
|
||||
}
|
||||
|
||||
if (isBack) {
|
||||
self.closedByBack = true;
|
||||
closeDialog(dlg);
|
||||
if (shouldClose) {
|
||||
close(dlg);
|
||||
}
|
||||
}
|
||||
|
||||
function onBackCommand(e) {
|
||||
if (e.detail.command === 'back') {
|
||||
self.closedByBack = true;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
closeDialog(dlg);
|
||||
close(dlg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,7 +77,9 @@ import '../../assets/css/scrollstyles.scss';
|
||||
inputManager.off(dlg, onBackCommand);
|
||||
}
|
||||
|
||||
window.removeEventListener('popstate', onHashChange);
|
||||
if (unlisten) {
|
||||
unlisten();
|
||||
}
|
||||
|
||||
removeBackdrop(dlg);
|
||||
dlg.classList.remove('opened');
|
||||
@ -86,10 +88,22 @@ import '../../assets/css/scrollstyles.scss';
|
||||
document.body.classList.remove('noScroll');
|
||||
}
|
||||
|
||||
if (!self.closedByBack && isHistoryEnabled(dlg)) {
|
||||
const state = window.history.state || {};
|
||||
if (state.dialogId === hash) {
|
||||
appRouter.back();
|
||||
if (isHistoryEnabled(dlg)) {
|
||||
const state = history.location.state || {};
|
||||
if (state.dialogs?.length > 0) {
|
||||
if (state.dialogs[state.dialogs.length - 1] === hash) {
|
||||
history.back();
|
||||
} else if (state.dialogs.includes(hash)) {
|
||||
console.warn('[dialogHelper] dialog "%s" was closed, but is not the last dialog opened', hash);
|
||||
// Remove the closed dialog hash from the history state
|
||||
history.replace(
|
||||
`${history.location.pathname}${history.location.search}`,
|
||||
{
|
||||
...state,
|
||||
dialogs: state.dialogs.filter(dialog => dialog !== hash)
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,14 +126,18 @@ import '../../assets/css/scrollstyles.scss';
|
||||
//resolve();
|
||||
// if we just called history.back(), then use a timeout to allow the history events to fire first
|
||||
setTimeout(() => {
|
||||
dlg.dispatchEvent(new CustomEvent('close', {
|
||||
bubbles: false,
|
||||
cancelable: false
|
||||
}));
|
||||
|
||||
resolve({
|
||||
element: dlg,
|
||||
closedByBack: self.closedByBack
|
||||
element: dlg
|
||||
});
|
||||
}, 1);
|
||||
}
|
||||
|
||||
dlg.addEventListener('close', onDialogClosed);
|
||||
dlg.addEventListener('_close', onDialogClosed);
|
||||
|
||||
const center = !dlg.classList.contains('dialog-fixedSize');
|
||||
if (center) {
|
||||
@ -144,9 +162,20 @@ import '../../assets/css/scrollstyles.scss';
|
||||
animateDialogOpen(dlg);
|
||||
|
||||
if (isHistoryEnabled(dlg)) {
|
||||
appRouter.show(`/dialog?dlg=${hash}`, { dialogId: hash });
|
||||
const state = history.location.state || {};
|
||||
const dialogs = state.dialogs || [];
|
||||
// Add new dialog to the list of open dialogs
|
||||
dialogs.push(hash);
|
||||
|
||||
window.addEventListener('popstate', onHashChange);
|
||||
history.push(
|
||||
`${history.location.pathname}${history.location.search}`,
|
||||
{
|
||||
...state,
|
||||
dialogs
|
||||
}
|
||||
);
|
||||
|
||||
unlisten = history.listen(onHashChange);
|
||||
} else {
|
||||
inputManager.on(dlg, onBackCommand);
|
||||
}
|
||||
@ -213,16 +242,6 @@ import '../../assets/css/scrollstyles.scss';
|
||||
}
|
||||
|
||||
export function close(dlg) {
|
||||
if (isOpened(dlg)) {
|
||||
if (isHistoryEnabled(dlg)) {
|
||||
appRouter.back();
|
||||
} else {
|
||||
closeDialog(dlg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function closeDialog(dlg) {
|
||||
if (!dlg.classList.contains('hide')) {
|
||||
dlg.dispatchEvent(new CustomEvent('closing', {
|
||||
bubbles: false,
|
||||
@ -233,7 +252,7 @@ import '../../assets/css/scrollstyles.scss';
|
||||
focusManager.popScope(dlg);
|
||||
|
||||
dlg.classList.add('hide');
|
||||
dlg.dispatchEvent(new CustomEvent('close', {
|
||||
dlg.dispatchEvent(new CustomEvent('_close', {
|
||||
bubbles: false,
|
||||
cancelable: false
|
||||
}));
|
||||
@ -348,7 +367,7 @@ import '../../assets/css/scrollstyles.scss';
|
||||
if (enableAnimation()) {
|
||||
backdrop.classList.remove('dialogBackdropOpened');
|
||||
|
||||
// this is not firing animatonend
|
||||
// this is not firing animationend
|
||||
setTimeout(onAnimationFinish, 300);
|
||||
return;
|
||||
}
|
||||
|
@ -1088,9 +1088,7 @@ import template from './metadataEditor.template.html';
|
||||
|
||||
export default {
|
||||
show: function (itemId, serverId) {
|
||||
return new Promise(function (resolve) {
|
||||
return show(itemId, serverId, resolve);
|
||||
});
|
||||
return new Promise(resolve => show(itemId, serverId, resolve));
|
||||
},
|
||||
|
||||
embed: function (elem, itemId, serverId) {
|
||||
|
@ -560,11 +560,6 @@ import { appRouter } from '../components/appRouter';
|
||||
serverRequest: true
|
||||
});
|
||||
|
||||
defineRoute({
|
||||
path: '/dialog',
|
||||
dummyRoute: true
|
||||
});
|
||||
|
||||
defineRoute({
|
||||
path: '/',
|
||||
autoFocus: false,
|
||||
|
Loading…
Reference in New Issue
Block a user