mirror of
https://github.com/dscalzi/HeliosLauncher.git
synced 2024-12-22 11:42:14 -08:00
eae490b0a7
This commit introduces support for Microsoft Authentication via the settings menu. There are a few known issues and TODOs which should not be hard to fix. Once the auth flow from the settings screen is complete, the auth folow for first-time login (ie no accounts added yet) must be added. Should not be very difficult. The plan is to add one more view with two login buttons. The Mojang button will just bring you to the login page. The microsoft one will launch OAuth2.
326 lines
10 KiB
JavaScript
326 lines
10 KiB
JavaScript
const remoteMain = require('@electron/remote/main')
|
|
remoteMain.initialize()
|
|
|
|
// Requirements
|
|
const { app, BrowserWindow, ipcMain, Menu } = require('electron')
|
|
const autoUpdater = require('electron-updater').autoUpdater
|
|
const ejse = require('ejs-electron')
|
|
const fs = require('fs')
|
|
const isDev = require('./app/assets/js/isdev')
|
|
const path = require('path')
|
|
const semver = require('semver')
|
|
const { pathToFileURL } = require('url')
|
|
const { AZURE_CLIENT_ID, MSFT_OPCODE, MSFT_REPLY_TYPE, MSFT_ERROR } = require('./app/assets/js/ipcconstants')
|
|
|
|
// Setup auto updater.
|
|
function initAutoUpdater(event, data) {
|
|
|
|
if(data){
|
|
autoUpdater.allowPrerelease = true
|
|
} else {
|
|
// Defaults to true if application version contains prerelease components (e.g. 0.12.1-alpha.1)
|
|
// autoUpdater.allowPrerelease = true
|
|
}
|
|
|
|
if(isDev){
|
|
autoUpdater.autoInstallOnAppQuit = false
|
|
autoUpdater.updateConfigPath = path.join(__dirname, 'dev-app-update.yml')
|
|
}
|
|
if(process.platform === 'darwin'){
|
|
autoUpdater.autoDownload = false
|
|
}
|
|
autoUpdater.on('update-available', (info) => {
|
|
event.sender.send('autoUpdateNotification', 'update-available', info)
|
|
})
|
|
autoUpdater.on('update-downloaded', (info) => {
|
|
event.sender.send('autoUpdateNotification', 'update-downloaded', info)
|
|
})
|
|
autoUpdater.on('update-not-available', (info) => {
|
|
event.sender.send('autoUpdateNotification', 'update-not-available', info)
|
|
})
|
|
autoUpdater.on('checking-for-update', () => {
|
|
event.sender.send('autoUpdateNotification', 'checking-for-update')
|
|
})
|
|
autoUpdater.on('error', (err) => {
|
|
event.sender.send('autoUpdateNotification', 'realerror', err)
|
|
})
|
|
}
|
|
|
|
// Open channel to listen for update actions.
|
|
ipcMain.on('autoUpdateAction', (event, arg, data) => {
|
|
switch(arg){
|
|
case 'initAutoUpdater':
|
|
console.log('Initializing auto updater.')
|
|
initAutoUpdater(event, data)
|
|
event.sender.send('autoUpdateNotification', 'ready')
|
|
break
|
|
case 'checkForUpdate':
|
|
autoUpdater.checkForUpdates()
|
|
.catch(err => {
|
|
event.sender.send('autoUpdateNotification', 'realerror', err)
|
|
})
|
|
break
|
|
case 'allowPrereleaseChange':
|
|
if(!data){
|
|
const preRelComp = semver.prerelease(app.getVersion())
|
|
if(preRelComp != null && preRelComp.length > 0){
|
|
autoUpdater.allowPrerelease = true
|
|
} else {
|
|
autoUpdater.allowPrerelease = data
|
|
}
|
|
} else {
|
|
autoUpdater.allowPrerelease = data
|
|
}
|
|
break
|
|
case 'installUpdateNow':
|
|
autoUpdater.quitAndInstall()
|
|
break
|
|
default:
|
|
console.log('Unknown argument', arg)
|
|
break
|
|
}
|
|
})
|
|
// Redirect distribution index event from preloader to renderer.
|
|
ipcMain.on('distributionIndexDone', (event, res) => {
|
|
event.sender.send('distributionIndexDone', res)
|
|
})
|
|
|
|
// Disable hardware acceleration.
|
|
// https://electronjs.org/docs/tutorial/offscreen-rendering
|
|
app.disableHardwareAcceleration()
|
|
|
|
|
|
const REDIRECT_URI_PREFIX = 'https://login.microsoftonline.com/common/oauth2/nativeclient?'
|
|
|
|
// Microsoft Auth Login
|
|
let msftAuthWindow
|
|
let msftAuthSuccess
|
|
ipcMain.on(MSFT_OPCODE.OPEN_LOGIN, (ipcEvent) => {
|
|
if (msftAuthWindow) {
|
|
ipcEvent.reply(MSFT_OPCODE.REPLY_LOGIN, MSFT_REPLY_TYPE.ERROR, MSFT_ERROR.ALREADY_OPEN)
|
|
return
|
|
}
|
|
msftAuthSuccess = false
|
|
msftAuthWindow = new BrowserWindow({
|
|
title: 'Microsoft Login',
|
|
backgroundColor: '#222222',
|
|
width: 520,
|
|
height: 600,
|
|
frame: true,
|
|
icon: getPlatformIcon('SealCircle')
|
|
})
|
|
|
|
msftAuthWindow.on('closed', () => {
|
|
msftAuthWindow = undefined
|
|
})
|
|
|
|
msftAuthWindow.on('close', () => {
|
|
if(!msftAuthSuccess) {
|
|
ipcEvent.reply(MSFT_OPCODE.REPLY_LOGIN, MSFT_REPLY_TYPE.ERROR, MSFT_ERROR.NOT_FINISHED)
|
|
}
|
|
})
|
|
|
|
msftAuthWindow.webContents.on('did-navigate', (_, uri) => {
|
|
if (uri.startsWith(REDIRECT_URI_PREFIX)) {
|
|
let queries = uri.substring(REDIRECT_URI_PREFIX.length).split('#', 1).toString().split('&')
|
|
let queryMap = {}
|
|
|
|
queries.forEach(query => {
|
|
const [name, value] = query.split('=')
|
|
queryMap[name] = decodeURI(value)
|
|
})
|
|
|
|
ipcEvent.reply(MSFT_OPCODE.REPLY_LOGIN, MSFT_REPLY_TYPE.SUCCESS, queryMap)
|
|
|
|
msftAuthSuccess = true
|
|
msftAuthWindow.close()
|
|
msftAuthWindow = null
|
|
}
|
|
})
|
|
|
|
msftAuthWindow.removeMenu()
|
|
msftAuthWindow.loadURL(`https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?prompt=select_account&client_id=${AZURE_CLIENT_ID}&response_type=code&scope=XboxLive.signin%20offline_access&redirect_uri=https://login.microsoftonline.com/common/oauth2/nativeclient`)
|
|
})
|
|
|
|
// Microsoft Auth Logout
|
|
let msftLogoutWindow
|
|
let msftLogoutSuccess
|
|
ipcMain.on(MSFT_OPCODE.OPEN_LOGOUT, (ipcEvent, uuid, isLastAccount) => {
|
|
if (msftLogoutWindow) {
|
|
ipcEvent.reply(MSFT_OPCODE.REPLY_LOGOUT, MSFT_REPLY_TYPE.ERROR, MSFT_ERROR.ALREADY_OPEN)
|
|
return
|
|
}
|
|
|
|
msftLogoutSuccess = false
|
|
msftLogoutWindow = new BrowserWindow({
|
|
title: 'Microsoft Logout',
|
|
backgroundColor: '#222222',
|
|
width: 520,
|
|
height: 600,
|
|
frame: true,
|
|
icon: getPlatformIcon('SealCircle')
|
|
})
|
|
|
|
msftLogoutWindow.on('closed', () => {
|
|
msftLogoutWindow = undefined
|
|
})
|
|
|
|
msftLogoutWindow.on('close', () => {
|
|
if(!msftLogoutSuccess) {
|
|
ipcEvent.reply(MSFT_OPCODE.REPLY_LOGOUT, MSFT_REPLY_TYPE.ERROR, MSFT_ERROR.NOT_FINISHED)
|
|
}
|
|
})
|
|
|
|
msftLogoutWindow.webContents.on('did-navigate', () => {
|
|
setTimeout(() => {
|
|
if(msftLogoutWindow) {
|
|
ipcEvent.reply(MSFT_OPCODE.REPLY_LOGOUT, MSFT_REPLY_TYPE.SUCCESS, uuid, isLastAccount)
|
|
msftLogoutSuccess = true
|
|
|
|
if(msftLogoutWindow) {
|
|
msftLogoutWindow.close()
|
|
msftLogoutWindow = null
|
|
}
|
|
}
|
|
}, 5000)
|
|
})
|
|
|
|
msftLogoutWindow.removeMenu()
|
|
msftLogoutWindow.loadURL('https://login.microsoftonline.com/common/oauth2/v2.0/logout')
|
|
})
|
|
|
|
// 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
|
|
|
|
function createWindow() {
|
|
|
|
win = new BrowserWindow({
|
|
width: 980,
|
|
height: 552,
|
|
icon: getPlatformIcon('SealCircle'),
|
|
frame: false,
|
|
webPreferences: {
|
|
preload: path.join(__dirname, 'app', 'assets', 'js', 'preloader.js'),
|
|
nodeIntegration: true,
|
|
contextIsolation: false
|
|
},
|
|
backgroundColor: '#171614'
|
|
})
|
|
remoteMain.enable(win.webContents)
|
|
|
|
ejse.data('bkid', Math.floor((Math.random() * fs.readdirSync(path.join(__dirname, 'app', 'assets', 'images', 'backgrounds')).length)))
|
|
|
|
win.loadURL(pathToFileURL(path.join(__dirname, 'app', 'app.ejs')).toString())
|
|
|
|
/*win.once('ready-to-show', () => {
|
|
win.show()
|
|
})*/
|
|
|
|
win.removeMenu()
|
|
|
|
win.resizable = true
|
|
|
|
win.on('closed', () => {
|
|
win = null
|
|
})
|
|
}
|
|
|
|
function createMenu() {
|
|
|
|
if(process.platform === 'darwin') {
|
|
|
|
// Extend default included application menu to continue support for quit keyboard shortcut
|
|
let applicationSubMenu = {
|
|
label: 'Application',
|
|
submenu: [{
|
|
label: 'About Application',
|
|
selector: 'orderFrontStandardAboutPanel:'
|
|
}, {
|
|
type: 'separator'
|
|
}, {
|
|
label: 'Quit',
|
|
accelerator: 'Command+Q',
|
|
click: () => {
|
|
app.quit()
|
|
}
|
|
}]
|
|
}
|
|
|
|
// New edit menu adds support for text-editing keyboard shortcuts
|
|
let editSubMenu = {
|
|
label: 'Edit',
|
|
submenu: [{
|
|
label: 'Undo',
|
|
accelerator: 'CmdOrCtrl+Z',
|
|
selector: 'undo:'
|
|
}, {
|
|
label: 'Redo',
|
|
accelerator: 'Shift+CmdOrCtrl+Z',
|
|
selector: 'redo:'
|
|
}, {
|
|
type: 'separator'
|
|
}, {
|
|
label: 'Cut',
|
|
accelerator: 'CmdOrCtrl+X',
|
|
selector: 'cut:'
|
|
}, {
|
|
label: 'Copy',
|
|
accelerator: 'CmdOrCtrl+C',
|
|
selector: 'copy:'
|
|
}, {
|
|
label: 'Paste',
|
|
accelerator: 'CmdOrCtrl+V',
|
|
selector: 'paste:'
|
|
}, {
|
|
label: 'Select All',
|
|
accelerator: 'CmdOrCtrl+A',
|
|
selector: 'selectAll:'
|
|
}]
|
|
}
|
|
|
|
// Bundle submenus into a single template and build a menu object with it
|
|
let menuTemplate = [applicationSubMenu, editSubMenu]
|
|
let menuObject = Menu.buildFromTemplate(menuTemplate)
|
|
|
|
// Assign it to the application
|
|
Menu.setApplicationMenu(menuObject)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function getPlatformIcon(filename){
|
|
let ext
|
|
switch(process.platform) {
|
|
case 'win32':
|
|
ext = 'ico'
|
|
break
|
|
case 'darwin':
|
|
case 'linux':
|
|
default:
|
|
ext = 'png'
|
|
break
|
|
}
|
|
|
|
return path.join(__dirname, 'app', 'assets', 'images', `${filename}.${ext}`)
|
|
}
|
|
|
|
app.on('ready', createWindow)
|
|
app.on('ready', createMenu)
|
|
|
|
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('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()
|
|
}
|
|
}) |