mirror of
https://github.com/vector-im/element-web.git
synced 2024-11-16 05:04:57 +08:00
Fix page reloading on initial update (#21410)
Remove the hash event listener before reloading the page, as the reload was being swallowed by our router. Along the way, refactor out routing logic form app.tsx to avoid causing a circular import.
This commit is contained in:
parent
1f97bc2325
commit
adad5e16c2
@ -29,70 +29,18 @@ import SdkConfig, { parseSsoRedirectOptions } from "matrix-react-sdk/src/SdkConf
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { createClient } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import type MatrixChatType from "matrix-react-sdk/src/components/structures/MatrixChat";
|
||||
import { parseQs, parseQsFromFragment } from './url_utils';
|
||||
import { parseQs } from './url_utils';
|
||||
import VectorBasePlatform from "./platform/VectorBasePlatform";
|
||||
import { getScreenFromLocation, init as initRouting, onNewScreen } from "./routing";
|
||||
|
||||
// add React and ReactPerf to the global namespace, to make them easier to access via the console
|
||||
// this incidentally means we can forget our React imports in JSX files without penalty.
|
||||
window.React = React;
|
||||
|
||||
let lastLocationHashSet: string = null;
|
||||
|
||||
logger.log(`Application is running in ${process.env.NODE_ENV} mode`);
|
||||
|
||||
window.matrixLogger = logger;
|
||||
|
||||
// Parse the given window.location and return parameters that can be used when calling
|
||||
// MatrixChat.showScreen(screen, params)
|
||||
function getScreenFromLocation(location: Location) {
|
||||
const fragparts = parseQsFromFragment(location);
|
||||
return {
|
||||
screen: fragparts.location.substring(1),
|
||||
params: fragparts.params,
|
||||
};
|
||||
}
|
||||
|
||||
// Here, we do some crude URL analysis to allow
|
||||
// deep-linking.
|
||||
function routeUrl(location: Location) {
|
||||
if (!window.matrixChat) return;
|
||||
|
||||
logger.log("Routing URL ", location.href);
|
||||
const s = getScreenFromLocation(location);
|
||||
(window.matrixChat as MatrixChatType).showScreen(s.screen, s.params);
|
||||
}
|
||||
|
||||
function onHashChange(ev: HashChangeEvent) {
|
||||
if (decodeURIComponent(window.location.hash) === lastLocationHashSet) {
|
||||
// we just set this: no need to route it!
|
||||
return;
|
||||
}
|
||||
routeUrl(window.location);
|
||||
}
|
||||
|
||||
// This will be called whenever the SDK changes screens,
|
||||
// so a web page can update the URL bar appropriately.
|
||||
function onNewScreen(screen: string, replaceLast = false) {
|
||||
logger.log("newscreen " + screen);
|
||||
const hash = '#/' + screen;
|
||||
lastLocationHashSet = hash;
|
||||
|
||||
// if the new hash is a substring of the old one then we are stripping fields e.g `via` so replace history
|
||||
if (screen.startsWith("room/") &&
|
||||
window.location.hash.includes("/$") === hash.includes("/$") && // only if both did or didn't contain event link
|
||||
window.location.hash.startsWith(hash)
|
||||
) {
|
||||
replaceLast = true;
|
||||
}
|
||||
|
||||
if (replaceLast) {
|
||||
window.location.replace(hash);
|
||||
} else {
|
||||
window.location.assign(hash);
|
||||
}
|
||||
}
|
||||
|
||||
// We use this to work out what URL the SDK should
|
||||
// pass through when registering to allow the user to
|
||||
// click back to the client having registered.
|
||||
@ -141,8 +89,7 @@ function onTokenLoginCompleted() {
|
||||
}
|
||||
|
||||
export async function loadApp(fragParams: {}) {
|
||||
window.addEventListener('hashchange', onHashChange);
|
||||
|
||||
initRouting();
|
||||
const platform = PlatformPeg.get();
|
||||
|
||||
const params = parseQs(window.location);
|
||||
|
@ -28,6 +28,7 @@ import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import VectorBasePlatform from './VectorBasePlatform';
|
||||
import { parseQs } from "../url_utils";
|
||||
import { reloadPage } from "../routing";
|
||||
|
||||
const POKE_RATE_MS = 10 * 60 * 1000; // 10 min
|
||||
|
||||
@ -128,9 +129,11 @@ export default class WebPlatform extends VectorBasePlatform {
|
||||
//
|
||||
// Ideally, loading an old copy would be impossible with the
|
||||
// cache-control: nocache HTTP header set, but Firefox doesn't always obey it :/
|
||||
console.log("startUpdater, current version is " + this.getNormalizedAppVersion(process.env.VERSION));
|
||||
this.pollForUpdate((version: string, newVersion: string) => {
|
||||
const query = parseQs(location);
|
||||
if (query.updated === "1") {
|
||||
console.log("Update reloaded but still on an old version, stopping");
|
||||
// We just reloaded already and are still on the old version!
|
||||
// Show the toast rather than reload in a loop.
|
||||
showUpdateToast(version, newVersion);
|
||||
@ -146,8 +149,7 @@ export default class WebPlatform extends VectorBasePlatform {
|
||||
suffix = "&" + suffix;
|
||||
}
|
||||
|
||||
// This line has the effect of loading the page at the new location
|
||||
window.location.href = window.location.href + suffix;
|
||||
reloadPage(window.location.href + suffix);
|
||||
});
|
||||
setInterval(() => this.pollForUpdate(showUpdateToast, hideUpdateToast), POKE_RATE_MS);
|
||||
}
|
||||
@ -165,10 +167,14 @@ export default class WebPlatform extends VectorBasePlatform {
|
||||
|
||||
if (currentVersion !== mostRecentVersion) {
|
||||
if (this.shouldShowUpdate(mostRecentVersion)) {
|
||||
console.log("Update available to " + mostRecentVersion + ", will notify user");
|
||||
showUpdate(currentVersion, mostRecentVersion);
|
||||
} else {
|
||||
console.log("Update available to " + mostRecentVersion + " but won't be shown");
|
||||
}
|
||||
return { status: UpdateCheckStatus.Ready };
|
||||
} else {
|
||||
console.log("No update available, already on " + mostRecentVersion);
|
||||
showNoUpdate?.();
|
||||
}
|
||||
|
||||
|
83
src/vector/routing.ts
Normal file
83
src/vector/routing.ts
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
Copyright 2022 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.
|
||||
*/
|
||||
|
||||
// Parse the given window.location and return parameters that can be used when calling
|
||||
// MatrixChat.showScreen(screen, params)
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import MatrixChatType from "matrix-react-sdk/src/components/structures/MatrixChat";
|
||||
|
||||
import { parseQsFromFragment } from "./url_utils";
|
||||
|
||||
let lastLocationHashSet: string = null;
|
||||
|
||||
export function getScreenFromLocation(location: Location) {
|
||||
const fragparts = parseQsFromFragment(location);
|
||||
return {
|
||||
screen: fragparts.location.substring(1),
|
||||
params: fragparts.params,
|
||||
};
|
||||
}
|
||||
|
||||
// Here, we do some crude URL analysis to allow
|
||||
// deep-linking.
|
||||
function routeUrl(location: Location) {
|
||||
if (!window.matrixChat) return;
|
||||
|
||||
logger.log("Routing URL ", location.href);
|
||||
const s = getScreenFromLocation(location);
|
||||
(window.matrixChat as MatrixChatType).showScreen(s.screen, s.params);
|
||||
}
|
||||
|
||||
function onHashChange(ev: HashChangeEvent) {
|
||||
if (decodeURIComponent(window.location.hash) === lastLocationHashSet) {
|
||||
// we just set this: no need to route it!
|
||||
return;
|
||||
}
|
||||
routeUrl(window.location);
|
||||
}
|
||||
|
||||
// This will be called whenever the SDK changes screens,
|
||||
// so a web page can update the URL bar appropriately.
|
||||
export function onNewScreen(screen: string, replaceLast = false) {
|
||||
logger.log("newscreen " + screen);
|
||||
const hash = '#/' + screen;
|
||||
lastLocationHashSet = hash;
|
||||
|
||||
// if the new hash is a substring of the old one then we are stripping fields e.g `via` so replace history
|
||||
if (screen.startsWith("room/") &&
|
||||
window.location.hash.includes("/$") === hash.includes("/$") && // only if both did or didn't contain event link
|
||||
window.location.hash.startsWith(hash)
|
||||
) {
|
||||
replaceLast = true;
|
||||
}
|
||||
|
||||
if (replaceLast) {
|
||||
window.location.replace(hash);
|
||||
} else {
|
||||
window.location.assign(hash);
|
||||
}
|
||||
}
|
||||
|
||||
// reload the page to a different url
|
||||
export function reloadPage(newUrl: string) {
|
||||
console.log("reloadPage to " + newUrl);
|
||||
window.removeEventListener('hashchange', onHashChange);
|
||||
window.location.href = newUrl;
|
||||
}
|
||||
|
||||
export function init() {
|
||||
window.addEventListener('hashchange', onHashChange);
|
||||
}
|
Loading…
Reference in New Issue
Block a user