feat: implement openExternalUrl utility for consistent external link handling

This commit is contained in:
2026-01-24 07:59:45 +11:00
parent c0af925420
commit a6b76a9be7
5 changed files with 29 additions and 12 deletions

View File

@@ -1,3 +1,4 @@
import { openExternalUrl } from '../../utils/tauri';
import { Box, Button, color, config, Dialog, Header, Icon, IconButton, Icons, Text } from 'folds';
import React, { useCallback, useEffect, useState } from 'react';
import { StageComponentProps } from './types';
@@ -20,8 +21,8 @@ export function SSOStage({
}, [submitAuthDict, session]);
const handleContinue = () => {
const w = window.open(ssoRedirectURL, '_blank');
setSSOWindow(w ?? undefined);
openExternalUrl(ssoRedirectURL);
setSSOWindow(undefined);
};
useEffect(() => {

View File

@@ -1,4 +1,5 @@
import React, { MouseEventHandler, useCallback, useMemo, useState } from 'react';
import { openExternalUrl } from '../../utils/tauri';
import { useNavigate } from 'react-router-dom';
import FocusTrap from 'focus-trap-react';
import { isKeyHotkey } from 'is-hotkey';
@@ -110,7 +111,7 @@ export function ServerChip({ server }: { server: string }) {
size="300"
radii="300"
onClick={() => {
window.open(`https://${server}`, '_blank');
openExternalUrl(`https://${server}`);
close();
}}
>

View File

@@ -1,4 +1,5 @@
import React, { useCallback, useState } from 'react';
import { openExternalUrl } from '../../../utils/tauri';
import { Box, Button, config, Menu, Spinner, Text } from 'folds';
import { AuthDict, IMyDevice, MatrixError } from 'matrix-js-sdk';
import { SequenceCard } from '../../../components/sequence-card';
@@ -33,11 +34,10 @@ export function OtherDevices({ devices, refreshDeviceList, showVerification }: O
const authUrl = authMetadata?.account_management_uri ?? authMetadata?.issuer;
if (!authUrl) return;
window.open(
openExternalUrl(
withSearchParam(authUrl, {
action: accountManagementActions.sessionsList,
}),
'_blank'
})
);
}, [authMetadata, accountManagementActions]);
@@ -46,12 +46,11 @@ export function OtherDevices({ devices, refreshDeviceList, showVerification }: O
const authUrl = authMetadata?.account_management_uri ?? authMetadata?.issuer;
if (!authUrl) return;
window.open(
openExternalUrl(
withSearchParam(authUrl, {
action: accountManagementActions.sessionEnd,
device_id: deviceId,
}),
'_blank'
})
);
},
[authMetadata, accountManagementActions]

View File

@@ -35,6 +35,7 @@ import { stopPropagation } from '../../../utils/keyboard';
import { useAuthMetadata } from '../../../hooks/useAuthMetadata';
import { withSearchParam } from '../../../pages/pathUtils';
import { useAccountManagementActions } from '../../../hooks/useAccountManagement';
import { openExternalUrl } from '../../../utils/tauri';
type VerificationStatusBadgeProps = {
verificationStatus: VerificationStatus;
@@ -273,11 +274,10 @@ export function DeviceVerificationOptions() {
if (authMetadata) {
const authUrl = authMetadata.account_management_uri ?? authMetadata.issuer;
window.open(
openExternalUrl(
withSearchParam(authUrl, {
action: accountManagementActions.crossSigningReset,
}),
'_blank'
})
);
return;
}

View File

@@ -1,3 +1,19 @@
/**
* Open an external URL using Tauri shell on desktop/mobile, or window.open in browser
* @param url The URL to open
*/
export const openExternalUrl = async (url: string): Promise<void> => {
if (isTauri()) {
try {
const { open } = await import('@tauri-apps/plugin-shell');
await open(url);
return;
} catch (err) {
console.warn('Tauri shell.open failed, falling back to window.open:', err);
}
}
window.open(url, '_blank');
};
/**
* Tauri-specific utilities for desktop and mobile platforms
*/