Tumortisch-Dist/resources/app/app/main.js

397 lines
11 KiB
JavaScript

/* globals require, __dirname, process */
/*eslint no-console: ["error", { allow: ["log"] }]*/
const { app, BrowserWindow, BrowserView, ipcMain, dialog, shell } = require('electron')
const electronLocalshortcut = require('electron-localshortcut')
//const electron = require('electron')
const os = require('os')
const fs = require('fs')
const path = require('path')
const { URL } = require('url')
const Store = require('./store.js')
const { prettyPrint } = require('html')
// Use this constant to start the application in kiosk-mode or in development mode
const DEVELOPMENT = true
// true: Dev-Tools are open
// false (KIOSK-Mode): No application switcher, no menu, no taskbar (or dock on a mac), shortcuts are working
global.multiUserMode = false
global.errorCount = 0
global.stopTestsOnError = false
global.jsonData = { value: null }
// UO: Experimental feature using Native Windows
global.useBrowserView = false
global.useMinimalPad = true
global.menu = null
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win
let browsers = new Map() // url: BrowserWindow
const store = new Store({
// We'll call our data file 'user-preferences'
configName: 'user-preferences',
defaults: {
url: `file://${__dirname}/test.html`,
devTools: DEVELOPMENT,
multiUserBrowser: true
}
})
function createWindow() {
console.log("createWindow")
const {session} = require('electron')
session.defaultSession.on('will-download', (event, item, webContents) => {
// event.preventDefault()
})
let { screen } = require('electron')
let displays = screen.getAllDisplays()
let externalDisplay = null
let bounds = store.get('storedBounds')
? store.get('storedBounds')
: screen.getPrimaryDisplay().bounds
// externalDisplay = displays[displays.length-1]
// const {width, height} =displays[displays.length-1].workAreaSize
// externalDisplay = displays[0]
// const {width, height} =displays[0].workAreaSize
win = new BrowserWindow({
x: bounds.x,
y: bounds.y,
width: bounds.width,
height: bounds.height,
fullscreenable: true,
fullscreen: !DEVELOPMENT,
title: 'IWM Browser',
show: false,
kiosk: !DEVELOPMENT,
acceptFirstMouse: true,
webPreferences: {
webSecurity: false,
allowRunningInsecureContent: true,
nodeIntegration: true,
webviewTag: true,
nativeWindowOpen: true,
devTools: true,
preload: path.join(__dirname, './preload.js')
},
icon: path.join(__dirname, 'assets/icons/png/64x64.png')
})
module.exports.win = win
let url = store.get('url')
if (process.argv.length > 2) {
let path = process.argv[2]
url = `file://${__dirname}/../${path}`
console.log('Using process.argv[2]', url)
}
let indpath = "index.html"
url = url = `file://${__dirname}/${indpath}`
console.log('Using', url)
win.maximize()
// BAD: All other methods don't work (like ensureFileSync, fileExists...)
/*try {
let settings = require('./settings.json')
console.log('Using settings', `file://${__dirname}/${settings.url}`)
win.loadURL(`file://${__dirname}/${settings.url}`)
} catch (ex) {
console.log('FAILED', url)
win.loadURL(url)
}*/
win.loadURL(url)
const { webContents } = win
//
// if (process.platform === 'win32' && win.isKiosk()) {
// webContents.on('did-finish-load', function() {
// webContents.executeJavaScript('document.body.style.cursor = "none";')
// })
// }
// Add the app menu
let menu = require('./menu.js')
global.menu = menu
// Add global shortcuts
// Esc quits the app
electronLocalshortcut.register('Esc', () => {
app.quit()
})
electronLocalshortcut.register('CommandOrControl+Shift+F', () => {
win.webContents.send('globalSearch')
})
// Command (Mac) or Control (Win) + K toggles the Kiosk mode
electronLocalshortcut.register('CommandOrControl+K', () => {
if (win) {
win.setKiosk(!win.isKiosk())
}
})
// Show if its ready.
win.once('ready-to-show', () => {
webContents.send('preparePads')
win.show()
})
// Clear cache
webContents.session.clearCache(() => console.log('Cache cleared'))
// Open dev tools when in development mode
if (store.get('devTools')) {
webContents.openDevTools({ mode: 'right' })
} else {
webContents.closeDevTools()
}
webContents.on('devtools-opened', () => {
store.set('devTools', true)
})
webContents.on('devtools-closed', () => {
store.set('devTools', false)
})
webContents.on('did-navigate', (event, url) => {
menu.setHistoryStatus()
})
/* UO: At this point we have no access to the event or link position*/
webContents.on('new-window', (event, url, frameName, disposition, options, additionalFeatures) => {
console.log('new-window', global.multiUserMode)
if (global.multiUserMode) {
event.preventDefault()
webContents.send('newPad', url, options.x, options.y)
}
})
// WORKAROUND: On windows, if the app was set to fullscreen, the menubar is not hidden
if (win.isKiosk()) {
win.setMenuBarVisibility(false)
}
win.on('focus', event => {
menu.focus()
})
win.on('blur', event => {
menu.blur()
})
win.on('enter-full-screen', () => {
win.setMenuBarVisibility(false)
})
win.on('leave-full-screen', () => {
win.setMenuBarVisibility(true)
})
win.on('enter-html-full-screen', () => {
win.setMenuBarVisibility(false)
})
win.on('leave-html-full-screen', () => {
win.setMenuBarVisibility(true)
})
win.on('close', () => {
store.set('storedBounds', win.getBounds())
})
// Emitted when the window is closed.
win.on('closed', () => {
app.quit()
})
}
// When work makes progress, show the progress bar
function onProgress(progress) {
// Use values 0 to 1, or -1 to hide the progress bar
try {
win.setProgressBar(progress || -1) // Progress bar works on all platforms
} catch (e) {
if (DEVELOPMENT) console.log(e.message)
}
}
function trySend(target, ...args) {
try {
target.send(...args)
} catch (e) {
if (DEVELOPMENT) console.log(e.message)
}
}
ipcMain.on('multiUserMode', (e, opts = {}) => {
global.multiUserMode = opts
})
ipcMain.on('padContainerLoaded', e => {
win.webContents.send('padContainerAvailable')
})
ipcMain.on('createScreenshot', (e, opts = {}) => {
opts = Object.assign(
{},
{
name: `iwmbrowser-${new Date()
.toISOString()
.replace(/:/g, '-')}.png`,
path: os.tmpdir()
},
opts
)
win.webContents.capturePage(image => {
if (image) {
let file = path.join(opts.path, opts.name)
fs.writeFile(file, image.toPNG(), err => {
if (err) {
//throw err
} else {
console.log(`Screenshot saved: ${file}`)
}
})
}
})
})
ipcMain.on('directoryListing', (e, opts = {}) => {
let { directory, files, folders } = opts
console.log("directoryListing", opts)
let listing = fs.readdirSync(directory)
let result = { directory, files: [], folders: [] }
for (let name of listing) {
if (name.startsWith('.'))
continue
let fullPath = path.join(directory, name)
let stat = fs.lstatSync(fullPath)
if (files && stat.isFile()) {
if (typeof files == 'string' && !files.endsWith(files))
continue
result.files.push(name)
}
if (folders && stat.isDirectory())
result.folders.push(name)
}
e.sender.send('directoryListing', result)
})
ipcMain.on('createTextfile', (e, opts = {}) => {
opts = Object.assign(
{},
{
name: `iwmbrowser-${new Date()
.toISOString()
.replace(/:/g, '-')}.txt`,
path: os.tmpdir(),
text: ''
},
opts
)
let file = path.join(opts.path, opts.name)
fs.writeFile(file, opts.text, err => {
if (err) {
//throw err
} else {
console.log(`Textfile saved: ${file}`)
}
})
})
ipcMain.on('error', e => {
console.log('Received error notification')
global.errorCount += 1
})
ipcMain.on('openExternal', (e, url=null) => {
console.log('Received openExternal', url)
if (url) {
shell.openExternal(url)
}
})
ipcMain.on('save', (e, opts = {}) => {
let { url, html, saveAs, action } = opts
// url must absolute URL
let urlObj = new URL(url)
let pathname = urlObj.pathname
if (saveAs) {
pathname = dialog.showSaveDialog(win, { title: 'Save as:', defaultPath: pathname })
if (typeof pathname == 'undefined')
return
}
try {
console.log("Saving", pathname, action)
html = prettyPrint(html, { indent_size: 4 });
fs.writeFileSync(pathname, html, 'utf-8')
if (saveAs) {
let normalized = pathname.replace(/\\/g, '/')
e.sender.send('savedAs', {url: `file://${normalized}`, action})
}
}
catch (e) {
console.warn('Failed to save the file', pathname)
e.sender.send('saveFailed', pathname)
}
})
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on(
'select-client-certificate',
(event, webContents, url, list, callback) => {
console.log('select-client-certificate', url, list)
event.preventDefault()
ipc.once('client-certificate-selected', (event, item) => {
console.log('selected:', item)
callback(item)
})
mainWindow.webContents.send('select-client-certificate', list)
}
)
app.on(
'certificate-error',
(event, webContents, url, error, certificate, callback) => {
console.log('certificate-error', url)
event.preventDefault()
const result = true // TODO: do real validation here
callback(result)
}
)
app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (win === null) {
createWindow()
}
})
module.exports = {
store: store
}