import axios from 'axios' ; import { app , autoUpdater , BrowserView , BrowserWindow , dialog , ipcMain , IpcMainInvokeEvent , nativeTheme } from 'electron' ; import isDev from 'electron-is-dev' ; import { ViewData } from '../background/services/os-service' ; import { initContextMenu } from './context-menu' ; import { onNavigation } from './helpers' ; import { updateZoomLevels } from './main-window' ; declare const LANDSCAPE_PRELOAD_WEBPACK_ENTRY ; declare const PROMPT_WEBPACK_ENTRY ; export const views = new Map < string , BrowserView > ( ) ; const viewQueue = [ ] ; async function openDialog ( event , options ) { return await dialog . showOpenDialog ( options ) ; } function setTitle ( window , event , title ) { window . setTitle ( title ) ; return title ; } async function clearData ( window ) { const session = window . webContents . session ; await session . clearCache ( ) ; await session . clearStorageData ( { storages : [ 'appcache' , 'filesystem' , 'indexdb' , 'localstorage' , 'cachestorage' ] } ) ; } export async function toggleDevTools ( mainWindow , bgWindow ? ) { mainWindow . webContents . toggleDevTools ( ) ; const views = mainWindow . getBrowserViews ( ) ; if ( views ) { views . forEach ( view => view . webContents . openDevTools ( ) ) ; } if ( bgWindow ) { if ( bgWindow . isVisible ( ) ) { bgWindow . hide ( ) ; } else { bgWindow . show ( ) ; } bgWindow . webContents . toggleDevTools ( ) ; } } async function createView ( mainWindow , createNewWindow , onNewWindow , data ) { const { url , ship , code } = data ; let view = views . get ( url ) ; const newView = ! view ; if ( newView ) { console . log ( Date . now ( ) , 'creating view' , url ) ; view = new BrowserView ( { webPreferences : { partition : `persist:${ ship }` , devTools : true , preload : LANDSCAPE_PRELOAD_WEBPACK_ENTRY } } ) ; initContextMenu ( createNewWindow , undefined , mainWindow . webContents . getURL ( ) , view ) ; const session = view . webContents . session ; const cookies = await session . cookies . get ( { name : `urbauth-${ ship }` } ) ; isDev && console . log ( 'auth cookies' , cookies ) ; if ( code && cookies . length === 0 ) { isDev && console . log ( Date . now ( ) , 'logging in' ) ; const response = await axios . post ( `${ url }/~/login` , `password=${ code . trim ( ) }` , { withCredentials : true } ) ; const cookie = response . headers [ 'set-cookie' ] ; const parts = new RegExp ( /(urbauth-~[\w-]+)=(.*); Path=\/;/ ) . exec ( cookie || '' ) ; isDev && console . log ( cookie ) ; isDev && console . log ( parts ) ; if ( cookie ) { session . cookies . set ( { url , name : parts [ 1 ] , value : parts [ 2 ] } ) ; } isDev && console . log ( Date . now ( ) , 'logged in' ) ; } try { isDev && console . log ( Date . now ( ) , 'loading URL' ) ; isDev && view . webContents . toggleDevTools ( ) ; await view . webContents . loadURL ( url ) ; } catch ( err ) { isDev && console . log ( err ) ; return { error : err . message } ; } view . webContents . on ( 'will-navigate' , ( event , urlTarget ) => { onNavigation ( { preventDefault : event . preventDefault , currentUrl : view . webContents . getURL ( ) , urlTarget , createNewWindow , mainWindow } ) ; } ) ; view . webContents . on ( 'new-window' , onNewWindow ( url ) ) ; views . set ( url , view ) ; viewQueue . push ( url ) ; } const browserViews = mainWindow . getBrowserViews ( ) ; if ( browserViews . length > 0 ) { browserViews . forEach ( browserView => { mainWindow . removeBrowserView ( browserView ) ; } ) ; } mainWindow . addBrowserView ( view ) ; mainWindow . webContents . zoomFactor = mainWindow . webContents . zoomFactor + 0 ; view . webContents . zoomFactor = mainWindow . webContents . zoomFactor ; const mainBounds = mainWindow . getBounds ( ) ; mainWindow . setBounds ( { ... mainBounds , width : mainBounds . width + 1 , height : mainBounds . height + 1 } ) ; mainWindow . setBounds ( mainBounds ) ; setTimeout ( ( ) => { setViewBounds ( view , mainWindow , data ) ; updateZoomLevels ( mainWindow ) ; } , 10 ) ; isDev && console . log ( Date . now ( ) , 'view created' ) ; return { success : true } ; } function setViewBounds ( view , mainWindow , { bounds } ) { const { x , y , width , height } = bounds ; const mainZoom = mainWindow . webContents . zoomFactor ; const zoom = mainZoom ; isDev && console . log ( { zoom , bounds } ) ; view . setBounds ( { x : Math . round ( x * zoom ) , y : Math . round ( y * zoom ) , width : Math . round ( width * zoom ) , height : Math . round ( height * zoom ) } ) ; } async function updateViewBounds ( data , mainWindow ) { const view = views . get ( data . url ) ; if ( view ) { setViewBounds ( view , mainWindow , data ) ; updateZoomLevels ( mainWindow ) ; } } async function removeView ( mainWindow , url ) { const view = views . get ( url ) ; if ( view ) { isDev && console . log ( 'removing' , url ) ; mainWindow . removeBrowserView ( view ) ; if ( viewQueue . length >= 5 ) { const oldUrl = viewQueue . shift ( ) ; const oldView = views . get ( oldUrl ) ; ( oldView . webContents as any ) . destroy ( ) ; views . delete ( oldUrl ) ; } } } function installUpdates ( bgWindow ) { if ( ! isDev ) { bgWindow . close ( ) ; autoUpdater . quitAndInstall ( ) ; } else { console . log ( 'quitting' ) ; bgWindow . close ( ) ; app . quit ( ) ; } } function prompt ( event , args ) { promptResponse = null ; let promptWindow = new BrowserWindow ( { width : 400 , height : 144 , show : false , resizable : false , movable : false , alwaysOnTop : true , frame : false , backgroundColor : nativeTheme . shouldUseDarkColors ? '#000000' : '#FFFFFF' , webPreferences : { devTools : true , nodeIntegration : true } } ) ; promptWindow . loadURL ( PROMPT_WEBPACK_ENTRY ) ; promptWindow . moveTop ( ) ; promptWindow . show ( ) ; promptWindow . focus ( ) ; promptWindow . on ( 'closed' , function ( ) { event . returnValue = promptResponse ; promptWindow = null ; } ) ; ipcMain . once ( 'prompt-initialize' , ( event ) => { event . returnValue = args ; } ) ; } function respondToPrompt ( event , arg ) { if ( arg === '' ) { arg = null ; } promptResponse = arg ; } let promptResponse ; export function start ( mainWindow , createNewWindow , onNewWindow , bgWindow ? ) { ipcMain . handle ( 'quit' , ( ) => app . quit ( ) ) ; ipcMain . handle ( 'open-dialog' , openDialog ) ; ipcMain . handle ( 'set-title' , ( event , args ) => setTitle ( mainWindow , event , args ) ) ; ipcMain . handle ( 'clear-data' , ( ) => clearData ( mainWindow ) ) ; ipcMain . handle ( 'toggle-dev-tools' , ( ) => toggleDevTools ( mainWindow , bgWindow ) ) ; ipcMain . handle ( 'create-view' , ( event , args ) => createView ( mainWindow , createNewWindow , onNewWindow , args ) ) ; ipcMain . handle ( 'update-view-bounds' , ( event , args ) => updateViewBounds ( args , mainWindow ) ) ; ipcMain . handle ( 'remove-view' , ( event , args ) => removeView ( mainWindow , args ) ) ; ipcMain . handle ( 'install-updates' , ( ) => installUpdates ( bgWindow ) ) ; ipcMain . on ( 'prompt' , prompt ) ; ipcMain . on ( 'prompt-response' , respondToPrompt ) ; }