CORE+LATEST

This commit is contained in:
|| Prof. - Xadk3!#0000 || @naryal2580 2023-05-20 20:32:19 +05:30
parent 074436668f
commit f95fef17d2
257 changed files with 11319 additions and 0 deletions

54
core/src/app/Constants.js Normal file
View File

@ -0,0 +1,54 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
// before we can set up (and export) our constants, we first need to grab bootstrap's constants
// so we can merge them in with our constants
function init(bootstrapConstants) {
const APP_NAME = bootstrapConstants.APP_NAME;
const API_ENDPOINT = bootstrapConstants.API_ENDPOINT;
const NEW_UPDATE_ENDPOINT = bootstrapConstants.NEW_UPDATE_ENDPOINT;
const UPDATE_ENDPOINT = bootstrapConstants.UPDATE_ENDPOINT;
const APP_ID = bootstrapConstants.APP_ID;
const DEFAULT_MAIN_WINDOW_ID = 0;
const MAIN_APP_DIRNAME = __dirname;
const UpdaterEvents = {
UPDATE_NOT_AVAILABLE: 'UPDATE_NOT_AVAILABLE',
CHECKING_FOR_UPDATES: 'CHECKING_FOR_UPDATES',
UPDATE_ERROR: 'UPDATE_ERROR',
UPDATE_MANUALLY: 'UPDATE_MANUALLY',
UPDATE_AVAILABLE: 'UPDATE_AVAILABLE',
MODULE_INSTALL_PROGRESS: 'MODULE_INSTALL_PROGRESS',
UPDATE_DOWNLOADED: 'UPDATE_DOWNLOADED',
MODULE_INSTALLED: 'MODULE_INSTALLED',
CHECK_FOR_UPDATES: 'CHECK_FOR_UPDATES',
QUIT_AND_INSTALL: 'QUIT_AND_INSTALL',
MODULE_INSTALL: 'MODULE_INSTALL',
MODULE_QUERY: 'MODULE_QUERY',
UPDATER_HISTORY_QUERY_AND_TRUNCATE: 'UPDATER_HISTORY_QUERY_AND_TRUNCATE',
UPDATER_HISTORY_RESPONSE: 'UPDATER_HISTORY_RESPONSE'
};
const MenuEvents = {
OPEN_HELP: 'menu:open-help',
OPEN_SETTINGS: 'menu:open-settings',
CHECK_FOR_UPDATES: 'menu:check-for-updates'
};
const exported = {
APP_NAME,
DEFAULT_MAIN_WINDOW_ID,
MAIN_APP_DIRNAME,
APP_ID,
API_ENDPOINT,
NEW_UPDATE_ENDPOINT,
UPDATE_ENDPOINT,
UpdaterEvents,
MenuEvents
};
for (const [k, v] of Object.entries(exported)) {
module.exports[k] = v;
}
}
module.exports = {
init
};

View File

@ -0,0 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getEnableHardwareAcceleration = getEnableHardwareAcceleration;
exports.setEnableHardwareAcceleration = setEnableHardwareAcceleration;
var _electron = require("electron");
var _appSettings = require("./bootstrapModules/appSettings");
const settings = _appSettings.appSettings.getSettings();
function getEnableHardwareAcceleration() {
// TODO: This should probably a constant
return settings.get('enableHardwareAcceleration', true);
}
function setEnableHardwareAcceleration(enableHardwareAcceleration) {
settings.set('enableHardwareAcceleration', enableHardwareAcceleration);
settings.save();
_electron.app.relaunch();
_electron.app.exit(0);
}

86
core/src/app/appBadge.js Normal file
View File

@ -0,0 +1,86 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.hasInit = void 0;
exports.init = init;
var _electron = require("electron");
var _utils = require("./utils");
var _mainScreen = require("./mainScreen");
var _ipcMain = _interopRequireDefault(require("./ipcMain"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
let hasInit = false;
exports.hasInit = hasInit;
let lastIndex;
let appIcons;
/**
* Used on Windows to set the taskbar icon
*/
function init() {
// Only init on win32 platforms
if (process.platform !== 'win32') return;
if (hasInit) {
console.warn('appBadge: Has already init! Cancelling init.');
return;
}
exports.hasInit = hasInit = true;
lastIndex = null;
appIcons = [];
const resourcePath = `app/images/badges`;
for (let i = 1; i <= 11; i++) {
appIcons.push((0, _utils.exposeModuleResource)(resourcePath, `badge-${i}.ico`));
}
_ipcMain.default.on('APP_BADGE_SET', (_event, count) => setAppBadge(count));
}
function setAppBadge(count) {
const win = _electron.BrowserWindow.fromId((0, _mainScreen.getMainWindowId)());
const {
index,
description
} = getOverlayIconData(count);
// Prevent setting a new icon when the icon is the same
if (lastIndex !== index) {
if (index == null) {
win.setOverlayIcon(null, description);
} else {
win.setOverlayIcon(appIcons[index], description);
}
lastIndex = index;
}
}
/*
* -1 is bullet
* 0 is nothing
* 1-9 is a number badge
* 10+ is `9+`
*/
function getOverlayIconData(count) {
// Unread message badge
if (count === -1) {
return {
index: 10,
// this.appIcons.length - 1
description: `Unread messages`
};
}
// Clear overlay icon
if (count === 0) {
return {
index: null,
// null is used to clear the overlay icon
description: 'No Notifications'
};
}
// Notification badge
const index = Math.max(1, Math.min(count, 10)) - 1; // arrays are 0 based
return {
index,
description: `${index} notifications`
};
}

49
core/src/app/appConfig.js Normal file
View File

@ -0,0 +1,49 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.hasInit = void 0;
exports.init = init;
var _autoStart = require("./bootstrapModules/autoStart");
var _appSettings = require("./bootstrapModules/appSettings");
var _ipcMain = _interopRequireDefault(require("./ipcMain"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const settings = _appSettings.appSettings.getSettings();
const NOOP = () => {};
let hasInit = false;
exports.hasInit = hasInit;
function init() {
if (hasInit) {
console.warn('appConfig: Has already init! Cancelling init.');
return;
}
exports.hasInit = hasInit = true;
_ipcMain.default.on('TOGGLE_MINIMIZE_TO_TRAY', (_event, value) => setMinimizeOnClose(value));
_ipcMain.default.on('TOGGLE_OPEN_ON_STARTUP', (_event, value) => toggleRunOnStartup(value));
_ipcMain.default.on('TOGGLE_START_MINIMIZED', (_event, value) => toggleStartMinimized(value));
_ipcMain.default.on('UPDATE_OPEN_ON_STARTUP', _event => updateOpenOnStartup());
}
function setMinimizeOnClose(minimizeToTray) {
settings.set('MINIMIZE_TO_TRAY', minimizeToTray);
}
function toggleRunOnStartup(openOnStartup) {
settings.set('OPEN_ON_STARTUP', openOnStartup);
if (openOnStartup) {
_autoStart.autoStart.install(NOOP);
} else {
_autoStart.autoStart.uninstall(NOOP);
}
}
function toggleStartMinimized(startMinimized) {
settings.set('START_MINIMIZED', startMinimized);
_autoStart.autoStart.isInstalled(installed => {
// Only update the registry for this toggle if the app was already set to autorun
if (installed) {
_autoStart.autoStart.install(NOOP);
}
});
}
function updateOpenOnStartup() {
_autoStart.autoStart.update(NOOP);
}

View File

@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getFeatures = getFeatures;
exports.init = init;
var _FeatureFlags = _interopRequireDefault(require("../common/FeatureFlags"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
let features;
function init() {
features = new _FeatureFlags.default();
}
function getFeatures() {
return features;
}

View File

@ -0,0 +1,150 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _electron = require("electron");
var _securityUtils = require("../../common/securityUtils");
var Constants = _interopRequireWildcard(require("../Constants"));
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); }
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; }
const {
MenuEvents
} = Constants;
const SEPARATOR = {
type: 'separator'
};
function getWindow() {
let window = _electron.BrowserWindow.getFocusedWindow();
if (!window) {
const windowList = _electron.BrowserWindow.getAllWindows();
if (windowList && windowList[0]) {
window = windowList[0];
window.show();
window.focus();
}
}
return window;
}
var _default = enableDevtools => [{
label: 'Discord',
submenu: [{
label: 'About Discord',
selector: 'orderFrontStandardAboutPanel:'
}, {
label: 'Check for Updates...',
click: () => _electron.app.emit(MenuEvents.CHECK_FOR_UPDATES)
}, {
label: 'Acknowledgements',
click: () => (0, _securityUtils.saferShellOpenExternal)('https://discord.com/acknowledgements')
}, SEPARATOR, {
label: 'Preferences',
click: () => _electron.app.emit(MenuEvents.OPEN_SETTINGS),
accelerator: 'Command+,'
}, SEPARATOR, {
label: 'Services',
submenu: []
}, SEPARATOR, {
label: 'Hide Discord',
selector: 'hide:',
accelerator: 'Command+H'
}, {
label: 'Hide Others',
selector: 'hideOtherApplications:',
accelerator: 'Command+Alt+H'
}, {
label: 'Show All',
selector: 'unhideAllApplications:'
}, SEPARATOR, {
label: 'Quit',
click: () => _electron.app.quit(),
accelerator: 'Command+Q'
}]
}, {
label: 'Edit',
submenu: [{
role: 'undo',
accelerator: 'Command+Z'
}, {
role: 'redo',
accelerator: 'Shift+Command+Z'
}, SEPARATOR, {
role: 'cut',
accelerator: 'Command+X'
}, {
role: 'copy',
accelerator: 'Command+C'
}, {
role: 'paste',
accelerator: 'Command+V'
}, {
role: 'selectAll',
accelerator: 'Command+A'
}]
}, {
label: 'View',
submenu: [{
label: 'Reload',
click: () => {
const window = getWindow();
if (window) {
window.webContents.reloadIgnoringCache();
}
},
accelerator: 'Command+R'
}, {
label: 'Toggle Full Screen',
click: () => {
const window = getWindow();
if (window) {
window.setFullScreen(!window.isFullScreen());
}
},
accelerator: 'Command+Control+F'
}, ...(enableDevtools ? [SEPARATOR, {
label: 'Developer',
submenu: [{
label: 'Toggle Developer Tools',
click: () => {
const window = getWindow();
if (window) {
window.toggleDevTools();
}
},
accelerator: 'Alt+Command+I'
}]
}] : [])]
}, {
label: 'Window',
submenu: [{
label: 'Minimize',
selector: 'performMiniaturize:',
accelerator: 'Command+M'
}, {
label: 'Zoom',
selector: 'performZoom:'
}, {
label: 'Close',
accelerator: 'Command+W',
click: (_, window) => {
// Main window
if (window == null || window.windowKey == null) {
_electron.Menu.sendActionToFirstResponder('hide:');
} else {
window.close();
}
}
}, SEPARATOR, {
label: 'Bring All to Front',
selector: 'arrangeInFront:'
}]
}, {
label: 'Help',
submenu: [{
label: 'Discord Help',
click: () => _electron.app.emit(MenuEvents.OPEN_HELP)
}]
}];
exports.default = _default;
module.exports = exports.default;

View File

@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _electron = require("electron");
const createMenu = require('./' + process.platform);
var _default = enableDevtools => _electron.Menu.buildFromTemplate(createMenu(enableDevtools));
exports.default = _default;
module.exports = exports.default;

View File

@ -0,0 +1,78 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _electron = require("electron");
var Constants = _interopRequireWildcard(require("../Constants"));
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); }
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; }
const {
MenuEvents
} = Constants;
const SEPARATOR = {
type: 'separator'
};
var _default = enableDevtools => [{
label: '&File',
submenu: [{
label: '&Options',
click: () => _electron.app.emit(MenuEvents.OPEN_SETTINGS),
accelerator: 'Control+,'
}, SEPARATOR, {
label: 'E&xit',
click: () => _electron.app.quit(),
accelerator: 'Control+Q'
}]
}, {
label: '&Edit',
submenu: [{
role: 'undo',
accelerator: 'Control+Z'
}, {
role: 'redo',
accelerator: 'Shift+Control+Z'
}, SEPARATOR, {
role: 'cut',
accelerator: 'Control+X'
}, {
role: 'copy',
accelerator: 'Control+C'
}, {
role: 'paste',
accelerator: 'Control+V'
}, {
role: 'selectAll',
accelerator: 'Control+A'
}]
}, {
label: '&View',
submenu: [{
label: '&Reload',
click: () => _electron.BrowserWindow.getFocusedWindow().webContents.reloadIgnoringCache(),
accelerator: 'Control+R'
}, {
label: 'Toggle &Full Screen',
click: () => _electron.BrowserWindow.getFocusedWindow().setFullScreen(!_electron.BrowserWindow.getFocusedWindow().isFullScreen()),
accelerator: 'Control+Shift+F'
}, ...(enableDevtools ? [SEPARATOR, {
label: '&Developer',
submenu: [{
label: 'Toggle Developer &Tools',
click: () => _electron.BrowserWindow.getFocusedWindow().toggleDevTools(),
accelerator: 'Control+Shift+I'
}]
}] : [])]
}, {
label: '&Help',
submenu: [{
label: 'Check for Updates',
click: () => _electron.app.emit(MenuEvents.CHECK_FOR_UPDATES)
}, SEPARATOR, {
label: 'Discord Help',
click: () => _electron.app.emit(MenuEvents.OPEN_HELP)
}]
}];
exports.default = _default;
module.exports = exports.default;

View File

@ -0,0 +1,57 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _electron = require("electron");
var Constants = _interopRequireWildcard(require("../Constants"));
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); }
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; }
const {
MenuEvents
} = Constants;
const SEPARATOR = {
type: 'separator'
};
var _default = enableDevtools => [{
label: '&File',
submenu: [{
label: '&Options',
click: () => _electron.app.emit(MenuEvents.OPEN_SETTINGS),
accelerator: 'Ctrl+,'
}, SEPARATOR, {
label: '&Exit',
click: () => _electron.app.quit(),
accelerator: 'Alt+F4'
}]
}, {
label: '&View',
submenu: [{
label: '&Reload',
click: () => _electron.BrowserWindow.getFocusedWindow().webContents.reloadIgnoringCache(),
accelerator: 'Control+R'
}, {
label: 'Toggle &Full Screen',
click: () => _electron.BrowserWindow.getFocusedWindow().setFullScreen(!_electron.BrowserWindow.getFocusedWindow().isFullScreen()),
accelerator: 'Control+Shift+F'
}, ...(enableDevtools ? [SEPARATOR, {
label: '&Developer',
submenu: [{
label: 'Toggle Developer &Tools',
click: () => _electron.BrowserWindow.getFocusedWindow().toggleDevTools(),
accelerator: 'Control+Shift+I'
}]
}] : [])]
}, {
label: '&Help',
submenu: [{
label: 'Check for Updates',
click: () => _electron.app.emit(MenuEvents.CHECK_FOR_UPDATES)
}, SEPARATOR, {
label: 'Discord Help',
click: () => _electron.app.emit(MenuEvents.OPEN_HELP)
}]
}];
exports.default = _default;
module.exports = exports.default;

View File

@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "appSettings", {
enumerable: true,
get: function () {
return _bootstrapModules.appSettings;
}
});
var _bootstrapModules = require("./bootstrapModules");

View File

@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "autoStart", {
enumerable: true,
get: function () {
return _bootstrapModules.autoStart;
}
});
var _bootstrapModules = require("./bootstrapModules");

View File

@ -0,0 +1,52 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.crashReporterSetup = exports.buildInfo = exports.autoStart = exports.appSettings = exports.GPUSettings = exports.Constants = void 0;
exports.init = init;
exports.updater = exports.splashScreen = exports.requireNative = exports.paths = exports.moduleUpdater = void 0;
let hasInit = false;
// NOTE: We may want to instead of initializing these to null, instead initialize them to their normal files.
// This way each one (see `crashReporterSetup`) would not need to do their own self-detection of loading when
// inside the overlay (or any future relevant code).
let paths = null;
exports.paths = paths;
let splashScreen = null;
exports.splashScreen = splashScreen;
let autoStart = null;
exports.autoStart = autoStart;
let requireNative = null;
exports.requireNative = requireNative;
let appSettings = null;
exports.appSettings = appSettings;
let Constants = null;
exports.Constants = Constants;
let GPUSettings = null;
exports.GPUSettings = GPUSettings;
let buildInfo = null;
exports.buildInfo = buildInfo;
let moduleUpdater = null;
exports.moduleUpdater = moduleUpdater;
let updater = null;
exports.updater = updater;
let crashReporterSetup = null;
exports.crashReporterSetup = crashReporterSetup;
function init(bootstrapModules) {
if (hasInit) {
throw new Error(`bootstrapModules has already init`);
}
exports.paths = paths = bootstrapModules.paths;
exports.splashScreen = splashScreen = bootstrapModules.splashScreen;
exports.autoStart = autoStart = bootstrapModules.autoStart;
exports.requireNative = requireNative = bootstrapModules.requireNative;
exports.appSettings = appSettings = bootstrapModules.appSettings;
exports.Constants = Constants = bootstrapModules.Constants;
exports.GPUSettings = GPUSettings = bootstrapModules.GPUSettings;
exports.buildInfo = buildInfo = bootstrapModules.buildInfo;
exports.moduleUpdater = moduleUpdater = bootstrapModules.moduleUpdater;
exports.updater = updater = bootstrapModules.updater;
exports.crashReporterSetup = crashReporterSetup = bootstrapModules.crashReporterSetup;
hasInit = true;
}

