mt-music-player
Version:
A simply web music player app.
136 lines (111 loc) • 3.21 kB
JavaScript
import { store, updateStore } from '../models/index.js';
import storage from '../utils/storage.js';
import { capitalize } from '../utils/string.js';
const colseHandleMap = new WeakMap();
const generateState = (data, close) => {
if (data.$key) throw new Error('`$key` is not allowed');
if (data.$close) throw new Error('`$close` is not allowed');
const $key = performance.now();
const state = {
...data,
$key,
$close: !!close,
};
colseHandleMap.set(state, close);
return state;
};
const history = {
forward() {
window.history.forward();
},
back() {
window.history.back();
},
push(options) {
const { path, close } = options;
const query = options.query || '';
const data = options.data || {};
const title = options.title || document.title;
const { list, currentIndex } = store.historyState;
const state = generateState(data, close);
const historyItem = {
state,
title,
path,
query,
};
window.history.pushState(state, title, path + query);
const newList = list.slice(0, currentIndex + 1).concat(historyItem);
updateStore('historyState', {
list: newList,
currentIndex: newList.length - 1,
});
document.title = capitalize(title);
},
replace(options) {
const { path, close } = options;
const query = options.query || '';
const data = options.data || {};
const title = options.title || document.title;
const state = generateState(data, close);
window.history.replaceState(state, title, path + query);
const { list, currentIndex } = store.historyState;
list.splice(currentIndex, 1, {
path,
query,
state,
title,
});
updateStore('historyState', {
list,
});
document.title = capitalize(title);
},
};
if (!window.history.state) {
// first time use app
const { pathname, search } = window.location;
history.push({ path: pathname, query: search });
} else if (window.history.state.$close) {
// reload on page with modal window
history.back();
}
updateStore('historyState', storage.getSession('historyState'));
window.addEventListener('unload', () => {
storage.setSession('historyState', store.historyState);
});
window.addEventListener('popstate', (event) => {
// forward or back
// none replace
// prev data
const { list, currentIndex } = store.historyState;
if (event.state === null) {
const {
state, title, path, query,
} = list[0];
window.history.pushState(state, title, path + query);
return;
}
const currentState = list[currentIndex];
const newStateIndex = list.findIndex(
historyState => historyState.state.$key === event.state.$key,
);
if (currentState.state.$close) {
const closeHandle = colseHandleMap.get(currentState.state);
if (closeHandle) {
// reason: back button close modal
closeHandle();
} else {
// reason: reload modal
}
}
updateStore('historyState', {
currentIndex: newStateIndex,
});
if (list[newStateIndex]) {
document.title = capitalize(list[newStateIndex].title);
}
});
export default history;
// eslint-disable-next-line
window._history = history;