Compare commits

..

No commits in common. "a48258da4503426f6b7eb164889d5d8be9f8f19d" and "a212dba6bbe3652e2fd046ae9686d16f6db692c5" have entirely different histories.

16 changed files with 203 additions and 286 deletions

8
package-lock.json generated
View file

@ -1,12 +1,12 @@
{ {
"name": "ArmCord", "name": "armcord",
"version": "3.1.0", "version": "3.0.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ArmCord", "name": "armcord",
"version": "3.1.0", "version": "3.0.0",
"license": "OSL-3.0", "license": "OSL-3.0",
"dependencies": { "dependencies": {
"electron-json-storage": "^4.5.0", "electron-json-storage": "^4.5.0",

View file

@ -1,6 +1,6 @@
{ {
"name": "ArmCord", "name": "ArmCord",
"version": "3.0.4", "version": "3.0.3",
"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",
"scripts": { "scripts": {
@ -8,6 +8,7 @@
"watch": "tsc -w", "watch": "tsc -w",
"start": "npm run build && electron ./ts-out/main.js", "start": "npm run build && electron ./ts-out/main.js",
"package": "npm run build && electron-builder" "package": "npm run build && electron-builder"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -20,12 +21,12 @@
}, },
"homepage": "https://github.com/armcord/armcord#readme", "homepage": "https://github.com/armcord/armcord#readme",
"devDependencies": { "devDependencies": {
"electron": "^16.0.7",
"@types/electron-json-storage": "^4.5.0", "@types/electron-json-storage": "^4.5.0",
"@types/node": "^14.18.2", "@types/node": "^14.18.2",
"typescript": "^4.5.4",
"copyfiles": "^2.4.1", "copyfiles": "^2.4.1",
"electron": "^16.0.7", "electron-builder": "^22.14.5"
"electron-builder": "^22.14.5",
"typescript": "^4.5.4"
}, },
"dependencies": { "dependencies": {
"electron-json-storage": "^4.5.0", "electron-json-storage": "^4.5.0",

View file

@ -1,5 +1,5 @@
.info-1sUqUG:last-child:before { .info-1VyQPT:last-child:before {
content: "ArmCord Version: 3.1.0"!important; content: "ArmCord Version: 3.0.0"!important;
height: auto; height: auto;
line-height: 16px; line-height: 16px;
text-align: center; text-align: center;

View file

@ -1 +0,0 @@
<h1>settings, really cool</h1>

View file

@ -42,10 +42,10 @@
} else { } else {
console.log("Starting ArmCord Setup..."); console.log("Starting ArmCord Setup...");
document.getElementById("express").addEventListener("click", function () { document.getElementById("express").addEventListener("click", function () {
window.armcordinternal.saveSettings(true, "stable", true, "cumcord"); window.armcord.saveSettings(true, "stable", true, "cumcord");
fade(document.getElementById("setup")); fade(document.getElementById("setup"));
setTimeout(function () { setTimeout(function () {
window.armcordinternal.restart() window.armcord.restart()
}, 5000); }, 5000);
}) })
document.getElementById("full").addEventListener("click", function () { document.getElementById("full").addEventListener("click", function () {
@ -90,18 +90,18 @@
.getElementById("next") .getElementById("next")
.addEventListener("click", function () { .addEventListener("click", function () {
var mod = document.getElementById("mod").value; var mod = document.getElementById("mod").value;
window.armcordinternal.saveSettings(true, branch, true, mod); window.armcord.saveSettings(true, branch, true, mod);
fade(document.getElementById("setup")); fade(document.getElementById("setup"));
setTimeout(function () { setTimeout(function () {
window.armcordinternal.restart(); window.armcord.restart();
}, 5000); }, 5000);
}); });
} else { } else {
//saveSettings(customTitlebarSetting: boolean, channelSetting: string, armcordCSPSetting: boolean, modsSetting: string) //saveSettings(customTitlebarSetting: boolean, channelSetting: string, armcordCSPSetting: boolean, modsSetting: string)
window.armcordinternal.saveSettings(true, branch, true, "none"); window.armcord.saveSettings(true, branch, true, "none");
fade(document.getElementById("setup")); fade(document.getElementById("setup"));
setTimeout(function () { setTimeout(function () {
window.armcordinternal.restart() window.armcord.restart()
}, 5000); }, 5000);
} }
}); });

View file

@ -42,7 +42,7 @@
} }
}); });
setTimeout(() => { setTimeout(() => {
window.armcordinternal.splashEnd(); window.armcord.splashEnd();
switch (window.armcord.channel) { switch (window.armcord.channel) {
case "stable": case "stable":
window.location.replace("https://discord.com/app"); window.location.replace("https://discord.com/app");

View file

@ -1,70 +0,0 @@
//ipc stuff
import { app, ipcMain, shell, desktopCapturer } from "electron";
import { mainWindow } from "./window";
import { saveSettings, getVersion } from "./utils";
import { settings, customTitlebar } from "./main";
import { createSettingsWindow } from "./settings/main";
export function registerIpc() {
ipcMain.on("get-app-path", (event, arg) => {
event.reply("app-path", app.getAppPath());
});
ipcMain.on("open-external-link", (event, href: string) => {
shell.openExternal(href);
});
ipcMain.on("win-maximize", (event, arg) => {
mainWindow.maximize();
});
ipcMain.on("win-isMaximized", (event, arg) => {
event.returnValue = mainWindow.isMaximized();
});
ipcMain.on("win-minimize", (event, arg) => {
mainWindow.minimize();
});
ipcMain.on("win-unmaximize", (event, arg) => {
mainWindow.unmaximize();
});
ipcMain.on("win-show", (event, arg) => {
mainWindow.show();
});
ipcMain.on("win-hide", (event, arg) => {
mainWindow.hide();
});
ipcMain.on("get-app-version", (event) => {
event.returnValue = getVersion();
});
ipcMain.on("splashEnd", (event, arg) => {
mainWindow.setSize(800, 600);
});
ipcMain.on("restart", (event, arg) => {
app.relaunch();
app.exit();
});
ipcMain.on("saveSettings", (event, ...args) => {
//@ts-ignore
saveSettings(...args);
});
ipcMain.on("channel", (event) => {
event.returnValue = settings.channel;
});
ipcMain.on("clientmod", (event, arg) => {
event.returnValue = settings.mods;
});
ipcMain.on("titlebar", (event, arg) => {
event.returnValue = customTitlebar;
});
ipcMain.on("openSettingsWindow", (event, arg) => {
createSettingsWindow();
});
ipcMain.on("setting-armcordCSP", (event) => {
if (settings.armcordCSP) {
event.returnValue = true;
} else {
event.returnValue = false;
}
});
ipcMain.handle("DESKTOP_CAPTURER_GET_SOURCES", (event, opts) =>
desktopCapturer.getSources(opts)
);
}

View file

@ -2,21 +2,24 @@
import { import {
app, app,
BrowserWindow, BrowserWindow,
ipcMain,
shell,
desktopCapturer,
session, session,
} from "electron"; } from "electron";
import * as path from "path"; import * as path from "path";
import "v8-compile-cache"; import "v8-compile-cache";
import * as storage from "electron-json-storage"; import * as storage from "electron-json-storage";
import { getConfigUnsafe, setup } from "./utils"; import { saveSettings, getVersion, setup, getConfigUnsafe } from "./utils";
import "./extensions/mods"; import "./extensions/mods";
import "./extensions/plugin"; import "./extensions/plugin";
import "./tray"; import "./tray";
import { mainWindow, createCustomWindow, createNativeWindow } from "./window";
import "./shortcuts"; import "./shortcuts";
export var contentPath: string; var contentPath: string;
var channel: string; var channel: string;
export var settings: any; export var mainWindow: BrowserWindow;
export var customTitlebar: boolean; var settings: any;
storage.has("settings", function (error, hasKey) { storage.has("settings", function (error, hasKey) {
if (error) throw error; if (error) throw error;
@ -24,41 +27,119 @@ storage.has("settings", function (error, hasKey) {
console.log("First run of the ArmCord. Starting setup."); console.log("First run of the ArmCord. Starting setup.");
setup(); setup();
contentPath = path.join(__dirname, "/content/setup.html"); contentPath = path.join(__dirname, "/content/setup.html");
if (!contentPath.includes("ts-out")) { if(!contentPath.includes("ts-out")) {
contentPath = path.join(__dirname, "/ts-out/content/setup.html"); contentPath = path.join(__dirname,"/ts-out/content/setup.html");
} }
} else { } else {
console.log("ArmCord has been run before. Skipping setup."); console.log("ArmCord has been run before. Skipping setup.");
contentPath = path.join(__dirname, "/content/splash.html"); contentPath = path.join(__dirname,"/content/splash.html");
if (!contentPath.includes("ts-out")) { if(!contentPath.includes("ts-out")) {
contentPath = path.join(__dirname, "/ts-out/content/splash.html"); contentPath = path.join(__dirname,"/ts-out/content/splash.html");
}
} }
}); }});
storage.get("settings", function (error, data: any) { storage.get("settings", function (error, data: any) {
if (error) throw error; if (error) throw error;
console.log(data); console.log(data);
channel = data.channel; channel = data.channel;
settings = data; settings = data;
}); });
app.whenReady().then(async () => { var titlebar:any = getConfigUnsafe("customTitlebar")
if (await getConfigUnsafe("customTitlebar") == true) { console.log(!titlebar)
console.log("Creating custom titlebar window."); function createWindow() {
customTitlebar = true; mainWindow = new BrowserWindow({
createCustomWindow(); width: 300,
} else if (await getConfigUnsafe("customTitlebar") == "setup") { height: 350,
//rare case of setup window title: "ArmCord",
console.log("Creating setup window."); darkTheme: true,
customTitlebar = true; icon: path.join(__dirname, "/assets/icon_transparent.png"),
createCustomWindow(); frame: !titlebar,
} else { autoHideMenuBar: true,
console.log("Creating native titlebar window."); webPreferences: {
customTitlebar = false; preload: path.join(__dirname, "preload/preload.js"),
createNativeWindow(); },
});
ipcMain.on("get-app-path", (event, arg) => {
event.reply("app-path", app.getAppPath());
});
ipcMain.on("open-external-link", (event, href: string) => {
shell.openExternal(href);
});
ipcMain.on("win-maximize", (event, arg) => {
mainWindow.maximize();
});
ipcMain.on("win-isMaximized", (event, arg) => {
event.returnValue = mainWindow.isMaximized();
});
ipcMain.on("win-minimize", (event, arg) => {
mainWindow.minimize();
});
ipcMain.on("win-unmaximize", (event, arg) => {
mainWindow.unmaximize();
});
ipcMain.on("win-show", (event, arg) => {
mainWindow.show();
});
ipcMain.on("win-hide", (event, arg) => {
mainWindow.hide();
});
ipcMain.on("get-app-version", (event) => {
event.returnValue = getVersion();
});
ipcMain.on("splashEnd", (event, arg) => {
mainWindow.setSize(800, 600);
});
ipcMain.on("restart", (event, arg) => {
app.relaunch();
app.exit();
});
ipcMain.on("saveSettings", (event, ...args) => {
//@ts-ignore
saveSettings(...args);
});
ipcMain.on("channel", (event) => {
event.returnValue = channel;
});
ipcMain.on("clientmod", (event, arg) => {
event.returnValue = settings.mods;
});
ipcMain.on("setting-armcordCSP", (event) => {
storage.get("settings", function (error, data: any) {
if (error) throw error;
if (data.armcordCSP) {
event.returnValue = true;
} else {
event.returnValue = false;
}
});
});
ipcMain.handle("DESKTOP_CAPTURER_GET_SOURCES", (event, opts) =>
desktopCapturer.getSources(opts)
);
mainWindow.webContents.userAgent =
"Mozilla/5.0 (X11; Linux x86) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"; //fake useragent for screenshare to work
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
shell.openExternal(url);
return { action: "deny" };
});
console.log(contentPath)
try {
mainWindow.loadFile(contentPath);
} catch(e) {
console.log("Major error detected while starting up. User is most likely on Windows platform. Fallback to alternative startup.")
mainWindow.loadURL(`file://${__dirname}/ts-out/content/splash.html`);
} }
}
app.whenReady().then(() => {
createWindow();
session session
.fromPartition("some-partition") .fromPartition("some-partition")
.setPermissionRequestHandler((webContents, permission, callback) => { .setPermissionRequestHandler((webContents, permission, callback) => {
const url = webContents.getURL(); //unused?
if (permission === "notifications") { if (permission === "notifications") {
// Approves the permissions request // Approves the permissions request
callback(true); callback(true);
@ -67,21 +148,21 @@ app.whenReady().then(async () => {
// Approves the permissions request // Approves the permissions request
callback(true); callback(true);
} }
}); if (url.startsWith("discord://")) {
mainWindow.webContents.session.webRequest.onBeforeRequest( // Denies the permissions request
(details, callback) => { return callback(false);
if (/api\/v\d\/science$/g.test(details.url))
return callback({ cancel: true });
return callback({});
}
);
app.on("activate", function () {
if (BrowserWindow.getAllWindows().length === 0)
if (!settings.customTitlebar) {
createNativeWindow();
} else {
createCustomWindow();
} }
if (url.startsWith("discord.com/science")) {
// Denies the permissions request
return callback(false);
}
if (url.startsWith("discord.com/tracing")) {
// Denies the permissions request
return callback(false);
}
});
app.on("activate", function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
}); });
}); });

View file

@ -11,22 +11,24 @@ contextBridge.exposeInMainWorld("armcord", {
}, },
titlebar: { titlebar: {
injectTitlebar: () => injectTitlebar(), injectTitlebar: () => injectTitlebar(),
isTitlebar: ipcRenderer.sendSync("titlebar"),
}, },
electron: process.versions.electron, electron: process.versions.electron,
channel: ipcRenderer.sendSync("channel"), channel: ipcRenderer.sendSync("channel"),
version: ipcRenderer.sendSync("get-app-version", "app-version"), version: ipcRenderer.sendSync("get-app-version", "app-version"),
getDisplayMediaSelector: getDisplayMediaSelector, getDisplayMediaSelector: getDisplayMediaSelector,
openSettingsWindow: () => ipcRenderer.send("openSettingsWindow"), restart: () => ipcRenderer.send("restart"),
saveSettings: (...args: any) => ipcRenderer.send("saveSettings", ...args),
splashEnd: () => ipcRenderer.send("splashEnd"),
});
contextBridge.exposeInMainWorld("electron", {
//deprecated, used for legacy purposes, will be removed in future versions
window: {
show: () => ipcRenderer.send("win-show"),
hide: () => ipcRenderer.send("win-hide"),
minimize: () => ipcRenderer.send("win-minimize"),
maximize: () => ipcRenderer.send("win-maximize"),
},
electron: process.versions.electron,
warning: 'This is a deprecated API and will be removed in future versions (3.0.0 --> 3.1.0).',
version: ipcRenderer.sendSync("get-app-version", "app-version"),
}); });
//to be only used inside armcord internal setup/splash etc
if (
window.location.href.indexOf("splash.html") > -1 ||
window.location.href.indexOf("setup.html") > -1
) {
contextBridge.exposeInMainWorld("armcordinternal", {
restart: () => ipcRenderer.send("restart"),
saveSettings: (...args: any) => ipcRenderer.send("saveSettings", ...args),
splashEnd: () => ipcRenderer.send("splashEnd"),
});
}

View file

@ -6,11 +6,6 @@ import { injectTitlebar } from "./titlebar";
import { sleep, addStyle } from "../utils"; import { sleep, addStyle } from "../utils";
import { ipcRenderer } from "electron"; import { ipcRenderer } from "electron";
declare global {
interface Window {
armcord: any;
}
}
const clientMods = { const clientMods = {
goosemod: "https://api.goosemod.com/inject.js", goosemod: "https://api.goosemod.com/inject.js",
cumcord: cumcord:
@ -31,9 +26,7 @@ console.log("ArmCord");
if (window.location.href.indexOf("splash.html") > -1) { if (window.location.href.indexOf("splash.html") > -1) {
console.log("Skipping titlebar injection and client mod injection."); console.log("Skipping titlebar injection and client mod injection.");
} else { } else {
if (ipcRenderer.sendSync("titlebar")) { injectTitlebar();
injectTitlebar();
}
sleep(5000).then(() => { sleep(5000).then(() => {
const cssPath = path.join(__dirname, "../", "/content/css/discord.css"); const cssPath = path.join(__dirname, "../", "/content/css/discord.css");
addStyle(fs.readFileSync(cssPath, "utf8")); addStyle(fs.readFileSync(cssPath, "utf8"));

View file

@ -1,25 +0,0 @@
import { BrowserWindow, shell } from "electron";
import path from "path";
var settingsWindow;
export function createSettingsWindow() {
settingsWindow = new BrowserWindow({
width: 500,
height: 600,
title: "ArmCord Settings",
darkTheme: true,
icon: path.join(__dirname, "/assets/icon_transparent.png"),
frame: false,
autoHideMenuBar: true,
webPreferences: {
preload: path.join(__dirname, "preload/preload.js"),
},
});
settingsWindow.webContents.setWindowOpenHandler(({ url }) => {
shell.openExternal(url);
return { action: "deny" };
});
settingsWindow.loadFile("settings.html");
}

View file

@ -1 +0,0 @@
console.log("test")

View file

@ -1,18 +1,35 @@
import { app } from "electron";
import {mainWindow} from './window'; import { Menu, MenuItem } from "electron";
//https://github.com/electron/electron/issues/1334#issuecomment-716080005 import { mainWindow } from "./main";
// TO-DO add more const menu = new Menu();
app.on("web-contents-created", (webContentsCreatedEvent, webContents) => { menu.append(
webContents.on("before-input-event", (beforeInputEvent, input) => { new MenuItem({
// console.log('Main console::', input) label: "ArmCord" + process.env.npm_package_version,
const { code, alt, control, shift, meta } = input; submenu: [
// Shortcut: toggle devTools {
if (shift && control && !alt && !meta && code === "KeyI") { role: "toggleDevTools",
mainWindow.webContents.toggleDevTools(); accelerator:
} process.platform === "darwin" ? "Ctrl+Cmd+I" : "Ctrl+Shift+I",
// Shortcut: window reload click: () => {
if (shift && control && !alt && !meta && code === "KeyR") { mainWindow.webContents.toggleDevTools();
mainWindow.reload(); },
} },
}); {
}); role: "toggleDevTools",
accelerator: "F12",
click: () => {
mainWindow.webContents.toggleDevTools();
},
},
{
role: "reload",
accelerator:
"Ctrl+F5",
click: () => {
mainWindow.webContents.reload();
},
},
],
})
);
Menu.setApplicationMenu(menu);

View file

@ -1,5 +1,5 @@
import { app, Menu, Tray } from 'electron'; import { app, Menu, Tray } from 'electron';
import {mainWindow} from './window'; import {mainWindow} from './main';
import * as path from 'path' import * as path from 'path'
let tray = null let tray = null
app.whenReady().then(() => { app.whenReady().then(() => {

View file

@ -1,8 +1,6 @@
import * as storage from "electron-json-storage"; import * as storage from "electron-json-storage";
import * as fs from "fs"; import * as fs from "fs";
import { app } from "electron"; import { app } from "electron";
import path from "path";
export var firstRun: boolean;
//utillity functions that are used all over the codebase or just too obscure to be put in the file used in //utillity 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) {
@ -23,9 +21,9 @@ export function setup() {
{ {
customTitlebar: true, customTitlebar: true,
channel: "stable", channel: "stable",
doneSetup: true, firstRun: "done",
armcordCSP: true, armcordCSP: true,
mods: "cumcord", mods: "cumcord"
}, },
function (error) { function (error) {
if (error) throw error; if (error) throw error;
@ -47,7 +45,7 @@ export function saveSettings(
{ {
customTitlebar: customTitlebarSetting, customTitlebar: customTitlebarSetting,
channel: channelSetting, channel: channelSetting,
doneSetup: true, firstRun: "done",
armcordCSP: armcordCSPSetting, armcordCSP: armcordCSPSetting,
mods: modsSetting, mods: modsSetting,
}, },
@ -57,20 +55,15 @@ export function saveSettings(
); );
} }
export async function getConfigUnsafe(object: string) { export async function getConfigUnsafe(object: string) {
try { const userDataPath = app.getPath("userData");
const userDataPath = app.getPath("userData"); const storagePath = userDataPath + "/storage/";
const storagePath = path.join(userDataPath, "/storage/"); let rawdata = fs.readFileSync(storagePath + "settings.json", "utf-8");
let rawdata = fs.readFileSync(storagePath + "settings.json", "utf-8"); let returndata = JSON.parse(rawdata);
let returndata = JSON.parse(rawdata); console.log(returndata[object]);
console.log(returndata[object]); return returndata[object]
return returndata[object];
} catch (e) {
console.log("Config probably doesn't exist yet. Returning setup value.");
firstRun = true;
return "setup";
}
} }
export function getVersion() { export function getVersion() {
//to-do better way of doing this //to-do better way of doing this
return "3.1.0"; return '3.0.1';
} }

View file

@ -1,73 +0,0 @@
// To allow seamless switching between custom titlebar and native os titlebar,
// 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 } from "electron";
import path from "path";
import { contentPath } from "./main";
import { firstRun } from "./utils";
import { registerIpc } from "./ipc";
export let mainWindow: BrowserWindow;
function doAfterDefiningTheWindow() {
registerIpc();
mainWindow.webContents.userAgent =
"Mozilla/5.0 (X11; Linux x86) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"; //fake useragent for screenshare to work
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
shell.openExternal(url);
return { action: "deny" };
});
console.log(contentPath);
try {
mainWindow.loadFile(contentPath);
} catch (e) {
console.log(
"Major error detected while starting up. User is most likely on Windows platform. Fallback to alternative startup."
);
console.log(process.platform);
if (process.platform === "win32") {
if (firstRun) {
mainWindow.loadURL(`file://${__dirname}/content/setup.html`);
} else {
mainWindow.loadURL(`file://${__dirname}/content/splash.html`);
}
} else {
if (firstRun) {
mainWindow.loadURL(`file://${__dirname}/ts-out/content/setup.html`);
} else {
mainWindow.loadURL(`file://${__dirname}/ts-out/content/splash.html`);
}
}
}
}
export function createCustomWindow() {
mainWindow = new BrowserWindow({
width: 300,
height: 350,
title: "ArmCord",
darkTheme: true,
icon: path.join(__dirname, "/assets/icon_transparent.png"),
frame: false,
autoHideMenuBar: true,
webPreferences: {
preload: path.join(__dirname, "preload/preload.js"),
},
});
doAfterDefiningTheWindow();
}
export function createNativeWindow() {
mainWindow = new BrowserWindow({
width: 300,
height: 350,
title: "ArmCord",
darkTheme: true,
icon: path.join(__dirname, "/assets/icon_transparent.png"),
frame: true,
autoHideMenuBar: true,
webPreferences: {
preload: path.join(__dirname, "preload/preload.js"),
},
});
doAfterDefiningTheWindow();
}