40 lines
1.5 KiB
TypeScript
40 lines
1.5 KiB
TypeScript
import { Capacitor } from '@capacitor/core';
|
|
import { Browser } from '@capacitor/browser';
|
|
|
|
export const isNativePlatform = (): boolean => Capacitor.isNativePlatform();
|
|
|
|
export const isAndroidPlatform = (): boolean => Capacitor.getPlatform() === 'android';
|
|
|
|
export const openExternalUrl = async (url: string): Promise<void> => {
|
|
if (isNativePlatform()) {
|
|
await Browser.open({ url });
|
|
} else {
|
|
window.open(url, '_blank', 'noopener');
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Intercepts clicks on <a target="_blank"> links in Capacitor
|
|
* and opens them via the Browser plugin instead of inside the WebView.
|
|
* Call once at app startup.
|
|
*/
|
|
export const setupExternalLinkHandler = (): (() => void) | undefined => {
|
|
if (!isNativePlatform()) return undefined;
|
|
|
|
const handler = (e: MouseEvent) => {
|
|
const anchor = (e.target as HTMLElement).closest?.('a[target="_blank"]') as HTMLAnchorElement | null;
|
|
if (!anchor?.href) return;
|
|
// Mention pills are rendered as matrix.to links with data-mention-id; they
|
|
// have their own React onClick that opens an in-app profile card. Letting
|
|
// this capture-phase handler preventDefault + Browser.open() would race
|
|
// React's synthetic click and jerk the user to matrix.to in the system
|
|
// browser on native.
|
|
if (anchor.dataset.mentionId) return;
|
|
|
|
e.preventDefault();
|
|
Browser.open({ url: anchor.href });
|
|
};
|
|
|
|
document.addEventListener('click', handler, true);
|
|
return () => document.removeEventListener('click', handler, true);
|
|
};
|