View File

@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "buildInfo", {
enumerable: true,
get: function () {
return _bootstrapModules.buildInfo;
}
});
var _bootstrapModules = require("./bootstrapModules");

View File

@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.crashReporterSetup = void 0;
var _bootstrapModules = require("./bootstrapModules");
// Note: bootstrapCrashReporterSetup will not be set in the overlay.
const crashReporterSetup = _bootstrapModules.crashReporterSetup ?? require('../../common/crashReporterSetup');
exports.crashReporterSetup = crashReporterSetup;

View File

@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "moduleUpdater", {
enumerable: true,
get: function () {
return _bootstrapModules.moduleUpdater;
}
});
var _bootstrapModules = require("./bootstrapModules");

View File

@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "paths", {
enumerable: true,
get: function () {
return _bootstrapModules.paths;
}
});
var _bootstrapModules = require("./bootstrapModules");

View File

@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "splashScreen", {
enumerable: true,
get: function () {
return _bootstrapModules.splashScreen;
}
});
var _bootstrapModules = require("./bootstrapModules");

View File

@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "updater", {
enumerable: true,
get: function () {
return _bootstrapModules.updater;
}
});
var _bootstrapModules = require("./bootstrapModules");

3865
core/src/app/data/cacert.pem Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
"use strict";
var _electron = _interopRequireDefault(require("electron"));
var _DiscordIPC = require("../common/DiscordIPC");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.ACCESSIBILITY_GET_ENABLED, _ => {
return Promise.resolve(_electron.default.app.accessibilitySupportEnabled);
});

View File

@ -0,0 +1,96 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.injectBuildInfo = injectBuildInfo;
exports.injectModuleUpdater = injectModuleUpdater;
exports.injectUpdater = injectUpdater;
var _electron = _interopRequireDefault(require("electron"));
var _DiscordIPC = require("../common/DiscordIPC");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/* eslint-disable require-await */
let injectedBuildInfo = null;
let injectedModuleUpdater = null;
let injectedUpdater = null;
function injectBuildInfo(buildInfo) {
injectedBuildInfo = buildInfo;
}
function injectModuleUpdater(moduleUpdater) {
injectedModuleUpdater = moduleUpdater;
}
function injectUpdater(updater) {
injectedUpdater = updater;
}
_DiscordIPC.DiscordIPC.main.on(_DiscordIPC.IPCEvents.APP_GET_RELEASE_CHANNEL_SYNC, event => {
event.returnValue = injectedBuildInfo.releaseChannel;
});
_DiscordIPC.DiscordIPC.main.on(_DiscordIPC.IPCEvents.APP_GET_HOST_VERSION_SYNC, event => {
event.returnValue = _electron.default.app.getVersion();
});
async function newUpdaterGetModuleVersions(updater) {
// eslint-disable-next-line camelcase
return (await updater.queryCurrentVersions()).current_modules;
}
function newUpdaterGetBuildNumber(updater) {
const version = updater.queryCurrentVersionsSync();
// eslint-disable-next-line camelcase
if (version.running_update != null) {
return version.running_update.metadata_version;
}
return version.last_successful_update.metadata_version;
}
_DiscordIPC.DiscordIPC.main.on(_DiscordIPC.IPCEvents.APP_GET_BUILD_NUMBER, event => {
var _injectedUpdater;
const newUpdater = (_injectedUpdater = injectedUpdater) === null || _injectedUpdater === void 0 ? void 0 : _injectedUpdater.getUpdater();
if (newUpdater != null) {
event.returnValue = newUpdaterGetBuildNumber(newUpdater);
return;
}
event.returnValue = null;
});
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.APP_GET_MODULE_VERSIONS, async _ => {
var _injectedUpdater2;
const newUpdater = (_injectedUpdater2 = injectedUpdater) === null || _injectedUpdater2 === void 0 ? void 0 : _injectedUpdater2.getUpdater();
if (newUpdater != null) {
return newUpdaterGetModuleVersions(newUpdater);
}
const versions = {};
const installed = injectedModuleUpdater != null ? injectedModuleUpdater.getInstalled() : {};
for (const name of Object.keys(installed)) {
versions[name] = installed[name].installedVersion;
}
return versions;
});
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.APP_GET_PATH, async (_, path) => {
// TODO: Fix argument in AsyncIPCEventMap.
return _electron.default.app.getPath(path);
});
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.APP_SET_BADGE_COUNT, async (_, count) => {
_electron.default.app.setBadgeCount(count);
});
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.APP_DOCK_SET_BADGE, async (_, badge) => {
if (_electron.default.app.dock != null) {
_electron.default.app.dock.setBadge(badge);
}
});
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.APP_DOCK_BOUNCE, async (_, type) => {
if (_electron.default.app.dock != null) {
return _electron.default.app.dock.bounce(type);
} else {
return -1;
}
});
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.APP_DOCK_CANCEL_BOUNCE, async (_, id) => {
if (_electron.default.app.dock != null) {
_electron.default.app.dock.cancelBounce(id);
}
});
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.APP_RELAUNCH, async _ => {
_electron.default.app.relaunch();
_electron.default.app.exit(0);
});
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.APP_GET_DEFAULT_DOUBLE_CLICK_ACTION, async _ => {
return _electron.default.systemPreferences.getUserDefault('AppleActionOnDoubleClick', 'string');
});

View File

@ -0,0 +1,19 @@
"use strict";
// @ts-nocheck
/* eslint-disable */
const electron = require('electron');
const {
CLIPBOARD_COPY,
CLIPBOARD_CUT,
CLIPBOARD_PASTE
} = require('../common/constants').IPCEvents;
electron.ipcMain.handle(CLIPBOARD_COPY, async _ => {
electron.webContents.getFocusedWebContents().copy();
});
electron.ipcMain.handle(CLIPBOARD_CUT, async _ => {
electron.webContents.getFocusedWebContents().cut();
});
electron.ipcMain.handle(CLIPBOARD_PASTE, async _ => {
electron.webContents.getFocusedWebContents().paste();
});

View File

@ -0,0 +1,134 @@
"use strict";
var _buffer = _interopRequireDefault(require("buffer"));
var _promises = _interopRequireDefault(require("fs/promises"));
var _path = _interopRequireDefault(require("path"));
var _DiscordIPC = require("../common/DiscordIPC");
var _fileutils = require("../common/fileutils");
var _utils = require("../common/utils");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/* eslint-disable no-console */
const MAX_LENGTH = _buffer.default.constants.MAX_LENGTH;
const DISCORD_HEADER_NAME = 'dscl';
const INVALID_FILE_ERROR = 'Invalid file';
class InvalidFileError extends Error {}
function verifyIsMP4(buffer) {
if (getBoxHeaderName(buffer, 0) !== 'ftyp') {
throw new InvalidFileError(INVALID_FILE_ERROR);
}
}
function verifyHasMP4Extension(filename) {
if (_path.default.parse(filename).ext !== '.mp4') {
throw new InvalidFileError(INVALID_FILE_ERROR);
}
}
function getBoxSize(buffer, startIndex) {
return buffer.readUInt32BE(startIndex);
}
function getBoxHeaderName(buffer, startIndex) {
return buffer.toString('ascii', startIndex + 4, startIndex + 8);
}
function verifyValidClip(buffer) {
let currIndex = 0;
while (currIndex < buffer.byteLength) {
const boxHeaderName = getBoxHeaderName(buffer, currIndex);
if (boxHeaderName === DISCORD_HEADER_NAME) {
return;
}
const boxSize = getBoxSize(buffer, currIndex);
//box size must be at least 8 to account for header, so return false for malformed file
if (boxSize < 8) {
throw new InvalidFileError(INVALID_FILE_ERROR);
}
currIndex += boxSize;
}
throw new InvalidFileError(INVALID_FILE_ERROR);
}
async function loadClip(filename) {
try {
verifyHasMP4Extension(filename);
const result = await (0, _fileutils.readFulfilledFiles)([filename], MAX_LENGTH, true);
const buffer = result[0].data;
verifyIsMP4(buffer);
verifyValidClip(buffer);
return result[0];
} catch (e) {
if (e instanceof InvalidFileError) {
console.log(`Invalid clips file: ${e}`);
} else {
console.error(`Invalid clips file: ${e}`);
}
throw new Error(INVALID_FILE_ERROR);
}
}
async function getClipMetadata(filename, dirPath) {
try {
verifyHasMP4Extension(filename);
} catch (e) {
return null;
}
const filepath = _path.default.join(dirPath, filename);
const handle = await _promises.default.open(filepath, 'r');
const stats = await handle.stat();
let currIndex = 0;
const mp4HeaderBuffer = Buffer.alloc(8);
try {
await handle.read({
buffer: mp4HeaderBuffer,
position: 0
});
verifyIsMP4(mp4HeaderBuffer);
currIndex += getBoxSize(mp4HeaderBuffer, currIndex);
while (currIndex < stats.size) {
await handle.read({
buffer: mp4HeaderBuffer,
position: currIndex
});
const boxSize = getBoxSize(mp4HeaderBuffer, 0);
if (boxSize < 8) {
return null;
}
const header = getBoxHeaderName(mp4HeaderBuffer, 0);
if (header === DISCORD_HEADER_NAME) {
const metadataBuffer = Buffer.alloc(boxSize - 8);
await handle.read({
buffer: metadataBuffer,
position: currIndex + 8
});
const metadata = JSON.parse(metadataBuffer.toString('utf-8'));
return {
filepath: filepath,
metadata: metadata
};
}
currIndex += boxSize;
}
return null;
} catch (e) {
console.log(`error: ${e}`);
return null;
} finally {
await handle.close();
}
}
async function deleteClip(path) {
try {
await loadClip(path);
await (0, _fileutils.deleteFile)(path);
} catch (e) {
console.log(`Invalid clips file to delete: ${e}`);
throw new Error(INVALID_FILE_ERROR);
}
}
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.LOAD_CLIP, (_, path) => {
return loadClip(path);
});
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.LOAD_CLIPS_DIRECTORY, async (_, dirPath) => {
const filenames = await (0, _fileutils.getFilesnamesFromDirectory)(dirPath);
const filteredFiles = (await Promise.all(filenames.map(filename => getClipMetadata(filename, dirPath)))).filter(_utils.isNotNullish);
return filteredFiles;
});
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.DELETE_CLIP, (_, path) => {
return deleteClip(path);
});

View File

@ -0,0 +1,26 @@
"use strict";
// @ts-nocheck
/* eslint-disable */
const electron = require('electron');
const {
CONSTANTS_GET
} = require('../common/constants').IPCEvents;
const {
APP_NAME,
APP_ID,
API_ENDPOINT,
UPDATE_ENDPOINT
} = require('../../Constants');
const exposedConstants = {
APP_NAME,
APP_ID,
API_ENDPOINT,
UPDATE_ENDPOINT
};
electron.ipcMain.handle(CONSTANTS_GET, async (_, name) => {
if (!exposedConstants.hasOwnProperty(name)) {
return undefined;
}
return exposedConstants[name];
});

View File

@ -0,0 +1,25 @@
"use strict";
var _assert = _interopRequireDefault(require("assert"));
var _electron = _interopRequireDefault(require("electron"));
var _lodash = _interopRequireDefault(require("lodash"));
var _crashReporterUtils = require("../../../common/crashReporterUtils");
var _crashReporterSetup = require("../../bootstrapModules/crashReporterSetup");
var _DiscordIPC = require("../common/DiscordIPC");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.CRASH_REPORTER_UPDATE_METADATA, (_, additionalMetadata) => {
const metadata = _crashReporterSetup.crashReporterSetup.metadata;
(0, _assert.default)(metadata != null, 'Metadata imported improperly.');
const finalMetadata = _lodash.default.defaultsDeep(metadata, additionalMetadata ?? {});
(0, _crashReporterUtils.reconcileCrashReporterMetadata)(_electron.default.crashReporter, finalMetadata);
return Promise.resolve({
metadata: finalMetadata
});
});
// Internal test for unhandled JS exception
_electron.default.ipcMain.handle(_DiscordIPC.IPCEvents.UNHANDLED_JS_EXCEPTION, _ => {
setTimeout(() => {
throw new Error('UNHANDLED_EXCEPTION ' + process.type);
}, 50);
});

View File

@ -0,0 +1,8 @@
"use strict";
var _electron = _interopRequireDefault(require("electron"));
var _DiscordIPC = require("../common/DiscordIPC");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.DESKTOP_CAPTURER_GET_SOURCES, (_, opts) => {
return _electron.default.desktopCapturer.getSources(opts);
});

View File

@ -0,0 +1,25 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.injectFeaturesBackend = injectFeaturesBackend;
var _DiscordIPC = require("../common/DiscordIPC");
let injectedFeatures = null;
function getFeatures() {
return injectedFeatures != null ? injectedFeatures : {
getSupported: () => {
return [];
},
supports: () => {
return false;
},
declareSupported: () => {}
};
}
function injectFeaturesBackend(features) {
injectedFeatures = features;
}
_DiscordIPC.DiscordIPC.main.on(_DiscordIPC.IPCEvents.FEATURES_GET_BROWSER_FEATURES, event => {
event.returnValue = getFeatures().getSupported();
});

View File

@ -0,0 +1,32 @@
"use strict";
var _electron = _interopRequireDefault(require("electron"));
var _DiscordIPC = require("../common/DiscordIPC");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/* eslint-disable require-await */
function getModulePath() {
// The smoketest's need to be able to:
// 1) store multiple running instances data separately,
// 2) have it in a known location so it can be used as a build artifact.
if (process.env.DISCORD_USER_DATA_DIR != null) {
return process.env.DISCORD_USER_DATA_DIR;
}
return global.moduleDataPath ?? global.modulePath;
}
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.FILE_MANAGER_GET_MODULE_PATH, async _ => {
return getModulePath();
});
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.FILE_MANAGER_SHOW_SAVE_DIALOG, async (_, dialogOptions) => {
return await _electron.default.dialog.showSaveDialog(dialogOptions);
});
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.FILE_MANAGER_SHOW_OPEN_DIALOG, async (_, dialogOptions) => {
return await _electron.default.dialog.showOpenDialog(dialogOptions);
});
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.FILE_MANAGER_SHOW_ITEM_IN_FOLDER, async (_, path) => {
_electron.default.shell.showItemInFolder(path);
});
_DiscordIPC.DiscordIPC.main.on(_DiscordIPC.IPCEvents.FILE_MANAGER_GET_MODULE_DATA_PATH_SYNC, event => {
// This is kind of a lie... we offer no promise that moduleDataPath or modulePath are set.
event.returnValue = getModulePath();
});

View File

@ -0,0 +1,89 @@
"use strict";
var _electron = _interopRequireDefault(require("electron"));
var _path = _interopRequireDefault(require("path"));
var _url = require("url");
var _processUtils = require("../../../common/processUtils");
var _mainScreen = require("../../mainScreen");
var _DiscordIPC = require("../common/DiscordIPC");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/* eslint-disable no-console */
let interactiveWindow = null;
// let transparentWindow: electron.BrowserWindow | null = null;
// We need to be restrictive about what url's are accepted.
function isValidUrl(url) {
try {
const parsedUrl = new _url.URL(url);
if (parsedUrl.origin !== _mainScreen.WEBAPP_ENDPOINT) {
console.error(`isValidUrl: "${parsedUrl.origin}" !== "${_mainScreen.WEBAPP_ENDPOINT}" (${url})`);
return false;
}
if (parsedUrl.pathname !== '/overlay') {
console.error(`isValidUrl: Invalid pathname "${parsedUrl.pathname}" (${url})`);
return false;
}
return true;
} catch (e) {
console.error(`isValidUrl: Error "${e}" (${url})`);
return false;
}
}
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.GLOBAL_OVERLAY_OPEN, (_, url) => {
if (!_processUtils.IS_WIN) {
console.log('GLOBAL_OVERLAY_OPEN: Windows only.');
return Promise.resolve();
}
// TODO: Check if the url has changed...?
if (interactiveWindow != null) {
console.log('GLOBAL_OVERLAY_OPEN: Window already open.');
return Promise.resolve();
}
if (!isValidUrl(url)) {
return Promise.resolve();
}
// The title is randomized to prevent multiple instances from having conflicting titles.
// We may want a global lock on there being a single global overlay tho.
// TODO: The titlebar is blanked out by the javascript code, which is fine'ish for now because the mixture
// of window class and window title are unique for the time being.
const windowOptions = {
width: 0,
height: 0,
x: 0,
y: 0,
transparent: true,
title: 'Discord_Overlay3' + Math.round(Math.random() * 1e9).toString(16),
// TODO: For some reason, it does not workout if the window starts hidden. Perhaps it's not loading and the native
// code isn't firing?
// show: false, // It's shown when initialized by the native code.
frame: false,
// Sets WS_EX_NOACTIVATE, which keeps it out of the taskbar prior to our initialization running.
// Disabled for the time being as it appears to make opening dev tools impossible.
// focusable: true,
webPreferences: {
preload: _path.default.join(__dirname, '..', '..', 'mainScreenPreload.js'),
nodeIntegration: false,
sandbox: false,
contextIsolation: true
}
};
try {
interactiveWindow = new _electron.default.BrowserWindow(windowOptions);
interactiveWindow.once('closed', () => {
// Untested code path.
interactiveWindow = null;
console.log('GLOBAL_OVERLAY_OPEN: closed');
});
// Enable when finally working on the non-interactive layer.
// transparentWindow = new electron.BrowserWindow(windowOptions);
interactiveWindow.loadURL(url + '#global_overlay');
} catch (e) {
console.log(`GLOBAL_OVERLAY_OPEN: Error "${e.text}"\n${e.stack}`);
}
return Promise.resolve();
});

