[Splash > Backend] Self-rewrite main code (not updater parts)

This commit is contained in:
Ducko 2022-02-11 22:41:40 +00:00
parent 14c5f4939d
commit 7f1d6d12c4
2 changed files with 130 additions and 227 deletions

View file

@ -1,43 +1,141 @@
"use strict"; const { join } = require('path');
const fs = require('fs');
const _events = require('events');
const { BrowserWindow, app } = require('electron');
Object.defineProperty(exports, "__esModule", { const paths = require('../paths');
value: true const Backoff = require('../utils/Backoff');
}); const moduleUpdater = require("../updater/moduleUpdater");
exports.initSplash = initSplash; const updater = require("../updater/updater");
exports.focusWindow = focusWindow;
exports.pageReady = pageReady;
exports.events = exports.APP_SHOULD_SHOW = exports.APP_SHOULD_LAUNCH = void 0;
var _electron = require("electron"); let splashState = {};
let launchedMainWindow = false;
let updateAttempt = 0;
let restartRequired = false;
var _events = require("events");
var _fs = _interopRequireDefault(require("fs")); exports.initSplash = (startMinimized = false) => {
log('Splash', `Initing`);
var _path = _interopRequireDefault(require("path")); newUpdater = updater.getUpdater();
var _url = _interopRequireDefault(require("url")); if (newUpdater == null) initOldUpdater();
var _Backoff = _interopRequireDefault(require("../utils/Backoff")); launchSplashWindow(startMinimized);
var moduleUpdater = _interopRequireWildcard(require("../updater/moduleUpdater")); if (newUpdater != null) {
updateUntilCurrent();
} else {
moduleUpdater.installPendingUpdates();
}
var paths = _interopRequireWildcard(require("../paths")); if (process.env.OPENASAR_QUICKSTART || oaConfig.quickstart) setTimeout(() => {
destroySplash();
var _updater = require("../updater/updater"); if (newUpdater != null) { // Manually load desktop_core module path for faster requiring
require('../utils/u2LoadModulePath')();
}
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } launchMainWindow();
setTimeout(() => {
events.emit(APP_SHOULD_SHOW);
}, 100);
}, 300);
};
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } exports.focusWindow = () => splashWindow?.focus?.();
exports.pageReady = () => destroySplash() || process.nextTick(() => events.emit(APP_SHOULD_SHOW));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const destroySplash = () => {
log('Splash', 'Destroy');
const UPDATE_TIMEOUT_WAIT = 10000; stopUpdateTimeout();
const RETRY_CAP_SECONDS = 60; // citron note: atom seems to add about 50px height to the frame on mac but not windows if (!splashWindow) return;
// TODO: see if we can eliminate fudge by using useContentSize BrowserWindow option
splashWindow.setSkipTaskbar(true);
setTimeout(() => {
if (!splashWindow) return;
splashWindow.hide();
splashWindow.close();
splashWindow = null;
}, 100);
};
const launchMainWindow = () => {
log('Splash', 'Launch main');
removeModulesListeners();
if (!launchedMainWindow && splashWindow != null) {
launchedMainWindow = true;
events.emit(APP_SHOULD_LAUNCH);
}
};
const updateSplashState = (status) => splashWindow && splashWindow.webContents.send('SPLASH_STATE', { status, ...splashState });
const launchSplashWindow = (startMinimized) => {
const windowConfig = {
width: 300,
height: process.platform === 'darwin' ? 300 : 350,
transparent: false,
frame: false,
resizable: false,
center: true,
show: false,
backgroundColor: '#2f3136',
webPreferences: {
preload: join(__dirname, 'preload.js')
}
};
splashWindow = new BrowserWindow(windowConfig);
const win = splashWindow;
const wc = win.webContents;
if (process.platform !== 'darwin') win.on('closed', () => { if (!launchedMainWindow) app.quit(); });
wc.once('dom-ready', () => {
if (oaConfig.themeSync !== false) try { // Inject themesync CSS
wc.insertCSS(JSON.parse(fs.readFileSync(join(paths.getUserData(), 'userDataCache.json'), 'utf8')).openasarSplashCSS);
} catch (e) { }
if (oaConfig.splashText === true) try {
const buildInfo = require('../utils/buildInfo.js');
wc.executeJavaScript(`debug.textContent = '${buildInfo.releaseChannel} ${buildInfo.version}\\nOpenAsar ${oaVersion}'`);
} catch (e) { }
});
if (!startMinimized) win.once('ready-to-show', () => win.show());
win.loadURL('file:///' + join(__dirname, 'index.html'));
};
const addModulesListener = (event, listener) => {
if (newUpdater) return;
modulesListeners[event] = listener;
moduleUpdater.events.addListener(event, listener);
};
const removeModulesListeners = () => {
if (newUpdater) return;
for (const e in modulesListeners) moduleUpdater.events.removeListener(e, modulesListeners[e]);
};
const startUpdateTimeout = () => !updateTimeout && (updateTimeout = setTimeout(() => scheduleUpdateCheck(), 10000));
const stopUpdateTimeout = () => updateTimeout && clearTimeout(updateTimeout) && (updateTimeout = null);
const scheduleUpdateCheck = () => {
updateAttempt++;
const wait = Math.min(updateAttempt * 10, 60);
splashState.seconds = wait;
setTimeout(() => moduleUpdater.checkForUpdates(), retryInSeconds * 1000);
};
const LOADING_WINDOW_WIDTH = 300;
const LOADING_WINDOW_HEIGHT = process.platform === 'darwin' ? 300 : 350; // TODO: addModulesListener events should use Module's constants
const CHECKING_FOR_UPDATES = 'checking-for-updates'; const CHECKING_FOR_UPDATES = 'checking-for-updates';
const UPDATE_CHECK_FINISHED = 'update-check-finished'; const UPDATE_CHECK_FINISHED = 'update-check-finished';
@ -56,35 +154,18 @@ const INSTALLING_MODULE_PROGRESS = 'installing-module-progress';
const INSTALLING_MODULES_FINISHED = 'installing-modules-finished'; const INSTALLING_MODULES_FINISHED = 'installing-modules-finished';
const UPDATE_MANUALLY = 'update-manually'; const UPDATE_MANUALLY = 'update-manually';
const APP_SHOULD_LAUNCH = 'APP_SHOULD_LAUNCH'; const APP_SHOULD_LAUNCH = 'APP_SHOULD_LAUNCH';
exports.APP_SHOULD_LAUNCH = APP_SHOULD_LAUNCH;
const APP_SHOULD_SHOW = 'APP_SHOULD_SHOW'; const APP_SHOULD_SHOW = 'APP_SHOULD_SHOW';
exports.APP_SHOULD_SHOW = APP_SHOULD_SHOW;
const events = new _events.EventEmitter(); const events = new _events.EventEmitter();
exports.APP_SHOULD_LAUNCH = APP_SHOULD_LAUNCH;
exports.APP_SHOULD_SHOW = APP_SHOULD_SHOW;
exports.events = events; exports.events = events;
function webContentsSend(win, event, ...args) {
// log('Splash', `Sending to webcontents:`, event, args);
if (splashWindow != null && !splashWindow.isDestroyed() && !splashWindow.webContents.isDestroyed()) {
try {
win.webContents.send(`DISCORD_${event}`, ...args);
} catch (e) { // Mostly ignore, probably just destroyed
log('Splash', 'Failed to send to webcontents');
}
}
}
let splashWindow; let splashWindow;
let modulesListeners; let modulesListeners;
let updateTimeout; let updateTimeout;
let updateAttempt;
let splashState;
let launchedMainWindow;
let restartRequired = false;
let newUpdater; let newUpdater;
const updateBackoff = new _Backoff.default(1000, 30000); // TODO(eiz): some of this logic should probably not live in the splash. const updateBackoff = new Backoff(1000, 30000);
//
// Disabled because Rust interop stuff is going on in here.
class TaskProgress { class TaskProgress {
constructor() { constructor() {
@ -96,10 +177,10 @@ class TaskProgress {
recordProgress(progress, task) { recordProgress(progress, task) {
this.allTasks.add(task.package_sha256); this.allTasks.add(task.package_sha256);
if (progress.state !== _updater.TASK_STATE_WAITING) { if (progress.state !== updater.TASK_STATE_WAITING) {
this.inProgress.set(task.package_sha256, progress.percent); this.inProgress.set(task.package_sha256, progress.percent);
if (progress.state === _updater.TASK_STATE_COMPLETE) { if (progress.state === updater.TASK_STATE_COMPLETE) {
this.finished.add(task.package_sha256); this.finished.add(task.package_sha256);
} }
} }
@ -277,182 +358,4 @@ function initOldUpdater() {
splashState.newVersion = newVersion; splashState.newVersion = newVersion;
updateSplashState(UPDATE_MANUALLY); updateSplashState(UPDATE_MANUALLY);
}); });
}
function initSplash(startMinimized = false) {
log('Splash', `Initing splash`);
splashState = {};
launchedMainWindow = false;
updateAttempt = 0;
newUpdater = (0, _updater.getUpdater)();
if (newUpdater == null) initOldUpdater();
launchSplashWindow(startMinimized);
if (newUpdater != null) {
updateUntilCurrent();
} else {
moduleUpdater.installPendingUpdates();
}
if (process.env.OPENASAR_QUICKSTART || oaConfig.quickstart) setTimeout(() => {
destroySplash();
if (newUpdater != null) { // Manually load desktop_core module path for faster requiring
require('../utils/u2LoadModulePath')();
}
launchMainWindow();
setTimeout(() => {
events.emit(APP_SHOULD_SHOW);
}, 100);
}, 50);
}
function destroySplash() {
log('Splash', `Destroying splash`);
stopUpdateTimeout();
if (splashWindow) {
splashWindow.setSkipTaskbar(true); // defer the window hiding for a short moment so it gets covered by the main window
const _nukeWindow = () => {
if (splashWindow != null) {
splashWindow.hide();
splashWindow.close();
splashWindow = null;
}
};
setTimeout(_nukeWindow, 100);
}
}
function addModulesListener(event, listener) {
if (newUpdater != null) return;
modulesListeners[event] = listener;
moduleUpdater.events.addListener(event, listener);
}
function removeModulesListeners() {
if (newUpdater != null) return;
for (const event of Object.keys(modulesListeners)) {
moduleUpdater.events.removeListener(event, modulesListeners[event]);
}
}
function startUpdateTimeout() {
if (!updateTimeout) {
updateTimeout = setTimeout(() => scheduleUpdateCheck(), UPDATE_TIMEOUT_WAIT);
}
}
function stopUpdateTimeout() {
if (updateTimeout) {
clearTimeout(updateTimeout);
updateTimeout = null;
}
}
function updateSplashState(event) {
webContentsSend(splashWindow, 'SPLASH_UPDATE_STATE', {
status: event,
...splashState
});
}
function launchSplashWindow(startMinimized) {
const windowConfig = {
width: LOADING_WINDOW_WIDTH,
height: LOADING_WINDOW_HEIGHT,
transparent: false,
frame: false,
resizable: false,
center: true,
show: false,
backgroundColor: '#2f3136',
webPreferences: {
nodeIntegration: false,
enableRemoteModule: false,
contextIsolation: true,
preload: _path.default.join(__dirname, 'preload.js')
}
};
splashWindow = new _electron.BrowserWindow(windowConfig); // prevent users from dropping links to navigate in splash window
log('Splash', 'Created BrowserWindow');
if (process.platform !== 'darwin') {
// citron note: this causes a crash on quit while the window is open on osx
splashWindow.on('closed', () => {
splashWindow = null;
if (!launchedMainWindow) {
// user has closed this window before we launched the app, so let's quit
_electron.app.quit();
}
});
}
const win = splashWindow;
const wc = win.webContents;
wc.once('dom-ready', () => {
if (oaConfig.themeSync !== false) try { // Inject themesync CSS
wc.insertCSS(JSON.parse(_fs.default.readFileSync(_path.default.join(paths.getUserData(), 'userDataCache.json'), 'utf8')).openasarSplashCSS);
} catch (e) { }
if (oaConfig.splashText === true) try {
const buildInfo = require('../utils/buildInfo.js');
wc.executeJavaScript(`debug.textContent = '${buildInfo.releaseChannel} ${buildInfo.version}\\nOpenAsar ${oaVersion}'`);
} catch (e) { }
if (!startMinimized) win.once('ready-to-show', () => win.show());
});
const splashUrl = _url.default.format({
protocol: 'file',
slashes: true,
pathname: _path.default.join(__dirname, 'index.html')
});
win.loadURL(splashUrl);
log('Splash', `Loading window (with url ${splashUrl})`);
}
function launchMainWindow() {
removeModulesListeners();
if (!launchedMainWindow && splashWindow != null) {
launchedMainWindow = true;
events.emit(APP_SHOULD_LAUNCH);
}
}
function scheduleUpdateCheck() {
// TODO: can we use backoff here?
updateAttempt += 1;
const retryInSeconds = Math.min(updateAttempt * 10, RETRY_CAP_SECONDS);
splashState.seconds = retryInSeconds;
setTimeout(() => moduleUpdater.checkForUpdates(), retryInSeconds * 1000);
}
function focusWindow() {
log('Splash', `Told to focus splash window`);
if (splashWindow != null) {
splashWindow.focus();
}
}
function pageReady() {
log('Splash', `Page ready called, destroying splash and marking app to show`);
destroySplash();
process.nextTick(() => events.emit(APP_SHOULD_SHOW));
} }

View file

@ -2,5 +2,5 @@ const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('DiscordSplash', { contextBridge.exposeInMainWorld('DiscordSplash', {
onStateUpdate: callback => ipcRenderer.on('DISCORD_SPLASH_UPDATE_STATE', (_, state) => callback(state)) onStateUpdate: callback => ipcRenderer.on('SPLASH_STATE', (_, state) => callback(state))
}); });