Add preference for custom web instances, use it for Element

This commit is contained in:
Mira Nord
2025-03-16 20:54:38 +01:00
parent 22ad0e9289
commit 50a25dd04c
3 changed files with 40 additions and 14 deletions
+17
View File
@@ -25,6 +25,7 @@ export class Preferences extends EventEmitter {
// used to differentiate web from native if a client supports both // used to differentiate web from native if a client supports both
this.platform = null; this.platform = null;
this.homeservers = null; this.homeservers = null;
this.preferredWebInstances = {};
const prefsStr = localStorage.getItem("preferred_client"); const prefsStr = localStorage.getItem("preferred_client");
if (prefsStr) { if (prefsStr) {
@@ -36,6 +37,10 @@ export class Preferences extends EventEmitter {
if (serversStr) { if (serversStr) {
this.homeservers = JSON.parse(serversStr); this.homeservers = JSON.parse(serversStr);
} }
const preferredWebInstancesStr = localStorage.getItem("preferred_web_instances");
if (preferredWebInstancesStr) {
this.preferredWebInstances = JSON.parse(preferredWebInstancesStr);
}
} }
setClient(id, platform) { setClient(id, platform) {
@@ -54,12 +59,24 @@ export class Preferences extends EventEmitter {
} }
} }
setPreferredWebInstance(client_id, instance_url) {
this.preferredWebInstances[client_id] = instance_url;
this._localStorage.setItem("preferred_web_instances", JSON.stringify(this.preferredWebInstances));
this.emit("canClear");
}
getPreferredWebInstance(client_id) {
return this.preferredWebInstances[client_id];
}
clear() { clear() {
this._localStorage.removeItem("preferred_client"); this._localStorage.removeItem("preferred_client");
this._localStorage.removeItem("consented_servers"); this._localStorage.removeItem("consented_servers");
this._localStorage.removeItem("preferred_web_instances");
this.clientId = null; this.clientId = null;
this.platform = null; this.platform = null;
this.homeservers = null; this.homeservers = null;
this.preferredWebInstances = {};
} }
get canClear() { get canClear() {
+19 -11
View File
@@ -59,11 +59,11 @@ export class ClientViewModel extends ViewModel {
if (this._proposedPlatform === this._nativePlatform) { if (this._proposedPlatform === this._nativePlatform) {
deepLinkLabel = "Open in app"; deepLinkLabel = "Open in app";
} else { } else {
deepLinkLabel = `Open on ${this._client.getPreferredWebInstance(this._link)}`; deepLinkLabel = `Open on ${this.preferredWebInstance}`;
} }
} }
const actions = []; const actions = [];
const proposedDeepLink = this._client.getDeepLink(this._proposedPlatform, this._link); const proposedDeepLink = this._client.getDeepLink(this._proposedPlatform, this._link, this.preferredWebInstance);
if (proposedDeepLink) { if (proposedDeepLink) {
actions.push({ actions.push({
label: deepLinkLabel, label: deepLinkLabel,
@@ -83,8 +83,8 @@ export class ClientViewModel extends ViewModel {
// show only if there is a preferred instance, and if we don't already link to it in the first button // show only if there is a preferred instance, and if we don't already link to it in the first button
if (hasPreferredWebInstance && this._webPlatform && this._proposedPlatform !== this._webPlatform) { if (hasPreferredWebInstance && this._webPlatform && this._proposedPlatform !== this._webPlatform) {
actions.push({ actions.push({
label: `Open on ${this._client.getPreferredWebInstance(this._link)}`, label: `Open on ${this.preferredWebInstance}`,
url: this._client.getDeepLink(this._webPlatform, this._link), url: this._client.getDeepLink(this._webPlatform, this._link, this.preferredWebInstance),
kind: "open-in-web", kind: "open-in-web",
activated: () => {} // don't persist this choice as we don't persist the preferred web instance, it's in the url activated: () => {} // don't persist this choice as we don't persist the preferred web instance, it's in the url
}); });
@@ -108,10 +108,10 @@ export class ClientViewModel extends ViewModel {
actions.push(...nativeActions); actions.push(...nativeActions);
} }
if (this._webPlatform) { if (this._webPlatform) {
const webDeepLink = this._client.getDeepLink(this._webPlatform, this._link); const webDeepLink = this._client.getDeepLink(this._webPlatform, this._link, this.preferredWebInstance);
if (webDeepLink) { if (webDeepLink) {
const webLabel = this.hasPreferredWebInstance ? const webLabel = this.hasPreferredWebInstance ?
`Open on ${this._client.getPreferredWebInstance(this._link)}` : `Open on ${this.preferredWebInstance}` :
`Continue in your browser`; `Continue in your browser`;
actions.push({ actions.push({
label: webLabel, label: webLabel,
@@ -128,14 +128,22 @@ export class ClientViewModel extends ViewModel {
return actions; return actions;
} }
get hasPreferredWebInstance() { get preferredWebInstance() {
// also check there is a web platform that matches the platforms the user is on (mobile or desktop web) // also check there is a web platform that matches the platforms the user is on (mobile or desktop web)
return this._webPlatform && typeof this._client.getPreferredWebInstance(this._link) === "string"; if (!this._webPlatform) return undefined;
return (
this.preferences.getPreferredWebInstance(this._client.id)
|| this._client.getPreferredWebInstance(this._link)
);
}
get hasPreferredWebInstance() {
return typeof this.preferredWebInstance === "string";
} }
get hostedByBannerLabel() { get hostedByBannerLabel() {
const preferredWebInstance = this._client.getPreferredWebInstance(this._link); if (this.hasPreferredWebInstance) {
if (this._webPlatform && preferredWebInstance) { const preferredWebInstance = this.preferredWebInstance;
let label = preferredWebInstance; let label = preferredWebInstance;
const subDomainIdx = preferredWebInstance.lastIndexOf(".", preferredWebInstance.lastIndexOf(".") - 1); const subDomainIdx = preferredWebInstance.lastIndexOf(".", preferredWebInstance.lastIndexOf(".") - 1);
if (subDomainIdx !== -1) { if (subDomainIdx !== -1) {
@@ -188,7 +196,7 @@ export class ClientViewModel extends ViewModel {
get showDeepLinkInInstall() { get showDeepLinkInInstall() {
// we can assume this._nativePlatform as this._clientCanIntercept already checks it // we can assume this._nativePlatform as this._clientCanIntercept already checks it
return this._clientCanIntercept && !!this._client.getDeepLink(this._nativePlatform, this._link); return this._clientCanIntercept && !!this._client.getDeepLink(this._nativePlatform, this._link, this.preferredWebInstance);
} }
get availableOnPlatformNames() { get availableOnPlatformNames() {
+4 -3
View File
@@ -55,8 +55,9 @@ export class Element {
get homepage() { return "https://element.io"; } get homepage() { return "https://element.io"; }
get author() { return "Element"; } get author() { return "Element"; }
getMaturity(platform) { return Maturity.Stable; } getMaturity(platform) { return Maturity.Stable; }
get supportsCustomInstances() { return true; }
getDeepLink(platform, link) { getDeepLink(platform, link, preferredWebInstance) {
let fragmentPath; let fragmentPath;
switch (link.kind) { switch (link.kind) {
case LinkKind.User: case LinkKind.User:
@@ -82,8 +83,8 @@ export class Element {
let instanceHost = trustedWebInstances[0]; let instanceHost = trustedWebInstances[0];
// we use app.element.io which iOS will intercept, but it likely won't intercept any other trusted instances // we use app.element.io which iOS will intercept, but it likely won't intercept any other trusted instances
// so only use a preferred web instance for true web links. // so only use a preferred web instance for true web links.
if (isWebPlatform && trustedWebInstances.includes(link.webInstances[this.id])) { if (isWebPlatform && preferredWebInstance) {
instanceHost = link.webInstances[this.id]; instanceHost = preferredWebInstance;
} }
return `https://${instanceHost}/#/${fragmentPath}`; return `https://${instanceHost}/#/${fragmentPath}`;
} else if (platform === Platform.Linux || platform === Platform.Windows || platform === Platform.macOS) { } else if (platform === Platform.Linux || platform === Platform.Windows || platform === Platform.macOS) {