View File

@ -0,0 +1,25 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.injectGpuSettingsBackend = injectGpuSettingsBackend;
// @ts-nocheck
/* eslint-disable */
const electron = require('electron');
const {
GPU_SETTINGS_SET_ENABLE_HWACCEL,
GPU_SETTINGS_GET_ENABLE_HWACCEL_SYNC
} = require('../common/constants').IPCEvents;
let injectedGpuSettings = null;
function injectGpuSettingsBackend(gpuSettings) {
injectedGpuSettings = gpuSettings;
}
electron.ipcMain.handle(GPU_SETTINGS_SET_ENABLE_HWACCEL, async (_, enable) => {
if (injectedGpuSettings) {
injectedGpuSettings.setEnableHardwareAcceleration(enable);
}
});
electron.ipcMain.on(GPU_SETTINGS_GET_ENABLE_HWACCEL_SYNC, event => {
event.returnValue = injectedGpuSettings != null ? injectedGpuSettings.getEnableHardwareAcceleration() : false;
});

View File

@ -0,0 +1,97 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.injectModuleUpdater = injectModuleUpdater;
exports.injectUpdater = injectUpdater;
const childProcess = require('child_process');
const electron = require('electron');
const {
once
} = require('events');
const path = require('path');
const process = require('process');
const {
getGlobalPaths
} = require('../../../common/nodeGlobalPaths');
const {
NATIVE_MODULES_GET_PATHS,
NATIVE_MODULES_INSTALL,
NATIVE_MODULES_FINISH_UPDATER_BOOTSTRAP,
NATIVE_MODULES_GET_HAS_NEW_UPDATER
} = require('../common/constants').IPCEvents;
let injectedModuleUpdater = null;
let injectedUpdater = null;
function injectModuleUpdater(moduleUpdater) {
injectedModuleUpdater = moduleUpdater;
}
function injectUpdater(updater) {
injectedUpdater = updater;
}
electron.ipcMain.on(NATIVE_MODULES_GET_PATHS, event => {
event.returnValue = {
mainAppDirname: global.mainAppDirname,
browserModulePaths: getGlobalPaths()
};
});
async function newUpdaterInstall(updater, moduleName) {
try {
await updater.installModule(moduleName);
await updater.commitModules();
} catch (e) {
throw new Error(`Failed to install ${moduleName}: ${e}`);
}
}
electron.ipcMain.handle(NATIVE_MODULES_INSTALL, async (_, moduleName) => {
var _injectedUpdater;
const newUpdater = (_injectedUpdater = injectedUpdater) === null || _injectedUpdater === void 0 ? void 0 : _injectedUpdater.getUpdater();
if (newUpdater != null) {
return newUpdaterInstall(newUpdater, moduleName);
}
const updater = injectedModuleUpdater;
if (!updater) {
throw new Error('Module updater is not available!');
}
const waitForInstall = new Promise((resolve, reject) => {
const installedHandler = installedModuleEvent => {
if (installedModuleEvent.name === moduleName) {
updater.events.removeListener(updater.INSTALLED_MODULE, installedHandler);
if (installedModuleEvent.succeeded) {
resolve();
} else {
reject(new Error(`Failed to install ${moduleName}`));
}
}
};
updater.events.on(updater.INSTALLED_MODULE, installedHandler);
});
updater.install(moduleName, false);
await waitForInstall;
});
electron.ipcMain.on(NATIVE_MODULES_GET_HAS_NEW_UPDATER, event => {
var _injectedUpdater2;
event.returnValue = ((_injectedUpdater2 = injectedUpdater) === null || _injectedUpdater2 === void 0 ? void 0 : _injectedUpdater2.getUpdater()) != null;
});
// This endpoint is a bit special in the sense that it's exposed from
// discord_updater_bootstrap instead of discord_desktop_core. The reason for
// this is so that a malicious app can't pass in an arbitrary version number to
// launch.
electron.ipcMain.on(NATIVE_MODULES_FINISH_UPDATER_BOOTSTRAP, async (_, [major, minor, revision]) => {
// TODO(eiz): This code is currently duplicated between the updater and here
// due to bootstrapping reasons. I'd like to not have it be that way.
if (typeof major !== 'number' || typeof minor !== 'number' || typeof revision !== 'number') {
throw new Error('You tried.');
}
const hostVersionStr = `${major}.${minor}.${revision}`;
const hostExePath = path.join(path.dirname(process.execPath), '..', `app-${hostVersionStr}`, path.basename(process.execPath));
electron.app.once('will-quit', () => {
childProcess.spawn(hostExePath, [], {
detached: true,
stdio: 'inherit'
});
});
console.log(`Restarting from ${path.resolve(process.execPath)} to ${path.resolve(hostExePath)}`);
electron.app.quit();
});

View File

@ -0,0 +1,33 @@
"use strict";
const electron = require('electron');
const {
POWER_MONITOR_RESUME,
POWER_MONITOR_SUSPEND,
POWER_MONITOR_LOCK_SCREEN,
POWER_MONITOR_UNLOCK_SCREEN,
POWER_MONITOR_GET_SYSTEM_IDLE_TIME
} = require('../common/constants').IPCEvents;
electron.ipcMain.handle(POWER_MONITOR_GET_SYSTEM_IDLE_TIME, async _ => {
return electron.powerMonitor.getSystemIdleTime() * 1000;
});
function sendToAllWindows(channel) {
electron.BrowserWindow.getAllWindows().forEach(win => {
const contents = win.webContents;
if (contents != null) {
contents.send(channel);
}
});
}
electron.powerMonitor.on('resume', () => {
sendToAllWindows(POWER_MONITOR_RESUME);
});
electron.powerMonitor.on('suspend', () => {
sendToAllWindows(POWER_MONITOR_SUSPEND);
});
electron.powerMonitor.on('lock-screen', () => {
sendToAllWindows(POWER_MONITOR_LOCK_SCREEN);
});
electron.powerMonitor.on('unlock-screen', () => {
sendToAllWindows(POWER_MONITOR_UNLOCK_SCREEN);
});

View File

@ -0,0 +1,25 @@
"use strict";
const electron = require('electron');
const {
POWER_SAVE_BLOCKER_BLOCK_DISPLAY_SLEEP,
POWER_SAVE_BLOCKER_UNBLOCK_DISPLAY_SLEEP,
POWER_SAVE_BLOCKER_CLEANUP_DISPLAY_SLEEP
} = require('../common/constants').IPCEvents;
const powerSaveBlockerIds = new Set();
electron.ipcMain.handle(POWER_SAVE_BLOCKER_BLOCK_DISPLAY_SLEEP, async _ => {
const newId = electron.powerSaveBlocker.start('prevent-display-sleep');
powerSaveBlockerIds.add(newId);
return newId;
});
electron.ipcMain.handle(POWER_SAVE_BLOCKER_UNBLOCK_DISPLAY_SLEEP, async (_, id) => {
electron.powerSaveBlocker.stop(id);
powerSaveBlockerIds.delete(id);
});
electron.ipcMain.handle(POWER_SAVE_BLOCKER_CLEANUP_DISPLAY_SLEEP, async _ => {
// cleanup all previous sleeps
for (const id of powerSaveBlockerIds) {
electron.powerSaveBlocker.stop(id);
}
powerSaveBlockerIds.clear();
});

View File

@ -0,0 +1,80 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.processUtilsSettings = void 0;
var _electron = _interopRequireDefault(require("electron"));
var _os = _interopRequireDefault(require("os"));
var _process = _interopRequireDefault(require("process"));
var _systeminformation = _interopRequireDefault(require("systeminformation"));
var _DiscordIPC = require("../common/DiscordIPC");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// Since crashes normally happen inside of the renderer process, we can store crash information inside of the
// browser/main process, and report it back after the next startup.
// lastRunsStoredInformation is set from currentStoredInformation, and currentStoredInformation is cleared on startup.
const processUtilsSettings = {
rendererCrashReason: null,
rendererCrashExitCode: null,
lastRunsStoredInformation: {},
currentStoredInformation: {}
};
exports.processUtilsSettings = processUtilsSettings;
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.PROCESS_UTILS_GET_CPU_USAGE, _ => {
let totalProcessorUsagePercent = 0.0;
for (const processMetric of _electron.default.app.getAppMetrics()) {
totalProcessorUsagePercent += processMetric.cpu.percentCPUUsage;
}
return Promise.resolve(totalProcessorUsagePercent);
});
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.PROCESS_UTILS_GET_LAST_CRASH, _ => {
return Promise.resolve({
..._electron.default.crashReporter.getLastCrashReport(),
rendererCrashReason: processUtilsSettings.rendererCrashReason,
rendererCrashExitCode: processUtilsSettings.rendererCrashExitCode,
storedInformation: processUtilsSettings.lastRunsStoredInformation
});
});
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.PROCESS_UTILS_GET_MEMORY_INFO, _ => {
return _process.default.getProcessMemoryInfo();
});
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.PROCESS_UTILS_GET_SYSTEM_INFO, async _ => {
const gpuInfo = await _systeminformation.default.graphics();
return {
cpus: _os.default.cpus().map(cpu => ({
model: cpu.model,
speed: cpu.speed
})),
gpus: gpuInfo.controllers.map(({
model,
vendor,
vram
}) => ({
model,
vendor,
memory: vram ?? -1
})),
total_memory: _os.default.totalmem()
};
});
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.PROCESS_UTILS_FLUSH_DNS_CACHE, _ => {
const defaultSession = _electron.default.session.defaultSession;
if (defaultSession != null && defaultSession.clearHostResolverCache != null) {
defaultSession.clearHostResolverCache();
}
return Promise.resolve();
});
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.PROCESS_UTILS_FLUSH_COOKIES, _ => {
return _electron.default.session.defaultSession.cookies.flushStore();
});
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.PROCESS_UTILS_FLUSH_STORAGE_DATA, _ => {
_electron.default.session.defaultSession.flushStorageData();
return Promise.resolve();
});
_DiscordIPC.DiscordIPC.main.on(_DiscordIPC.IPCEvents.PROCESS_UTILS_GET_MAIN_ARGV_SYNC, event => {
event.returnValue = _process.default.argv;
});
_DiscordIPC.DiscordIPC.main.handle(_DiscordIPC.IPCEvents.PROCESS_UTILS_SET_CRASH_INFORMATION, (_, crashInformation, state) => {
processUtilsSettings.currentStoredInformation[crashInformation] = state;
return Promise.resolve();
});

View File

@ -0,0 +1,29 @@
"use strict";
const electron = require('electron');
const {
SAFE_STORAGE_IS_ENCRYPTION_AVAILABLE,
SAFE_STORAGE_ENCRYPT_STRING,
SAFE_STORAGE_DECRYPT_STRING
} = require('../common/constants').IPCEvents;
electron.ipcMain.on(SAFE_STORAGE_IS_ENCRYPTION_AVAILABLE, event => {
event.returnValue = electron.safeStorage != null && electron.safeStorage.isEncryptionAvailable();
});
electron.ipcMain.on(SAFE_STORAGE_ENCRYPT_STRING, (event, plainText) => {
if (plainText) {
event.returnValue = electron.safeStorage.encryptString(plainText).toString('base64');
} else {
event.returnValue = null;
}
});
electron.ipcMain.on(SAFE_STORAGE_DECRYPT_STRING, (event, encrypted) => {
if (encrypted) {
try {
event.returnValue = electron.safeStorage.decryptString(Buffer.from(encrypted, 'base64'));
} catch {
event.returnValue = null;
}
} else {
event.returnValue = null;
}
});

View File

@ -0,0 +1,36 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.injectSettingsBackend = injectSettingsBackend;
const electron = require('electron');
const {
SETTINGS_GET,
SETTINGS_SET,
SETTINGS_GET_SYNC
} = require('../common/constants').IPCEvents;
let injectedSettings = null;
function getSettings() {
return injectedSettings != null ? injectedSettings : {
get: () => {},
set: () => {},
save: () => {}
};
}
function injectSettingsBackend(settings) {
injectedSettings = settings;
}
electron.ipcMain.handle(SETTINGS_GET, (_, name, defaultValue) => {
const settings = getSettings();
return settings.get(name, defaultValue);
});
electron.ipcMain.handle(SETTINGS_SET, (_, name, value) => {
const settings = getSettings();
settings.set(name, value);
settings.save();
});
electron.ipcMain.on(SETTINGS_GET_SYNC, (event, name, defaultValue) => {
const settings = getSettings();
event.returnValue = settings.get(name, defaultValue);
});

View File

@ -0,0 +1,39 @@
"use strict";
const electron = require('electron');
const {
SPELLCHECK_REPLACE_MISSPELLING,
SPELLCHECK_GET_AVAILABLE_DICTIONARIES,
SPELLCHECK_SET_LOCALE,
SPELLCHECK_SET_LEARNED_WORDS
} = require('../common/constants').IPCEvents;
let _learnedWords = new Set();
let _hasLoadedLearnedWords = false;
electron.ipcMain.handle(SPELLCHECK_REPLACE_MISSPELLING, async (event, correction) => {
event.sender.replaceMisspelling(correction);
});
electron.ipcMain.handle(SPELLCHECK_GET_AVAILABLE_DICTIONARIES, async _ => {
return electron.session.defaultSession.availableSpellCheckerLanguages;
});
electron.ipcMain.handle(SPELLCHECK_SET_LOCALE, async (_, locale) => {
electron.session.defaultSession.setSpellCheckerLanguages([locale]);
});
electron.ipcMain.handle(SPELLCHECK_SET_LEARNED_WORDS, async (_, newLearnedWords) => {
const session = electron.session.defaultSession;
if (!_hasLoadedLearnedWords) {
const dictionaryContents = await session.listWordsInSpellCheckerDictionary();
_learnedWords = new Set(dictionaryContents);
_hasLoadedLearnedWords = true;
}
_learnedWords.forEach(word => {
if (!newLearnedWords.has(word)) {
session.removeWordFromSpellCheckerDictionary(word);
}
});
newLearnedWords.forEach(word => {
if (!_learnedWords.has(word)) {
session.addWordToSpellCheckerDictionary(word);
}
});
_learnedWords = new Set(newLearnedWords);
});

View File

@ -0,0 +1,54 @@
"use strict";
var _electron = _interopRequireDefault(require("electron"));
var _fs = _interopRequireDefault(require("fs"));
var _path = _interopRequireDefault(require("path"));
var _appFeatures = require("../../appFeatures");
var _paths = require("../../bootstrapModules/paths");
var _constants = require("../common/constants");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const {
USER_DATA_CACHE_SAVE,
USER_DATA_CACHE_GET,
USER_DATA_CACHE_DELETE
} = _constants.IPCEvents;
const features = (0, _appFeatures.getFeatures)();
function getCachePath() {
return _path.default.join(_paths.paths.getUserData(), 'userDataCache.json');
}
function getMigratedPath() {
return _path.default.join(_paths.paths.getUserData(), 'domainMigrated');
}
function cacheUserData(userData) {
_fs.default.writeFile(getCachePath(), userData, e => {
if (e) {
console.warn('Failed updating user data cache with error: ', e);
}
});
}
function getCachedUserData() {
try {
return JSON.parse(_fs.default.readFileSync(getCachePath()));
} catch (_err) {}
return null;
}
function deleteCachedUserData() {
try {
_fs.default.unlinkSync(getCachePath());
_fs.default.writeFile(getMigratedPath(), '', e => {
if (e) {
console.warn('Failed to create domainMigrated file with error: ', e);
}
});
} catch (_err) {}
}
_electron.default.ipcMain.handle(USER_DATA_CACHE_GET, () => {
return getCachedUserData();
});
_electron.default.ipcMain.on(USER_DATA_CACHE_SAVE, (_event, userData) => {
cacheUserData(userData);
});
_electron.default.ipcMain.on(USER_DATA_CACHE_DELETE, _event => {
deleteCachedUserData();
});
features.declareSupported('user_data_cache');

View File

