[*] 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",
"description": "ArmCord is a custom client designed to enhance your Discord experience while keeping everything lightweight.",
"main": "ts-out/main.js",
"engines": {
"node": ">=18.0.0"
},
"scripts": {
"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",
@ -11,6 +14,7 @@
"package": "npm run build && electron-builder",
"packageQuick": "npm run build && electron-builder --dir",
"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",
"prepare": "git config --local core.hooksPath .hooks/"
},
@ -27,10 +31,16 @@
"devDependencies": {
"@types/node": "^18.11.9",
"@types/ws": "^8.5.3",
"@typescript-eslint/eslint-plugin": "^5.59.2",
"@typescript-eslint/parser": "^5.59.2",
"chalk-cli": "^5.0.0",
"copyfiles": "^2.4.1",
"electron": "^24.1.2",
"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",
"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) {
if (name in object) {
var original = object[name];
const original = object[name];
object[name] = createNewFunction(original);
}
}

View file

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

View file

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

View file

@ -1,44 +1,42 @@
//ipc stuff
import {app, ipcMain, shell, desktopCapturer, nativeImage, screen} from "electron";
import {app, desktopCapturer, ipcMain, nativeImage, shell} from "electron";
import {mainWindow} from "./window";
import {
setConfigBulk,
getVersion,
getConfig,
setLang,
getLang,
getWindowState,
packageVersion,
getDisplayVersion,
getLang,
getVersion,
getWindowState,
modInstallState,
installModLoader
packageVersion,
setConfigBulk,
setLang
} from "./utils";
import {customTitlebar} from "./main";
import {createSettingsWindow} from "./settings/main";
import os from "os";
import fs from "fs";
import path from "path";
export function registerIpc() {
ipcMain.on("get-app-path", (event, arg) => {
export function registerIpc(): void {
ipcMain.on("get-app-path", (event) => {
event.reply("app-path", app.getAppPath());
});
ipcMain.on("setLang", (event, lang: string) => {
ipcMain.on("setLang", (_event, lang: string) => {
setLang(lang);
});
ipcMain.handle("getLang", (event, toGet: string) => {
ipcMain.handle("getLang", (_event, toGet: string) => {
return getLang(toGet);
});
ipcMain.on("open-external-link", (event, href: string) => {
ipcMain.on("open-external-link", (_event, href: string) => {
shell.openExternal(href);
});
ipcMain.on("setPing", (event, pingCount: number) => {
ipcMain.on("setPing", (_event, pingCount: number) => {
switch (os.platform()) {
case "linux" ?? "macos":
app.setBadgeCount(pingCount);
break;
case "win32":
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");
} else {
mainWindow.setOverlayIcon(null, "badgeCount");
@ -46,28 +44,28 @@ export function registerIpc() {
break;
}
});
ipcMain.on("win-maximize", (event, arg) => {
ipcMain.on("win-maximize", () => {
mainWindow.maximize();
});
ipcMain.on("win-isMaximized", (event, arg) => {
ipcMain.on("win-isMaximized", (event) => {
event.returnValue = mainWindow.isMaximized();
});
ipcMain.on("win-isNormal", (event, arg) => {
ipcMain.on("win-isNormal", (event) => {
event.returnValue = mainWindow.isNormal();
});
ipcMain.on("win-minimize", (event, arg) => {
ipcMain.on("win-minimize", () => {
mainWindow.minimize();
});
ipcMain.on("win-unmaximize", (event, arg) => {
ipcMain.on("win-unmaximize", () => {
mainWindow.unmaximize();
});
ipcMain.on("win-show", (event, arg) => {
ipcMain.on("win-show", () => {
mainWindow.show();
});
ipcMain.on("win-hide", (event, arg) => {
ipcMain.on("win-hide", () => {
mainWindow.hide();
});
ipcMain.on("win-quit", (event, arg) => {
ipcMain.on("win-quit", () => {
app.exit();
});
ipcMain.on("get-app-version", (event) => {
@ -83,14 +81,19 @@ export function registerIpc() {
event.returnValue = packageVersion;
});
ipcMain.on("splashEnd", async () => {
let width = 800,
height = 600,
isMaximized = true,
xValue = 0,
yValue = 0;
try {
var width = (await getWindowState("width")) ?? 800;
var height = (await getWindowState("height")) ?? 600;
var isMaximized = (await getWindowState("isMaximized")) ?? false;
var xValue = await getWindowState("x");
var yValue = await getWindowState("y");
} catch (e) {
console.log("[Window state manager] No window state file found. Fallbacking to default values.");
width = (await getWindowState("width")) ?? 800;
height = (await getWindowState("height")) ?? 600;
isMaximized = (await getWindowState("isMaximized")) ?? false;
xValue = await getWindowState("x");
yValue = await getWindowState("y");
} catch (_e) {
console.log("[Window state manager] No window state file found. Falling back to default values.");
mainWindow.setSize(800, 600);
}
if (isMaximized) {
@ -102,11 +105,11 @@ export function registerIpc() {
console.log("[Window state manager] Not maximized.");
}
});
ipcMain.on("restart", (event, arg) => {
ipcMain.on("restart", () => {
app.relaunch();
app.exit();
});
ipcMain.on("saveSettings", (event, args) => {
ipcMain.on("saveSettings", (_event, args) => {
setConfigBulk(args);
});
ipcMain.on("minimizeToTray", async (event) => {
@ -115,28 +118,28 @@ export function registerIpc() {
ipcMain.on("channel", async (event) => {
event.returnValue = await getConfig("channel");
});
ipcMain.on("clientmod", async (event, arg) => {
ipcMain.on("clientmod", async (event) => {
event.returnValue = await getConfig("mods");
});
ipcMain.on("legacyCapturer", async (event, arg) => {
ipcMain.on("legacyCapturer", async (event) => {
event.returnValue = await getConfig("useLegacyCapturer");
});
ipcMain.on("trayIcon", async (event, arg) => {
ipcMain.on("trayIcon", async (event) => {
event.returnValue = await getConfig("trayIcon");
});
ipcMain.on("disableAutogain", async (event, arg) => {
ipcMain.on("disableAutogain", async (event) => {
event.returnValue = await getConfig("disableAutogain");
});
ipcMain.on("titlebar", (event, arg) => {
ipcMain.on("titlebar", (event) => {
event.returnValue = customTitlebar;
});
ipcMain.on("mobileMode", async (event, arg) => {
ipcMain.on("mobileMode", async (event) => {
event.returnValue = await getConfig("mobileMode");
});
ipcMain.on("shouldPatch", async (event, arg) => {
ipcMain.on("shouldPatch", async (event) => {
event.returnValue = await getConfig("automaticPatches");
});
ipcMain.on("openSettingsWindow", (event, arg) => {
ipcMain.on("openSettingsWindow", () => {
createSettingsWindow();
});
ipcMain.on("setting-armcordCSP", async (event) => {
@ -146,5 +149,5 @@ export function registerIpc() {
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
import {app, BrowserWindow, crashReporter, session} from "electron";
import {BrowserWindow, app, crashReporter, session} from "electron";
import "v8-compile-cache";
import {
Settings,
checkForDataFolder,
getConfig,
checkIfConfigExists,
getConfig,
injectElectronFlags,
setConfig,
installModLoader,
getConfigLocation
setConfig
} from "./utils";
import "./extensions/mods";
import "./tray";
import fs from "fs";
import {createCustomWindow, createNativeWindow, createTransparentWindow, mainWindow} from "./window";
import {createCustomWindow, createNativeWindow, createTransparentWindow} from "./window";
import path from "path";
export var iconPath: string;
export var settings: any;
export var customTitlebar: boolean;
export var clientName: "ArmCord";
async function args() {
var argNum = 2;
export let iconPath: string;
export let settings: any;
export let customTitlebar: boolean;
async function args(): Promise<void> {
let argNum = 2;
if (process.argv[0] == "electron") argNum++;
var args = process.argv[argNum];
let args = process.argv[argNum];
if (args == undefined) return;
if (args.startsWith("--")) return; //electron flag
if (args.includes("=")) {
var e = args.split("=");
await setConfig(e[0], e[1]);
console.log("Setting " + e[0] + " to " + e[1]);
let e = args.split("=");
await setConfig(e[0] as keyof Settings, e[1]);
console.log(`Setting ${e[0]} to ${e[1]}`);
app.relaunch();
app.exit();
}
@ -70,7 +68,7 @@ if (!app.requestSingleInstanceLock()) {
} else {
iconPath = path.join(__dirname, "../", "/assets/ac_icon_transparent.png");
}
async function init() {
async function init(): Promise<void> {
switch (await getConfig("windowStyle")) {
case "default":
createCustomWindow();
@ -93,7 +91,7 @@ if (!app.requestSingleInstanceLock()) {
}
await init();
await installModLoader();
session.fromPartition("some-partition").setPermissionRequestHandler((webContents, permission, callback) => {
session.fromPartition("some-partition").setPermissionRequestHandler((_webContents, permission, callback) => {
if (permission === "notifications") {
// Approves the permissions request
callback(true);

View file

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

View file

@ -9,7 +9,7 @@ interface IPCSources {
name: string;
thumbnail: HTMLCanvasElement;
}
async function getDisplayMediaSelector() {
async function getDisplayMediaSelector(): Promise<string> {
const sources: IPCSources[] = await desktopCapturer.getSources({
types: ["screen", "window"]
});
@ -54,7 +54,7 @@ contextBridge.exposeInMainWorld("armcord", {
ipcRenderer.invoke("getLang", toGet).then((result) => {
return result;
}),
getDisplayMediaSelector: getDisplayMediaSelector,
getDisplayMediaSelector,
version: ipcRenderer.sendSync("get-app-version", "app-version"),
mods: ipcRenderer.sendSync("clientmod"),
packageVersion: ipcRenderer.sendSync("get-package-version", "app-version"),
@ -63,9 +63,11 @@ contextBridge.exposeInMainWorld("armcord", {
});
let windowCallback: (arg0: object) => void;
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);
});
//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
//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 path from "path";

View file

@ -1,9 +1,8 @@
import {ipcRenderer} from "electron";
import {addStyle} from "../utils";
import * as fs from "fs";
import * as path from "path";
export function injectMobileStuff() {
document.addEventListener("DOMContentLoaded", function (event) {
export function injectMobileStuff(): void {
document.addEventListener("DOMContentLoaded", function () {
const mobileCSS = path.join(__dirname, "../", "/content/css/mobile.css");
addStyle(fs.readFileSync(mobileCSS, "utf8"));
// 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 {injectJS} from "../utils";
var patchEndpoint = "https://patch.armcord.xyz/";
var version = ipcRenderer.sendSync("get-app-version", "app-version");
const patchEndpoint = "https://patch.armcord.xyz";
const version = ipcRenderer.sendSync("get-app-version", "app-version");
if (ipcRenderer.sendSync("shouldPatch")) {
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) => {
if (res.patch == true) {
console.log("Found a patch. Injecting...");
injectJS(patchEndpoint + version + "/patch.js");
injectJS(`${patchEndpoint}/${version}/patch.js`);
} else {
console.log("No patches have been found.");
}

View file

@ -15,9 +15,8 @@ if (ipcRenderer.sendSync("legacyCapturer")) {
import("./capturer");
}
var version = ipcRenderer.sendSync("displayVersion");
var channel = ipcRenderer.sendSync("channel");
async function updateLang() {
const version = ipcRenderer.sendSync("displayVersion");
async function updateLang(): Promise<void> {
if (window.location.href.indexOf("setup.html") > -1) {
console.log("Setup, skipping lang update");
} else {
@ -32,8 +31,8 @@ declare global {
}
}
console.log("ArmCord " + version);
ipcRenderer.on("themeLoader", (event, message) => {
console.log(`ArmCord ${version}`);
ipcRenderer.on("themeLoader", (_event, message) => {
addStyle(message);
});
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 path from "path";
import os from "os";
export function injectTitlebar() {
document.addEventListener("DOMContentLoaded", function (event) {
var elem = document.createElement("div");
export function injectTitlebar(): void {
document.addEventListener("DOMContentLoaded", function (_event) {
const elem = document.createElement("div");
elem.innerHTML = `<nav class="titlebar">
<div class="window-title" id="window-title"></div>
<div id="window-controls-container">
@ -28,9 +28,9 @@ export function injectTitlebar() {
document.body.setAttribute("customTitlebar", "");
document.body.setAttribute("armcord-platform", os.platform());
var minimize = document.getElementById("minimize");
var maximize = document.getElementById("maximize");
var quit = document.getElementById("quit");
const minimize = document.getElementById("minimize");
const maximize = document.getElementById("maximize");
const quit = document.getElementById("quit");
minimize!.addEventListener("click", () => {
ipcRenderer.send("win-minimize");
@ -55,8 +55,8 @@ export function injectTitlebar() {
});
}
export function fixTitlebar() {
var elem = document.createElement("div");
export function fixTitlebar(): void {
const elem = document.createElement("div");
elem.innerHTML = `<nav class="titlebar">
<div class="window-title" id="window-title"></div>
<div id="window-controls-container">
@ -72,9 +72,9 @@ export function fixTitlebar() {
} else {
document.getElementById("app-mount")!.prepend(elem);
}
var minimize = document.getElementById("minimize");
var maximize = document.getElementById("maximize");
var quit = document.getElementById("quit");
const minimize = document.getElementById("minimize");
const maximize = document.getElementById("maximize");
const quit = document.getElementById("quit");
minimize!.addEventListener("click", () => {
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 {iconPath} from "../main";
var capturerWindow: BrowserWindow;
function registerCustomHandler() {
let capturerWindow: BrowserWindow;
function registerCustomHandler(): void {
session.defaultSession.setDisplayMediaRequestHandler(async (request, callback) => {
console.log(request);
const sources = await desktopCapturer.getSources({
@ -23,11 +23,11 @@ function registerCustomHandler() {
preload: path.join(__dirname, "preload.js")
}
});
ipcMain.once("selectScreenshareSource", (event, id, name) => {
ipcMain.once("selectScreenshareSource", (_event, id, name) => {
//console.log(sources[id]);
//console.log(id);
capturerWindow.close();
var result = {id, name, width: 9999, height: 9999};
let result = {id, name, width: 9999, height: 9999};
callback({video: result});
});
capturerWindow.loadURL(`file://${__dirname}/picker.html`);

View file

@ -1,16 +1,15 @@
import {IpcMain, ipcRenderer} from "electron";
import {ipcRenderer} from "electron";
interface IPCSources {
id: string;
name: string;
thumbnail: HTMLCanvasElement;
}
async function addDisplays() {
ipcRenderer.once("getSources", (event, arg) => {
var sources: IPCSources[] = arg;
async function addDisplays(): Promise<void> {
ipcRenderer.once("getSources", (_event, arg) => {
let sources: IPCSources[] = arg;
console.log(sources);
const selectionElem = document.createElement("div");
//@ts-ignore
selectionElem.classList = ["desktop-capturer-selection"];
selectionElem.classList.add("desktop-capturer-selection");
selectionElem.innerHTML = `<div class="desktop-capturer-selection__scroller">
<ul class="desktop-capturer-selection__list">
${sources
@ -39,7 +38,7 @@ async function addDisplays() {
const id = button.getAttribute("data-id");
const title = button.getAttribute("title");
if (id === "${CANCEL_ID}") {
new Error("Cancelled by user");
throw new Error("Cancelled by user");
} else {
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 {
checkForDataFolder,
getConfig,
setConfigBulk,
Settings,
getLang,
getVersion,
getConfig,
getConfigLocation,
getDisplayVersion,
getLangName,
sleep,
getDisplayVersion
getVersion,
setConfigBulk,
sleep
} from "../utils";
import path from "path";
import os from "os";
import fs from "fs";
import {mainWindow} from "../window";
import {crash} from "process";
var settingsWindow: BrowserWindow;
var instance: number = 0;
let settingsWindow: BrowserWindow;
let instance = 0;
//checkForDataFolder();
const userDataPath = app.getPath("userData");
const storagePath = path.join(userDataPath, "/storage/");
const themesPath = path.join(userDataPath, "/themes/");
const pluginsPath = path.join(userDataPath, "/plugins/");
export function createSettingsWindow() {
export function createSettingsWindow(): void {
console.log("Creating a settings window.");
instance = instance + 1;
instance += 1;
if (instance > 1) {
if (settingsWindow) {
settingsWindow.show();
@ -45,11 +41,11 @@ export function createSettingsWindow() {
preload: path.join(__dirname, "preload.js")
}
});
async function settingsLoadPage() {
async function settingsLoadPage(): Promise<void> {
settingsWindow.loadURL(`file://${__dirname}/settings.html`);
}
const userDataPath = app.getPath("userData");
const themesFolder = userDataPath + "/themes/";
const themesFolder = `${userDataPath}/themes/`;
if (!fs.existsSync(themesFolder)) {
fs.mkdirSync(themesFolder);
console.log("Created missing theme folder");
@ -58,7 +54,7 @@ export function createSettingsWindow() {
fs.readdirSync(themesFolder).forEach((file) => {
try {
const manifest = fs.readFileSync(`${themesFolder}/${file}/manifest.json`, "utf8");
var themeFile = JSON.parse(manifest);
let themeFile = JSON.parse(manifest);
settingsWindow.webContents.send(
"themeLoader",
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);
setConfigBulk(args);
});
ipcMain.on("openStorageFolder", async (event) => {
ipcMain.on("openStorageFolder", async () => {
shell.showItemInFolder(storagePath);
await sleep(1000);
});
ipcMain.on("openThemesFolder", async (event) => {
ipcMain.on("openThemesFolder", async () => {
shell.showItemInFolder(themesPath);
await sleep(1000);
});
ipcMain.on("openPluginsFolder", async (event) => {
ipcMain.on("openPluginsFolder", async () => {
shell.showItemInFolder(pluginsPath);
await sleep(1000);
});
ipcMain.on("openCrashesFolder", async (event) => {
shell.showItemInFolder(path.join(app.getPath("temp"), app.getName() + " Crashes"));
ipcMain.on("openCrashesFolder", async () => {
shell.showItemInFolder(path.join(app.getPath("temp"), `${app.getName()} Crashes`));
await sleep(1000);
});
ipcMain.on("getLangName", async (event) => {
event.returnValue = await getLangName();
});
ipcMain.on("crash", async (event) => {
ipcMain.on("crash", async () => {
process.crash();
});
ipcMain.handle("getSetting", (event, toGet: string) => {
ipcMain.handle("getSetting", (_event, toGet: keyof Settings) => {
return getConfig(toGet);
});
ipcMain.on("copyDebugInfo", (event) => {
ipcMain.on("copyDebugInfo", () => {
let settingsFileContent = fs.readFileSync(getConfigLocation(), "utf-8");
clipboard.writeText(
"**OS:** " +
os.platform() +
" " +
os.version() +
"\n**Architecture:** " +
os.arch() +
"\n**ArmCord version:** " +
getVersion() +
"\n**Electron version:** " +
process.versions.electron +
"\n`" +
settingsFileContent +
"`"
`**OS:** ${os.platform()} ${os.version()}\n**Architecture:** ${os.arch()}\n**ArmCord version:** ${getVersion()}\n**Electron version:** ${
process.versions.electron
}\n\`${settingsFileContent}\``
);
});
settingsWindow.webContents.setWindowOpenHandler(({url}) => {
@ -121,7 +107,7 @@ export function createSettingsWindow() {
return {action: "deny"};
});
settingsLoadPage();
settingsWindow.on("close", (event: Event) => {
settingsWindow.on("close", () => {
ipcMain.removeHandler("getSetting");
ipcMain.removeAllListeners("saveSettings");
instance = 0;

View file

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

View file

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

View file

@ -1,31 +1,31 @@
import * as fs from "fs";
import {app, dialog, Rectangle} from "electron";
import {app, dialog} from "electron";
import path from "path";
import fetch from "cross-fetch";
import extract from "extract-zip";
import util from "util";
const streamPipeline = util.promisify(require("stream").pipeline);
export var firstRun: boolean;
export var contentPath: string;
export var transparency: boolean;
export let firstRun: boolean;
export let contentPath: string;
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
export function addStyle(styleString: string) {
export function addStyle(styleString: string): void {
const style = document.createElement("style");
style.textContent = styleString;
document.head.append(style);
}
export function addScript(scriptString: string) {
var script = document.createElement("script");
export function addScript(scriptString: string): void {
let script = document.createElement("script");
script.textContent = scriptString;
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));
}
export async function checkIfConfigIsBroken() {
export async function checkIfConfigIsBroken(): Promise<void> {
if ((await getConfig("0")) == "d") {
console.log("Detected a corrupted config");
setup();
@ -36,7 +36,7 @@ export async function checkIfConfigIsBroken() {
}
}
export function setup() {
export function setup(): void {
console.log("Setting up temporary ArmCord settings.");
const defaults: Settings = {
windowStyle: "default",
@ -55,7 +55,9 @@ export function setup() {
useLegacyCapturer: false,
mobileMode: false,
trayIcon: "default",
doneSetup: false
doneSetup: false,
clientName: "ArmCord",
customIcon: path.join(__dirname, "../", "/assets/ac_icon_transparent.png")
};
setConfigBulk({
...defaults
@ -63,12 +65,12 @@ export function setup() {
}
//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;
}
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
if ((app.getVersion() == packageVersion) == false) {
if ((app.getVersion() == process.versions.electron) == true) {
@ -80,7 +82,7 @@ export function getDisplayVersion() {
return packageVersion;
}
}
export async function injectJS(inject: string) {
export async function injectJS(inject: string): Promise<void> {
const js = await (await fetch(`${inject}`)).text();
const el = document.createElement("script");
@ -89,7 +91,7 @@ export async function injectJS(inject: string) {
document.body.appendChild(el);
}
export async function injectElectronFlags() {
export async function injectElectronFlags(): Promise<void> {
// MIT License
// Copyright (c) 2022 GooseNest
@ -135,43 +137,43 @@ export async function injectElectronFlags() {
});
}
}
export async function setLang(language: string) {
const langConfigFile = path.join(app.getPath("userData"), "/storage/") + "lang.json";
export async function setLang(language: string): Promise<void> {
const langConfigFile = `${path.join(app.getPath("userData"), "/storage/")}lang.json`;
if (!fs.existsSync(langConfigFile)) {
fs.writeFileSync(langConfigFile, "{}", "utf-8");
}
let rawdata = fs.readFileSync(langConfigFile, "utf-8");
let parsed = JSON.parse(rawdata);
parsed["lang"] = language;
parsed.lang = language;
let toSave = JSON.stringify(parsed, null, 4);
fs.writeFileSync(langConfigFile, toSave, "utf-8");
}
var language: string;
export async function getLang(object: string) {
let language: string;
export async function getLang(object: string): Promise<string> {
if (language == undefined) {
try {
const userDataPath = app.getPath("userData");
const storagePath = path.join(userDataPath, "/storage/");
const langConfigFile = storagePath + "lang.json";
const langConfigFile = `${storagePath}lang.json`;
let rawdata = fs.readFileSync(langConfigFile, "utf-8");
let parsed = JSON.parse(rawdata);
language = parsed["lang"];
} catch (e) {
language = parsed.lang;
} catch (_e) {
console.log("Language config file doesn't exist. Fallback to English.");
language = "en-US";
}
}
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)) {
langPath = path.join(__dirname, "../", "/assets/lang/en-US.json");
}
let rawdata = fs.readFileSync(langPath, "utf-8");
let parsed = JSON.parse(rawdata);
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");
rawdata = fs.readFileSync(langPath, "utf-8");
parsed = JSON.parse(rawdata);
@ -180,22 +182,22 @@ export async function getLang(object: string) {
return parsed[object];
}
}
export async function getLangName() {
export async function getLangName(): Promise<string> {
if (language == undefined) {
try {
const userDataPath = app.getPath("userData");
const storagePath = path.join(userDataPath, "/storage/");
const langConfigFile = storagePath + "lang.json";
const langConfigFile = `${storagePath}lang.json`;
let rawdata = fs.readFileSync(langConfigFile, "utf-8");
let parsed = JSON.parse(rawdata);
language = parsed["lang"];
} catch (e) {
language = parsed.lang;
} catch (_e) {
console.log("Language config file doesn't exist. Fallback to English.");
language = "en-US";
}
}
if (language.length == 2) {
language = language + "-" + language.toUpperCase();
language = `${language}-${language.toUpperCase()}`;
}
return language;
}
@ -207,26 +209,26 @@ export interface WindowState {
y: number;
isMaximized: boolean;
}
export async function setWindowState(object: WindowState) {
export async function setWindowState(object: WindowState): Promise<void> {
const userDataPath = app.getPath("userData");
const storagePath = path.join(userDataPath, "/storage/");
const saveFile = storagePath + "window.json";
const saveFile = `${storagePath}window.json`;
let toSave = JSON.stringify(object, null, 4);
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 storagePath = path.join(userDataPath, "/storage/");
const settingsFile = storagePath + "window.json";
const settingsFile = `${storagePath}window.json`;
let rawdata = fs.readFileSync(settingsFile, "utf-8");
let returndata = JSON.parse(rawdata);
console.log(returndata);
console.log("[Window state manager] " + returndata);
console.log(`[Window state manager] ${returndata}`);
return returndata[object];
}
//ArmCord Settings/Storage manager
export function checkForDataFolder() {
export function checkForDataFolder(): void {
const dataPath = path.join(path.dirname(app.getPath("exe")), "armcord-data");
if (fs.existsSync(dataPath) && fs.statSync(dataPath).isDirectory()) {
console.log("Found armcord-data folder. Running in portable mode.");
@ -235,6 +237,14 @@ export function checkForDataFolder() {
}
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;
channel: string;
armcordCSP: boolean;
@ -252,33 +262,34 @@ export interface Settings {
disableAutogain: boolean;
trayIcon: string;
doneSetup: boolean;
clientName: string;
}
export function getConfigLocation() {
export function getConfigLocation(): string {
const userDataPath = app.getPath("userData");
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 returndata = JSON.parse(rawdata);
console.log("[Config manager] " + object + ": " + returndata[object]);
console.log(`[Config manager] ${object}: ${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 parsed = JSON.parse(rawdata);
parsed[object] = toSet;
let toSave = JSON.stringify(parsed, null, 4);
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);
fs.writeFileSync(getConfigLocation(), toSave, "utf-8");
}
export async function checkIfConfigExists() {
export async function checkIfConfigExists(): Promise<void> {
const userDataPath = app.getPath("userData");
const storagePath = path.join(userDataPath, "/storage/");
const settingsFile = storagePath + "settings.json";
const settingsFile = `${storagePath}settings.json`;
if (!fs.existsSync(settingsFile)) {
if (!fs.existsSync(storagePath)) {
@ -288,27 +299,25 @@ export async function checkIfConfigExists() {
console.log("First run of the ArmCord. Starting setup.");
setup();
firstRun = true;
} else {
if ((await getConfig("doneSetup")) == false) {
} else if ((await getConfig("doneSetup")) == false) {
console.log("First run of the ArmCord. Starting setup.");
setup();
firstRun = true;
} else {
console.log("ArmCord has been run before. Skipping setup.");
}
}
}
// Mods
async function updateModBundle() {
async function updateModBundle(): Promise<void> {
if ((await getConfig("noBundleUpdates")) == undefined ?? false) {
try {
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)) {
//waiting
}
var name: string = await getConfig("mods");
let name: string = await getConfig("mods");
const clientMods = {
vencord: "https://github.com/Vendicated/Vencord/releases/download/devbuild/browser.js",
cordwood: "https://raw.githubusercontent.com/Cordwood/builds/master/index.js",
@ -319,10 +328,10 @@ async function updateModBundle() {
cordwood: "https://armcord.xyz/placeholder.css",
shelter: "https://armcord.xyz/placeholder.css"
};
var bundle: string = await (await fetch(clientMods[name as keyof typeof clientMods])).text();
fs.writeFileSync(distFolder + "bundle.js", bundle, "utf-8");
var css: string = await (await fetch(clientModsCss[name as keyof typeof clientModsCss])).text();
fs.writeFileSync(distFolder + "bundle.css", css, "utf-8");
let bundle: string = await (await fetch(clientMods[name as keyof typeof clientMods])).text();
fs.writeFileSync(`${distFolder}bundle.js`, bundle, "utf-8");
let css: string = await (await fetch(clientModsCss[name as keyof typeof clientModsCss])).text();
fs.writeFileSync(`${distFolder}bundle.css`, css, "utf-8");
} catch (e) {
console.log("[Mod loader] Failed to install mods");
console.error(e);
@ -336,25 +345,25 @@ async function updateModBundle() {
}
}
export var modInstallState: string;
export async function installModLoader() {
export let modInstallState: string;
export async function installModLoader(): Promise<void> {
if ((await getConfig("mods")) == "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");
console.log("[Mod loader] Skipping");
} else {
const pluginFolder = app.getPath("userData") + "/plugins/";
if (!fs.existsSync(pluginFolder + "loader") || !fs.existsSync(pluginFolder + "loader/dist/" + "bundle.css")) {
const pluginFolder = `${app.getPath("userData")}/plugins/`;
if (!fs.existsSync(`${pluginFolder}loader`) || !fs.existsSync(`${pluginFolder}loader/dist/bundle.css`)) {
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";
var zipPath = app.getPath("temp") + "/" + "loader.zip";
let zipPath = `${app.getPath("temp")}/loader.zip`;
if (!fs.existsSync(pluginFolder)) {
fs.mkdirSync(pluginFolder);
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}`);
await streamPipeline(loaderZip.body, fs.createWriteStream(zipPath));
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
// 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.
import {BrowserWindow, shell, app, dialog, nativeImage} from "electron";
import {BrowserWindow, app, dialog, nativeImage, shell} from "electron";
import path from "path";
import {
checkIfConfigIsBroken,
contentPath,
firstRun,
getConfig,
contentPath,
modInstallState,
setConfig,
setLang,
setWindowState,
transparency,
sleep,
modInstallState
transparency
} from "./utils";
import {registerIpc} from "./ipc";
import {setMenu} from "./menu";
@ -26,13 +26,13 @@ import {iconPath} from "./main";
export let mainWindow: BrowserWindow;
export let inviteWindow: BrowserWindow;
var osType = os.type();
let osType = os.type();
contextMenu({
showSaveImageAs: true,
showCopyImageAddress: true,
showSearchWithGoogle: false,
showSearchWithDuckDuckGo: false,
prepend: (defaultActions, parameters, browserWindow) => [
prepend: (_defaultActions, parameters) => [
{
label: "Search with Google",
// Only show it when right-clicking text
@ -51,7 +51,7 @@ contextMenu({
}
]
});
async function doAfterDefiningTheWindow() {
async function doAfterDefiningTheWindow(): Promise<void> {
if (await getConfig("startMinimized")) {
mainWindow.hide();
} else {
@ -66,7 +66,7 @@ async function doAfterDefiningTheWindow() {
}
});
}
var ignoreProtocolWarning = await getConfig("ignoreProtocolWarning");
let ignoreProtocolWarning = await getConfig("ignoreProtocolWarning");
await checkIfConfigIsBroken();
registerIpc();
if (await getConfig("mobileMode")) {
@ -75,11 +75,11 @@ async function doAfterDefiningTheWindow() {
} else {
// A little sloppy but it works :p
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
}
app.on("second-instance", (event, commandLine, workingDirectory, additionalData) => {
app.on("second-instance", (_event, _commandLine, _workingDirectory, additionalData) => {
// Print out data received from the second instance.
console.log(additionalData);
@ -102,8 +102,7 @@ async function doAfterDefiningTheWindow() {
return {action: "allow"};
if (url.startsWith("https:") || url.startsWith("http:") || url.startsWith("mailto:")) {
shell.openExternal(url);
} else {
if (ignoreProtocolWarning) {
} else if (ignoreProtocolWarning) {
shell.openExternal(url);
} else {
const options = {
@ -128,12 +127,9 @@ async function doAfterDefiningTheWindow() {
}
if (response == 0) {
shell.openExternal(url);
} else {
return;
}
});
}
}
return {action: "deny"};
});
if ((await getConfig("useLegacyCapturer")) == false) {
@ -147,8 +143,8 @@ async function doAfterDefiningTheWindow() {
);
if ((await getConfig("trayIcon")) == "default" || (await getConfig("dynamicIcon"))) {
mainWindow.webContents.on("page-favicon-updated", async (event) => {
var faviconBase64 = await mainWindow.webContents.executeJavaScript(`
mainWindow.webContents.on("page-favicon-updated", async () => {
let faviconBase64 = await mainWindow.webContents.executeJavaScript(`
var getFavicon = function(){
var favicon = undefined;
var nodeList = document.getElementsByTagName("link");
@ -163,7 +159,7 @@ async function doAfterDefiningTheWindow() {
}
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");
let trayPath = nativeImage.createFromPath(path.join(app.getPath("temp"), "/", "tray.png"));
if (process.platform === "darwin" && trayPath.getSize().height > 22)
@ -178,7 +174,7 @@ async function doAfterDefiningTheWindow() {
});
}
const userDataPath = app.getPath("userData");
const themesFolder = userDataPath + "/themes/";
const themesFolder = `${userDataPath}/themes/`;
if (!fs.existsSync(themesFolder)) {
fs.mkdirSync(themesFolder);
console.log("Created missing theme folder");
@ -187,7 +183,7 @@ async function doAfterDefiningTheWindow() {
fs.readdirSync(themesFolder).forEach((file) => {
try {
const manifest = fs.readFileSync(`${themesFolder}/${file}/manifest.json`, "utf8");
var themeFile = JSON.parse(manifest);
let themeFile = JSON.parse(manifest);
mainWindow.webContents.send(
"themeLoader",
fs.readFileSync(`${themesFolder}/${file}/${themeFile.theme}`, "utf-8")
@ -202,8 +198,8 @@ async function doAfterDefiningTheWindow() {
mainWindow.on("close", async (e) => {
let [width, height] = mainWindow.getSize();
await setWindowState({
width: width,
height: height,
width,
height,
isMaximized: mainWindow.isMaximized(),
x: mainWindow.getPosition()[0],
y: mainWindow.getPosition()[1]
@ -232,12 +228,11 @@ async function doAfterDefiningTheWindow() {
});
console.log(contentPath);
if ((await getConfig("inviteWebsocket")) == true) {
//@ts-ignore
require("arrpc");
//await startServer();
}
if (firstRun) {
await setLang(Intl.DateTimeFormat().resolvedOptions().locale);
await setLang(new Intl.DateTimeFormat().resolvedOptions().locale);
mainWindow.setSize(390, 470);
await mainWindow.loadFile(path.join(__dirname, "/content/setup.html"));
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});
tray.setImage(trayPath);
} else if ((await getConfig("skipSplash")) == true) {
// It's modified elsewhere.
// eslint-disable-next-line no-unmodified-loop-condition
while (modInstallState == "installing") {
await sleep(1000);
}
@ -277,7 +274,7 @@ async function doAfterDefiningTheWindow() {
mainWindow.show();
}
}
export function createCustomWindow() {
export function createCustomWindow(): void {
mainWindow = new BrowserWindow({
width: 300,
height: 350,
@ -296,7 +293,7 @@ export function createCustomWindow() {
});
doAfterDefiningTheWindow();
}
export function createNativeWindow() {
export function createNativeWindow(): void {
mainWindow = new BrowserWindow({
width: 300,
height: 350,
@ -315,7 +312,7 @@ export function createNativeWindow() {
});
doAfterDefiningTheWindow();
}
export function createTransparentWindow() {
export function createTransparentWindow(): void {
mainWindow = new BrowserWindow({
width: 300,
height: 350,
@ -334,7 +331,7 @@ export function createTransparentWindow() {
});
doAfterDefiningTheWindow();
}
export function createInviteWindow(code: string) {
export function createInviteWindow(code: string): void {
inviteWindow = new BrowserWindow({
width: 800,
height: 600,
@ -348,7 +345,7 @@ export function createInviteWindow(code: string) {
spellcheck: true
}
});
var formInviteURL = `https://discord.com/invite/${code}`;
let formInviteURL = `https://discord.com/invite/${code}`;
inviteWindow.webContents.session.webRequest.onBeforeRequest((details, callback) => {
if (details.url.includes("ws://")) return callback({cancel: true});
return callback({});