- Mobile launches use the store-driven panel (no route push) so the background tab no longer changes and closing returns to where you launched from. - Tab-only apps open directly (in-app WebView on companion / new tab on PWA) — no "this app opens in a tab" interstitial. - Shared AppLoadingScreen (app icon + progress bar) on the app session and the legacy iframe overlay instead of a black screen. - Pin the dashboard to 100dvh on mobile so the mesh chat/tools panes stop sliding under the bottom tab bar in mobile browsers (no-op in the companion WebView). - ElectrumX/electrs/electrs-ui ids now resolve to the real ElectrumX icon in My Apps. - isMobile made reactive so overlay/footer/teleport decisions track the viewport. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
48 lines
1.7 KiB
TypeScript
48 lines
1.7 KiB
TypeScript
/**
|
|
* Open a URL in the device's real browser.
|
|
*
|
|
* In a normal mobile/desktop browser this is just `window.open(_blank)`. Inside
|
|
* the Android companion app the page runs in a WebView where `window.open` is
|
|
* unreliable (noopener/noreferrer can suppress onCreateWindow), so the native
|
|
* shell injects a `window.ArchipelagoNative.openExternal(url)` bridge that hands
|
|
* the URL to an ACTION_VIEW intent. We prefer the bridge when present and fall
|
|
* back to `window.open` otherwise — so the working mobile-browser path is
|
|
* untouched.
|
|
*/
|
|
interface ArchipelagoNativeBridge {
|
|
openExternal?: (url: string) => void
|
|
openInApp?: (url: string) => void
|
|
}
|
|
|
|
function nativeBridge(): ArchipelagoNativeBridge | undefined {
|
|
return (window as unknown as { ArchipelagoNative?: ArchipelagoNativeBridge }).ArchipelagoNative
|
|
}
|
|
|
|
export function openExternalUrl(url: string): void {
|
|
if (!url) return
|
|
const native = nativeBridge()
|
|
if (native && typeof native.openExternal === 'function') {
|
|
native.openExternal(url)
|
|
return
|
|
}
|
|
window.open(url, '_blank', 'noopener,noreferrer')
|
|
}
|
|
|
|
/**
|
|
* Launch an app that can't be embedded in an iframe (X-Frame-Options) from a
|
|
* mobile surface — with NO "this app opens in a tab" interstitial.
|
|
*
|
|
* - Android companion: hand it to the in-app WebView (`openInApp`) so it stays
|
|
* inside Archipelago with the native back/forward/reload/close controls.
|
|
* - Plain mobile browser (PWA): open directly in a new browser tab.
|
|
*/
|
|
export function openInAppOrNewTab(url: string): void {
|
|
if (!url) return
|
|
const native = nativeBridge()
|
|
if (native && typeof native.openInApp === 'function') {
|
|
native.openInApp(url)
|
|
return
|
|
}
|
|
window.open(url, '_blank', 'noopener,noreferrer')
|
|
}
|