@ -0,0 +1,97 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.injectGetWindow = injectGetWindow;
const electron = require('electron');
const process = require('process');
const {
WINDOW_BLUR,
WINDOW_CLOSE,
WINDOW_FOCUS,
WINDOW_MAXIMIZE,
WINDOW_MINIMIZE,
WINDOW_RESTORE,
WINDOW_FLASH_FRAME,
WINDOW_TOGGLE_FULLSCREEN,
WINDOW_SET_BACKGROUND_THROTTLING,
WINDOW_SET_PROGRESS_BAR,
WINDOW_IS_ALWAYS_ON_TOP,
WINDOW_SET_ALWAYS_ON_TOP
} = require('../common/constants').IPCEvents;
let injectedGetWindow = _key => {
return null;
};
function injectGetWindow(getWindow) {
injectedGetWindow = getWindow;
}
electron.ipcMain.handle(WINDOW_FLASH_FRAME, async (_, flag) => {
const currentWindow = injectedGetWindow();
if (currentWindow == null || currentWindow.flashFrame == null) return;
currentWindow.flashFrame(!currentWindow.isFocused() && flag);
});
electron.ipcMain.handle(WINDOW_MINIMIZE, async (_, key) => {
const win = injectedGetWindow(key);
if (win == null) return;
win.minimize();
});
electron.ipcMain.handle(WINDOW_RESTORE, async (_, key) => {
const win = injectedGetWindow(key);
if (win == null) return;
win.restore();
});
electron.ipcMain.handle(WINDOW_MAXIMIZE, async (_, key) => {
const win = injectedGetWindow(key);
if (win == null) return;
if (win.isMaximized()) {
win.unmaximize();
} else {
win.maximize();
}
});
electron.ipcMain.handle(WINDOW_FOCUS, async (_, key) => {
const win = injectedGetWindow(key);
if (win == null) return;
win.show();
win.setSkipTaskbar(false);
});
electron.ipcMain.handle(WINDOW_SET_ALWAYS_ON_TOP, async (_, key, enabled) => {
const win = injectedGetWindow(key);
if (win == null) return;
win.setAlwaysOnTop(enabled);
});
electron.ipcMain.handle(WINDOW_IS_ALWAYS_ON_TOP, async (_, key) => {
const win = injectedGetWindow(key);
if (win == null) return false;
return win.isAlwaysOnTop();
});
electron.ipcMain.handle(WINDOW_BLUR, async (_, key) => {
const win = injectedGetWindow(key);
if (win != null && !win.isDestroyed()) {
win.blur();
}
});
electron.ipcMain.handle(WINDOW_SET_PROGRESS_BAR, async (_, key, progress) => {
const win = injectedGetWindow(key);
if (win == null) return;
win.setProgressBar(progress);
});
electron.ipcMain.handle(WINDOW_TOGGLE_FULLSCREEN, async (_, key) => {
const currentWindow = injectedGetWindow(key);
currentWindow.setFullScreen(!currentWindow.isFullScreen());
});
electron.ipcMain.handle(WINDOW_CLOSE, async (_, key) => {
if (key == null && process.platform === 'darwin') {
electron.Menu.sendActionToFirstResponder('hide:');
} else {
const win = injectedGetWindow(key);
if (win == null) return;
win.close();
}
});
electron.ipcMain.handle(WINDOW_SET_BACKGROUND_THROTTLING, async (_, enabled) => {
const win = injectedGetWindow();
if (win == null) return;
win.webContents.setBackgroundThrottling(enabled);
});

View File

@ -0,0 +1,62 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.DiscordIPC = void 0;
Object.defineProperty(exports, "IPCEvents", {
enumerable: true,
get: function () {
return _constants.IPCEvents;
}
});
var _electron = _interopRequireDefault(require("electron"));
var _constants = require("./constants");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/* eslint-disable prefer-spread */
// Save people from needing two imports.
class DiscordMainIPC {
/**
* For handling sync events.
*/
static on(channel, listener) {
_electron.default.ipcMain.on(channel, (...args) => {
return listener.apply(this, args);
});
}
/**
* For handling async events.
*/
static handle(channel, listener) {
return _electron.default.ipcMain.handle(channel, (...args) => {
return listener.apply(this, args);
});
}
}
class DiscordRendererIPC {
/**
* For sending sync events.
*/
static sendSync(...args) {
return _electron.default.ipcRenderer.sendSync.apply(_electron.default.ipcRenderer, args);
}
/**
* For sending async events.
*/
static invoke(...args) {
return _electron.default.ipcRenderer.invoke.apply(_electron.default.ipcRenderer, args);
}
}
const DiscordIPC = {
main: DiscordMainIPC,
renderer: DiscordRendererIPC
};
exports.DiscordIPC = DiscordIPC;

View File

@ -0,0 +1,116 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.IPCEvents = void 0;
exports.getDiscordIPCEvent = getDiscordIPCEvent;
const discordPrefixRegex = /^DISCORD_/;
function getDiscordIPCEvent(ev) {
return discordPrefixRegex.test(ev) ? ev : `DISCORD_${ev}`;
}
// Namespace all event names with DISCORD_
let IPCEvents;
exports.IPCEvents = IPCEvents;
(function (IPCEvents) {
IPCEvents["ACCESSIBILITY_GET_ENABLED"] = "DISCORD_ACCESSIBILITY_GET_ENABLED";
IPCEvents["APP_BADGE_SET"] = "DISCORD_APP_BADGE_SET";
IPCEvents["APP_GET_RELEASE_CHANNEL_SYNC"] = "DISCORD_APP_GET_RELEASE_CHANNEL_SYNC";
IPCEvents["APP_GET_HOST_VERSION_SYNC"] = "DISCORD_APP_GET_HOST_VERSION_SYNC";
IPCEvents["APP_GET_BUILD_NUMBER"] = "DISCORD_APP_GET_BUILD_NUMBER";
IPCEvents["APP_GET_MODULE_VERSIONS"] = "DISCORD_APP_GET_MODULE_VERSIONS";
IPCEvents["APP_GET_PATH"] = "DISCORD_APP_GET_PATH";
IPCEvents["APP_SET_BADGE_COUNT"] = "DISCORD_APP_SET_BADGE_COUNT";
IPCEvents["APP_DOCK_SET_BADGE"] = "DISCORD_APP_DOCK_SET_BADGE";
IPCEvents["APP_DOCK_BOUNCE"] = "DISCORD_APP_DOCK_BOUNCE";
IPCEvents["APP_DOCK_CANCEL_BOUNCE"] = "DISCORD_APP_DOCK_CANCEL_BOUNCE";
IPCEvents["APP_RELAUNCH"] = "DISCORD_APP_RELAUNCH";
IPCEvents["APP_GET_DEFAULT_DOUBLE_CLICK_ACTION"] = "DISCORD_APP_GET_DEFAULT_DOUBLE_CLICK_ACTION";
IPCEvents["CLIPBOARD_COPY"] = "DISCORD_CLIPBOARD_COPY";
IPCEvents["CLIPBOARD_CUT"] = "DISCORD_CLIPBOARD_CUT";
IPCEvents["CLIPBOARD_PASTE"] = "DISCORD_CLIPBOARD_PASTE";
IPCEvents["LOAD_CLIP"] = "DISCORD_LOAD_CLIP";
IPCEvents["LOAD_CLIPS_DIRECTORY"] = "DISCORD_LOAD_CLIPS_DIRECTORY";
IPCEvents["DELETE_CLIP"] = "DISCORD_DELETE_CLIP";
IPCEvents["CHECK_FOR_UPDATES"] = "DISCORD_CHECK_FOR_UPDATES";
IPCEvents["DESKTOP_CAPTURER_GET_SOURCES"] = "DISCORD_DESKTOP_CAPTURER_GET_SOURCES";
IPCEvents["CONSTANTS_GET"] = "DISCORD_CONSTANTS_GET";
IPCEvents["CRASH_REPORTER_UPDATE_METADATA"] = "DISCORD_CRASH_REPORTER_UPDATE_METADATA";
IPCEvents["FEATURES_GET_BROWSER_FEATURES"] = "DISCORD_FEATURES_GET_BROWSER_FEATURES";
IPCEvents["FILE_MANAGER_GET_MODULE_PATH"] = "DISCORD_FILE_MANAGER_GET_MODULE_PATH";
IPCEvents["FILE_MANAGER_GET_MODULE_DATA_PATH_SYNC"] = "DISCORD_FILE_MANAGER_GET_MODULE_DATA_PATH_SYNC";
IPCEvents["FILE_MANAGER_SHOW_SAVE_DIALOG"] = "DISCORD_FILE_MANAGER_SHOW_SAVE_DIALOG";
IPCEvents["FILE_MANAGER_SHOW_OPEN_DIALOG"] = "DISCORD_FILE_MANAGER_SHOW_OPEN_DIALOG";
IPCEvents["FILE_MANAGER_SHOW_ITEM_IN_FOLDER"] = "DISCORD_FILE_MANAGER_SHOW_ITEM_IN_FOLDER";
IPCEvents["GPU_SETTINGS_SET_ENABLE_HWACCEL"] = "DISCORD_GPU_SETTINGS_SET_ENABLE_HWACCEL";
IPCEvents["GPU_SETTINGS_GET_ENABLE_HWACCEL_SYNC"] = "DISCORD_GPU_SETTINGS_GET_ENABLE_HWACCEL_SYNC";
IPCEvents["NATIVE_MODULES_GET_PATHS"] = "DISCORD_NATIVE_MODULES_GET_PATHS";
IPCEvents["NATIVE_MODULES_INSTALL"] = "DISCORD_NATIVE_MODULES_INSTALL";
IPCEvents["NATIVE_MODULES_FINISH_UPDATER_BOOTSTRAP"] = "DISCORD_NATIVE_MODULES_FINISH_UPDATER_BOOTSTRAP";
IPCEvents["NATIVE_MODULES_GET_HAS_NEW_UPDATER"] = "DISCORD_NATIVE_MODULES_GET_HAS_NEW_UPDATER";
IPCEvents["NOTIFICATION_CLOSE"] = "DISCORD_NOTIFICATION_CLOSE";
IPCEvents["NOTIFICATION_SHOW"] = "DISCORD_NOTIFICATION_SHOW";
IPCEvents["NOTIFICATIONS_CLEAR"] = "DISCORD_NOTIFICATIONS_CLEAR";
IPCEvents["OPEN_EXTERNAL_URL"] = "DISCORD_OPEN_EXTERNAL_URL";
IPCEvents["GLOBAL_OVERLAY_OPEN"] = "DISCORD_GLOBAL_OVERLAY_OPEN";
IPCEvents["POWER_MONITOR_RESUME"] = "DISCORD_POWER_MONITOR_RESUME";
IPCEvents["POWER_MONITOR_SUSPEND"] = "DISCORD_POWER_MONITOR_SUSPEND";
IPCEvents["POWER_MONITOR_LOCK_SCREEN"] = "DISCORD_POWER_MONITOR_LOCK_SCREEN";
IPCEvents["POWER_MONITOR_UNLOCK_SCREEN"] = "DISCORD_POWER_MONITOR_UNLOCK_SCREEN";
IPCEvents["POWER_MONITOR_GET_SYSTEM_IDLE_TIME"] = "DISCORD_POWER_MONITOR_GET_SYSTEM_IDLE_TIME";
IPCEvents["POWER_SAVE_BLOCKER_BLOCK_DISPLAY_SLEEP"] = "DISCORD_POWER_SAVE_BLOCKER_BLOCK_DISPLAY_SLEEP";
IPCEvents["POWER_SAVE_BLOCKER_UNBLOCK_DISPLAY_SLEEP"] = "DISCORD_POWER_SAVE_BLOCKER_UNBLOCK_DISPLAY_SLEEP";
IPCEvents["POWER_SAVE_BLOCKER_CLEANUP_DISPLAY_SLEEP"] = "DISCORD_POWER_SAVE_BLOCKER_CLEANUP_DISPLAY_SLEEP";
IPCEvents["PROCESS_UTILS_GET_CPU_USAGE"] = "DISCORD_PROCESS_UTILS_GET_CPU_USAGE";
IPCEvents["PROCESS_UTILS_GET_MEMORY_INFO"] = "DISCORD_PROCESS_UTILS_GET_MEMORY_INFO";
IPCEvents["PROCESS_UTILS_FLUSH_DNS_CACHE"] = "DISCORD_PROCESS_UTILS_FLUSH_DNS_CACHE";
IPCEvents["PROCESS_UTILS_FLUSH_COOKIES"] = "DISCORD_PROCESS_UTILS_FLUSH_COOKIES";
IPCEvents["PROCESS_UTILS_FLUSH_STORAGE_DATA"] = "DISCORD_PROCESS_UTILS_FLUSH_STORAGE_DATA";
IPCEvents["PROCESS_UTILS_GET_MAIN_ARGV_SYNC"] = "DISCORD_PROCESS_UTILS_GET_MAIN_ARGV_SYNC";
IPCEvents["PROCESS_UTILS_GET_LAST_CRASH"] = "DISCORD_PROCESS_UTILS_GET_LAST_CRASH";
IPCEvents["PROCESS_UTILS_SET_CRASH_INFORMATION"] = "DISCORD_PROCESS_UTILS_SET_CRASH_INFORMATION";
IPCEvents["PROCESS_UTILS_GET_SYSTEM_INFO"] = "DISCORD_PROCESS_UTILS_GET_SYSTEM_INFO";
IPCEvents["QUIT_AND_INSTALL"] = "DISCORD_QUIT_AND_INSTALL";
IPCEvents["SAFE_STORAGE_DECRYPT_STRING"] = "DISCORD_SAFE_STORAGE_DECRYPT_STRING";
IPCEvents["SAFE_STORAGE_ENCRYPT_STRING"] = "DISCORD_SAFE_STORAGE_ENCRYPT_STRING";
IPCEvents["SAFE_STORAGE_IS_ENCRYPTION_AVAILABLE"] = "DISCORD_SAFE_STORAGE_IS_ENCRYPTION_AVAILABLE";
IPCEvents["SETTINGS_GET"] = "DISCORD_SETTINGS_GET";
IPCEvents["SETTINGS_SET"] = "DISCORD_SETTINGS_SET";
IPCEvents["SETTINGS_GET_SYNC"] = "DISCORD_SETTINGS_GET_SYNC";
IPCEvents["SETTINGS_UPDATE_BACKGROUND_COLOR"] = "DISCORD_SETTINGS_UPDATE_BACKGROUND_COLOR";
IPCEvents["SPELLCHECK_RESULT"] = "DISCORD_SPELLCHECK_RESULT";
IPCEvents["SPELLCHECK_REPLACE_MISSPELLING"] = "DISCORD_SPELLCHECK_REPLACE_MISSPELLING";
IPCEvents["SPELLCHECK_GET_AVAILABLE_DICTIONARIES"] = "DISCORD_SPELLCHECK_GET_AVAILABLE_DICTIONARIES";
IPCEvents["SPELLCHECK_SET_LOCALE"] = "DISCORD_SPELLCHECK_SET_LOCALE";
IPCEvents["SPELLCHECK_SET_LEARNED_WORDS"] = "DISCORD_SPELLCHECK_SET_LEARNED_WORDS";
IPCEvents["SYSTEM_TRAY_SET_ICON"] = "DISCORD_SYSTEM_TRAY_SET_ICON";
IPCEvents["SYSTEM_TRAY_SET_APPLICATIONS"] = "DISCORD_SYSTEM_TRAY_SET_APPLICATIONS";
IPCEvents["THUMBAR_BUTTONS_UPDATE"] = "DISCORD_THUMBAR_BUTTONS_UPDATE";
IPCEvents["THUMBAR_BUTTONS_CLICKED"] = "DISCORD_THUMBAR_BUTTONS_CLICKED";
IPCEvents["TOGGLE_MINIMIZE_TO_TRAY"] = "DISCORD_TOGGLE_MINIMIZE_TO_TRAY";
IPCEvents["TOGGLE_OPEN_ON_STARTUP"] = "DISCORD_TOGGLE_OPEN_ON_STARTUP";
IPCEvents["TOGGLE_START_MINIMIZED"] = "DISCORD_TOGGLE_START_MINIMIZED";
IPCEvents["UPDATE_OPEN_ON_STARTUP"] = "DISCORD_UPDATE_OPEN_ON_STARTUP";
IPCEvents["UNHANDLED_JS_EXCEPTION"] = "DISCORD_UNHANDLED_JS_EXCEPTION";
IPCEvents["UPDATER_HISTORY_QUERY_AND_TRUNCATE"] = "DISCORD_UPDATER_HISTORY_QUERY_AND_TRUNCATE";
IPCEvents["UPDATED_QUOTES"] = "DISCORD_UPDATED_QUOTES";
IPCEvents["USER_DATA_CACHE_DELETE"] = "DISCORD_USER_DATA_CACHE_DELETE";
IPCEvents["USER_DATA_CACHE_GET"] = "DISCORD_USER_DATA_CACHE_GET";
IPCEvents["USER_DATA_CACHE_SAVE"] = "DISCORD_USER_DATA_CACHE_SAVE";
IPCEvents["WINDOW_BLUR"] = "DISCORD_WINDOW_BLUR";
IPCEvents["WINDOW_CLOSE"] = "DISCORD_WINDOW_CLOSE";
IPCEvents["WINDOW_FOCUS"] = "DISCORD_WINDOW_FOCUS";
IPCEvents["WINDOW_MAXIMIZE"] = "DISCORD_WINDOW_MAXIMIZE";
IPCEvents["WINDOW_MINIMIZE"] = "DISCORD_WINDOW_MINIMIZE";
IPCEvents["WINDOW_RESTORE"] = "DISCORD_WINDOW_RESTORE";
IPCEvents["WINDOW_FLASH_FRAME"] = "DISCORD_WINDOW_FLASH_FRAME";
IPCEvents["WINDOW_TOGGLE_FULLSCREEN"] = "DISCORD_WINDOW_TOGGLE_FULLSCREEN";
IPCEvents["WINDOW_SET_BACKGROUND_THROTTLING"] = "DISCORD_WINDOW_SET_BACKGROUND_THROTTLING";
IPCEvents["WINDOW_SET_PROGRESS_BAR"] = "DISCORD_WINDOW_SET_PROGRESS_BAR";
IPCEvents["WINDOW_IS_ALWAYS_ON_TOP"] = "DISCORD_WINDOW_IS_ALWAYS_ON_TOP";
IPCEvents["WINDOW_SET_ALWAYS_ON_TOP"] = "DISCORD_WINDOW_SET_ALWAYS_ON_TOP";
IPCEvents["WINDOW_DEVTOOLS_OPENED"] = "DISCORD_WINDOW_DEVTOOLS_OPENED";
IPCEvents["WINDOW_DEVTOOLS_CLOSED"] = "DISCORD_WINDOW_DEVTOOLS_CLOSED";
IPCEvents["GET_MOUSE_COORDINATES"] = "DISCORD_GET_MOUSE_COORDINATES";
})(IPCEvents || (exports.IPCEvents = IPCEvents = {}));

