mirror of
https://github.com/element-hq/element-web.git
synced 2025-12-07 01:21:02 +00:00
Compare commits
1 Commits
hs/track-k
...
hs/url-han
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa90f14e66 |
@@ -524,4 +524,10 @@ export default abstract class BasePlatform {
|
||||
* @returns {Promise<boolean>} True if the lock was acquired, false otherwise.
|
||||
*/
|
||||
public abstract getSessionLock(_onNewInstance: () => Promise<void>): Promise<boolean>;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param urlPattern
|
||||
*/
|
||||
public registerProtocolHandler?(urlPattern: `${string}%s`): Promise<void>
|
||||
}
|
||||
|
||||
@@ -43,6 +43,10 @@ enum Views {
|
||||
|
||||
// Another instance of the application has started up. We just show an error page.
|
||||
LOCK_STOLEN,
|
||||
|
||||
// Another instance of the application has opened and this session had a matrixuri, so we
|
||||
// just show a warning and close.
|
||||
SENT_URI,
|
||||
}
|
||||
|
||||
export default Views;
|
||||
|
||||
@@ -140,6 +140,7 @@ import { ShareFormat, type SharePayload } from "../../dispatcher/payloads/ShareP
|
||||
import Markdown from "../../Markdown";
|
||||
import { sanitizeHtmlParams } from "../../Linkify";
|
||||
import { isOnlyAdmin } from "../../utils/membership";
|
||||
import mxModuleApi from "../../modules/Api";
|
||||
|
||||
// legacy export
|
||||
export { default as Views } from "../../Views";
|
||||
@@ -234,6 +235,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||
private fontWatcher?: FontWatcher;
|
||||
private readonly stores: SdkContextClass;
|
||||
private loadSessionAbortController = new AbortController();
|
||||
private newUriBroadcastChannel = new BroadcastChannel("io.element.broadcast.new_uri");
|
||||
|
||||
private sessionLoadStarted = false;
|
||||
|
||||
@@ -283,6 +285,12 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||
// object field used for tracking the status info appended to the title tag.
|
||||
// we don't do it as react state as i'm scared about triggering needless react refreshes.
|
||||
this.subTitleStatus = "";
|
||||
|
||||
this.newUriBroadcastChannel.addEventListener("message", (ev) => {
|
||||
const { screen, params } = ev.data;
|
||||
console.log(ev, ev.data);
|
||||
this.showScreen(screen, params);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -470,6 +478,7 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||
|
||||
initSentry(SdkConfig.get("sentry"));
|
||||
window.addEventListener("resize", this.onWindowResized);
|
||||
console.log("MatrixCHAT IS LOADING")
|
||||
|
||||
// Once we start loading the MatrixClient, we can't stop, even if MatrixChat gets unmounted (as it does
|
||||
// in React's Strict Mode). So, start loading the session now, but only if this MatrixChat was not previously
|
||||
@@ -478,8 +487,18 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||
this.sessionLoadStarted = true;
|
||||
const platform = PlatformPeg.get();
|
||||
if (platform && !platform.checkSessionLockFree()) {
|
||||
// another instance holds the lock; confirm its theft before proceeding
|
||||
setTimeout(() => this.setState({ view: Views.CONFIRM_LOCK_THEFT }), 0);
|
||||
console.log("screenAfterLogin", this.screenAfterLogin);
|
||||
if (this.screenAfterLogin?.screen.startsWith("matrix")) {
|
||||
console.log("Got URI req");
|
||||
// The user has clicked on a matrixuri link, so we need to forward it to them.
|
||||
this.newUriBroadcastChannel.postMessage({screen: this.screenAfterLogin.screen, params: this.screenAfterLogin.params});
|
||||
// This will put the application in a final state so the other instance can handle the URI.
|
||||
setTimeout(() => this.setState({ view: Views.SENT_URI }), 0);
|
||||
} else {
|
||||
// another instance holds the lock; confirm its theft before proceeding
|
||||
setTimeout(() => this.setState({ view: Views.CONFIRM_LOCK_THEFT }), 0);
|
||||
|
||||
}
|
||||
} else {
|
||||
this.startInitSession();
|
||||
}
|
||||
@@ -1752,6 +1771,10 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||
}
|
||||
|
||||
public showScreen(screen: string, params?: { [key: string]: any }): void {
|
||||
if (this.state.view === Views.SENT_URI) {
|
||||
// Ignore any screens once we've reached this state.
|
||||
return;
|
||||
}
|
||||
const cli = MatrixClientPeg.get();
|
||||
const isLoggedOutOrGuest = !cli || cli.isGuest();
|
||||
if (!isLoggedOutOrGuest && AUTH_SCREENS.includes(screen)) {
|
||||
@@ -1817,6 +1840,11 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||
}
|
||||
} else if (screen === "settings") {
|
||||
dis.fire(Action.ViewUserSettings);
|
||||
} else if (screen.startsWith("matrix")) {
|
||||
console.log("matrix:", screen, params);
|
||||
mxModuleApi.navigation.toMatrixToLink(screen, false).catch((ex) => {
|
||||
console.log('Failed to handle matrix uri', ex);
|
||||
})
|
||||
} else if (screen === "welcome") {
|
||||
dis.dispatch({
|
||||
action: "view_welcome_page",
|
||||
@@ -2098,6 +2126,10 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
|
||||
}}
|
||||
/>
|
||||
);
|
||||
} else if (this.state.view === Views.SENT_URI) {
|
||||
view = (
|
||||
<b>PLACEHOLDER: The URI has been broadcast to the other app.</b>
|
||||
);
|
||||
} else if (this.state.view === Views.COMPLETE_SECURITY) {
|
||||
view = <CompleteSecurity onFinished={this.onCompleteSecurityE2eSetupFinished} />;
|
||||
} else if (this.state.view === Views.E2E_SETUP) {
|
||||
|
||||
@@ -363,6 +363,8 @@ export default class PreferencesUserSettingsTab extends React.Component<IProps,
|
||||
<SettingsSubsection heading={_t("common|general")} stretchContent>
|
||||
{this.renderGroup(PreferencesUserSettingsTab.GENERAL_SETTINGS)}
|
||||
|
||||
<SettingsFlag name="protocolHandlerRegistered" level={SettingLevel.DEVICE} />
|
||||
|
||||
<SettingsFlag name="Electron.showTrayIcon" level={SettingLevel.PLATFORM} hideIfCannotSet />
|
||||
<SettingsFlag
|
||||
name="Electron.enableHardwareAcceleration"
|
||||
|
||||
@@ -50,6 +50,7 @@ import { SortingAlgorithm } from "../stores/room-list-v3/skip-list/sorters/index
|
||||
import MediaPreviewConfigController from "./controllers/MediaPreviewConfigController.ts";
|
||||
import InviteRulesConfigController from "./controllers/InviteRulesConfigController.ts";
|
||||
import { type ComputedInviteConfig } from "../@types/invite-rules.ts";
|
||||
import ProtocolHandlerController from "./controllers/ProtocolHandlerController.ts";
|
||||
|
||||
export const defaultWatchManager = new WatchManager();
|
||||
|
||||
@@ -370,6 +371,7 @@ export interface Settings {
|
||||
"mediaPreviewConfig": IBaseSetting<MediaPreviewConfig>;
|
||||
"inviteRules": IBaseSetting<ComputedInviteConfig>;
|
||||
"Developer.elementCallUrl": IBaseSetting<string>;
|
||||
protocolHandlerRegistered: IBaseSetting<boolean>;
|
||||
}
|
||||
|
||||
export type SettingKey = keyof Settings;
|
||||
@@ -1345,6 +1347,11 @@ export const SETTINGS: Settings = {
|
||||
// Contains room IDs
|
||||
shouldExportToRageshake: false,
|
||||
},
|
||||
"protocolHandlerRegistered": {
|
||||
default: false,
|
||||
controller: new ProtocolHandlerController(),
|
||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG,
|
||||
},
|
||||
/**
|
||||
* Enable or disable the release announcement feature
|
||||
*/
|
||||
|
||||
26
src/settings/controllers/ProtocolHandlerController.ts
Normal file
26
src/settings/controllers/ProtocolHandlerController.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import SettingController from "./SettingController";
|
||||
import PlatformPeg from "../../PlatformPeg";
|
||||
|
||||
export default class ProtocolHandlerController extends SettingController {
|
||||
public constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
public get settingDisabled() {
|
||||
return PlatformPeg.get()?.registerProtocolHandler === undefined;
|
||||
}
|
||||
|
||||
public onChange(): void {
|
||||
const platform = PlatformPeg.get()!;
|
||||
const uri = platform.baseUrl;
|
||||
platform.registerProtocolHandler!(`${uri}#/%s`);
|
||||
}
|
||||
}
|
||||
@@ -277,4 +277,8 @@ export default class WebPlatform extends BasePlatform {
|
||||
public async getSessionLock(onNewInstance: () => Promise<void>): Promise<boolean> {
|
||||
return SessionLock.getSessionLock(onNewInstance);
|
||||
}
|
||||
|
||||
public async registerProtocolHandler(urlPattern: `${string}%s`) {
|
||||
navigator.registerProtocolHandler("matrix", urlPattern);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user