[*] ESLint: The Lintening (#393)

* [*] ESLint: The Lintening

* Missed a couple unused vals in utils

* [*] Tend to DeepScan remarks

* [*] sigh, remove some duplicate crap
This commit is contained in:
Alyxia Sother 2023-05-08 21:24:30 +02:00 committed by GitHub
parent 974f90fd35
commit a2a997df30
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 1091 additions and 293 deletions

35
.eslintrc.yml Normal file
View file

@ -0,0 +1,35 @@
extends: eslint-config-dmitmel/presets/node
env:
browser: true
plugins: ["prettier"]
settings:
node:
tryExtensions: [".tsx", ".ts", ".jsx", ".js", ".json", ".node"]
ignorePatterns: ["src/arrpc/**"]
rules:
prettier/prettier:
- error
node/no-unsupported-features/es-syntax:
- error
- ignores:
- modules
overrides:
- files: "**/*.ts*"
extends:
- eslint-config-dmitmel/presets/typescript-addon
parserOptions:
project: "tsconfig.json"
sourceType: module
rules:
eqeqeq: 0
require-await: 0
no-undefined: 0
node/no-unsupported-features/es-syntax: 0
"@typescript-eslint/no-dynamic-delete": 0
"@typescript-eslint/no-explicit-any": 0
"@typescript-eslint/no-non-null-asserted-optional-chain": 0
"@typescript-eslint/naming-convention": 0

View file

@ -3,6 +3,9 @@
"version": "3.2.0", "version": "3.2.0",
"description": "ArmCord is a custom client designed to enhance your Discord experience while keeping everything lightweight.", "description": "ArmCord is a custom client designed to enhance your Discord experience while keeping everything lightweight.",
"main": "ts-out/main.js", "main": "ts-out/main.js",
"engines": {
"node": ">=18.0.0"
},
"scripts": { "scripts": {
"build": "tsc && copyfiles -u 1 src/**/*.html src/**/**/*.css src/**/**/*.js ts-out/ && copyfiles package.json ts-out/ && copyfiles assets/**/** ts-out/", "build": "tsc && copyfiles -u 1 src/**/*.html src/**/**/*.css src/**/**/*.js ts-out/ && copyfiles package.json ts-out/ && copyfiles assets/**/** ts-out/",
"watch": "tsc -w", "watch": "tsc -w",
@ -11,6 +14,7 @@
"package": "npm run build && electron-builder", "package": "npm run build && electron-builder",
"packageQuick": "npm run build && electron-builder --dir", "packageQuick": "npm run build && electron-builder --dir",
"format": "prettier --write src *.json", "format": "prettier --write src *.json",
"lint": "eslint src --ext .js,.jsx,.ts,.tsx --ignore-path .gitignore",
"CIbuild": "npm run build && electron-builder --linux zip && electron-builder --windows zip && electron-builder --macos zip", "CIbuild": "npm run build && electron-builder --linux zip && electron-builder --windows zip && electron-builder --macos zip",
"prepare": "git config --local core.hooksPath .hooks/" "prepare": "git config --local core.hooksPath .hooks/"
}, },
@ -27,10 +31,16 @@
"devDependencies": { "devDependencies": {
"@types/node": "^18.11.9", "@types/node": "^18.11.9",
"@types/ws": "^8.5.3", "@types/ws": "^8.5.3",
"@typescript-eslint/eslint-plugin": "^5.59.2",
"@typescript-eslint/parser": "^5.59.2",
"chalk-cli": "^5.0.0", "chalk-cli": "^5.0.0",
"copyfiles": "^2.4.1", "copyfiles": "^2.4.1",
"electron": "^24.1.2", "electron": "^24.1.2",
"electron-builder": "^23.6.0", "electron-builder": "^23.6.0",
"eslint": "^8.40.0",
"eslint-config-dmitmel": "github:dmitmel/eslint-config-dmitmel",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^4.2.1",
"prettier": "^2.7.1", "prettier": "^2.7.1",
"typescript": "^4.9.3" "typescript": "^4.9.3"
}, },

File diff suppressed because it is too large Load diff

View file

@ -65,7 +65,7 @@ function disableAutogain(constraints) {
function patchFunction(object, name, createNewFunction) { function patchFunction(object, name, createNewFunction) {
if (name in object) { if (name in object) {
var original = object[name]; const original = object[name];
object[name] = createNewFunction(original); object[name] = createNewFunction(original);
} }
} }

View file

@ -1,7 +1,7 @@
import electron from "electron"; import electron from "electron";
import {getConfig} from "../utils"; import {getConfig} from "../utils";
const unstrictCSP = () => { const unstrictCSP = (): void => {
console.log("Setting up CSP unstricter..."); console.log("Setting up CSP unstricter...");
electron.session.defaultSession.webRequest.onHeadersReceived(({responseHeaders, resourceType}, done) => { electron.session.defaultSession.webRequest.onHeadersReceived(({responseHeaders, resourceType}, done) => {
@ -15,7 +15,7 @@ const unstrictCSP = () => {
responseHeaders["content-type"] = ["text/css"]; responseHeaders["content-type"] = ["text/css"];
} }
done({responseHeaders}); return done({responseHeaders});
}); });
}; };

View file

@ -1,7 +1,7 @@
import * as fs from "fs"; import * as fs from "fs";
import {app, session} from "electron"; import {app, session} from "electron";
const userDataPath = app.getPath("userData"); const userDataPath = app.getPath("userData");
const pluginFolder = userDataPath + "/plugins/"; const pluginFolder = `${userDataPath}/plugins`;
if (!fs.existsSync(pluginFolder)) { if (!fs.existsSync(pluginFolder)) {
fs.mkdirSync(pluginFolder); fs.mkdirSync(pluginFolder);
console.log("Created missing plugin folder"); console.log("Created missing plugin folder");
@ -9,9 +9,9 @@ if (!fs.existsSync(pluginFolder)) {
app.whenReady().then(() => { app.whenReady().then(() => {
fs.readdirSync(pluginFolder).forEach((file) => { fs.readdirSync(pluginFolder).forEach((file) => {
try { try {
const manifest = fs.readFileSync(`${userDataPath}/plugins/${file}/manifest.json`, "utf8"); const manifest = fs.readFileSync(`${pluginFolder}/${file}/manifest.json`, "utf8");
var pluginFile = JSON.parse(manifest); const pluginFile = JSON.parse(manifest);
session.defaultSession.loadExtension(`${userDataPath}/plugins/${file}`); session.defaultSession.loadExtension(`${pluginFolder}/${file}`);
console.log(`[Mod loader] Loaded ${pluginFile.name} made by ${pluginFile.author}`); console.log(`[Mod loader] Loaded ${pluginFile.name} made by ${pluginFile.author}`);
} catch (err) { } catch (err) {
console.error(err); console.error(err);

View file

@ -1,44 +1,42 @@
//ipc stuff //ipc stuff
import {app, ipcMain, shell, desktopCapturer, nativeImage, screen} from "electron"; import {app, desktopCapturer, ipcMain, nativeImage, shell} from "electron";
import {mainWindow} from "./window"; import {mainWindow} from "./window";
import { import {
setConfigBulk,
getVersion,
getConfig, getConfig,
setLang,
getLang,
getWindowState,
packageVersion,
getDisplayVersion, getDisplayVersion,
getLang,
getVersion,
getWindowState,
modInstallState, modInstallState,
installModLoader packageVersion,
setConfigBulk,
setLang
} from "./utils"; } from "./utils";
import {customTitlebar} from "./main"; import {customTitlebar} from "./main";
import {createSettingsWindow} from "./settings/main"; import {createSettingsWindow} from "./settings/main";
import os from "os"; import os from "os";
import fs from "fs";
import path from "path"; import path from "path";
export function registerIpc() { export function registerIpc(): void {
ipcMain.on("get-app-path", (event, arg) => { ipcMain.on("get-app-path", (event) => {
event.reply("app-path", app.getAppPath()); event.reply("app-path", app.getAppPath());
}); });
ipcMain.on("setLang", (event, lang: string) => { ipcMain.on("setLang", (_event, lang: string) => {
setLang(lang); setLang(lang);
}); });
ipcMain.handle("getLang", (event, toGet: string) => { ipcMain.handle("getLang", (_event, toGet: string) => {
return getLang(toGet); return getLang(toGet);
}); });
ipcMain.on("open-external-link", (event, href: string) => { ipcMain.on("open-external-link", (_event, href: string) => {
shell.openExternal(href); shell.openExternal(href);
}); });
ipcMain.on("setPing", (event, pingCount: number) => { ipcMain.on("setPing", (_event, pingCount: number) => {
switch (os.platform()) { switch (os.platform()) {
case "linux" ?? "macos": case "linux" ?? "macos":
app.setBadgeCount(pingCount); app.setBadgeCount(pingCount);
break; break;
case "win32": case "win32":
if (pingCount > 0) { if (pingCount > 0) {
var image = nativeImage.createFromPath(path.join(__dirname, "../", `/assets/ping.png`)); let image = nativeImage.createFromPath(path.join(__dirname, "../", `/assets/ping.png`));
mainWindow.setOverlayIcon(image, "badgeCount"); mainWindow.setOverlayIcon(image, "badgeCount");
} else { } else {
mainWindow.setOverlayIcon(null, "badgeCount"); mainWindow.setOverlayIcon(null, "badgeCount");
@ -46,28 +44,28 @@ export function registerIpc() {
break; break;
} }
}); });
ipcMain.on("win-maximize", (event, arg) => { ipcMain.on("win-maximize", () => {
mainWindow.maximize(); mainWindow.maximize();
}); });
ipcMain.on("win-isMaximized", (event, arg) => { ipcMain.on("win-isMaximized", (event) => {
event.returnValue = mainWindow.isMaximized(); event.returnValue = mainWindow.isMaximized();
}); });
ipcMain.on("win-isNormal", (event, arg) => { ipcMain.on("win-isNormal", (event) => {
event.returnValue = mainWindow.isNormal(); event.returnValue = mainWindow.isNormal();
}); });
ipcMain.on("win-minimize", (event, arg) => { ipcMain.on("win-minimize", () => {
mainWindow.minimize(); mainWindow.minimize();
}); });
ipcMain.on("win-unmaximize", (event, arg) => { ipcMain.on("win-unmaximize", () => {
mainWindow.unmaximize(); mainWindow.unmaximize();
}); });
ipcMain.on("win-show", (event, arg) => { ipcMain.on("win-show", () => {
mainWindow.show(); mainWindow.show();
}); });
ipcMain.on("win-hide", (event, arg) => { ipcMain.on("win-hide", () => {
mainWindow.hide(); mainWindow.hide();
}); });
ipcMain.on("win-quit", (event, arg) => { ipcMain.on("win-quit", () => {
app.exit(); app.exit();
}); });
ipcMain.on("get-app-version", (event) => { ipcMain.on("get-app-version", (event) => {
@ -83,14 +81,19 @@ export function registerIpc() {
event.returnValue = packageVersion; event.returnValue = packageVersion;
}); });
ipcMain.on("splashEnd", async () => { ipcMain.on("splashEnd", async () => {
let width = 800,
height = 600,
isMaximized = true,
xValue = 0,
yValue = 0;
try { try {
var width = (await getWindowState("width")) ?? 800; width = (await getWindowState("width")) ?? 800;
var height = (await getWindowState("height")) ?? 600; height = (await getWindowState("height")) ?? 600;
var isMaximized = (await getWindowState("isMaximized")) ?? false; isMaximized = (await getWindowState("isMaximized")) ?? false;
var xValue = await getWindowState("x"); xValue = await getWindowState("x");
var yValue = await getWindowState("y"); yValue = await getWindowState("y");
} catch (e) { } catch (_e) {
console.log("[Window state manager] No window state file found. Fallbacking to default values."); console.log("[Window state manager] No window state file found. Falling back to default values.");
mainWindow.setSize(800, 600); mainWindow.setSize(800, 600);
} }
if (isMaximized) { if (isMaximized) {
@ -102,11 +105,11 @@ export function registerIpc() {
console.log("[Window state manager] Not maximized."); console.log("[Window state manager] Not maximized.");
} }
}); });
ipcMain.on("restart", (event, arg) => { ipcMain.on("restart", () => {
app.relaunch(); app.relaunch();
app.exit(); app.exit();
}); });
ipcMain.on("saveSettings", (event, args) => { ipcMain.on("saveSettings", (_event, args) => {
setConfigBulk(args); setConfigBulk(args);
}); });
ipcMain.on("minimizeToTray", async (event) => { ipcMain.on("minimizeToTray", async (event) => {
@ -115,28 +118,28 @@ export function registerIpc() {
ipcMain.on("channel", async (event) => { ipcMain.on("channel", async (event) => {
event.returnValue = await getConfig("channel"); event.returnValue = await getConfig("channel");
}); });
ipcMain.on("clientmod", async (event, arg) => { ipcMain.on("clientmod", async (event) => {
event.returnValue = await getConfig("mods"); event.returnValue = await getConfig("mods");
}); });
ipcMain.on("legacyCapturer", async (event, arg) => { ipcMain.on("legacyCapturer", async (event) => {
event.returnValue = await getConfig("useLegacyCapturer"); event.returnValue = await getConfig("useLegacyCapturer");
}); });
ipcMain.on("trayIcon", async (event, arg) => { ipcMain.on("trayIcon", async (event) => {
event.returnValue = await getConfig("trayIcon"); event.returnValue = await getConfig("trayIcon");
}); });
ipcMain.on("disableAutogain", async (event, arg) => { ipcMain.on("disableAutogain", async (event) => {
event.returnValue = await getConfig("disableAutogain"); event.returnValue = await getConfig("disableAutogain");
}); });
ipcMain.on("titlebar", (event, arg) => { ipcMain.on("titlebar", (event) => {
event.returnValue = customTitlebar; event.returnValue = customTitlebar;
}); });
ipcMain.on("mobileMode", async (event, arg) => { ipcMain.on("mobileMode", async (event) => {
event.returnValue = await getConfig("mobileMode"); event.returnValue = await getConfig("mobileMode");
}); });
ipcMain.on("shouldPatch", async (event, arg) => { ipcMain.on("shouldPatch", async (event) => {
event.returnValue = await getConfig("automaticPatches"); event.returnValue = await getConfig("automaticPatches");
}); });
ipcMain.on("openSettingsWindow", (event, arg) => { ipcMain.on("openSettingsWindow", () => {
createSettingsWindow(); createSettingsWindow();
}); });
ipcMain.on("setting-armcordCSP", async (event) => { ipcMain.on("setting-armcordCSP", async (event) => {
@ -146,5 +149,5 @@ export function registerIpc() {
event.returnValue = false; event.returnValue = false;
} }
}); });
ipcMain.handle("DESKTOP_CAPTURER_GET_SOURCES", (event, opts) => desktopCapturer.getSources(opts)); ipcMain.handle("DESKTOP_CAPTURER_GET_SOURCES", (_event, opts) => desktopCapturer.getSources(opts));
} }

View file

@ -1,34 +1,32 @@
// Modules to control application life and create native browser window // Modules to control application life and create native browser window
import {app, BrowserWindow, crashReporter, session} from "electron"; import {BrowserWindow, app, crashReporter, session} from "electron";
import "v8-compile-cache"; import "v8-compile-cache";
import { import {
Settings,
checkForDataFolder, checkForDataFolder,
getConfig,
checkIfConfigExists, checkIfConfigExists,
getConfig,
injectElectronFlags, injectElectronFlags,
setConfig,
installModLoader, installModLoader,
getConfigLocation setConfig
} from "./utils"; } from "./utils";
import "./extensions/mods"; import "./extensions/mods";
import "./tray"; import "./tray";
import fs from "fs"; import {createCustomWindow, createNativeWindow, createTransparentWindow} from "./window";
import {createCustomWindow, createNativeWindow, createTransparentWindow, mainWindow} from "./window";
import path from "path"; import path from "path";
export var iconPath: string; export let iconPath: string;
export var settings: any; export let settings: any;
export var customTitlebar: boolean; export let customTitlebar: boolean;
export var clientName: "ArmCord"; async function args(): Promise<void> {
async function args() { let argNum = 2;
var argNum = 2;
if (process.argv[0] == "electron") argNum++; if (process.argv[0] == "electron") argNum++;
var args = process.argv[argNum]; let args = process.argv[argNum];
if (args == undefined) return; if (args == undefined) return;
if (args.startsWith("--")) return; //electron flag if (args.startsWith("--")) return; //electron flag
if (args.includes("=")) { if (args.includes("=")) {
var e = args.split("="); let e = args.split("=");
await setConfig(e[0], e[1]); await setConfig(e[0] as keyof Settings, e[1]);
console.log("Setting " + e[0] + " to " + e[1]); console.log(`Setting ${e[0]} to ${e[1]}`);
app.relaunch(); app.relaunch();
app.exit(); app.exit();
} }
@ -70,7 +68,7 @@ if (!app.requestSingleInstanceLock()) {
} else { } else {
iconPath = path.join(__dirname, "../", "/assets/ac_icon_transparent.png"); iconPath = path.join(__dirname, "../", "/assets/ac_icon_transparent.png");
} }
async function init() { async function init(): Promise<void> {
switch (await getConfig("windowStyle")) { switch (await getConfig("windowStyle")) {
case "default": case "default":
createCustomWindow(); createCustomWindow();
@ -93,7 +91,7 @@ if (!app.requestSingleInstanceLock()) {
} }
await init(); await init();
await installModLoader(); await installModLoader();
session.fromPartition("some-partition").setPermissionRequestHandler((webContents, permission, callback) => { session.fromPartition("some-partition").setPermissionRequestHandler((_webContents, permission, callback) => {
if (permission === "notifications") { if (permission === "notifications") {
// Approves the permissions request // Approves the permissions request
callback(true); callback(true);

View file

@ -3,7 +3,7 @@ import {mainWindow} from "./window";
import {getConfig} from "./utils"; import {getConfig} from "./utils";
import {createSettingsWindow} from "./settings/main"; import {createSettingsWindow} from "./settings/main";
function paste(contents: any) { function paste(contents: any): void {
const contentTypes = clipboard.availableFormats().toString(); const contentTypes = clipboard.availableFormats().toString();
//Workaround: fix pasting the images. //Workaround: fix pasting the images.
if (contentTypes.includes("image/") && contentTypes.includes("text/html")) { if (contentTypes.includes("image/") && contentTypes.includes("text/html")) {
@ -11,7 +11,7 @@ function paste(contents: any) {
} }
contents.paste(); contents.paste();
} }
export async function setMenu() { export async function setMenu(): Promise<void> {
if ((await getConfig("alternativePaste")) == true) { if ((await getConfig("alternativePaste")) == true) {
mainWindow.on("focus", function () { mainWindow.on("focus", function () {
console.log("[Window state manager] Focus"); console.log("[Window state manager] Focus");
@ -39,7 +39,7 @@ export async function setMenu() {
globalShortcut.unregister("CmdOrCtrl+V"); globalShortcut.unregister("CmdOrCtrl+V");
}); });
} }
var template: Electron.MenuItemConstructorOptions[] = [ let template: Electron.MenuItemConstructorOptions[] = [
{ {
label: "ArmCord", label: "ArmCord",
submenu: [ submenu: [
@ -48,28 +48,28 @@ export async function setMenu() {
{ {
label: "Developer tools", label: "Developer tools",
accelerator: "CmdOrCtrl+Shift+I", accelerator: "CmdOrCtrl+Shift+I",
click: function () { click() {
BrowserWindow.getFocusedWindow()!.webContents.toggleDevTools(); BrowserWindow.getFocusedWindow()!.webContents.toggleDevTools();
} }
}, },
{ {
label: "Open settings", label: "Open settings",
accelerator: "CmdOrCtrl+Shift+'", accelerator: "CmdOrCtrl+Shift+'",
click: function () { click() {
createSettingsWindow(); createSettingsWindow();
} }
}, },
{ {
label: "Reload", label: "Reload",
accelerator: "CmdOrCtrl+R", accelerator: "CmdOrCtrl+R",
click: function () { click() {
mainWindow.reload(); mainWindow.reload();
} }
}, },
{ {
label: "Quit", label: "Quit",
accelerator: "CmdOrCtrl+Q", accelerator: "CmdOrCtrl+Q",
click: function () { click() {
app.quit(); app.quit();
} }
} }
@ -86,7 +86,7 @@ export async function setMenu() {
{ {
label: "Paste", label: "Paste",
accelerator: "CmdOrCtrl+V", accelerator: "CmdOrCtrl+V",
click: function () { click() {
paste(mainWindow.webContents); paste(mainWindow.webContents);
} }
}, },

View file

@ -9,7 +9,7 @@ interface IPCSources {
name: string; name: string;
thumbnail: HTMLCanvasElement; thumbnail: HTMLCanvasElement;
} }
async function getDisplayMediaSelector() { async function getDisplayMediaSelector(): Promise<string> {
const sources: IPCSources[] = await desktopCapturer.getSources({ const sources: IPCSources[] = await desktopCapturer.getSources({
types: ["screen", "window"] types: ["screen", "window"]
}); });
@ -54,7 +54,7 @@ contextBridge.exposeInMainWorld("armcord", {
ipcRenderer.invoke("getLang", toGet).then((result) => { ipcRenderer.invoke("getLang", toGet).then((result) => {
return result; return result;
}), }),
getDisplayMediaSelector: getDisplayMediaSelector, getDisplayMediaSelector,
version: ipcRenderer.sendSync("get-app-version", "app-version"), version: ipcRenderer.sendSync("get-app-version", "app-version"),
mods: ipcRenderer.sendSync("clientmod"), mods: ipcRenderer.sendSync("clientmod"),
packageVersion: ipcRenderer.sendSync("get-package-version", "app-version"), packageVersion: ipcRenderer.sendSync("get-package-version", "app-version"),
@ -63,9 +63,11 @@ contextBridge.exposeInMainWorld("armcord", {
}); });
let windowCallback: (arg0: object) => void; let windowCallback: (arg0: object) => void;
contextBridge.exposeInMainWorld("ArmCordRPC", { contextBridge.exposeInMainWorld("ArmCordRPC", {
listen: (callback: any) => (windowCallback = callback) listen: (callback: any) => {
windowCallback = callback;
}
}); });
ipcRenderer.on("rpc", (event, data: object) => { ipcRenderer.on("rpc", (_event, data: object) => {
windowCallback(data); windowCallback(data);
}); });
//to be only used inside armcord internal setup/splash etc //to be only used inside armcord internal setup/splash etc

View file

@ -1,6 +1,6 @@
//Fixed context isolation version https://github.com/getferdi/ferdi/blob/develop/src/webview/screenshare.ts //Fixed context isolation version https://github.com/getferdi/ferdi/blob/develop/src/webview/screenshare.ts
//original https://github.com/electron/electron/issues/16513#issuecomment-602070250 //original https://github.com/electron/electron/issues/16513#issuecomment-602070250
import {addStyle, addScript} from "../utils"; import {addScript, addStyle} from "../utils";
import fs from "fs"; import fs from "fs";
import path from "path"; import path from "path";

View file

@ -1,9 +1,8 @@
import {ipcRenderer} from "electron";
import {addStyle} from "../utils"; import {addStyle} from "../utils";
import * as fs from "fs"; import * as fs from "fs";
import * as path from "path"; import * as path from "path";
export function injectMobileStuff() { export function injectMobileStuff(): void {
document.addEventListener("DOMContentLoaded", function (event) { document.addEventListener("DOMContentLoaded", function () {
const mobileCSS = path.join(__dirname, "../", "/content/css/mobile.css"); const mobileCSS = path.join(__dirname, "../", "/content/css/mobile.css");
addStyle(fs.readFileSync(mobileCSS, "utf8")); addStyle(fs.readFileSync(mobileCSS, "utf8"));
// TO-DO: clicking on the logo, or additional button triggers ESC button to move around the UI quicker // TO-DO: clicking on the logo, or additional button triggers ESC button to move around the UI quicker

View file

@ -4,16 +4,16 @@
import {ipcRenderer} from "electron"; import {ipcRenderer} from "electron";
import {injectJS} from "../utils"; import {injectJS} from "../utils";
var patchEndpoint = "https://patch.armcord.xyz/"; const patchEndpoint = "https://patch.armcord.xyz";
var version = ipcRenderer.sendSync("get-app-version", "app-version"); const version = ipcRenderer.sendSync("get-app-version", "app-version");
if (ipcRenderer.sendSync("shouldPatch")) { if (ipcRenderer.sendSync("shouldPatch")) {
document.addEventListener("DOMContentLoaded", function () { document.addEventListener("DOMContentLoaded", function () {
fetch(patchEndpoint + version + "/info.json", {cache: "no-store"}) //lmao fetch(`${patchEndpoint}/${version}/info.json`, {cache: "no-store"}) //lmao
.then((res) => res.json()) .then((res) => res.json())
.then((res) => { .then((res) => {
if (res.patch == true) { if (res.patch == true) {
console.log("Found a patch. Injecting..."); console.log("Found a patch. Injecting...");
injectJS(patchEndpoint + version + "/patch.js"); injectJS(`${patchEndpoint}/${version}/patch.js`);
} else { } else {
console.log("No patches have been found."); console.log("No patches have been found.");
} }

View file

@ -15,9 +15,8 @@ if (ipcRenderer.sendSync("legacyCapturer")) {
import("./capturer"); import("./capturer");
} }
var version = ipcRenderer.sendSync("displayVersion"); const version = ipcRenderer.sendSync("displayVersion");
var channel = ipcRenderer.sendSync("channel"); async function updateLang(): Promise<void> {
async function updateLang() {
if (window.location.href.indexOf("setup.html") > -1) { if (window.location.href.indexOf("setup.html") > -1) {
console.log("Setup, skipping lang update"); console.log("Setup, skipping lang update");
} else { } else {
@ -32,8 +31,8 @@ declare global {
} }
} }
console.log("ArmCord " + version); console.log(`ArmCord ${version}`);
ipcRenderer.on("themeLoader", (event, message) => { ipcRenderer.on("themeLoader", (_event, message) => {
addStyle(message); addStyle(message);
}); });
if (window.location.href.indexOf("splash.html") > -1) { if (window.location.href.indexOf("splash.html") > -1) {

View file

@ -3,9 +3,9 @@ import {addStyle} from "../utils";
import * as fs from "fs"; import * as fs from "fs";
import * as path from "path"; import * as path from "path";
import os from "os"; import os from "os";
export function injectTitlebar() { export function injectTitlebar(): void {
document.addEventListener("DOMContentLoaded", function (event) { document.addEventListener("DOMContentLoaded", function (_event) {
var elem = document.createElement("div"); const elem = document.createElement("div");
elem.innerHTML = `<nav class="titlebar"> elem.innerHTML = `<nav class="titlebar">
<div class="window-title" id="window-title"></div> <div class="window-title" id="window-title"></div>
<div id="window-controls-container"> <div id="window-controls-container">
@ -28,9 +28,9 @@ export function injectTitlebar() {
document.body.setAttribute("customTitlebar", ""); document.body.setAttribute("customTitlebar", "");
document.body.setAttribute("armcord-platform", os.platform()); document.body.setAttribute("armcord-platform", os.platform());
var minimize = document.getElementById("minimize"); const minimize = document.getElementById("minimize");
var maximize = document.getElementById("maximize"); const maximize = document.getElementById("maximize");
var quit = document.getElementById("quit"); const quit = document.getElementById("quit");
minimize!.addEventListener("click", () => { minimize!.addEventListener("click", () => {
ipcRenderer.send("win-minimize"); ipcRenderer.send("win-minimize");
@ -55,8 +55,8 @@ export function injectTitlebar() {
}); });
} }
export function fixTitlebar() { export function fixTitlebar(): void {
var elem = document.createElement("div"); const elem = document.createElement("div");
elem.innerHTML = `<nav class="titlebar"> elem.innerHTML = `<nav class="titlebar">
<div class="window-title" id="window-title"></div> <div class="window-title" id="window-title"></div>
<div id="window-controls-container"> <div id="window-controls-container">
@ -72,9 +72,9 @@ export function fixTitlebar() {
} else { } else {
document.getElementById("app-mount")!.prepend(elem); document.getElementById("app-mount")!.prepend(elem);
} }
var minimize = document.getElementById("minimize"); const minimize = document.getElementById("minimize");
var maximize = document.getElementById("maximize"); const maximize = document.getElementById("maximize");
var quit = document.getElementById("quit"); const quit = document.getElementById("quit");
minimize!.addEventListener("click", () => { minimize!.addEventListener("click", () => {
ipcRenderer.send("win-minimize"); ipcRenderer.send("win-minimize");

View file

@ -1,8 +1,8 @@
import {BrowserWindow, desktopCapturer, DesktopCapturerSource, ipcMain, session, shell} from "electron"; import {BrowserWindow, desktopCapturer, ipcMain, session} from "electron";
import path from "path"; import path from "path";
import {iconPath} from "../main"; import {iconPath} from "../main";
var capturerWindow: BrowserWindow; let capturerWindow: BrowserWindow;
function registerCustomHandler() { function registerCustomHandler(): void {
session.defaultSession.setDisplayMediaRequestHandler(async (request, callback) => { session.defaultSession.setDisplayMediaRequestHandler(async (request, callback) => {
console.log(request); console.log(request);
const sources = await desktopCapturer.getSources({ const sources = await desktopCapturer.getSources({
@ -23,11 +23,11 @@ function registerCustomHandler() {
preload: path.join(__dirname, "preload.js") preload: path.join(__dirname, "preload.js")
} }
}); });
ipcMain.once("selectScreenshareSource", (event, id, name) => { ipcMain.once("selectScreenshareSource", (_event, id, name) => {
//console.log(sources[id]); //console.log(sources[id]);
//console.log(id); //console.log(id);
capturerWindow.close(); capturerWindow.close();
var result = {id, name, width: 9999, height: 9999}; let result = {id, name, width: 9999, height: 9999};
callback({video: result}); callback({video: result});
}); });
capturerWindow.loadURL(`file://${__dirname}/picker.html`); capturerWindow.loadURL(`file://${__dirname}/picker.html`);

View file

@ -1,16 +1,15 @@
import {IpcMain, ipcRenderer} from "electron"; import {ipcRenderer} from "electron";
interface IPCSources { interface IPCSources {
id: string; id: string;
name: string; name: string;
thumbnail: HTMLCanvasElement; thumbnail: HTMLCanvasElement;
} }
async function addDisplays() { async function addDisplays(): Promise<void> {
ipcRenderer.once("getSources", (event, arg) => { ipcRenderer.once("getSources", (_event, arg) => {
var sources: IPCSources[] = arg; let sources: IPCSources[] = arg;
console.log(sources); console.log(sources);
const selectionElem = document.createElement("div"); const selectionElem = document.createElement("div");
//@ts-ignore selectionElem.classList.add("desktop-capturer-selection");
selectionElem.classList = ["desktop-capturer-selection"];
selectionElem.innerHTML = `<div class="desktop-capturer-selection__scroller"> selectionElem.innerHTML = `<div class="desktop-capturer-selection__scroller">
<ul class="desktop-capturer-selection__list"> <ul class="desktop-capturer-selection__list">
${sources ${sources
@ -39,7 +38,7 @@ async function addDisplays() {
const id = button.getAttribute("data-id"); const id = button.getAttribute("data-id");
const title = button.getAttribute("title"); const title = button.getAttribute("title");
if (id === "${CANCEL_ID}") { if (id === "${CANCEL_ID}") {
new Error("Cancelled by user"); throw new Error("Cancelled by user");
} else { } else {
ipcRenderer.sendSync("selectScreenshareSource", id, title); ipcRenderer.sendSync("selectScreenshareSource", id, title);
} }

View file

@ -1,31 +1,27 @@
import {BrowserWindow, shell, ipcMain, app, clipboard} from "electron"; import {BrowserWindow, app, clipboard, ipcMain, shell} from "electron";
import { import {
checkForDataFolder,
getConfig,
setConfigBulk,
Settings, Settings,
getLang, getConfig,
getVersion,
getConfigLocation, getConfigLocation,
getDisplayVersion,
getLangName, getLangName,
sleep, getVersion,
getDisplayVersion setConfigBulk,
sleep
} from "../utils"; } from "../utils";
import path from "path"; import path from "path";
import os from "os"; import os from "os";
import fs from "fs"; import fs from "fs";
import {mainWindow} from "../window"; let settingsWindow: BrowserWindow;
import {crash} from "process"; let instance = 0;
var settingsWindow: BrowserWindow;
var instance: number = 0;
//checkForDataFolder(); //checkForDataFolder();
const userDataPath = app.getPath("userData"); const userDataPath = app.getPath("userData");
const storagePath = path.join(userDataPath, "/storage/"); const storagePath = path.join(userDataPath, "/storage/");
const themesPath = path.join(userDataPath, "/themes/"); const themesPath = path.join(userDataPath, "/themes/");
const pluginsPath = path.join(userDataPath, "/plugins/"); const pluginsPath = path.join(userDataPath, "/plugins/");
export function createSettingsWindow() { export function createSettingsWindow(): void {
console.log("Creating a settings window."); console.log("Creating a settings window.");
instance = instance + 1; instance += 1;
if (instance > 1) { if (instance > 1) {
if (settingsWindow) { if (settingsWindow) {
settingsWindow.show(); settingsWindow.show();
@ -45,11 +41,11 @@ export function createSettingsWindow() {
preload: path.join(__dirname, "preload.js") preload: path.join(__dirname, "preload.js")
} }
}); });
async function settingsLoadPage() { async function settingsLoadPage(): Promise<void> {
settingsWindow.loadURL(`file://${__dirname}/settings.html`); settingsWindow.loadURL(`file://${__dirname}/settings.html`);
} }
const userDataPath = app.getPath("userData"); const userDataPath = app.getPath("userData");
const themesFolder = userDataPath + "/themes/"; const themesFolder = `${userDataPath}/themes/`;
if (!fs.existsSync(themesFolder)) { if (!fs.existsSync(themesFolder)) {
fs.mkdirSync(themesFolder); fs.mkdirSync(themesFolder);
console.log("Created missing theme folder"); console.log("Created missing theme folder");
@ -58,7 +54,7 @@ export function createSettingsWindow() {
fs.readdirSync(themesFolder).forEach((file) => { fs.readdirSync(themesFolder).forEach((file) => {
try { try {
const manifest = fs.readFileSync(`${themesFolder}/${file}/manifest.json`, "utf8"); const manifest = fs.readFileSync(`${themesFolder}/${file}/manifest.json`, "utf8");
var themeFile = JSON.parse(manifest); let themeFile = JSON.parse(manifest);
settingsWindow.webContents.send( settingsWindow.webContents.send(
"themeLoader", "themeLoader",
fs.readFileSync(`${themesFolder}/${file}/${themeFile.theme}`, "utf-8") fs.readFileSync(`${themesFolder}/${file}/${themeFile.theme}`, "utf-8")
@ -69,51 +65,41 @@ export function createSettingsWindow() {
} }
}); });
}); });
ipcMain.on("saveSettings", (event, args: Settings) => { ipcMain.on("saveSettings", (_event, args: Settings) => {
console.log(args); console.log(args);
setConfigBulk(args); setConfigBulk(args);
}); });
ipcMain.on("openStorageFolder", async (event) => { ipcMain.on("openStorageFolder", async () => {
shell.showItemInFolder(storagePath); shell.showItemInFolder(storagePath);
await sleep(1000); await sleep(1000);
}); });
ipcMain.on("openThemesFolder", async (event) => { ipcMain.on("openThemesFolder", async () => {
shell.showItemInFolder(themesPath); shell.showItemInFolder(themesPath);
await sleep(1000); await sleep(1000);
}); });
ipcMain.on("openPluginsFolder", async (event) => { ipcMain.on("openPluginsFolder", async () => {
shell.showItemInFolder(pluginsPath); shell.showItemInFolder(pluginsPath);
await sleep(1000); await sleep(1000);
}); });
ipcMain.on("openCrashesFolder", async (event) => { ipcMain.on("openCrashesFolder", async () => {
shell.showItemInFolder(path.join(app.getPath("temp"), app.getName() + " Crashes")); shell.showItemInFolder(path.join(app.getPath("temp"), `${app.getName()} Crashes`));
await sleep(1000); await sleep(1000);
}); });
ipcMain.on("getLangName", async (event) => { ipcMain.on("getLangName", async (event) => {
event.returnValue = await getLangName(); event.returnValue = await getLangName();
}); });
ipcMain.on("crash", async (event) => { ipcMain.on("crash", async () => {
process.crash(); process.crash();
}); });
ipcMain.handle("getSetting", (event, toGet: string) => { ipcMain.handle("getSetting", (_event, toGet: keyof Settings) => {
return getConfig(toGet); return getConfig(toGet);
}); });
ipcMain.on("copyDebugInfo", (event) => { ipcMain.on("copyDebugInfo", () => {
let settingsFileContent = fs.readFileSync(getConfigLocation(), "utf-8"); let settingsFileContent = fs.readFileSync(getConfigLocation(), "utf-8");
clipboard.writeText( clipboard.writeText(
"**OS:** " + `**OS:** ${os.platform()} ${os.version()}\n**Architecture:** ${os.arch()}\n**ArmCord version:** ${getVersion()}\n**Electron version:** ${
os.platform() + process.versions.electron
" " + }\n\`${settingsFileContent}\``
os.version() +
"\n**Architecture:** " +
os.arch() +
"\n**ArmCord version:** " +
getVersion() +
"\n**Electron version:** " +
process.versions.electron +
"\n`" +
settingsFileContent +
"`"
); );
}); });
settingsWindow.webContents.setWindowOpenHandler(({url}) => { settingsWindow.webContents.setWindowOpenHandler(({url}) => {
@ -121,7 +107,7 @@ export function createSettingsWindow() {
return {action: "deny"}; return {action: "deny"};
}); });
settingsLoadPage(); settingsLoadPage();
settingsWindow.on("close", (event: Event) => { settingsWindow.on("close", () => {
ipcMain.removeHandler("getSetting"); ipcMain.removeHandler("getSetting");
ipcMain.removeAllListeners("saveSettings"); ipcMain.removeAllListeners("saveSettings");
instance = 0; instance = 0;

View file

@ -16,6 +16,6 @@ contextBridge.exposeInMainWorld("settings", {
crash: () => ipcRenderer.send("crash") crash: () => ipcRenderer.send("crash")
}); });
ipcRenderer.on("themeLoader", (event, message) => { ipcRenderer.on("themeLoader", (_event, message) => {
addStyle(message); addStyle(message);
}); });

View file

@ -1,13 +1,13 @@
import * as fs from "fs"; import * as fs from "fs";
import {app, Menu, Tray, nativeImage} from "electron"; import {Menu, Tray, app, nativeImage} from "electron";
import {createInviteWindow, mainWindow} from "./window"; import {createInviteWindow, mainWindow} from "./window";
import {getConfig, getConfigLocation, setWindowState, getDisplayVersion} from "./utils"; import {getConfig, getConfigLocation, getDisplayVersion, setWindowState} from "./utils";
import * as path from "path"; import * as path from "path";
import {createSettingsWindow} from "./settings/main"; import {createSettingsWindow} from "./settings/main";
export let tray: any = null; export let tray: any = null;
app.whenReady().then(async () => { app.whenReady().then(async () => {
let finishedSetup = await getConfig("doneSetup"); let finishedSetup = await getConfig("doneSetup");
var trayIcon = (await getConfig("trayIcon")) ?? "ac_plug_colored"; let trayIcon = (await getConfig("trayIcon")) ?? "ac_plug_colored";
let trayPath = nativeImage.createFromPath(path.join(__dirname, "../", `/assets/${trayIcon}.png`)); let trayPath = nativeImage.createFromPath(path.join(__dirname, "../", `/assets/${trayIcon}.png`));
let trayVerIcon; let trayVerIcon;
trayVerIcon = function () { trayVerIcon = function () {
@ -18,14 +18,15 @@ app.whenReady().then(async () => {
} else if (process.platform == "linux") { } else if (process.platform == "linux") {
return trayPath.resize({height: 24}); return trayPath.resize({height: 24});
} }
return undefined;
}; };
if (process.platform == "darwin" && trayPath.getSize().height > 22) trayPath = trayPath.resize({height: 22}); if (process.platform == "darwin" && trayPath.getSize().height > 22) trayPath = trayPath.resize({height: 22});
let clientName = (await getConfig("clientName")) ?? "ArmCord";
if ((await getConfig("windowStyle")) == "basic") { if ((await getConfig("windowStyle")) == "basic") {
var clientName = (await getConfig("clientName")) ?? "ArmCord";
tray = new Tray(trayPath); tray = new Tray(trayPath);
const contextMenu = function () { function contextMenu(): Electron.Menu {
if (finishedSetup == false) { if (finishedSetup == false) {
return Menu.buildFromTemplate([ return Menu.buildFromTemplate([
{ {
@ -34,7 +35,7 @@ app.whenReady().then(async () => {
}, },
{ {
label: `Quit ${clientName}`, label: `Quit ${clientName}`,
click: async function () { async click() {
fs.unlink(await getConfigLocation(), (err) => { fs.unlink(await getConfigLocation(), (err) => {
if (err) throw err; if (err) throw err;
@ -48,17 +49,17 @@ app.whenReady().then(async () => {
return Menu.buildFromTemplate([ return Menu.buildFromTemplate([
{ {
label: `Open ${clientName}`, label: `Open ${clientName}`,
click: function () { click() {
mainWindow.show(); mainWindow.show();
} }
}, },
{ {
label: `Quit ${clientName}`, label: `Quit ${clientName}`,
click: function () { click() {
let [width, height] = mainWindow.getSize(); let [width, height] = mainWindow.getSize();
setWindowState({ setWindowState({
width: width, width,
height: height, height,
isMaximized: mainWindow.isMaximized(), isMaximized: mainWindow.isMaximized(),
x: mainWindow.getPosition()[0], x: mainWindow.getPosition()[0],
y: mainWindow.getPosition()[1] y: mainWindow.getPosition()[1]
@ -68,12 +69,11 @@ app.whenReady().then(async () => {
} }
]); ]);
} }
}; }
tray.setToolTip(clientName); tray.setToolTip(clientName);
tray.setContextMenu(contextMenu); tray.setContextMenu(contextMenu);
} else { } else {
var clientName = (await getConfig("clientName")) ?? "ArmCord";
tray = new Tray(trayPath); tray = new Tray(trayPath);
if (finishedSetup == false) { if (finishedSetup == false) {
const contextMenu = Menu.buildFromTemplate([ const contextMenu = Menu.buildFromTemplate([
@ -83,7 +83,7 @@ app.whenReady().then(async () => {
}, },
{ {
label: `Quit ${clientName}`, label: `Quit ${clientName}`,
click: async function () { async click() {
fs.unlink(await getConfigLocation(), (err) => { fs.unlink(await getConfigLocation(), (err) => {
if (err) throw err; if (err) throw err;
@ -97,7 +97,7 @@ app.whenReady().then(async () => {
} else { } else {
const contextMenu = Menu.buildFromTemplate([ const contextMenu = Menu.buildFromTemplate([
{ {
label: `${clientName} ` + getDisplayVersion(), label: `${clientName} ${getDisplayVersion()}`,
icon: trayVerIcon(), icon: trayVerIcon(),
enabled: false enabled: false
}, },
@ -106,19 +106,19 @@ app.whenReady().then(async () => {
}, },
{ {
label: `Open ${clientName}`, label: `Open ${clientName}`,
click: function () { click() {
mainWindow.show(); mainWindow.show();
} }
}, },
{ {
label: "Open Settings", label: "Open Settings",
click: function () { click() {
createSettingsWindow(); createSettingsWindow();
} }
}, },
{ {
label: "Support Discord Server", label: "Support Discord Server",
click: function () { click() {
createInviteWindow("TnhxcqynZ2"); createInviteWindow("TnhxcqynZ2");
} }
}, },
@ -127,7 +127,7 @@ app.whenReady().then(async () => {
}, },
{ {
label: `Quit ${clientName}`, label: `Quit ${clientName}`,
click: function () { click() {
app.quit(); app.quit();
} }
} }

View file

@ -1,31 +1,31 @@
import * as fs from "fs"; import * as fs from "fs";
import {app, dialog, Rectangle} from "electron"; import {app, dialog} from "electron";
import path from "path"; import path from "path";
import fetch from "cross-fetch"; import fetch from "cross-fetch";
import extract from "extract-zip"; import extract from "extract-zip";
import util from "util"; import util from "util";
const streamPipeline = util.promisify(require("stream").pipeline); const streamPipeline = util.promisify(require("stream").pipeline);
export var firstRun: boolean; export let firstRun: boolean;
export var contentPath: string; export let contentPath: string;
export var transparency: boolean; export let transparency: boolean;
//utility functions that are used all over the codebase or just too obscure to be put in the file used in //utility functions that are used all over the codebase or just too obscure to be put in the file used in
export function addStyle(styleString: string) { export function addStyle(styleString: string): void {
const style = document.createElement("style"); const style = document.createElement("style");
style.textContent = styleString; style.textContent = styleString;
document.head.append(style); document.head.append(style);
} }
export function addScript(scriptString: string) { export function addScript(scriptString: string): void {
var script = document.createElement("script"); let script = document.createElement("script");
script.textContent = scriptString; script.textContent = scriptString;
document.body.append(script); document.body.append(script);
} }
export async function sleep(ms: number) { export async function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms)); return new Promise((resolve) => setTimeout(resolve, ms));
} }
export async function checkIfConfigIsBroken() { export async function checkIfConfigIsBroken(): Promise<void> {
if ((await getConfig("0")) == "d") { if ((await getConfig("0")) == "d") {
console.log("Detected a corrupted config"); console.log("Detected a corrupted config");
setup(); setup();
@ -36,7 +36,7 @@ export async function checkIfConfigIsBroken() {
} }
} }
export function setup() { export function setup(): void {
console.log("Setting up temporary ArmCord settings."); console.log("Setting up temporary ArmCord settings.");
const defaults: Settings = { const defaults: Settings = {
windowStyle: "default", windowStyle: "default",
@ -55,7 +55,9 @@ export function setup() {
useLegacyCapturer: false, useLegacyCapturer: false,
mobileMode: false, mobileMode: false,
trayIcon: "default", trayIcon: "default",
doneSetup: false doneSetup: false,
clientName: "ArmCord",
customIcon: path.join(__dirname, "../", "/assets/ac_icon_transparent.png")
}; };
setConfigBulk({ setConfigBulk({
...defaults ...defaults
@ -63,12 +65,12 @@ export function setup() {
} }
//Get the version value from the "package.json" file //Get the version value from the "package.json" file
export var packageVersion = require("../package.json").version; export const packageVersion = require("../package.json").version;
export function getVersion() { export function getVersion(): string {
return packageVersion; return packageVersion;
} }
export function getDisplayVersion() { export function getDisplayVersion(): string {
//Checks if the app version # has 4 sections (3.1.0.0) instead of 3 (3.1.0) / Shitty way to check if Kernel Mod is installed //Checks if the app version # has 4 sections (3.1.0.0) instead of 3 (3.1.0) / Shitty way to check if Kernel Mod is installed
if ((app.getVersion() == packageVersion) == false) { if ((app.getVersion() == packageVersion) == false) {
if ((app.getVersion() == process.versions.electron) == true) { if ((app.getVersion() == process.versions.electron) == true) {
@ -80,7 +82,7 @@ export function getDisplayVersion() {
return packageVersion; return packageVersion;
} }
} }
export async function injectJS(inject: string) { export async function injectJS(inject: string): Promise<void> {
const js = await (await fetch(`${inject}`)).text(); const js = await (await fetch(`${inject}`)).text();
const el = document.createElement("script"); const el = document.createElement("script");
@ -89,7 +91,7 @@ export async function injectJS(inject: string) {
document.body.appendChild(el); document.body.appendChild(el);
} }
export async function injectElectronFlags() { export async function injectElectronFlags(): Promise<void> {
// MIT License // MIT License
// Copyright (c) 2022 GooseNest // Copyright (c) 2022 GooseNest
@ -135,43 +137,43 @@ export async function injectElectronFlags() {
}); });
} }
} }
export async function setLang(language: string) { export async function setLang(language: string): Promise<void> {
const langConfigFile = path.join(app.getPath("userData"), "/storage/") + "lang.json"; const langConfigFile = `${path.join(app.getPath("userData"), "/storage/")}lang.json`;
if (!fs.existsSync(langConfigFile)) { if (!fs.existsSync(langConfigFile)) {
fs.writeFileSync(langConfigFile, "{}", "utf-8"); fs.writeFileSync(langConfigFile, "{}", "utf-8");
} }
let rawdata = fs.readFileSync(langConfigFile, "utf-8"); let rawdata = fs.readFileSync(langConfigFile, "utf-8");
let parsed = JSON.parse(rawdata); let parsed = JSON.parse(rawdata);
parsed["lang"] = language; parsed.lang = language;
let toSave = JSON.stringify(parsed, null, 4); let toSave = JSON.stringify(parsed, null, 4);
fs.writeFileSync(langConfigFile, toSave, "utf-8"); fs.writeFileSync(langConfigFile, toSave, "utf-8");
} }
var language: string; let language: string;
export async function getLang(object: string) { export async function getLang(object: string): Promise<string> {
if (language == undefined) { if (language == undefined) {
try { try {
const userDataPath = app.getPath("userData"); const userDataPath = app.getPath("userData");
const storagePath = path.join(userDataPath, "/storage/"); const storagePath = path.join(userDataPath, "/storage/");
const langConfigFile = storagePath + "lang.json"; const langConfigFile = `${storagePath}lang.json`;
let rawdata = fs.readFileSync(langConfigFile, "utf-8"); let rawdata = fs.readFileSync(langConfigFile, "utf-8");
let parsed = JSON.parse(rawdata); let parsed = JSON.parse(rawdata);
language = parsed["lang"]; language = parsed.lang;
} catch (e) { } catch (_e) {
console.log("Language config file doesn't exist. Fallback to English."); console.log("Language config file doesn't exist. Fallback to English.");
language = "en-US"; language = "en-US";
} }
} }
if (language.length == 2) { if (language.length == 2) {
language = language + "-" + language.toUpperCase(); language = `${language}-${language.toUpperCase()}`;
} }
var langPath = path.join(__dirname, "../", "/assets/lang/" + language + ".json"); let langPath = path.join(__dirname, "../", `/assets/lang/${language}.json`);
if (!fs.existsSync(langPath)) { if (!fs.existsSync(langPath)) {
langPath = path.join(__dirname, "../", "/assets/lang/en-US.json"); langPath = path.join(__dirname, "../", "/assets/lang/en-US.json");
} }
let rawdata = fs.readFileSync(langPath, "utf-8"); let rawdata = fs.readFileSync(langPath, "utf-8");
let parsed = JSON.parse(rawdata); let parsed = JSON.parse(rawdata);
if (parsed[object] == undefined) { if (parsed[object] == undefined) {
console.log(object + " is undefined in " + language); console.log(`${object} is undefined in ${language}`);
langPath = path.join(__dirname, "../", "/assets/lang/en-US.json"); langPath = path.join(__dirname, "../", "/assets/lang/en-US.json");
rawdata = fs.readFileSync(langPath, "utf-8"); rawdata = fs.readFileSync(langPath, "utf-8");
parsed = JSON.parse(rawdata); parsed = JSON.parse(rawdata);
@ -180,22 +182,22 @@ export async function getLang(object: string) {
return parsed[object]; return parsed[object];
} }
} }
export async function getLangName() { export async function getLangName(): Promise<string> {
if (language == undefined) { if (language == undefined) {
try { try {
const userDataPath = app.getPath("userData"); const userDataPath = app.getPath("userData");
const storagePath = path.join(userDataPath, "/storage/"); const storagePath = path.join(userDataPath, "/storage/");
const langConfigFile = storagePath + "lang.json"; const langConfigFile = `${storagePath}lang.json`;
let rawdata = fs.readFileSync(langConfigFile, "utf-8"); let rawdata = fs.readFileSync(langConfigFile, "utf-8");
let parsed = JSON.parse(rawdata); let parsed = JSON.parse(rawdata);
language = parsed["lang"]; language = parsed.lang;
} catch (e) { } catch (_e) {
console.log("Language config file doesn't exist. Fallback to English."); console.log("Language config file doesn't exist. Fallback to English.");
language = "en-US"; language = "en-US";
} }
} }
if (language.length == 2) { if (language.length == 2) {
language = language + "-" + language.toUpperCase(); language = `${language}-${language.toUpperCase()}`;
} }
return language; return language;
} }
@ -207,26 +209,26 @@ export interface WindowState {
y: number; y: number;
isMaximized: boolean; isMaximized: boolean;
} }
export async function setWindowState(object: WindowState) { export async function setWindowState(object: WindowState): Promise<void> {
const userDataPath = app.getPath("userData"); const userDataPath = app.getPath("userData");
const storagePath = path.join(userDataPath, "/storage/"); const storagePath = path.join(userDataPath, "/storage/");
const saveFile = storagePath + "window.json"; const saveFile = `${storagePath}window.json`;
let toSave = JSON.stringify(object, null, 4); let toSave = JSON.stringify(object, null, 4);
fs.writeFileSync(saveFile, toSave, "utf-8"); fs.writeFileSync(saveFile, toSave, "utf-8");
} }
export async function getWindowState(object: string) { export async function getWindowState<K extends keyof WindowState>(object: K): Promise<WindowState[K]> {
const userDataPath = app.getPath("userData"); const userDataPath = app.getPath("userData");
const storagePath = path.join(userDataPath, "/storage/"); const storagePath = path.join(userDataPath, "/storage/");
const settingsFile = storagePath + "window.json"; const settingsFile = `${storagePath}window.json`;
let rawdata = fs.readFileSync(settingsFile, "utf-8"); let rawdata = fs.readFileSync(settingsFile, "utf-8");
let returndata = JSON.parse(rawdata); let returndata = JSON.parse(rawdata);
console.log(returndata); console.log(returndata);
console.log("[Window state manager] " + returndata); console.log(`[Window state manager] ${returndata}`);
return returndata[object]; return returndata[object];
} }
//ArmCord Settings/Storage manager //ArmCord Settings/Storage manager
export function checkForDataFolder() { export function checkForDataFolder(): void {
const dataPath = path.join(path.dirname(app.getPath("exe")), "armcord-data"); const dataPath = path.join(path.dirname(app.getPath("exe")), "armcord-data");
if (fs.existsSync(dataPath) && fs.statSync(dataPath).isDirectory()) { if (fs.existsSync(dataPath) && fs.statSync(dataPath).isDirectory()) {
console.log("Found armcord-data folder. Running in portable mode."); console.log("Found armcord-data folder. Running in portable mode.");
@ -235,6 +237,14 @@ export function checkForDataFolder() {
} }
export interface Settings { export interface Settings {
// Referenced for detecting a broken config.
"0"?: string;
// Referenced once for disabling mod updating.
noBundleUpdates?: boolean;
// Only used for external url warning dialog.
ignoreProtocolWarning?: boolean;
customIcon: string;
windowStyle: string; windowStyle: string;
channel: string; channel: string;
armcordCSP: boolean; armcordCSP: boolean;
@ -252,33 +262,34 @@ export interface Settings {
disableAutogain: boolean; disableAutogain: boolean;
trayIcon: string; trayIcon: string;
doneSetup: boolean; doneSetup: boolean;
clientName: string;
} }
export function getConfigLocation() { export function getConfigLocation(): string {
const userDataPath = app.getPath("userData"); const userDataPath = app.getPath("userData");
const storagePath = path.join(userDataPath, "/storage/"); const storagePath = path.join(userDataPath, "/storage/");
return storagePath + "settings.json"; return `${storagePath}settings.json`;
} }
export async function getConfig(object: string) { export async function getConfig<K extends keyof Settings>(object: K): Promise<Settings[K]> {
let rawdata = fs.readFileSync(getConfigLocation(), "utf-8"); let rawdata = fs.readFileSync(getConfigLocation(), "utf-8");
let returndata = JSON.parse(rawdata); let returndata = JSON.parse(rawdata);
console.log("[Config manager] " + object + ": " + returndata[object]); console.log(`[Config manager] ${object}: ${returndata[object]}`);
return returndata[object]; return returndata[object];
} }
export async function setConfig(object: string, toSet: any) { export async function setConfig<K extends keyof Settings>(object: K, toSet: Settings[K]): Promise<void> {
let rawdata = fs.readFileSync(getConfigLocation(), "utf-8"); let rawdata = fs.readFileSync(getConfigLocation(), "utf-8");
let parsed = JSON.parse(rawdata); let parsed = JSON.parse(rawdata);
parsed[object] = toSet; parsed[object] = toSet;
let toSave = JSON.stringify(parsed, null, 4); let toSave = JSON.stringify(parsed, null, 4);
fs.writeFileSync(getConfigLocation(), toSave, "utf-8"); fs.writeFileSync(getConfigLocation(), toSave, "utf-8");
} }
export async function setConfigBulk(object: Settings) { export async function setConfigBulk(object: Settings): Promise<void> {
let toSave = JSON.stringify(object, null, 4); let toSave = JSON.stringify(object, null, 4);
fs.writeFileSync(getConfigLocation(), toSave, "utf-8"); fs.writeFileSync(getConfigLocation(), toSave, "utf-8");
} }
export async function checkIfConfigExists() { export async function checkIfConfigExists(): Promise<void> {
const userDataPath = app.getPath("userData"); const userDataPath = app.getPath("userData");
const storagePath = path.join(userDataPath, "/storage/"); const storagePath = path.join(userDataPath, "/storage/");
const settingsFile = storagePath + "settings.json"; const settingsFile = `${storagePath}settings.json`;
if (!fs.existsSync(settingsFile)) { if (!fs.existsSync(settingsFile)) {
if (!fs.existsSync(storagePath)) { if (!fs.existsSync(storagePath)) {
@ -288,27 +299,25 @@ export async function checkIfConfigExists() {
console.log("First run of the ArmCord. Starting setup."); console.log("First run of the ArmCord. Starting setup.");
setup(); setup();
firstRun = true; firstRun = true;
} else if ((await getConfig("doneSetup")) == false) {
console.log("First run of the ArmCord. Starting setup.");
setup();
firstRun = true;
} else { } else {
if ((await getConfig("doneSetup")) == false) { console.log("ArmCord has been run before. Skipping setup.");
console.log("First run of the ArmCord. Starting setup.");
setup();
firstRun = true;
} else {
console.log("ArmCord has been run before. Skipping setup.");
}
} }
} }
// Mods // Mods
async function updateModBundle() { async function updateModBundle(): Promise<void> {
if ((await getConfig("noBundleUpdates")) == undefined ?? false) { if ((await getConfig("noBundleUpdates")) == undefined ?? false) {
try { try {
console.log("Downloading mod bundle"); console.log("Downloading mod bundle");
const distFolder = app.getPath("userData") + "/plugins/loader/dist/"; const distFolder = `${app.getPath("userData")}/plugins/loader/dist/`;
while (!fs.existsSync(distFolder)) { while (!fs.existsSync(distFolder)) {
//waiting //waiting
} }
var name: string = await getConfig("mods"); let name: string = await getConfig("mods");
const clientMods = { const clientMods = {
vencord: "https://github.com/Vendicated/Vencord/releases/download/devbuild/browser.js", vencord: "https://github.com/Vendicated/Vencord/releases/download/devbuild/browser.js",
cordwood: "https://raw.githubusercontent.com/Cordwood/builds/master/index.js", cordwood: "https://raw.githubusercontent.com/Cordwood/builds/master/index.js",
@ -319,10 +328,10 @@ async function updateModBundle() {
cordwood: "https://armcord.xyz/placeholder.css", cordwood: "https://armcord.xyz/placeholder.css",
shelter: "https://armcord.xyz/placeholder.css" shelter: "https://armcord.xyz/placeholder.css"
}; };
var bundle: string = await (await fetch(clientMods[name as keyof typeof clientMods])).text(); let bundle: string = await (await fetch(clientMods[name as keyof typeof clientMods])).text();
fs.writeFileSync(distFolder + "bundle.js", bundle, "utf-8"); fs.writeFileSync(`${distFolder}bundle.js`, bundle, "utf-8");
var css: string = await (await fetch(clientModsCss[name as keyof typeof clientModsCss])).text(); let css: string = await (await fetch(clientModsCss[name as keyof typeof clientModsCss])).text();
fs.writeFileSync(distFolder + "bundle.css", css, "utf-8"); fs.writeFileSync(`${distFolder}bundle.css`, css, "utf-8");
} catch (e) { } catch (e) {
console.log("[Mod loader] Failed to install mods"); console.log("[Mod loader] Failed to install mods");
console.error(e); console.error(e);
@ -336,25 +345,25 @@ async function updateModBundle() {
} }
} }
export var modInstallState: string; export let modInstallState: string;
export async function installModLoader() { export async function installModLoader(): Promise<void> {
if ((await getConfig("mods")) == "none") { if ((await getConfig("mods")) == "none") {
modInstallState = "none"; modInstallState = "none";
fs.rmSync(app.getPath("userData") + "/plugins/loader", {recursive: true, force: true}); fs.rmSync(`${app.getPath("userData")}/plugins/loader`, {recursive: true, force: true});
import("./extensions/plugin"); import("./extensions/plugin");
console.log("[Mod loader] Skipping"); console.log("[Mod loader] Skipping");
} else { } else {
const pluginFolder = app.getPath("userData") + "/plugins/"; const pluginFolder = `${app.getPath("userData")}/plugins/`;
if (!fs.existsSync(pluginFolder + "loader") || !fs.existsSync(pluginFolder + "loader/dist/" + "bundle.css")) { if (!fs.existsSync(`${pluginFolder}loader`) || !fs.existsSync(`${pluginFolder}loader/dist/bundle.css`)) {
try { try {
fs.rmSync(app.getPath("userData") + "/plugins/loader", {recursive: true, force: true}); fs.rmSync(`${app.getPath("userData")}/plugins/loader`, {recursive: true, force: true});
modInstallState = "installing"; modInstallState = "installing";
var zipPath = app.getPath("temp") + "/" + "loader.zip"; let zipPath = `${app.getPath("temp")}/loader.zip`;
if (!fs.existsSync(pluginFolder)) { if (!fs.existsSync(pluginFolder)) {
fs.mkdirSync(pluginFolder); fs.mkdirSync(pluginFolder);
console.log("[Mod loader] Created missing plugin folder"); console.log("[Mod loader] Created missing plugin folder");
} }
var loaderZip = await fetch("https://armcord.xyz/loader.zip"); let loaderZip = await fetch("https://armcord.xyz/loader.zip");
if (!loaderZip.ok) throw new Error(`unexpected response ${loaderZip.statusText}`); if (!loaderZip.ok) throw new Error(`unexpected response ${loaderZip.statusText}`);
await streamPipeline(loaderZip.body, fs.createWriteStream(zipPath)); await streamPipeline(loaderZip.body, fs.createWriteStream(zipPath));
await extract(zipPath, {dir: path.join(app.getPath("userData"), "plugins")}); await extract(zipPath, {dir: path.join(app.getPath("userData"), "plugins")});

View file

@ -2,19 +2,19 @@
// I had to add most of the window creation code here to split both into seperete functions // I had to add most of the window creation code here to split both into seperete functions
// WHY? Because I can't use the same code for both due to annoying bug with value `frame` not responding to variables // WHY? Because I can't use the same code for both due to annoying bug with value `frame` not responding to variables
// I'm sorry for this mess but I'm not sure how to fix it. // I'm sorry for this mess but I'm not sure how to fix it.
import {BrowserWindow, shell, app, dialog, nativeImage} from "electron"; import {BrowserWindow, app, dialog, nativeImage, shell} from "electron";
import path from "path"; import path from "path";
import { import {
checkIfConfigIsBroken, checkIfConfigIsBroken,
contentPath,
firstRun, firstRun,
getConfig, getConfig,
contentPath, modInstallState,
setConfig, setConfig,
setLang, setLang,
setWindowState, setWindowState,
transparency,
sleep, sleep,
modInstallState transparency
} from "./utils"; } from "./utils";
import {registerIpc} from "./ipc"; import {registerIpc} from "./ipc";
import {setMenu} from "./menu"; import {setMenu} from "./menu";
@ -26,13 +26,13 @@ import {iconPath} from "./main";
export let mainWindow: BrowserWindow; export let mainWindow: BrowserWindow;
export let inviteWindow: BrowserWindow; export let inviteWindow: BrowserWindow;
var osType = os.type(); let osType = os.type();
contextMenu({ contextMenu({
showSaveImageAs: true, showSaveImageAs: true,
showCopyImageAddress: true, showCopyImageAddress: true,
showSearchWithGoogle: false, showSearchWithGoogle: false,
showSearchWithDuckDuckGo: false, showSearchWithDuckDuckGo: false,
prepend: (defaultActions, parameters, browserWindow) => [ prepend: (_defaultActions, parameters) => [
{ {
label: "Search with Google", label: "Search with Google",
// Only show it when right-clicking text // Only show it when right-clicking text
@ -51,7 +51,7 @@ contextMenu({
} }
] ]
}); });
async function doAfterDefiningTheWindow() { async function doAfterDefiningTheWindow(): Promise<void> {
if (await getConfig("startMinimized")) { if (await getConfig("startMinimized")) {
mainWindow.hide(); mainWindow.hide();
} else { } else {
@ -66,7 +66,7 @@ async function doAfterDefiningTheWindow() {
} }
}); });
} }
var ignoreProtocolWarning = await getConfig("ignoreProtocolWarning"); let ignoreProtocolWarning = await getConfig("ignoreProtocolWarning");
await checkIfConfigIsBroken(); await checkIfConfigIsBroken();
registerIpc(); registerIpc();
if (await getConfig("mobileMode")) { if (await getConfig("mobileMode")) {
@ -75,11 +75,11 @@ async function doAfterDefiningTheWindow() {
} else { } else {
// A little sloppy but it works :p // A little sloppy but it works :p
if (osType == "Windows_NT") { if (osType == "Windows_NT") {
osType = "Windows " + os.release().split(".")[0] + " (" + os.release() + ")"; osType = `Windows ${os.release().split(".")[0]} (${os.release()})`;
} }
mainWindow.webContents.userAgent = `Mozilla/5.0 (X11; ${osType} ${os.arch()}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36`; //fake useragent for screenshare to work mainWindow.webContents.userAgent = `Mozilla/5.0 (X11; ${osType} ${os.arch()}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36`; //fake useragent for screenshare to work
} }
app.on("second-instance", (event, commandLine, workingDirectory, additionalData) => { app.on("second-instance", (_event, _commandLine, _workingDirectory, additionalData) => {
// Print out data received from the second instance. // Print out data received from the second instance.
console.log(additionalData); console.log(additionalData);
@ -102,37 +102,33 @@ async function doAfterDefiningTheWindow() {
return {action: "allow"}; return {action: "allow"};
if (url.startsWith("https:") || url.startsWith("http:") || url.startsWith("mailto:")) { if (url.startsWith("https:") || url.startsWith("http:") || url.startsWith("mailto:")) {
shell.openExternal(url); shell.openExternal(url);
} else if (ignoreProtocolWarning) {
shell.openExternal(url);
} else { } else {
if (ignoreProtocolWarning) { const options = {
shell.openExternal(url); type: "question",
} else { buttons: ["Yes, please", "No, I don't"],
const options = { defaultId: 1,
type: "question", title: url,
buttons: ["Yes, please", "No, I don't"], message: `Do you want to open ${url}?`,
defaultId: 1, detail: "This url was detected to not use normal browser protocols. It could mean that this url leads to a local program on your computer. Please check if you recognise it, before proceeding!",
title: url, checkboxLabel: "Remember my answer and ignore this warning for future sessions",
message: `Do you want to open ${url}?`, checkboxChecked: false
detail: "This url was detected to not use normal browser protocols. It could mean that this url leads to a local program on your computer. Please check if you recognise it, before proceeding!", };
checkboxLabel: "Remember my answer and ignore this warning for future sessions",
checkboxChecked: false
};
dialog.showMessageBox(mainWindow, options).then(({response, checkboxChecked}) => { dialog.showMessageBox(mainWindow, options).then(({response, checkboxChecked}) => {
console.log(response, checkboxChecked); console.log(response, checkboxChecked);
if (checkboxChecked) { if (checkboxChecked) {
if (response == 0) {
setConfig("ignoreProtocolWarning", true);
} else {
setConfig("ignoreProtocolWarning", false);
}
}
if (response == 0) { if (response == 0) {
shell.openExternal(url); setConfig("ignoreProtocolWarning", true);
} else { } else {
return; setConfig("ignoreProtocolWarning", false);
} }
}); }
} if (response == 0) {
shell.openExternal(url);
}
});
} }
return {action: "deny"}; return {action: "deny"};
}); });
@ -147,8 +143,8 @@ async function doAfterDefiningTheWindow() {
); );
if ((await getConfig("trayIcon")) == "default" || (await getConfig("dynamicIcon"))) { if ((await getConfig("trayIcon")) == "default" || (await getConfig("dynamicIcon"))) {
mainWindow.webContents.on("page-favicon-updated", async (event) => { mainWindow.webContents.on("page-favicon-updated", async () => {
var faviconBase64 = await mainWindow.webContents.executeJavaScript(` let faviconBase64 = await mainWindow.webContents.executeJavaScript(`
var getFavicon = function(){ var getFavicon = function(){
var favicon = undefined; var favicon = undefined;
var nodeList = document.getElementsByTagName("link"); var nodeList = document.getElementsByTagName("link");
@ -163,7 +159,7 @@ async function doAfterDefiningTheWindow() {
} }
getFavicon() getFavicon()
`); `);
var buf = new Buffer(faviconBase64.replace(/^data:image\/\w+;base64,/, ""), "base64"); let buf = Buffer.from(faviconBase64.replace(/^data:image\/\w+;base64,/, ""), "base64");
fs.writeFileSync(path.join(app.getPath("temp"), "/", "tray.png"), buf, "utf-8"); fs.writeFileSync(path.join(app.getPath("temp"), "/", "tray.png"), buf, "utf-8");
let trayPath = nativeImage.createFromPath(path.join(app.getPath("temp"), "/", "tray.png")); let trayPath = nativeImage.createFromPath(path.join(app.getPath("temp"), "/", "tray.png"));
if (process.platform === "darwin" && trayPath.getSize().height > 22) if (process.platform === "darwin" && trayPath.getSize().height > 22)
@ -178,7 +174,7 @@ async function doAfterDefiningTheWindow() {
}); });
} }
const userDataPath = app.getPath("userData"); const userDataPath = app.getPath("userData");
const themesFolder = userDataPath + "/themes/"; const themesFolder = `${userDataPath}/themes/`;
if (!fs.existsSync(themesFolder)) { if (!fs.existsSync(themesFolder)) {
fs.mkdirSync(themesFolder); fs.mkdirSync(themesFolder);
console.log("Created missing theme folder"); console.log("Created missing theme folder");
@ -187,7 +183,7 @@ async function doAfterDefiningTheWindow() {
fs.readdirSync(themesFolder).forEach((file) => { fs.readdirSync(themesFolder).forEach((file) => {
try { try {
const manifest = fs.readFileSync(`${themesFolder}/${file}/manifest.json`, "utf8"); const manifest = fs.readFileSync(`${themesFolder}/${file}/manifest.json`, "utf8");
var themeFile = JSON.parse(manifest); let themeFile = JSON.parse(manifest);
mainWindow.webContents.send( mainWindow.webContents.send(
"themeLoader", "themeLoader",
fs.readFileSync(`${themesFolder}/${file}/${themeFile.theme}`, "utf-8") fs.readFileSync(`${themesFolder}/${file}/${themeFile.theme}`, "utf-8")
@ -202,8 +198,8 @@ async function doAfterDefiningTheWindow() {
mainWindow.on("close", async (e) => { mainWindow.on("close", async (e) => {
let [width, height] = mainWindow.getSize(); let [width, height] = mainWindow.getSize();
await setWindowState({ await setWindowState({
width: width, width,
height: height, height,
isMaximized: mainWindow.isMaximized(), isMaximized: mainWindow.isMaximized(),
x: mainWindow.getPosition()[0], x: mainWindow.getPosition()[0],
y: mainWindow.getPosition()[1] y: mainWindow.getPosition()[1]
@ -232,12 +228,11 @@ async function doAfterDefiningTheWindow() {
}); });
console.log(contentPath); console.log(contentPath);
if ((await getConfig("inviteWebsocket")) == true) { if ((await getConfig("inviteWebsocket")) == true) {
//@ts-ignore
require("arrpc"); require("arrpc");
//await startServer(); //await startServer();
} }
if (firstRun) { if (firstRun) {
await setLang(Intl.DateTimeFormat().resolvedOptions().locale); await setLang(new Intl.DateTimeFormat().resolvedOptions().locale);
mainWindow.setSize(390, 470); mainWindow.setSize(390, 470);
await mainWindow.loadFile(path.join(__dirname, "/content/setup.html")); await mainWindow.loadFile(path.join(__dirname, "/content/setup.html"));
let trayPath = nativeImage.createFromPath(path.join(__dirname, "../", `/assets/ac_plug_colored.png`)); let trayPath = nativeImage.createFromPath(path.join(__dirname, "../", `/assets/ac_plug_colored.png`));
@ -245,6 +240,8 @@ async function doAfterDefiningTheWindow() {
if (process.platform === "win32" && trayPath.getSize().height > 32) trayPath = trayPath.resize({height: 32}); if (process.platform === "win32" && trayPath.getSize().height > 32) trayPath = trayPath.resize({height: 32});
tray.setImage(trayPath); tray.setImage(trayPath);
} else if ((await getConfig("skipSplash")) == true) { } else if ((await getConfig("skipSplash")) == true) {
// It's modified elsewhere.
// eslint-disable-next-line no-unmodified-loop-condition
while (modInstallState == "installing") { while (modInstallState == "installing") {
await sleep(1000); await sleep(1000);
} }
@ -277,7 +274,7 @@ async function doAfterDefiningTheWindow() {
mainWindow.show(); mainWindow.show();
} }
} }
export function createCustomWindow() { export function createCustomWindow(): void {
mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
width: 300, width: 300,
height: 350, height: 350,
@ -296,7 +293,7 @@ export function createCustomWindow() {
}); });
doAfterDefiningTheWindow(); doAfterDefiningTheWindow();
} }
export function createNativeWindow() { export function createNativeWindow(): void {
mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
width: 300, width: 300,
height: 350, height: 350,
@ -315,7 +312,7 @@ export function createNativeWindow() {
}); });
doAfterDefiningTheWindow(); doAfterDefiningTheWindow();
} }
export function createTransparentWindow() { export function createTransparentWindow(): void {
mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
width: 300, width: 300,
height: 350, height: 350,
@ -334,7 +331,7 @@ export function createTransparentWindow() {
}); });
doAfterDefiningTheWindow(); doAfterDefiningTheWindow();
} }
export function createInviteWindow(code: string) { export function createInviteWindow(code: string): void {
inviteWindow = new BrowserWindow({ inviteWindow = new BrowserWindow({
width: 800, width: 800,
height: 600, height: 600,
@ -348,7 +345,7 @@ export function createInviteWindow(code: string) {
spellcheck: true spellcheck: true
} }
}); });
var formInviteURL = `https://discord.com/invite/${code}`; let formInviteURL = `https://discord.com/invite/${code}`;
inviteWindow.webContents.session.webRequest.onBeforeRequest((details, callback) => { inviteWindow.webContents.session.webRequest.onBeforeRequest((details, callback) => {
if (details.url.includes("ws://")) return callback({cancel: true}); if (details.url.includes("ws://")) return callback({cancel: true});
return callback({}); return callback({});