View File

@ -0,0 +1,105 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "basename", {
enumerable: true,
get: function () {
return _path.basename;
}
});
exports.deleteFile = deleteFile;
Object.defineProperty(exports, "dirname", {
enumerable: true,
get: function () {
return _path.dirname;
}
});
Object.defineProperty(exports, "extname", {
enumerable: true,
get: function () {
return _path.extname;
}
});
exports.getFilesnamesFromDirectory = getFilesnamesFromDirectory;
Object.defineProperty(exports, "join", {
enumerable: true,
get: function () {
return _path.join;
}
});
exports.readFiles = readFiles;
exports.readFulfilledFiles = readFulfilledFiles;
var _buffer = _interopRequireDefault(require("buffer"));
var _originalFs = _interopRequireDefault(require("original-fs"));
var _path = _interopRequireWildcard(require("path"));
var _util = _interopRequireDefault(require("util"));
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); }
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; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/* eslint-disable no-console */
// eslint-disable-line import/no-unresolved
// Reason for original-fs being import/no-unresolved: https://github.com/discord/discord/pull/74159#discussion_r893733771
const MAX_LENGTH = _buffer.default.constants.MAX_LENGTH;
const promiseFs = {
readdir: _util.default.promisify(_originalFs.default.readdir),
open: _util.default.promisify(_originalFs.default.open),
fstat: _util.default.promisify(_originalFs.default.fstat),
stat: _util.default.promisify(_originalFs.default.stat),
unlink: _util.default.promisify(_originalFs.default.unlink),
read: _util.default.promisify(_originalFs.default.read),
close: _util.default.promisify(_originalFs.default.close)
};
// Perform `readFiles` but only return `fulfilled` results.
// If [orException] is set, exception if any of the results were rejected.
async function readFulfilledFiles(filenames, maxSize, orException) {
const files = await readFiles(filenames, maxSize);
if (orException) {
files.forEach(result => {
if (result.status === 'rejected') {
throw result.reason;
}
});
}
return files.filter(result => result.status === 'fulfilled').map(result => result.value);
}
function readFiles(filenames, maxSize) {
maxSize = Math.min(maxSize, MAX_LENGTH);
return Promise.allSettled(filenames.map(async filename => {
const handle = await promiseFs.open(filename, 'r');
try {
const stats = await promiseFs.fstat(handle);
if (maxSize != null && stats.size > maxSize) {
// Used to help determine why openFiles failed.
// Cannot use an error here because context bridge will remove the code field.
// eslint-disable-next-line no-throw-literal
throw {
code: 'ETOOLARGE',
message: 'upload too large',
filesize: stats.size,
maxSize
};
}
const buffer = Buffer.alloc(stats.size);
const data = await promiseFs.read(handle, buffer, 0, stats.size, 0);
return {
data: data.buffer.slice(0, data.bytesRead),
filename: _path.default.basename(filename)
};
} finally {
promiseFs.close(handle); // No reason to await?
}
}));
}
function getFilesnamesFromDirectory(path) {
return promiseFs.readdir(path);
}
function deleteFile(filename) {
return promiseFs.unlink(filename);
}

View File

@ -0,0 +1,53 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getCrashFiles = getCrashFiles;
exports.getPath = getPath;
var _electron = _interopRequireDefault(require("electron"));
var _fs = _interopRequireDefault(require("fs"));
var _originalFs = _interopRequireDefault(require("original-fs"));
var _path = _interopRequireDefault(require("path"));
var _util = _interopRequireDefault(require("util"));
var _processUtils = require("../../../common/processUtils");
var _constants = require("../common/constants");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const allowedAppPaths = new Set(['home', 'appData', 'desktop', 'documents', 'downloads', 'crashDumps']);
const readdir = _util.default.promisify(_fs.default.readdir);
async function getPath(path) {
if (!allowedAppPaths.has(path)) {
throw new Error(`${path} is not an allowed app path`);
}
return _electron.default.ipcRenderer.invoke(_constants.IPCEvents.APP_GET_PATH, path);
}
function getTimes(filenames) {
return Promise.allSettled(filenames.map(filename => new Promise((resolve, reject) => {
_originalFs.default.stat(filename, (err, stats) => {
if (err) {
return reject(err);
}
if (!stats.isFile()) {
return reject(new Error('Not a file'));
}
return resolve({
filename,
mtime: stats.mtime
});
});
})));
}
async function orderedFiles(folder) {
try {
const filenames = await readdir(folder);
const times = await getTimes(filenames.map(filename => _path.default.join(folder, filename)));
return times.filter(result => result.status === 'fulfilled').map(result => result.value).sort((a, b) => b.mtime.getTime() - a.mtime.getTime()).map(a => a.filename);
} catch (err) {
return [];
}
}
async function getCrashFiles() {
const crashBaseFolder = await getPath('crashDumps');
const crashFolder = _processUtils.IS_WIN ? _path.default.join(crashBaseFolder, 'reports') : _path.default.join(crashBaseFolder, 'completed');
return orderedFiles(crashFolder);
}

View File

@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.isNotNullish = isNotNullish;
/**
* This function is primarly useful to type-erase the `null | undefined` in
* filter statements, allowing you to write more ergonomic code down-the-line.
*
* Usage:
*
* values.filter(isNotNullish).map(v => v.toFoo());
*/
function isNotNullish(value) {
return value != null;
}

View File

@ -0,0 +1,9 @@
"use strict";
var _DiscordIPC = require("../common/DiscordIPC");
function isAccessibilitySupportEnabled() {
return _DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.ACCESSIBILITY_GET_ENABLED);
}
module.exports = {
isAccessibilitySupportEnabled
};

View File

@ -0,0 +1,90 @@
"use strict";
var _electron = _interopRequireDefault(require("electron"));
var _DiscordIPC = require("../common/DiscordIPC");
var _paths = require("../common/paths");
var _crashReporter = require("./crashReporter");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const releaseChannel = _DiscordIPC.DiscordIPC.renderer.sendSync(_DiscordIPC.IPCEvents.APP_GET_RELEASE_CHANNEL_SYNC);
const hostVersion = _DiscordIPC.DiscordIPC.renderer.sendSync(_DiscordIPC.IPCEvents.APP_GET_HOST_VERSION_SYNC);
const buildNumber = _DiscordIPC.DiscordIPC.renderer.sendSync(_DiscordIPC.IPCEvents.APP_GET_BUILD_NUMBER);
(0, _crashReporter.updateCrashReporter)({
nativeBuildNumber: (buildNumber === null || buildNumber === void 0 ? void 0 : buildNumber.toString()) ?? 'null'
});
let moduleVersions = {};
_DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.APP_GET_MODULE_VERSIONS).then(versions => {
moduleVersions = versions;
});
// TODO: Fix this .on to be part of our typing.
_electron.default.ipcRenderer.on('DISCORD_MODULE_INSTALLED', async _ => {
moduleVersions = await _DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.APP_GET_MODULE_VERSIONS);
});
function getReleaseChannel() {
return releaseChannel;
}
function getVersion() {
return hostVersion;
}
function getBuildNumber() {
return buildNumber;
}
function getModuleVersions() {
return moduleVersions;
}
function setBadgeCount(count) {
_DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.APP_SET_BADGE_COUNT, count);
return Promise.resolve();
}
function dockSetBadge(badge) {
_DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.APP_DOCK_SET_BADGE, badge);
return Promise.resolve();
}
function dockBounce(type) {
_DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.APP_DOCK_BOUNCE, type);
return Promise.resolve();
}
function dockCancelBounce(id) {
_DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.APP_DOCK_CANCEL_BOUNCE, id);
return Promise.resolve();
}
function relaunch() {
_DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.APP_RELAUNCH);
return Promise.resolve();
}
function getDefaultDoubleClickAction() {
return _DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.APP_GET_DEFAULT_DOUBLE_CLICK_ACTION);
}
function registerUserInteractionHandler(elementId, eventType, callback) {
const element = document.getElementById(elementId);
if (element == null) {
throw new Error(`Element with id '${elementId}' was not found`);
}
function handleUserInteraction(ev) {
if (!ev.isTrusted) {
return;
}
callback(ev);
}
element.addEventListener(eventType, handleUserInteraction);
return () => {
element.removeEventListener(eventType, handleUserInteraction);
};
}
module.exports = {
getReleaseChannel,
getVersion,
getModuleVersions,
getBuildNumber,
getPath: _paths.getPath,
// used via DiscordNative.remoteApp.getPath
setBadgeCount,
dock: {
setBadge: dockSetBadge,
bounce: dockBounce,
cancelBounce: dockCancelBounce
},
relaunch,
getDefaultDoubleClickAction,
registerUserInteractionHandler
};

View File

@ -0,0 +1,42 @@
"use strict";
// @ts-nocheck
/* eslint-disable */
const electron = require('electron');
const invariant = require('invariant');
const {
CLIPBOARD_COPY,
CLIPBOARD_CUT,
CLIPBOARD_PASTE
} = require('../common/constants').IPCEvents;
function copy(text) {
if (text) {
electron.clipboard.writeText(text);
} else {
electron.ipcRenderer.invoke(CLIPBOARD_COPY);
}
}
function copyImage(imageArrayBuffer, imageSrc) {
invariant(imageArrayBuffer != null, 'Image data is empty');
const nativeImg = electron.nativeImage.createFromBuffer(imageArrayBuffer);
electron.clipboard.write({
html: `<img src="${imageSrc}">`,
image: nativeImg
});
}
function cut() {
electron.ipcRenderer.invoke(CLIPBOARD_CUT);
}
function paste() {
electron.ipcRenderer.invoke(CLIPBOARD_PASTE);
}
function read() {
return electron.clipboard.readText();
}
module.exports = {
copy,
copyImage,
cut,
paste,
read
};

View File

@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.deleteClip = deleteClip;
exports.loadClip = loadClip;
exports.loadClipsDirectory = loadClipsDirectory;
var _DiscordIPC = require("../common/DiscordIPC");
function loadClip(path) {
return _DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.LOAD_CLIP, path);
}
function loadClipsDirectory(path) {
return _DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.LOAD_CLIPS_DIRECTORY, path);
}
function deleteClip(path) {
return _DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.DELETE_CLIP, path);
}

View File

@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getMetadata = getMetadata;
exports.triggerUnhandledException = triggerUnhandledException;
exports.updateCrashReporter = updateCrashReporter;
var _electron = _interopRequireDefault(require("electron"));
var _crashReporterUtils = require("../../../common/crashReporterUtils");
var _DiscordIPC = require("../common/DiscordIPC");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
let metadata = {};
updateCrashReporter(metadata);
async function updateCrashReporter(additionalMetadata) {
const result = await _DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.CRASH_REPORTER_UPDATE_METADATA, additionalMetadata);
metadata = result.metadata ?? {};
(0, _crashReporterUtils.reconcileCrashReporterMetadata)(_electron.default.crashReporter, metadata);
}
function getMetadata() {
return metadata;
}
// Internal test for unhandled JS exception
async function triggerUnhandledException() {
await _electron.default.ipcRenderer.invoke(_DiscordIPC.IPCEvents.UNHANDLED_JS_EXCEPTION);
}

View File

@ -0,0 +1,25 @@
"use strict";
var _electron = _interopRequireDefault(require("electron"));
var _DiscordIPC = require("../common/DiscordIPC");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
async function getDesktopCaptureSources(options) {
let sources = null;
if (_electron.default.desktopCapturer != null) {
// TODO(atlante45): For backwards compatibility with Electron 13, remove once we've fully
// transitionned off of Electron 13
sources = await _electron.default.desktopCapturer.getSources(options);
} else {
sources = await _DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.DESKTOP_CAPTURER_GET_SOURCES, options);
}
return sources.map(source => {
return {
id: source.id,
name: source.name,
url: source.thumbnail.toDataURL()
};
});
}
module.exports = {
getDesktopCaptureSources
};

View File

@ -0,0 +1,14 @@
"use strict";
var _DiscordIPC = require("../common/DiscordIPC");
const supportedFeatures = new Set(_DiscordIPC.DiscordIPC.renderer.sendSync(_DiscordIPC.IPCEvents.FEATURES_GET_BROWSER_FEATURES));
function supports(feature) {
return supportedFeatures.has(feature);
}
function declareSupported(feature) {
supportedFeatures.add(feature);
}
module.exports = {
supports,
declareSupported
};

View File

@ -0,0 +1,167 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "basename", {
enumerable: true,
get: function () {
return _path.basename;
}
});
exports.cleanupTempFiles = cleanupTempFiles;
Object.defineProperty(exports, "dirname", {
enumerable: true,
get: function () {
return _path.dirname;
}
});
Object.defineProperty(exports, "extname", {
enumerable: true,
get: function () {
return _path.extname;
}
});
exports.getModuleDataPathSync = getModuleDataPathSync;
exports.getModulePath = getModulePath;
Object.defineProperty(exports, "join", {
enumerable: true,
get: function () {
return _path.join;
}
});
exports.openFiles = openFiles;
exports.readLogFiles = readLogFiles;
exports.readTimeSeriesLogFiles = readTimeSeriesLogFiles;
exports.saveWithDialog = saveWithDialog;
exports.showItemInFolder = showItemInFolder;
exports.showOpenDialog = showOpenDialog;
var _fs = _interopRequireDefault(require("fs"));
var _originalFs = _interopRequireDefault(require("original-fs"));
var _path = _interopRequireWildcard(require("path"));
var _util = _interopRequireDefault(require("util"));
var _DiscordIPC = require("../common/DiscordIPC");
var _fileutils = require("../common/fileutils");
var _paths = require("../common/paths");
var _files = require("./files");
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); }
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; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/* eslint-disable no-console */
// eslint-disable-line import/no-unresolved
// Reason for original-fs being import/no-unresolved: https://github.com/discord/discord/pull/74159#discussion_r893733771
const INVALID_FILENAME_CHAR_REGEX = /[^a-zA-Z0-9-_.]/g;
const promiseFs = {
readdir: _util.default.promisify(_originalFs.default.readdir),
open: _util.default.promisify(_originalFs.default.open),
fstat: _util.default.promisify(_originalFs.default.fstat),
stat: _util.default.promisify(_originalFs.default.stat),
unlink: _util.default.promisify(_originalFs.default.unlink),
read: _util.default.promisify(_originalFs.default.read),
close: _util.default.promisify(_originalFs.default.close)
};
async function saveWithDialog(fileContents, fileName) {
if (INVALID_FILENAME_CHAR_REGEX.test(fileName)) {
throw new Error('fileName has invalid characters');
}
const defaultPath = _path.default.join(await (0, _paths.getPath)('downloads'), fileName);
const results = await _DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.FILE_MANAGER_SHOW_SAVE_DIALOG, {
defaultPath
});
if (results != null && results.filePath != null) {
_fs.default.writeFileSync(results.filePath, fileContents);
}
}
async function showOpenDialog({
filters,
properties
}) {
const results = await _DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.FILE_MANAGER_SHOW_OPEN_DIALOG, {
filters,
properties
});
return results.filePaths;
}
async function readLogFiles(maxSize) {
// MAX_DEBUG_LOG_FILES may need to be increased as more files are added.
const modulePath = await getModulePath();
const voicePath = _path.default.join(modulePath, 'discord_voice');
const hookPath = _path.default.join(modulePath, 'discord_hook');
const utilsPath = _path.default.join(modulePath, 'discord_utils');
const filesToUpload = [_path.default.join(voicePath, 'discord-webrtc_0'), _path.default.join(voicePath, 'discord-webrtc_1'), _path.default.join(voicePath, 'discord-last-webrtc_0'), _path.default.join(voicePath, 'discord-last-webrtc_1'), _path.default.join(voicePath, 'audio_state.json'), _path.default.join(hookPath, 'hook.log'), _path.default.join(utilsPath, 'live_minidump.dmp')];
const crashFiles = await (0, _paths.getCrashFiles)();
if (crashFiles.length > 0) {
filesToUpload.push(crashFiles[0]);
}
return (0, _fileutils.readFulfilledFiles)(filesToUpload, maxSize, false);
}
async function readTimeSeriesLogFiles(maxSize, blindChannelId) {
if (blindChannelId == null) {
console.error('readTimeSeriesLogFiles: blindChannelId missing.');
return [];
}
const modulePath = await getModulePath();
const voicePath = _path.default.join(modulePath, 'discord_voice');
// Example filename: "channel.17812072731293278934.16605628624321906260.tsi"
const filter = new RegExp(`^channel\\.${blindChannelId}\\.\\d+\\.(?:tsi|tsd)$`, 'i');
const filenames = [];
for (const file of await promiseFs.readdir(voicePath)) {
if (filter.test(file)) {
filenames.push(_path.default.join(voicePath, file));
}
}
const allLogFiles = [...filenames];
const maxLogFiles = 10; // 10 is arbitrary but seems reasonable as each would be ~1mb.
if (filenames.length > maxLogFiles) {
console.warn(`readTimeSeriesLogFiles: Exceeded limit of ${maxLogFiles} files, had ${filenames.length}.`);
filenames.splice(maxLogFiles);
}
const readfiles = await (0, _fileutils.readFulfilledFiles)(filenames, maxSize, false);
// Delete the files after they've been read.
await Promise.all(allLogFiles.map(filename => promiseFs.unlink(filename)));
return readfiles;
}
async function cleanupTempFiles() {
// Since this runs on startup, handle and report all errors as cleanly as possible.
try {
const modulePath = await getModulePath();
const voicePath = _path.default.join(modulePath, 'discord_voice');
const deleteAgeTimeSpan = 1 * 24 * 60 * 60 * 1000; // 1 day.
const deleteAge = new Date(Date.now() - deleteAgeTimeSpan);
for (const filename of await promiseFs.readdir(voicePath)) {
if (!(0, _files.isTempFile)(filename)) {
continue;
}
const fullpath = _path.default.join(voicePath, filename);
const stat = await promiseFs.stat(fullpath);
if (!stat.isFile() || stat.mtime > deleteAge) {
continue;
}
console.log(`cleanupTempFiles: Deleting "${fullpath}" due to age.`);
try {
await promiseFs.unlink(fullpath);
} catch (e) {
console.error(`cleanupTempFiles: Failed to unlink ${fullpath}: ${e}`);
}
}
} catch (e) {
console.error(`cleanupTempFiles: Failed ${e}`);
}
}
function showItemInFolder(path) {
_DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.FILE_MANAGER_SHOW_ITEM_IN_FOLDER, path);
return Promise.resolve();
}
async function openFiles(dialogOptions, maxSize) {
const filenames = await showOpenDialog(dialogOptions);
return (0, _fileutils.readFulfilledFiles)(filenames, maxSize, true);
}
function getModulePath() {
return _DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.FILE_MANAGER_GET_MODULE_PATH);
}
function getModuleDataPathSync() {
return _DiscordIPC.DiscordIPC.renderer.sendSync(_DiscordIPC.IPCEvents.FILE_MANAGER_GET_MODULE_DATA_PATH_SYNC);
}

