skypager-project-types-electron-app
Version:
skypager electron app project type
377 lines (305 loc) • 8.8 kB
JavaScript
/**
* @method appWillQuit
* @method appIsQuitting
* @method appIsDuplicate
* @method prepareApplication
* @method applicationWillLaunch
* @method applicationDidLaunch
* @method handlePanelMessage
* @method secondInstanceWasLaunched
* @method appDidQuit
* @method prepareTray
* @method userOpenedFiles
* @method userSavedFiles
*/
import Helper from 'skypager-helper'
import { Tray, dialog, Menu, protocol, BrowserWindow, app } from 'electron'
import { join } from 'path'
export class Application extends Helper {
static attach(project) {
return Helper.attach(project, Application, {
registryProp: 'applications',
lookupProp: 'application',
registry: Helper.createContextRegistry('applications', {
context: require.context('./applications', false, /\.js$/),
dirname: __dirname,
filename: __filename,
})
})
}
info(...args) {
return this.project.info(...args)
}
debug(...args) {
return this.project.debug(...args)
}
error(...args) {
return this.project.error(...args)
}
initialize() {
this.applyMixin(this.provider, this.context, this)
this.lazy('defaultPanelOptions', () => this.tryResult('panelDefaults', {}))
this.debug('Initializing Application with Panel Options', {
panelOptions: this.defaultPanelOptions
})
if (this.tryResult('launchImmediately') !== false) {
if (app.isReady()) {
this.debug('App is already ready. Launching.')
this.launch()
.then(() => {
this.isLaunched = true
this.isLaunching = false
})
.catch((error) => {
this.isLaunched = true
this.isLaunching = false
this.launchError = error
})
} else {
app.once('ready', () => this.launch().then(() => this.isLaunched = true).catch(error => {
this.debug('App became ready. Launching.')
this.isLaunched = true
this.isLaunching = false
this.launchError = error
}))
}
}
app.on('before-quit', this._beforeQuit.bind(this))
app.on('will-quit', this._willQuit.bind(this))
app.on('quit', this._onQuit.bind(this))
this.lazy('storage', () => {
this.debug('Initializing storage')
return require('../runtime/storage')
})
this.hide('activePanels', {})
/*
protocol.registerBufferProtocol('skypager', (request, callback) => {
const { url, uploadData, method = 'GET', referrer = '' } = request
callback({
mimeType: 'text/html',
data: new Buffer(`Hi`)
})
})
*/
}
_willQuit(event) {
this.debug('App is quitting', event)
if (this.appIsQuitting) { this.appIsQuitting(event) }
}
_beforeQuit(event) {
this.debug('App will quit', event)
if (this.appWillQuit) { this.appWillQuit(event) }
}
getPath(...args) {
return app.getPath(...args)
}
get appPath() {
return this.get('options.appPath', this.get('project.paths.output', app.getAppPath()))
}
setApplicationMenu(...args) {
return this.Menu.setApplicationMenu(...args)
}
setAboutPanel(options = {}) {
return this.app.setAboutPanelOptions({
applicationName: this.tryResult('appName', this.project.getEither('manifest.productName', 'manifest.appName', 'manifest.name')),
applicationVersion: this.tryResult('appVersion', this.project.getEither('manifest.appVersion', 'manifest.version')),
...options,
})
}
async open(options = {}) {
const result = await new Promise((resolve, reject) => {
dialog.showOpenDialog(options, (files) => {
resolve({ files, options })
})
})
if (this.userOpenedFiles) {
await this.userOpenedFiles(result)
}
return result
}
async save(options = {}) {
const result = await new Promise((resolve, reject) => {
dialog.showSaveDialog(options, (file) => {
resolve({ file, options })
})
})
if (this.userSavedFiles) {
await this.userSavedFiles(result)
}
return result
}
get dock() {
return this.get('app.dock', app.dock)
}
get tmpdir() {
return this.getPath('temp')
}
get storagePath() {
return join(this.userDataPath, 'storage')
}
get userDataPath() {
return this.getPath('userData')
}
get userHomePath() {
return this.getPath('home')
}
findPanelForWindow(windowId) {
const browserWindow = this.get('browserWindows').find(b => b.windowId === windowId)
if (browserWindow) {
return browserWindow.getPanel()
}
}
async askPanel(id, payload, ...args) {
const response = this.panel(id).askPanel(payload, ...args)
return response
}
async tellPanel(id, payload, ...args) {
const response = this.panel(id).tellPanel(payload, ...args)
return response
}
panel(id, options = {}) {
const instanceId = options.instanceId || id
if (!options.fresh && this.get(['activePanels', instanceId])) {
return this.get(['activePanels', instanceId])
}
const object = this.project.panel(id, {
...this.get('defaultPanelOptions', {}),
...this.get(`panelOptions.${id}`, {}),
cacheHelper: !options.fresh,
...options,
}, {
appInstance: this
})
this.set(['activePanels', instanceId], object)
return object
}
get panelOptions() {
return this.tryGet('panels', {})
}
async launch() {
this.debug('App launch')
if (this.isSecondInstance) {
this.debug('App launched as second instance')
if (this.applicationIsDuplicate) {
this.debug('applicationIsDuplicate hook being called')
try {
await this.applicationIsDuplicate()
} catch(error) {
this.app.quit(0)
}
}
}
if (this.isLaunched) {
this.isLaunching = false
return this
}
this.isLaunching = true
this.debug('prepareSystem')
try {
await this.prepareSystem()
} catch(error) {
this.error('Error in prepareSystem', error)
}
this.debug('prepareApplication')
if (this.prepareApplication) {
try {
await this.prepareApplication()
this.debug('prepareApplication custom hook was called')
} catch(error) {
this.error('prepareApplication Error', error)
}
}
this.debug('applicationWillLaunch')
if (this.applicationWillLaunch) {
try {
await this.applicationWillLaunch()
this.debug('applicationWillLaunch custom hook was called')
} catch(error) {
this.error('applicationWillLaunch', error)
}
}
if (this.prepareTray) {
try {
this.debug('prepareTray')
this.prepareTray()
} catch(error) {
this.error('prepareTray Error', error)
}
}
if (this.applicationDidLaunch) {
try {
await this.applicationDidLaunch()
this.debug('applicationDidLaunch custom hook was called')
} catch(error) {
this.error('applicationDidLaunch Error', error)
}
}
this.isLaunching = false
return this
}
async receivePanelMessage({channel, panel, payload} = {}) {
if (this.handlePanelMessage) {
return this.handlePanelMessage({channel, panel, payload}).then((r) => r)
}
return payload
}
async prepareSystem() {
await this.prepareStorage()
await this.prepareLogging()
}
async prepareLogging() {
}
async prepareStorage() {
await this.project.mkdirpAsync(this.storagePath)
}
get app() {
return app
}
get browserWindows() {
return this.BrowserWindow.getAllWindows()
}
get BrowserWindow() {
return this.tryGet('BrowserWindow', BrowserWindow)
}
get Menu() {
return this.tryGet('Menu', Menu)
}
get dialog() {
return this.tryGet('dialog', dialog)
}
get protocol() {
return this.tryGet('protocol', protocol)
}
get Tray() {
return this.tryGet('Tray', Tray)
}
get ipcStream() {
return this.tryGet('ipcStream', require('./stream'))
}
get isSecondInstance() {
return app.makeSingleInstance((commandLine, workingDirectory) => {
this._secondInstance(commandLine, workingDirectory)
})
}
createTray(trayIcon) {
return new Tray(trayIcon)
}
/**
* Returns true if the application can only be a single instance
*/
get singleInstance() {
return this.tryGet('singleInstance', false)
}
_secondInstance(...args) {
if (this.secondInstanceWasLaunched) {
return this.secondInstanceWasLaunched(...args)
}
}
_onQuit(...args) {
if (this.appDidQuit) {
return this.appDidQuit(...args)
}
}
}
export default Application
export const attach = Application.attach