2020-10-06 18:03:12 +02:00
|
|
|
/*
|
|
|
|
Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
export class URLRouter {
|
2020-10-12 17:49:06 +02:00
|
|
|
constructor({history, navigation, parseUrlPath, stringifyPath}) {
|
2020-10-08 18:22:36 +02:00
|
|
|
this._history = history;
|
2020-10-06 18:03:12 +02:00
|
|
|
this._navigation = navigation;
|
2020-10-12 17:49:06 +02:00
|
|
|
this._parseUrlPath = parseUrlPath;
|
|
|
|
this._stringifyPath = stringifyPath;
|
2020-10-16 12:46:14 +02:00
|
|
|
this._subscription = null;
|
|
|
|
this._pathSubscription = null;
|
2020-10-19 12:55:42 +02:00
|
|
|
this._isApplyingUrl = false;
|
2021-05-18 13:52:13 +02:00
|
|
|
this._defaultSessionId = this._getLastSessionId();
|
|
|
|
}
|
|
|
|
|
|
|
|
_getLastSessionId() {
|
2021-05-18 14:27:09 +02:00
|
|
|
const navPath = this._urlAsNavPath(this._history.getLastUrl() || "");
|
|
|
|
const sessionId = navPath.get("session")?.value;
|
|
|
|
if (typeof sessionId === "string") {
|
|
|
|
return sessionId;
|
|
|
|
}
|
|
|
|
return null;
|
2020-10-06 18:03:12 +02:00
|
|
|
}
|
|
|
|
|
2020-10-09 09:56:01 +02:00
|
|
|
attach() {
|
2020-10-19 12:55:42 +02:00
|
|
|
this._subscription = this._history.subscribe(url => this._applyUrl(url));
|
2021-05-18 13:52:31 +02:00
|
|
|
// subscribe to path before applying initial url
|
2021-05-18 14:27:09 +02:00
|
|
|
// so redirects in _applyNavPathToHistory are reflected in url bar
|
|
|
|
this._pathSubscription = this._navigation.pathObservable.subscribe(path => this._applyNavPathToHistory(path));
|
2021-05-18 13:52:31 +02:00
|
|
|
this._applyUrl(this._history.get());
|
2020-10-07 09:40:51 +02:00
|
|
|
}
|
|
|
|
|
2020-10-12 17:49:06 +02:00
|
|
|
dispose() {
|
2020-10-06 18:03:12 +02:00
|
|
|
this._subscription = this._subscription();
|
2020-10-16 12:46:14 +02:00
|
|
|
this._pathSubscription = this._pathSubscription();
|
2020-10-06 18:03:12 +02:00
|
|
|
}
|
|
|
|
|
2021-05-18 14:27:09 +02:00
|
|
|
_applyNavPathToHistory(path) {
|
2020-10-19 12:55:42 +02:00
|
|
|
const url = this.urlForPath(path);
|
|
|
|
if (url !== this._history.get()) {
|
|
|
|
if (this._isApplyingUrl) {
|
|
|
|
// redirect
|
|
|
|
this._history.replaceUrlSilently(url);
|
|
|
|
} else {
|
|
|
|
this._history.pushUrlSilently(url);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-18 14:27:09 +02:00
|
|
|
_applyNavPathToNavigation(navPath) {
|
|
|
|
// this will cause _applyNavPathToHistory to be called,
|
2020-10-19 12:55:42 +02:00
|
|
|
// so set a flag whether this request came from ourselves
|
|
|
|
// (in which case it is a redirect if the url does not match the current one)
|
|
|
|
this._isApplyingUrl = true;
|
2020-10-12 17:49:06 +02:00
|
|
|
this._navigation.applyPath(navPath);
|
2020-10-19 12:55:42 +02:00
|
|
|
this._isApplyingUrl = false;
|
2020-10-06 18:03:12 +02:00
|
|
|
}
|
|
|
|
|
2021-05-18 14:27:09 +02:00
|
|
|
_urlAsNavPath(url) {
|
|
|
|
const urlPath = this._history.urlAsPath(url);
|
|
|
|
return this._navigation.pathFrom(this._parseUrlPath(urlPath, this._navigation.path, this._defaultSessionId));
|
|
|
|
}
|
|
|
|
|
|
|
|
_applyUrl(url) {
|
|
|
|
const navPath = this._urlAsNavPath(url);
|
|
|
|
this._applyNavPathToNavigation(navPath);
|
|
|
|
}
|
|
|
|
|
2020-10-16 12:46:14 +02:00
|
|
|
pushUrl(url) {
|
|
|
|
this._history.pushUrl(url);
|
|
|
|
}
|
|
|
|
|
2021-05-18 14:27:09 +02:00
|
|
|
tryRestoreLastUrl() {
|
|
|
|
const lastNavPath = this._urlAsNavPath(this._history.getLastUrl() || "");
|
|
|
|
if (lastNavPath.segments.length !== 0) {
|
2021-05-20 11:11:07 +02:00
|
|
|
this._applyNavPathToNavigation(lastNavPath);
|
2021-05-18 14:27:09 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2020-10-08 18:22:36 +02:00
|
|
|
}
|
|
|
|
|
2020-10-12 17:49:06 +02:00
|
|
|
urlForSegments(segments) {
|
|
|
|
let path = this._navigation.path;
|
|
|
|
for (const segment of segments) {
|
|
|
|
path = path.with(segment);
|
|
|
|
if (!path) {
|
|
|
|
return;
|
|
|
|
}
|
2020-10-06 18:03:12 +02:00
|
|
|
}
|
2020-10-12 17:49:06 +02:00
|
|
|
return this.urlForPath(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
urlForSegment(type, value) {
|
|
|
|
return this.urlForSegments([this._navigation.segment(type, value)]);
|
2020-10-06 18:03:12 +02:00
|
|
|
}
|
|
|
|
|
2020-10-14 14:53:52 +02:00
|
|
|
urlUntilSegment(type) {
|
|
|
|
return this.urlForPath(this._navigation.path.until(type));
|
|
|
|
}
|
|
|
|
|
2020-10-06 18:03:12 +02:00
|
|
|
urlForPath(path) {
|
2020-10-16 12:46:14 +02:00
|
|
|
return this._history.pathAsUrl(this._stringifyPath(path));
|
2020-10-12 17:49:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
openRoomActionUrl(roomId) {
|
|
|
|
// not a segment to navigation knowns about, so append it manually
|
|
|
|
const urlPath = `${this._stringifyPath(this._navigation.path.until("session"))}/open-room/${roomId}`;
|
2020-10-08 18:22:36 +02:00
|
|
|
return this._history.pathAsUrl(urlPath);
|
2020-10-06 18:03:12 +02:00
|
|
|
}
|
|
|
|
}
|