View File

@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.isTempFile = isTempFile;
function isTempFile(filename) {
return /(?:^channel\..+(?:tsi|tsd)$)|(?:^\.tmp.+)/i.test(filename);
}

View File

@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.openOverlay = openOverlay;
var _DiscordIPC = require("../common/DiscordIPC");
function openOverlay(url) {
return _DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.GLOBAL_OVERLAY_OPEN, url);
}

View File

@ -0,0 +1,20 @@
"use strict";
// @ts-nocheck
/* eslint-disable */
const electron = require('electron');
const {
GPU_SETTINGS_SET_ENABLE_HWACCEL,
GPU_SETTINGS_GET_ENABLE_HWACCEL_SYNC
} = require('../common/constants').IPCEvents;
const hardwareAccelerationEnabled = electron.ipcRenderer.sendSync(GPU_SETTINGS_GET_ENABLE_HWACCEL_SYNC);
function getEnableHardwareAcceleration() {
return hardwareAccelerationEnabled;
}
async function setEnableHardwareAcceleration(enable) {
electron.ipcRenderer.invoke(GPU_SETTINGS_SET_ENABLE_HWACCEL, enable);
}
module.exports = {
getEnableHardwareAcceleration,
setEnableHardwareAcceleration
};

View File

@ -0,0 +1,96 @@
"use strict";
const electron = require('electron');
const http = require('http');
const https = require('https');
const {
CONSTANTS_GET
} = require('../common/constants').IPCEvents;
async function getAPIEndpoint() {
const apiEndpoint = await electron.ipcRenderer.invoke(CONSTANTS_GET, 'API_ENDPOINT');
if (apiEndpoint == null || apiEndpoint === '') {
return null;
}
return apiEndpoint;
}
async function makeChunkedRequest(route, chunks, options) {
/**
* Given an array of chunks, make a slow request, only writing chunks
* after a specified amount of time
*
* route: string
* options: object
* method: the method of the request
* contentType: the content type of the request
* chunkInterval: how long to wait to upload a chunk after the last chunk was flushed
* token: the token to make an authorized request from
* chunks: chunked body of the request to upload
*/
const {
method,
chunkInterval,
token,
contentType
} = options;
let httpModule = http;
if (route.startsWith('https')) {
httpModule = https;
}
// we will force the URL to hit only API_ENDPOINT
const apiEndpoint = await getAPIEndpoint();
if (apiEndpoint == null) {
throw new Error('missing api endpoint setting');
}
const apiEndpointUrl = new URL(apiEndpoint);
const url = new URL(route, apiEndpoint);
url.protocol = apiEndpointUrl.protocol;
url.host = apiEndpointUrl.host;
if (!url.pathname.startsWith(apiEndpointUrl.pathname)) {
url.pathname = `${apiEndpointUrl.pathname}${url.pathname}`;
}
return new Promise(async (resolve, reject) => {
let writeTimeout;
const req = httpModule.request(url.toString(), {
method,
headers: {
authorization: token,
'Content-Type': contentType,
'Content-Length': Buffer.byteLength(chunks.join(''))
}
}, res => {
let responseData = '';
res.setEncoding('utf8');
res.on('data', chunk => {
responseData += chunk;
});
res.on('end', () => {
resolve({
status: res.statusCode,
body: responseData
});
});
});
req.on('error', e => {
if (writeTimeout != null) {
clearTimeout(writeTimeout);
}
reject(e);
});
for (let i = 0; i < chunks.length; i++) {
await new Promise(resolve => {
req.write(chunks[i], () => {
writeTimeout = setTimeout(resolve, chunkInterval);
});
});
}
req.end();
});
}
module.exports = {
getAPIEndpoint,
makeChunkedRequest: function (route, chunks, options, callback) {
makeChunkedRequest(route, chunks, options).then(body => callback(null, body)).catch(err => callback(err));
}
};

View File

@ -0,0 +1,35 @@
"use strict";
const electron = require('electron');
const {
getDiscordIPCEvent,
IPCEvents
} = require('../common/constants');
const ipcRenderer = electron.ipcRenderer;
const RENDERER_IPC_SEND_WHITELIST = new Set([IPCEvents.APP_BADGE_SET, IPCEvents.CHECK_FOR_UPDATES, IPCEvents.NOTIFICATION_CLOSE, IPCEvents.NOTIFICATION_SHOW, IPCEvents.NOTIFICATIONS_CLEAR, IPCEvents.OPEN_EXTERNAL_URL, IPCEvents.QUIT_AND_INSTALL, IPCEvents.SETTINGS_UPDATE_BACKGROUND_COLOR, IPCEvents.SYSTEM_TRAY_SET_ICON, IPCEvents.SYSTEM_TRAY_SET_APPLICATIONS, IPCEvents.THUMBAR_BUTTONS_UPDATE, IPCEvents.TOGGLE_MINIMIZE_TO_TRAY, IPCEvents.TOGGLE_OPEN_ON_STARTUP, IPCEvents.TOGGLE_START_MINIMIZED, IPCEvents.UPDATE_OPEN_ON_STARTUP, IPCEvents.UPDATER_HISTORY_QUERY_AND_TRUNCATE, IPCEvents.UPDATED_QUOTES]);
const RENDERER_IPC_INVOKE_WHITELIST = new Set([IPCEvents.GET_MOUSE_COORDINATES]);
function send(ev, ...args) {
const prefixedEvent = getDiscordIPCEvent(ev);
if (!RENDERER_IPC_SEND_WHITELIST.has(prefixedEvent)) {
throw new Error('cannot send this event');
}
ipcRenderer.send(prefixedEvent, ...args);
}
function on(ev, callback) {
ipcRenderer.on(getDiscordIPCEvent(ev), function () {
// Sender is dangerous, do not expose.
callback.apply(callback, [null, ...[...arguments].slice(1)]);
});
}
function invoke(ev, ...args) {
const prefixedEvent = getDiscordIPCEvent(ev);
if (!RENDERER_IPC_INVOKE_WHITELIST.has(prefixedEvent)) {
throw new Error('cannot invoke this event');
}
return ipcRenderer.invoke(prefixedEvent, ...args);
}
module.exports = {
send,
on,
invoke
};

View File

