more url router work, differentiate between path and url

rename hashobservable to history
This commit is contained in:
Bruno Windels 2020-10-08 18:22:36 +02:00
parent 547241f577
commit 4fe971775c
3 changed files with 37 additions and 27 deletions

View File

@ -17,17 +17,17 @@ limitations under the License.
import {Segment} from "./Navigation.js"; import {Segment} from "./Navigation.js";
export class URLRouter { export class URLRouter {
constructor(pathObservable, navigation) { constructor(history, navigation) {
this._subscription = null; this._subscription = null;
this._pathObservable = pathObservable; this._history = history;
this._navigation = navigation; this._navigation = navigation;
} }
start() { start() {
this._subscription = this._pathObservable.subscribe(url => { this._subscription = this._history.subscribe(url => {
this._applyUrl(url); this._applyUrl(url);
}); });
this._applyUrl(this._pathObservable.get()); this._applyUrl(this._history.get());
} }
_applyUrl(url) { _applyUrl(url) {
@ -40,7 +40,8 @@ export class URLRouter {
this._subscription = this._subscription(); this._subscription = this._subscription();
} }
_segmentsFromUrl(path) { _segmentsFromUrl(url) {
const path = this._history.urlAsPath(url);
const parts = path.split("/").filter(p => !!p); const parts = path.split("/").filter(p => !!p);
let index = 0; let index = 0;
const segments = []; const segments = [];
@ -58,6 +59,10 @@ export class URLRouter {
return segments; return segments;
} }
replaceUrl(url) {
this._history.replaceUrl(url);
}
urlForSegment(type, value) { urlForSegment(type, value) {
const path = this._navigation.path.with(new Segment(type, value)); const path = this._navigation.path.with(new Segment(type, value));
if (path) { if (path) {
@ -66,14 +71,14 @@ export class URLRouter {
} }
urlForPath(path) { urlForPath(path) {
let url = "#"; let urlPath = "";
for (const {type, value} of path.segments) { for (const {type, value} of path.segments) {
if (typeof value === "boolean") { if (typeof value === "boolean") {
url += `/${type}`; urlPath += `/${type}`;
} else { } else {
url += `/${type}/${value}`; urlPath += `/${type}/${value}`;
} }
} }
return url; return this._history.pathAsUrl(urlPath);
} }
} }

View File

@ -26,7 +26,7 @@ import {Navigation} from "./domain/navigation/Navigation.js";
import {URLRouter} from "./domain/navigation/URLRouter.js"; import {URLRouter} from "./domain/navigation/URLRouter.js";
import {BrawlView} from "./ui/web/BrawlView.js"; import {BrawlView} from "./ui/web/BrawlView.js";
import {Clock} from "./ui/web/dom/Clock.js"; import {Clock} from "./ui/web/dom/Clock.js";
import {HashObservable} from "./ui/web/dom/HashObservable.js"; import {History} from "./ui/web/dom/History.js";
import {OnlineStatus} from "./ui/web/dom/OnlineStatus.js"; import {OnlineStatus} from "./ui/web/dom/OnlineStatus.js";
import {CryptoDriver} from "./ui/web/dom/CryptoDriver.js"; import {CryptoDriver} from "./ui/web/dom/CryptoDriver.js";
import {WorkerPool} from "./utils/WorkerPool.js"; import {WorkerPool} from "./utils/WorkerPool.js";
@ -130,7 +130,7 @@ export async function main(container, paths, legacyExtras) {
return false; return false;
} }
}); });
const urlRouter = new URLRouter(new HashObservable(), navigation); const urlRouter = new URLRouter(new History(), navigation);
urlRouter.start(); urlRouter.start();
const vm = new BrawlViewModel({ const vm = new BrawlViewModel({

View File

@ -16,35 +16,40 @@ limitations under the License.
import {BaseObservableValue} from "../../../observable/ObservableValue.js"; import {BaseObservableValue} from "../../../observable/ObservableValue.js";
export class HashObservable extends BaseObservableValue { export class History extends BaseObservableValue {
constructor() { constructor() {
super(); super();
this._boundOnHashChange = null; this._boundOnHashChange = null;
this._expectSetEcho = false;
} }
_onHashChange() { _onHashChange() {
if (this._expectSetEcho) {
this._expectSetEcho = false;
return;
}
this.emit(this.get()); this.emit(this.get());
} }
get() { get() {
const hash = document.location.hash; return document.location.hash;
if (hash.length) {
// trim '#'
return hash.substr(1);
}
return hash;
} }
set(hash) { replaceUrl(url) {
if (this._boundOnHashChange) { window.history.replaceState(null, null, url);
this._expectSetEcho = true; // replaceState does not cause hashchange
this.emit(url);
}
pushUrl(url) {
document.location.hash = this.urlAsPath(url);
}
urlAsPath(url) {
if (url.startsWith("#")) {
return url.substr(1);
} else {
return url;
} }
document.location.hash = hash; }
pathAsUrl(path) {
return `#${path}`;
} }
onSubscribeFirst() { onSubscribeFirst() {