2017-10-12 00:01:37 +03:00
|
|
|
import { bind, debounce } from 'decko';
|
|
|
|
import { EventEmitter } from 'eventemitter3';
|
2018-03-26 18:14:38 +03:00
|
|
|
import { IS_BROWSER } from '../utils/';
|
2017-10-12 00:01:37 +03:00
|
|
|
|
|
|
|
const EVENT = 'hashchange';
|
|
|
|
|
2018-08-17 14:50:58 +03:00
|
|
|
export class HistoryService {
|
2017-10-12 00:01:37 +03:00
|
|
|
private _emiter;
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
this._emiter = new EventEmitter();
|
|
|
|
this.bind();
|
|
|
|
}
|
|
|
|
|
2018-08-17 14:50:58 +03:00
|
|
|
get currentId(): string {
|
|
|
|
return IS_BROWSER ? window.location.hash.substring(1) : '';
|
|
|
|
}
|
|
|
|
|
|
|
|
linkForId(id: string) {
|
2018-08-17 15:01:18 +03:00
|
|
|
if (!id) {
|
|
|
|
return '';
|
|
|
|
}
|
2018-08-17 14:50:58 +03:00
|
|
|
return '#' + id;
|
2017-10-12 00:01:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
subscribe(cb): () => void {
|
|
|
|
const emmiter = this._emiter.addListener(EVENT, cb);
|
|
|
|
return () => emmiter.removeListener(EVENT, cb);
|
|
|
|
}
|
|
|
|
|
|
|
|
emit = () => {
|
2018-08-17 14:50:58 +03:00
|
|
|
this._emiter.emit(EVENT, this.currentId);
|
2017-10-12 00:01:37 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
bind() {
|
2018-03-26 18:14:38 +03:00
|
|
|
if (IS_BROWSER) {
|
2018-01-09 20:00:17 +03:00
|
|
|
window.addEventListener('hashchange', this.emit, false);
|
|
|
|
}
|
2017-10-12 00:01:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
dispose() {
|
2018-03-26 18:14:38 +03:00
|
|
|
if (IS_BROWSER) {
|
2018-01-09 20:00:17 +03:00
|
|
|
window.removeEventListener('hashchange', this.emit);
|
|
|
|
}
|
2017-10-12 00:01:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
@bind
|
|
|
|
@debounce
|
2018-08-17 14:50:58 +03:00
|
|
|
replace(id: string | null, rewriteHistory: boolean = false) {
|
|
|
|
if (!IS_BROWSER) {
|
2018-01-22 21:30:53 +03:00
|
|
|
return;
|
|
|
|
}
|
2018-08-17 14:50:58 +03:00
|
|
|
|
2018-08-17 15:01:18 +03:00
|
|
|
if (id == null || id === this.currentId) {
|
2017-10-12 00:01:37 +03:00
|
|
|
return;
|
|
|
|
}
|
2018-08-17 14:50:58 +03:00
|
|
|
if (rewriteHistory) {
|
|
|
|
window.history.replaceState(
|
|
|
|
null,
|
|
|
|
'',
|
|
|
|
window.location.href.split('#')[0] + this.linkForId(id),
|
|
|
|
);
|
|
|
|
|
|
|
|
return;
|
2018-01-09 20:00:17 +03:00
|
|
|
}
|
2018-08-17 14:50:58 +03:00
|
|
|
window.history.pushState(null, '', window.location.href.split('#')[0] + this.linkForId(id));
|
2018-08-17 15:01:18 +03:00
|
|
|
this.emit();
|
2017-10-12 00:01:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-17 14:50:58 +03:00
|
|
|
export const history = new HistoryService();
|
2017-10-12 00:01:37 +03:00
|
|
|
|
|
|
|
if (module.hot) {
|
|
|
|
module.hot.dispose(() => {
|
2018-08-17 14:50:58 +03:00
|
|
|
history.dispose();
|
2017-10-12 00:01:37 +03:00
|
|
|
});
|
|
|
|
}
|