@ -0,0 +1,458 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.readMinidump = readMinidump;
var _fs = _interopRequireDefault(require("fs"));
var _util = _interopRequireDefault(require("util"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/* eslint-disable no-console */
/* eslint-disable @typescript-eslint/naming-convention */
const exceptionTypes = {
C0000005: 'EXCEPTION_ACCESS_VIOLATION',
'80000002': 'EXCEPTION_DATATYPE_MISALIGNMENT',
'80000003': 'EXCEPTION_BREAKPOINT',
'80000004': 'EXCEPTION_SINGLE_STEP',
C000008C: 'EXCEPTION_ARRAY_BOUNDS_EXCEEDED',
C000008D: 'EXCEPTION_FLT_DENORMAL_OPERAND',
C000008E: 'EXCEPTION_FLT_DIVIDE_BY_ZERO',
C000008F: 'EXCEPTION_FLT_INEXACT_RESULT',
C0000090: 'EXCEPTION_FLT_INVALID_OPERATION',
C0000091: 'EXCEPTION_FLT_OVERFLOW',
C0000092: 'EXCEPTION_FLT_STACK_CHECK',
C0000093: 'EXCEPTION_FLT_UNDERFLOW',
C0000094: 'EXCEPTION_INT_DIVIDE_BY_ZERO',
C0000095: 'EXCEPTION_INT_OVERFLOW',
C0000096: 'EXCEPTION_PRIV_INSTRUCTION',
C0000006: 'EXCEPTION_IN_PAGE_ERROR',
C000001D: 'EXCEPTION_ILLEGAL_INSTRUCTION',
C0000025: 'EXCEPTION_NONCONTINUABLE_EXCEPTION',
C00000FD: 'EXCEPTION_STACK_OVERFLOW',
C0000026: 'EXCEPTION_INVALID_DISPOSITION',
'80000001': 'EXCEPTION_GUARD_PAGE',
C0000008: 'EXCEPTION_INVALID_HANDLE'
};
class FileReader {
utf16Decoder = new _util.default.TextDecoder('utf-16');
static promiseFs = Object.freeze({
open: _util.default.promisify(_fs.default.open),
read: _util.default.promisify(_fs.default.read),
close: _util.default.promisify(_fs.default.close)
});
constructor(path, bufferSize = 2048) {
this.handle = FileReader.promiseFs.open(path, 'r');
this.buffer = new Uint8Array(bufferSize);
}
async read(u32toReadCount, position = null) {
const byteSize = u32toReadCount * 4;
await this.readCore(byteSize, position);
return new ReadResult(this.buffer.buffer.slice(0, byteSize));
}
async readMinidumpString(rva) {
if (rva === 0) {
return '';
}
// https://learn.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_string
await this.readCore(4, rva);
const length = this.buffer[0] | this.buffer[1] << 8 | this.buffer[2] << 16 | this.buffer[3] << 24;
await this.readCore(Math.min(length, this.buffer.byteLength), rva + 4);
return this.utf16Decoder.decode(this.buffer.slice(0, length));
}
async readCore(byteLength, position = null) {
if (byteLength > this.buffer.byteLength) {
throw new Error(`Requested nuber of bytes ${byteLength} exceeds buffer size ${this.buffer.byteLength}.`);
}
if (this.handle == null) {
throw new Error('Cannot use FileReader once closed.');
}
const handle = await this.handle;
const readResult = await FileReader.promiseFs.read(handle, this.buffer, 0, byteLength, position);
if (readResult.bytesRead < byteLength) {
throw new Error(`FileReader failed to read enough bytes: 0x${readResult.bytesRead}`);
}
}
async close() {
if (this.handle == null) {
return;
}
const handle = await this.handle;
this.handle = null;
await FileReader.promiseFs.close(handle);
}
}
class ReadResult {
index = 0;
// irl, this should likely take the uint8 and work from there, but this is fine for us.
// Maybe just steal my other impl here https://github.com/jlennox/WebWad/blob/main/wad.ts#L8
// but we likely don't want to load the entire file at once. But who knows, maybe the system
// call reduction is better and/or it irl doesn't matter either way.
constructor(buffer) {
this.u8 = new Uint8Array(buffer);
this.u16 = new Uint16Array(buffer);
this.u32 = new Uint32Array(buffer);
}
seek(index) {
this.index = index;
}
readuint32() {
const val = this.u32[this.index / 4];
this.index += 4;
return val;
}
readuint16() {
const val = this.u16[this.index / 2];
this.index += 2;
return val;
}
readByteArray(count) {
const val = Array.from(this.u8.slice(this.index, this.index + count));
this.index += count;
return val;
}
readuint64() {
const u32Index = this.index / 4;
const val = BigInt(this.u32[u32Index]) | BigInt(this.u32[u32Index + 1]) << BigInt(32);
this.index += 8;
return val;
}
}
function isMinidumpFilename(filename) {
return /\.dmp$/i.test(filename);
}
var MinidumpStreamType; // https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_header
(function (MinidumpStreamType) {
MinidumpStreamType[MinidumpStreamType["UnusedStream"] = 0] = "UnusedStream";
MinidumpStreamType[MinidumpStreamType["ReservedStream0"] = 1] = "ReservedStream0";
MinidumpStreamType[MinidumpStreamType["ReservedStream1"] = 2] = "ReservedStream1";
MinidumpStreamType[MinidumpStreamType["ThreadListStream"] = 3] = "ThreadListStream";
MinidumpStreamType[MinidumpStreamType["ModuleListStream"] = 4] = "ModuleListStream";
MinidumpStreamType[MinidumpStreamType["MemoryListStream"] = 5] = "MemoryListStream";
MinidumpStreamType[MinidumpStreamType["ExceptionStream"] = 6] = "ExceptionStream";
MinidumpStreamType[MinidumpStreamType["SystemInfoStream"] = 7] = "SystemInfoStream";
MinidumpStreamType[MinidumpStreamType["ThreadExListStream"] = 8] = "ThreadExListStream";
MinidumpStreamType[MinidumpStreamType["Memory64ListStream"] = 9] = "Memory64ListStream";
MinidumpStreamType[MinidumpStreamType["CommentStreamA"] = 10] = "CommentStreamA";
MinidumpStreamType[MinidumpStreamType["CommentStreamW"] = 11] = "CommentStreamW";
MinidumpStreamType[MinidumpStreamType["HandleDataStream"] = 12] = "HandleDataStream";
MinidumpStreamType[MinidumpStreamType["FunctionTableStream"] = 13] = "FunctionTableStream";
MinidumpStreamType[MinidumpStreamType["UnloadedModuleListStream"] = 14] = "UnloadedModuleListStream";
MinidumpStreamType[MinidumpStreamType["MiscInfoStream"] = 15] = "MiscInfoStream";
MinidumpStreamType[MinidumpStreamType["MemoryInfoListStream"] = 16] = "MemoryInfoListStream";
MinidumpStreamType[MinidumpStreamType["ThreadInfoListStream"] = 17] = "ThreadInfoListStream";
MinidumpStreamType[MinidumpStreamType["HandleOperationListStream"] = 18] = "HandleOperationListStream";
MinidumpStreamType[MinidumpStreamType["TokenStream"] = 19] = "TokenStream";
MinidumpStreamType[MinidumpStreamType["JavaScriptDataStream"] = 20] = "JavaScriptDataStream";
MinidumpStreamType[MinidumpStreamType["SystemMemoryInfoStream"] = 21] = "SystemMemoryInfoStream";
MinidumpStreamType[MinidumpStreamType["ProcessVmCountersStream"] = 22] = "ProcessVmCountersStream";
MinidumpStreamType[MinidumpStreamType["IptTraceStream"] = 23] = "IptTraceStream";
MinidumpStreamType[MinidumpStreamType["ThreadNamesStream"] = 24] = "ThreadNamesStream";
MinidumpStreamType[MinidumpStreamType["ceStreamNull"] = 32768] = "ceStreamNull";
MinidumpStreamType[MinidumpStreamType["ceStreamSystemInfo"] = 32769] = "ceStreamSystemInfo";
MinidumpStreamType[MinidumpStreamType["ceStreamException"] = 32770] = "ceStreamException";
MinidumpStreamType[MinidumpStreamType["ceStreamModuleList"] = 32771] = "ceStreamModuleList";
MinidumpStreamType[MinidumpStreamType["ceStreamProcessList"] = 32772] = "ceStreamProcessList";
MinidumpStreamType[MinidumpStreamType["ceStreamThreadList"] = 32773] = "ceStreamThreadList";
MinidumpStreamType[MinidumpStreamType["ceStreamThreadContextList"] = 32774] = "ceStreamThreadContextList";
MinidumpStreamType[MinidumpStreamType["ceStreamThreadCallStackList"] = 32775] = "ceStreamThreadCallStackList";
MinidumpStreamType[MinidumpStreamType["ceStreamMemoryVirtualList"] = 32776] = "ceStreamMemoryVirtualList";
MinidumpStreamType[MinidumpStreamType["ceStreamMemoryPhysicalList"] = 32777] = "ceStreamMemoryPhysicalList";
MinidumpStreamType[MinidumpStreamType["ceStreamBucketParameters"] = 32778] = "ceStreamBucketParameters";
MinidumpStreamType[MinidumpStreamType["ceStreamProcessModuleMap"] = 32779] = "ceStreamProcessModuleMap";
MinidumpStreamType[MinidumpStreamType["ceStreamDiagnosisList"] = 32780] = "ceStreamDiagnosisList";
MinidumpStreamType[MinidumpStreamType["LastReservedStream"] = 65535] = "LastReservedStream";
})(MinidumpStreamType || (MinidumpStreamType = {}));
class MINIDUMP_HEADER {
static U32_SIZE = 4;
constructor(reader) {
this.signature = reader.readuint32();
this.version = reader.readuint32();
this.numberOfStreams = reader.readuint32();
this.streamDirectoryOffset = reader.readuint32();
}
static async read(reader, position) {
return new MINIDUMP_HEADER(await reader.read(MINIDUMP_HEADER.U32_SIZE, position));
}
}
// https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_directory
class MINIDUMP_DIRECTORY {
static U32_SIZE = 3;
constructor(reader) {
this.streamType = reader.readuint32();
this.dataSize = reader.readuint32();
this.dataOffset = reader.readuint32();
}
static async read(reader, position) {
return new MINIDUMP_DIRECTORY(await reader.read(MINIDUMP_DIRECTORY.U32_SIZE, position));
}
}
// https://docs.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_exception_stream
class MINIDUMP_EXCEPTION_STREAM {
static U32_SIZE = 8;
constructor(reader) {
this.threadId = reader.readuint32();
this.alignment = reader.readuint32();
this.exceptionCode = reader.readuint32();
this.exceptionFlags = reader.readuint32();
this.exceptionRecord = reader.readuint64();
this.exceptionAddress = reader.readuint64();
}
static async read(reader, position) {
return new MINIDUMP_EXCEPTION_STREAM(await reader.read(MINIDUMP_EXCEPTION_STREAM.U32_SIZE, position));
}
getExceptionCodeString() {
const exceptionCode = this.exceptionCode.toString(16).toUpperCase().padStart(8, '0');
const exceptionString = exceptionTypes[exceptionCode] ?? exceptionCode;
return exceptionString;
}
}
// https://learn.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_location_descriptor
class MINIDUMP_LOCATION_DESCRIPTOR {
constructor(reader) {
this.dataSize = reader.readuint32();
this.rva = reader.readuint32();
}
}
// https://learn.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_module_list
class MINIDUMP_MODULE_LIST {
static U32_SIZE = 1;
constructor(reader) {
this.numberOfModules = reader.readuint32();
}
static async read(reader, position) {
return new MINIDUMP_MODULE_LIST(await reader.read(MINIDUMP_MODULE_LIST.U32_SIZE, position));
}
}
// https://learn.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_module
class MINIDUMP_MODULE {
// sizeof(MINIDUMP_MODULE) 108
// sizeof(VS_FIXEDFILEINFO) 52
// sizeof(MINIDUMP_LOCATION_DESCRIPTOR) 8
// sizeof(RVA) 4
static U32_SIZE = 108 / 4;
constructor(reader) {
this.baseOfImage = reader.readuint64();
this.sizeOfImage = reader.readuint32();
this.checkSum = reader.readuint32();
this.timeDateStamp = reader.readuint32();
this.moduleNameRva = reader.readuint32();
this.versionInfo = new VS_FIXEDFILEINFO(reader);
this.cvRecord = new MINIDUMP_LOCATION_DESCRIPTOR(reader);
this.miscRecord = new MINIDUMP_LOCATION_DESCRIPTOR(reader);
this.reserved0 = reader.readuint64();
this.reserved1 = reader.readuint64();
}
static async read(reader, position) {
return new MINIDUMP_MODULE(await reader.read(MINIDUMP_MODULE.U32_SIZE, position));
}
containsAddress(address) {
const endAddress = this.baseOfImage + BigInt(this.sizeOfImage);
return this.baseOfImage <= address && endAddress > address;
}
async getModuleFileName(reader) {
const moduleName = await reader.readMinidumpString(this.moduleNameRva);
let dirPos = moduleName.lastIndexOf('\\');
if (dirPos === -1) {
dirPos = moduleName.lastIndexOf('/');
}
dirPos = dirPos === -1 ? 0 : dirPos + 1;
return moduleName.slice(dirPos);
}
async getCVInfoIdString(reader) {
return (await CV_INFO.read(reader, this.cvRecord.rva)).getIdString();
}
getCodeIdString() {
return (this.timeDateStamp.toString(16).padStart(8, '0') + this.sizeOfImage.toString(16)).toUpperCase();
}
}
// https://learn.microsoft.com/en-us/windows/win32/api/verrsrc/ns-verrsrc-vs_fixedfileinfo
class VS_FIXEDFILEINFO {
constructor(reader) {
this.dwSignature = reader.readuint32();
this.dwStrucVersion = reader.readuint32();
this.dwFileVersionMS = reader.readuint32();
this.dwFileVersionLS = reader.readuint32();
this.dwProductVersionMS = reader.readuint32();
this.dwProductVersionLS = reader.readuint32();
this.dwFileFlagsMask = reader.readuint32();
this.dwFileFlags = reader.readuint32();
this.dwFileOS = reader.readuint32();
this.dwFileType = reader.readuint32();
this.dwFileSubtype = reader.readuint32();
this.dwFileDateMS = reader.readuint32();
this.dwFileDateLS = reader.readuint32();
}
getVersionString() {
const first = this.dwProductVersionMS >> 16 & 0xffff;
const second = this.dwProductVersionMS & 0xffff;
const third = this.dwProductVersionLS >> 16 & 0xffff;
const fourth = this.dwProductVersionLS & 0xffff;
return `${first}.${second}.${third}.${fourth}`;
}
}
// This isn't spec'ed on the minidump page (from what I could tell):
// https://github.com/rust-minidump/rust-minidump/blob/main/minidump/src/minidump.rs#L267
// This returns the ID string that is used by the Mozilla tools for PDB lookup.
class CV_INFO {
static async read(reader, position) {
if (position === 0) {
return new CV_INFO_UNKNOWN(0);
}
// 6 is the largest.
const readResult = await reader.read(6, position);
const cvSignature = readResult.readuint32();
switch (cvSignature) {
case CV_INFO_PDB20.SIGNATURE:
return new CV_INFO_PDB20(readResult);
case CV_INFO_PDB70.SIGNATURE:
return new CV_INFO_PDB70(readResult);
case CV_INFO_ELF.SIGNATURE:
return new CV_INFO_ELF();
default:
return new CV_INFO_UNKNOWN(cvSignature);
}
}
}
class CV_INFO_PDB20 {
static SIGNATURE = 0x3031424e;
constructor(reader) {
this.cvOffset = reader.readuint32();
this.signature = reader.readuint32();
this.age = reader.readuint32();
}
getIdString() {
// TODO: Probably uncommon at this point.
return 'CV_INFO_PDB20';
}
}
class GUID {
// fixed 8 length.
constructor(reader) {
this.data1 = reader.readuint32();
this.data2 = reader.readuint16();
this.data3 = reader.readuint16();
this.data4 = reader.readByteArray(8);
}
toString() {
if (this.data4.length !== 8) {
return 'Invalid';
}
return this.data1.toString(16).padStart(4, '0') + this.data2.toString(16).padStart(2, '0') + this.data3.toString(16).padStart(2, '0') + this.data4.map(b => b.toString(16).padStart(2, '0')).join('');
}
}
class CV_INFO_PDB70 {
static SIGNATURE = 0x53445352;
constructor(reader) {
this.signature = new GUID(reader);
this.age = reader.readuint32();
}
getIdString() {
// https://randomascii.wordpress.com/2013/03/09/symbols-the-microsoft-way/
return (this.signature.toString() + this.age.toString(16)).toUpperCase();
}
}
class CV_INFO_ELF {
static SIGNATURE = 0x4270454c;
getIdString() {
// TODO: Would be needed for macOS/linux support presumably?
return 'CV_INFO_ELF';
}
}
class CV_INFO_UNKNOWN {
constructor(cvSignature) {
this.cvSignature = cvSignature;
}
getIdString() {
return 'CV_INFO_UNKNOWN:' + this.cvSignature.toString(16).padStart(4, '0');
}
}
async function readMinidump(file) {
if (file == null || !isMinidumpFilename(file)) return null;
let reader = null;
const info = {};
try {
reader = new FileReader(file);
const header = await MINIDUMP_HEADER.read(reader, 0);
if (header.signature !== 0x504d444d) {
console.log(`readMinidump Bad signature: 0x${header.signature.toString(16)}`);
return null;
}
// Arbitrary number. Just a sanity check.
if (header.numberOfStreams > 0x100) {
console.log(`readMinidump Bad numberOfStreams: 0x${header.numberOfStreams.toString(16)}`);
return null;
}
const streamLookup = {};
// First create a lookup because we want to process the entries in a specific order.
for (let i = 0; i < header.numberOfStreams; ++i) {
const streamOffset = header.streamDirectoryOffset + i * 12;
const entry = await MINIDUMP_DIRECTORY.read(reader, streamOffset);
// We only care about a limited amount of stream types, so lets avoid some of the overhead.
switch (entry.streamType) {
case MinidumpStreamType.ExceptionStream:
case MinidumpStreamType.ModuleListStream:
break;
default:
continue;
}
streamLookup[entry.streamType] = entry;
}
const exceptionStreamEntry = streamLookup[MinidumpStreamType.ExceptionStream];
if (exceptionStreamEntry == null) {
console.log(`readMinidump: No ExceptionStream found.`);
return null;
}
const exceptionStream = await MINIDUMP_EXCEPTION_STREAM.read(reader, exceptionStreamEntry.dataOffset);
info.exceptionString = exceptionStream.getExceptionCodeString();
const exceptionAddrString = exceptionStream.exceptionAddress.toString(16);
console.log(`readMinidump exceptionCode: ${info.exceptionString}, exceptionAddress ${exceptionAddrString}`);
const moduleStreamEntry = streamLookup[MinidumpStreamType.ModuleListStream];
// Skip if `exceptionAddress` is 0 since there will be no crashing module.
if (moduleStreamEntry != null && exceptionStream.exceptionAddress !== BigInt(0)) {
// https://learn.microsoft.com/en-us/windows/win32/api/minidumpapiset/ns-minidumpapiset-minidump_module_list
// Do not read them all at once. This 1) allows us to exit early, 2) would require a variable sized buffer
// instead of our smaller fixed size buffer.
const moduleList = await MINIDUMP_MODULE_LIST.read(reader, moduleStreamEntry.dataOffset);
// Sanity check, this number is arbitrary.
if (moduleList.numberOfModules > 0x200) {
console.log(`readMinidump ModuleListstream Bad numberOfModules: 0x${moduleList.numberOfModules.toString(16)}`);
return info;
}
let moduleEntryOffset = moduleStreamEntry.dataOffset + 4;
for (let i = 0; i < moduleList.numberOfModules; ++i) {
const module = await MINIDUMP_MODULE.read(reader, moduleEntryOffset);
moduleEntryOffset += MINIDUMP_MODULE.U32_SIZE * 4;
if (module.containsAddress(exceptionStream.exceptionAddress)) {
info.exceptionModuleName = await module.getModuleFileName(reader);
info.exceptionModuleVersion = module.versionInfo.getVersionString();
info.relativeCrashAddress = (exceptionStream.exceptionAddress - module.baseOfImage).toString(16);
info.exceptionModuleCodeId = module.getCodeIdString();
break;
}
}
}
} catch (e) {
console.log(`readMinidump exception: ${e} ${e === null || e === void 0 ? void 0 : e.stack}`);
return null;
} finally {
var _reader;
(_reader = reader) === null || _reader === void 0 ? void 0 : _reader.close();
}
console.log(`readMinidump result ${JSON.stringify(info)}`);
return info;
}

View File

@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getNewestMinidumpInformation = getNewestMinidumpInformation;
var _processUtils = require("../../../common/processUtils");
var _paths = require("../common/paths");
var _minidump = require("./minidump");
/* eslint-disable no-console */
// This is unfortunately in its own file because Jest breaks when it sees original-fs.
async function getNewestMinidumpInformation() {
if (!_processUtils.IS_WIN) return null;
try {
const files = await (0, _paths.getCrashFiles)();
if (files == null || files.length === 0) return null;
return await (0, _minidump.readMinidump)(files[0]);
} catch (e) {
console.log(`getNewestMinidumpInformation exception: ${e}`);
return null;
}
}

View File

@ -0,0 +1,50 @@
"use strict";
const electron = require('electron');
const {
NATIVE_MODULES_GET_PATHS,
NATIVE_MODULES_INSTALL,
NATIVE_MODULES_GET_HAS_NEW_UPDATER
} = require('../common/constants').IPCEvents;
const modulePromises = {};
function getSanitizedModulePaths() {
let sanitizedModulePaths = [];
const {
mainAppDirname,
browserModulePaths
} = electron.ipcRenderer.sendSync(NATIVE_MODULES_GET_PATHS);
browserModulePaths.forEach(modulePath => {
if (!modulePath.includes('electron.asar')) {
sanitizedModulePaths.push(modulePath);
}
});
const rendererModulePaths = require('module')._nodeModulePaths(mainAppDirname);
sanitizedModulePaths = sanitizedModulePaths.concat(rendererModulePaths.slice(0, 2));
return sanitizedModulePaths;
}
function getHasNewUpdater() {
return electron.ipcRenderer.sendSync(NATIVE_MODULES_GET_HAS_NEW_UPDATER);
}
async function ensureModule(name) {
if (modulePromises[name] == null) {
modulePromises[name] = electron.ipcRenderer.invoke(NATIVE_MODULES_INSTALL, name);
}
const moduleInstall = modulePromises[name];
await moduleInstall.catch(e => {
modulePromises[name] = null;
return Promise.reject(e);
});
module.paths = getSanitizedModulePaths();
}
function requireModule(name) {
if (!/^discord_[a-z0-9_-]+$/.test(name) && name !== 'erlpack') {
throw new Error('"' + String(name) + '" is not a whitelisted native module');
}
return require(name);
}
module.paths = getSanitizedModulePaths();
module.exports = {
ensureModule,
requireModule,
canBootstrapNewUpdater: !getHasNewUpdater()
};

View File

@ -0,0 +1,12 @@
"use strict";
const os = require('os');
const process = require('process');
let arch = os.arch();
if (process.platform === 'win32' && process.env['PROCESSOR_ARCHITEW6432'] != null) {
arch = 'x64';
}
module.exports = {
release: os.release(),
arch
};

View File

@ -0,0 +1,42 @@
"use strict";
const electron = require('electron');
const EventEmitter = require('events');
const {
POWER_MONITOR_RESUME,
POWER_MONITOR_SUSPEND,
POWER_MONITOR_LOCK_SCREEN,
POWER_MONITOR_UNLOCK_SCREEN,
POWER_MONITOR_GET_SYSTEM_IDLE_TIME
} = require('../common/constants').IPCEvents;
const events = new EventEmitter();
electron.ipcRenderer.on(POWER_MONITOR_RESUME, () => {
events.emit('resume');
});
electron.ipcRenderer.on(POWER_MONITOR_SUSPEND, () => {
events.emit('suspend');
});
electron.ipcRenderer.on(POWER_MONITOR_LOCK_SCREEN, () => {
events.emit('lock-screen');
});
electron.ipcRenderer.on(POWER_MONITOR_UNLOCK_SCREEN, () => {
events.emit('unlock-screen');
});
function on() {
events.on.apply(events, arguments);
}
function removeListener() {
events.removeListener.apply(events, arguments);
}
function removeAllListeners() {
events.removeAllListeners.apply(events, arguments);
}
async function getSystemIdleTimeMs() {
return electron.ipcRenderer.invoke(POWER_MONITOR_GET_SYSTEM_IDLE_TIME);
}
module.exports = {
on,
removeListener,
removeAllListeners,
getSystemIdleTimeMs
};

View File

@ -0,0 +1,22 @@
"use strict";
const electron = require('electron');
const {
POWER_SAVE_BLOCKER_BLOCK_DISPLAY_SLEEP,
POWER_SAVE_BLOCKER_UNBLOCK_DISPLAY_SLEEP,
POWER_SAVE_BLOCKER_CLEANUP_DISPLAY_SLEEP
} = require('../common/constants').IPCEvents;
async function blockDisplaySleep() {
return electron.ipcRenderer.invoke(POWER_SAVE_BLOCKER_BLOCK_DISPLAY_SLEEP);
}
async function unblockDisplaySleep(id) {
return electron.ipcRenderer.invoke(POWER_SAVE_BLOCKER_UNBLOCK_DISPLAY_SLEEP, id);
}
async function cleanupDisplaySleep() {
return electron.ipcRenderer.invoke(POWER_SAVE_BLOCKER_CLEANUP_DISPLAY_SLEEP);
}
module.exports = {
blockDisplaySleep,
unblockDisplaySleep,
cleanupDisplaySleep
};

View File

@ -0,0 +1,18 @@
"use strict";
const process = require('process');
const env = process.env;
module.exports = {
platform: process.platform,
arch: process.arch,
env: {
DISCORD_TEST: env['DISCORD_TEST'],
DISCORD_GATEWAY_PLAINTEXT: env['DISCORD_GATEWAY_PLAINTEXT'],
DISCORD_DISALLOW_POPUPS: env['DISCORD_DISALLOW_POPUPS'],
LOCALAPPDATA: env['LOCALAPPDATA'],
'PROGRAMFILES(X86)': env['PROGRAMFILES(X86)'],
PROGRAMFILES: env['PROGRAMFILES'],
PROGRAMW6432: env['PROGRAMW6432'],
PROGRAMDATA: env['PROGRAMDATA']
}
};

View File

@ -0,0 +1,98 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.flushCookies = flushCookies;
exports.flushDNSCache = flushDNSCache;
exports.flushStorageData = flushStorageData;
exports.getCPUCoreCount = getCPUCoreCount;
exports.getCurrentCPUUsagePercent = getCurrentCPUUsagePercent;
exports.getCurrentMemoryUsageKB = getCurrentMemoryUsageKB;
exports.getLastCrash = getLastCrash;
exports.getMainArgvSync = getMainArgvSync;
exports.getSystemInfo = getSystemInfo;
exports.purgeMemory = purgeMemory;
exports.setCrashInformation = setCrashInformation;
var _electron = _interopRequireDefault(require("electron"));
var _os = _interopRequireDefault(require("os"));
var _process = _interopRequireDefault(require("process"));
var _DiscordIPC = require("../common/DiscordIPC");
var _minidumpReader = require("./minidumpReader");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// Note: CPU interval should be kept insync with Android's DeviceResourceUsageMonitor interval.
const CPU_USAGE_GATHER_INTERVAL = 1000;
const MEMORY_USAGE_GATHER_INTERVAL = 5000;
const mainArgv = _DiscordIPC.DiscordIPC.renderer.sendSync(_DiscordIPC.IPCEvents.PROCESS_UTILS_GET_MAIN_ARGV_SYNC);
let totalProcessorUsagePercent = 0;
let totalMemoryUsageKB = 0;
const cpuCoreCount = _os.default.cpus().length;
setInterval(() => {
_DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.PROCESS_UTILS_GET_CPU_USAGE).then(usage => totalProcessorUsagePercent = usage);
}, CPU_USAGE_GATHER_INTERVAL);
let memoryUsageTimerRunning = false;
function getCurrentMemoryUsageKB() {
// Lazy initialize because this is only needed when the native process_utils are not available/updated.
if (memoryUsageTimerRunning) {
return totalMemoryUsageKB;
}
memoryUsageTimerRunning = true;
function computeMemoryUsage() {
const memoryUsage = _process.default.memoryUsage();
return (memoryUsage.heapTotal + memoryUsage.external) / 1024;
}
setInterval(() => {
totalMemoryUsageKB = computeMemoryUsage();
}, MEMORY_USAGE_GATHER_INTERVAL);
totalMemoryUsageKB = computeMemoryUsage();
return totalMemoryUsageKB;
}
function flushDNSCache() {
return _DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.PROCESS_UTILS_FLUSH_DNS_CACHE);
}
async function getLastCrash() {
const lastCrash = await _DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.PROCESS_UTILS_GET_LAST_CRASH);
const minidumpInformation = lastCrash.id != null ? await (0, _minidumpReader.getNewestMinidumpInformation)() : null;
return {
date: lastCrash.date,
id: lastCrash.id,
rendererCrashReason: lastCrash.rendererCrashReason,
rendererCrashExitCode: lastCrash.rendererCrashExitCode,
minidumpInformation,
storedInformation: lastCrash.storedInformation
};
}
async function flushCookies(callback) {
try {
await _DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.PROCESS_UTILS_FLUSH_COOKIES);
callback();
} catch (err) {
callback(err);
}
}
function getSystemInfo() {
return _DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.PROCESS_UTILS_GET_SYSTEM_INFO);
}
async function flushStorageData(callback) {
try {
await _DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.PROCESS_UTILS_FLUSH_STORAGE_DATA);
callback();
} catch (err) {
callback(err);
}
}
function purgeMemory() {
_electron.default.webFrame.clearCache();
}
function getCurrentCPUUsagePercent() {
return totalProcessorUsagePercent;
}
function getCPUCoreCount() {
return cpuCoreCount;
}
function getMainArgvSync() {
return mainArgv;
}
function setCrashInformation(crashInformation, state) {
_DiscordIPC.DiscordIPC.renderer.invoke(_DiscordIPC.IPCEvents.PROCESS_UTILS_SET_CRASH_INFORMATION, crashInformation, state);
}

