import { URL } from 'url' ; import { app , BrowserWindow , WebContents } from "electron" ; import { InputEvent } from 'electron/main' ; import isDev from 'electron-is-dev' ; import { getPlatform } from "../get-platform" ; export function isOSX ( ) { return getPlatform ( ) === 'mac' ; } export function nativeTabsSupported ( ) { return isOSX ( ) ; } export const URBIT_PROTOCOL = 'web+urbitgraph' ; export function createUrbitUrl ( viewUrl , urbitUrl ) { const prefix = `${ viewUrl . protocol }//${ viewUrl . host }` ; return `${ prefix }/apps/grid/perma?ext=${ encodeURIComponent ( urbitUrl ) }` ; } export function showWindow ( window ) { window . setAlwaysOnTop ( true ) ; if ( window . isMaximized ( ) ) { window . maximize ( ) ; } else { window . showInactive ( ) ; } window . setAlwaysOnTop ( false ) ; window . focus ( ) ; app . focus ( { steal : true } ) ; } export function linkIsInternal ( currentUrl , newUrl , internalUrlRegex ? ) { if ( newUrl === 'about:blank' ) { return true ; } if ( internalUrlRegex ) { const regex = RegExp ( internalUrlRegex ) ; return regex . test ( newUrl ) ; } if ( newUrl . startsWith ( URBIT_PROTOCOL ) ) { return true ; } try { const currentDomain = new URL ( currentUrl ) . hostname . replace ( /^www\./ , '' ) ; const newDomain = new URL ( newUrl ) . hostname . replace ( /^www./ , '' ) ; const [ longerDomain , shorterDomain ] = currentDomain . length > newDomain . length ? [ currentDomain , newDomain ] : [ newDomain , currentDomain ] ; return longerDomain . endsWith ( shorterDomain ) ; } catch ( err ) { console . warn ( 'Failed to parse domains as determining if link is internal. From:' , currentUrl , 'To:' , newUrl , err ) ; return false ; } } export function onNewWindowHelper ( urlToGo , disposition , targetUrl , preventDefault , openExternal , createAboutBlankWindow , createNewWindow , blockExternal , onBlockedExternalUrl , mainWindow ) { if ( ! linkIsInternal ( targetUrl , urlToGo ) ) { preventDefault ( ) ; if ( blockExternal ) { onBlockedExternalUrl ( urlToGo ) ; } else { openExternal ( urlToGo ) ; } } else if ( urlToGo === 'about:blank' ) { const newWindow = createAboutBlankWindow ( ) ; preventDefault ( newWindow ) ; } else { onNavigation ( { preventDefault , urlTarget : urlToGo , currentUrl : targetUrl , createNewWindow , mainWindow } ) ; } } interface onNavigationParameters { preventDefault : ( ) => void ; currentUrl : string ; urlTarget : string ; createNewWindow ? : ( url : string ) => BrowserWindow ; mainWindow : BrowserWindow ; } export function onNavigation ( { urlTarget , currentUrl , preventDefault , createNewWindow , mainWindow } ) { const url = new URL ( currentUrl ) ; const targetUrl = new URL ( urlTarget ) ; const sameHost = targetUrl . hostname === url . hostname ; const sameApp = sameHost && targetUrl . pathname . startsWith ( url . pathname ) ; isDev && console . log ( 'navigating' , url . pathname , targetUrl . pathname ) ; const isProtocolLink = targetUrl . protocol . startsWith ( URBIT_PROTOCOL ) ; if ( ( ! sameHost || sameApp ) && ! isProtocolLink ) { return ; } if ( isProtocolLink ) { const view = mainWindow . getBrowserViews ( ) . find ( v => { const viewUrl = new URL ( v . webContents . getURL ( ) ) ; return url . host === viewUrl . host ; } ) ; const urbitUrl = createUrbitUrl ( url , urlTarget ) ; preventDefault ( ) ; if ( view ) { showWindow ( mainWindow ) ; return view . webContents . loadURL ( urbitUrl ) ; } else { return createNewWindow ( urbitUrl ) ; } } const targetWindow = BrowserWindow . getAllWindows ( ) . find ( b => { const path = b . webContents . getURL ( ) . replace ( `${ targetUrl . protocol }//${ targetUrl . hostname }` , '' ) ; return path . startsWith ( targetUrl . pathname ) ; } ) ; if ( ! sameApp && targetWindow ) { preventDefault ( ) ; targetWindow . focus ( ) ; if ( targetUrl . searchParams . has ( 'grid-note' ) || targetUrl . searchParams . has ( 'grid-link' ) ) { targetWindow . webContents . loadURL ( targetUrl . toString ( ) ) ; } return ; } if ( createNewWindow ) { preventDefault ( ) ; createNewWindow ( urlTarget ) ; } } export function leap ( mainWindow ) { const focusedWindow = BrowserWindow . getFocusedWindow ( ) ; const mainView = mainWindow . getBrowserViews ( ) [ 0 ] ; if ( ( ! mainView && ! focusedWindow ) || ( focusedWindow === mainWindow && ! mainView ) ) { return ; } const isLandscape = focusedWindow ?. webContents . getURL ( ) . includes ( '/apps/landscape' ) ; const contents = isLandscape ? focusedWindow . webContents : mainView . webContents ; showWindow ( isLandscape ? focusedWindow : mainWindow ) ; setTimeout ( ( ) => { contents . focus ( ) ; setTimeout ( ( ) => { sendKeybinding ( contents , '/' , [ 'ctrl' ] ) ; } , 15 ) ; } , 15 ) ; } function sendKeybinding ( contents , keyCode , modifiers ? ) { contents . sendInputEvent ( { type : 'keyDown' , modifiers , keyCode } ) ; contents . sendInputEvent ( { type : 'char' , modifiers , keyCode } ) ; contents . sendInputEvent ( { type : 'keyUp' , modifiers , keyCode } ) ; }