View File

@ -0,0 +1,22 @@
"use strict";
const electron = require('electron');
const {
SAFE_STORAGE_DECRYPT_STRING,
SAFE_STORAGE_ENCRYPT_STRING,
SAFE_STORAGE_IS_ENCRYPTION_AVAILABLE
} = require('../common/constants').IPCEvents;
function isEncryptionAvailable() {
return electron.ipcRenderer.sendSync(SAFE_STORAGE_IS_ENCRYPTION_AVAILABLE);
}
function decryptString(encrypted) {
return electron.ipcRenderer.sendSync(SAFE_STORAGE_DECRYPT_STRING, encrypted);
}
function encryptString(plainText) {
return electron.ipcRenderer.sendSync(SAFE_STORAGE_ENCRYPT_STRING, plainText);
}
module.exports = {
isEncryptionAvailable,
decryptString,
encryptString
};

View File

@ -0,0 +1,29 @@
"use strict";
const electron = require('electron');
const {
SETTINGS_GET,
SETTINGS_SET,
SETTINGS_GET_SYNC
} = require('../common/constants').IPCEvents;
// Updating app settings directly from the renderer is considered deprecated.
// Voice still sets a few options, so we whitelist those.
const RENDERER_SET_WHITELIST = ['audioSubsystem', 'useLegacyAudioDevice', 'debugLogging'];
async function get(name, defaultValue) {
return electron.ipcRenderer.invoke(SETTINGS_GET, name, defaultValue);
}
async function set(name, value) {
if (!RENDERER_SET_WHITELIST.includes(name)) {
throw new Error('cannot set this setting key');
}
return electron.ipcRenderer.invoke(SETTINGS_SET, name, value);
}
function getSync(name, defaultValue) {
return electron.ipcRenderer.sendSync(SETTINGS_GET_SYNC, name, defaultValue);
}
module.exports = {
get,
set,
getSync
};

View File

@ -0,0 +1,48 @@
"use strict";
const electron = require('electron');
const EventEmitter = require('events');
const {
SPELLCHECK_RESULT,
SPELLCHECK_REPLACE_MISSPELLING,
SPELLCHECK_GET_AVAILABLE_DICTIONARIES,
SPELLCHECK_SET_LOCALE,
SPELLCHECK_SET_LEARNED_WORDS
} = require('../common/constants').IPCEvents;
const events = new EventEmitter();
electron.ipcRenderer.on(SPELLCHECK_RESULT, handleSpellcheckData);
function handleSpellcheckData(_, misspelledWord, dictionarySuggestions) {
events.emit('spellcheck-result', misspelledWord, dictionarySuggestions);
}
function on() {
events.on.apply(events, arguments);
}
function removeListener() {
events.removeListener.apply(events, arguments);
}
async function getAvailableDictionaries() {
return electron.ipcRenderer.invoke(SPELLCHECK_GET_AVAILABLE_DICTIONARIES);
}
async function setLocale(locale) {
let succeeded = true;
try {
await electron.ipcRenderer.invoke(SPELLCHECK_SET_LOCALE, locale);
} catch (_) {
succeeded = false;
}
return succeeded;
}
async function setLearnedWords(learnedWords) {
return electron.ipcRenderer.invoke(SPELLCHECK_SET_LEARNED_WORDS, learnedWords);
}
async function replaceMisspelling(correction) {
return electron.ipcRenderer.invoke(SPELLCHECK_REPLACE_MISSPELLING, correction);
}
module.exports = {
on,
removeListener,
getAvailableDictionaries,
setLocale,
setLearnedWords,
replaceMisspelling
};

View File

@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _constants = require("../common/constants");
var _ipc = require("./ipc");
function setThumbarButtons(buttons, isSystemDarkMode) {
return (0, _ipc.send)(_constants.IPCEvents.THUMBAR_BUTTONS_UPDATE, buttons, isSystemDarkMode);
}
var _default = {
setThumbarButtons
};
exports.default = _default;
module.exports = exports.default;

View File

@ -0,0 +1,23 @@
"use strict";
const electron = require('electron');
const {
USER_DATA_CACHE_SAVE,
USER_DATA_CACHE_GET,
USER_DATA_CACHE_DELETE
} = require('../common/constants').IPCEvents;
async function getCached() {
const cached = await electron.ipcRenderer.invoke(USER_DATA_CACHE_GET);
return cached;
}
function cacheUserData(userData) {
electron.ipcRenderer.send(USER_DATA_CACHE_SAVE, userData);
}
function deleteCache() {
electron.ipcRenderer.send(USER_DATA_CACHE_DELETE);
}
module.exports = {
getCached,
cacheUserData,
deleteCache
};

View File

@ -0,0 +1,95 @@
"use strict";
const electron = require('electron');
const {
WINDOW_BLUR,
WINDOW_CLOSE,
WINDOW_FOCUS,
WINDOW_MAXIMIZE,
WINDOW_MINIMIZE,
WINDOW_RESTORE,
WINDOW_FLASH_FRAME,
WINDOW_TOGGLE_FULLSCREEN,
WINDOW_SET_BACKGROUND_THROTTLING,
WINDOW_SET_PROGRESS_BAR,
WINDOW_IS_ALWAYS_ON_TOP,
WINDOW_SET_ALWAYS_ON_TOP,
WINDOW_DEVTOOLS_OPENED,
WINDOW_DEVTOOLS_CLOSED
} = require('../common/constants').IPCEvents;
let devtoolsOpenedCallback = () => {};
let devtoolsClosedCallback = () => {};
electron.ipcRenderer.on(WINDOW_DEVTOOLS_OPENED, async _ => {
if (devtoolsOpenedCallback != null) {
devtoolsOpenedCallback();
}
});
electron.ipcRenderer.on(WINDOW_DEVTOOLS_CLOSED, async _ => {
if (devtoolsClosedCallback != null) {
devtoolsClosedCallback();
}
});
async function flashFrame(flag) {
electron.ipcRenderer.invoke(WINDOW_FLASH_FRAME, flag);
}
async function minimize(key) {
electron.ipcRenderer.invoke(WINDOW_MINIMIZE, key);
}
async function restore(key) {
electron.ipcRenderer.invoke(WINDOW_RESTORE, key);
}
async function maximize(key) {
electron.ipcRenderer.invoke(WINDOW_MAXIMIZE, key);
}
async function focus(_hack, key) {
electron.ipcRenderer.invoke(WINDOW_FOCUS, key);
}
async function setAlwaysOnTop(key, enabled) {
return electron.ipcRenderer.invoke(WINDOW_SET_ALWAYS_ON_TOP, key, enabled);
}
async function isAlwaysOnTop(key) {
return electron.ipcRenderer.invoke(WINDOW_IS_ALWAYS_ON_TOP, key);
}
async function blur(key) {
electron.ipcRenderer.invoke(WINDOW_BLUR, key);
}
async function setProgressBar(progress, key) {
electron.ipcRenderer.invoke(WINDOW_SET_PROGRESS_BAR, key, progress);
}
async function fullscreen(key) {
electron.ipcRenderer.invoke(WINDOW_TOGGLE_FULLSCREEN, key);
}
async function close(key) {
electron.ipcRenderer.invoke(WINDOW_CLOSE, key);
}
async function setZoomFactor(factor) {
if (!electron.webFrame.setZoomFactor) return;
electron.webFrame.setZoomFactor(factor / 100);
}
async function setBackgroundThrottling(enabled) {
electron.ipcRenderer.invoke(WINDOW_SET_BACKGROUND_THROTTLING, enabled);
}
async function setDevtoolsCallbacks(onOpened, onClosed) {
devtoolsOpenedCallback = onOpened;
devtoolsClosedCallback = onClosed;
}
// To synchronize web vs desktop release features
const USE_OSX_NATIVE_TRAFFIC_LIGHTS = true;
module.exports = {
flashFrame,
minimize,
restore,
maximize,
focus,
blur,
fullscreen,
close,
setAlwaysOnTop,
isAlwaysOnTop,
setZoomFactor,
setBackgroundThrottling,
setProgressBar,
setDevtoolsCallbacks,
USE_OSX_NATIVE_TRAFFIC_LIGHTS
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="20px" height="20px"
viewBox="40 40 20 20" enable-background="new 40 40 20 20" xml:space="preserve">
<title>Slice 1</title>
<description>Created with Sketch (http://www.bohemiancoding.com/sketch)</description>
<g id="Page_1">
<path id="Close" fill="#99aab5" d="M40.445,42.853l2.408-2.408c0.593-0.593,1.555-0.593,2.147,0l5,5l5-5
c0.593-0.593,1.554-0.593,2.147,0l2.408,2.408c0.593,0.593,0.593,1.554,0,2.147l-5,5l5,5c0.593,0.593,0.592,1.554,0,2.147
l-2.408,2.408c-0.593,0.593-1.555,0.593-2.147,0l-5-5l-5,5c-0.593,0.593-1.554,0.593-2.147,0l-2.408-2.408
c-0.593-0.593-0.593-1.554,0-2.147l5-5l-5-5C39.852,44.407,39.852,43.445,40.445,42.853z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 168 190" enable-background="new 0 0 168 190" xml:space="preserve">
<g>
<rect x="14.4" y="46.1" fill="#FFFFFF" width="139.2" height="97.7"/>
<g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="66.6616" y1="79.7119" x2="66.6616" y2="100.7434">
<stop offset="0" style="stop-color:#7491D5"/>
<stop offset="1" style="stop-color:#4E68A0"/>
</linearGradient>
<path fill="url(#SVGID_1_)" d="M66.7,79.7c-5.4,0-9.8,4.7-9.8,10.5c0,5.8,4.4,10.5,9.8,10.5c5.4,0,9.8-4.7,9.8-10.5
C76.5,84.4,72.1,79.7,66.7,79.7z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="101.661" y1="79.7119" x2="101.661" y2="100.7434">
<stop offset="0" style="stop-color:#7491D5"/>
<stop offset="1" style="stop-color:#4E68A0"/>
</linearGradient>
<path fill="url(#SVGID_2_)" d="M101.7,79.7c-5.4,0-9.8,4.7-9.8,10.5c0,5.8,4.4,10.5,9.8,10.5c5.4,0,9.8-4.7,9.8-10.5
C111.5,84.4,107.1,79.7,101.7,79.7z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="84" y1="-4.545736e-07" x2="84" y2="190">
<stop offset="0" style="stop-color:#7491D5"/>
<stop offset="1" style="stop-color:#4E68A0"/>
</linearGradient>
<path fill="url(#SVGID_3_)" d="M148.4,0H19.6C8.8,0,0,8.8,0,19.6v128.4c0,10.8,8.8,19.6,19.6,19.6h108.9l-5.1-17.5l12.3,11.3
l11.6,10.7L168,190v-41.9v-9.5V19.6C168,8.8,159.2,0,148.4,0z M111.3,124.1c0,0-3.4-4.1-6.3-7.7c12.6-3.5,17.4-11.3,17.4-11.3
c-4,2.6-7.7,4.4-11.1,5.6c-4.8,2-9.5,3.3-14,4.1c-9.2,1.7-17.6,1.3-24.9-0.1c-5.5-1-10.2-2.5-14.1-4.1c-2.2-0.8-4.6-1.9-7.1-3.3
c-0.3-0.2-0.6-0.3-0.9-0.5c-0.1-0.1-0.3-0.2-0.4-0.2c-1.7-1-2.6-1.6-2.6-1.6s4.6,7.6,16.8,11.2c-2.9,3.6-6.4,7.9-6.4,7.9
c-21.2-0.6-29.3-14.5-29.3-14.5c0-30.6,13.8-55.4,13.8-55.4c13.8-10.3,26.9-10,26.9-10l1,1.1C52.8,50.3,45,57.9,45,57.9
s2.1-1.2,5.7-2.7c10.3-4.5,18.4-5.7,21.8-6c0.5-0.1,1.1-0.2,1.6-0.2c5.9-0.7,12.5-0.9,19.4-0.2c9.1,1,18.9,3.7,28.9,9.1
c0,0-7.5-7.2-23.9-12.1l1.3-1.5c0,0,13.1-0.3,26.9,10c0,0,13.8,24.8,13.8,55.4C140.6,109.6,132.5,123.5,111.3,124.1z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 421 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 540 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 B

Some files were not shown because too many files have changed in this diff Show More