Updated titlebar and a few other things

This commit is contained in:
KayoticCarnige 2022-05-22 07:52:26 -04:00
parent b31d9d8d4a
commit 12c195a2fa
17 changed files with 239 additions and 146 deletions

View File

@ -1,6 +1,6 @@
<div align="center">
<img src="https://armcord.vercel.app/armcord_full_logo.png" width="720">
<img src="https://armcord.vercel.app/armcord_full_logo.png" width="520">
<br>ArmCord is a custom client designed to enhance your Discord experience while keeping everything lightweight.
</div>
@ -72,7 +72,8 @@ ArmCord is also available on the Snap store [here](https://snapcraft.io/armcord)
[GooseMod Extension](https://github.com/GooseMod/extension)
[electron-discord-webapp](https://github.com/SpacingBat3/electron-discord-webapp)
[custom-electron-titlebar (css only)](https://github.com/AlexTorresSk/custom-electron-titlebar)
[electron-builder](https://electron.build)
[electron-builder](https://electron.build)
[OpenAsar (~~stole~~ borrowed code for adding items to the settings modal seemlessly)](https://github.com/GooseMod/OpenAsar)
# Sponsors
[![JetBrains supports ArmCord with free licenses to their software to core developers](https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg)](https://jb.gg/OpenSourceSupport)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 16 KiB

BIN
assets/ac_plug_colored.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -1,15 +1,43 @@
.info-3pQQBb:last-child:before {
content: "ArmCord Version: 3.1.0" !important;
height: auto;
line-height: 16px;
text-align: center;
color: var(--text-muted);
font-size: 12px;
text-transform: none;
}
.notice-2HEN-u {
display: none;
}
.sidebar-1tnWFu {
border-top-left-radius: 8px !important;
border-top-left-radius: 8px;
}
.scroller-3X7KbA {
padding: 0;
padding-top: 4px;
}
[class^="socialLinks-"] + [class^="info-"] {
padding-right: 0;
}
#ac-ver {
text-transform: none;
cursor: pointer;
color: var(--text-muted);
}
#ac-ver:hover {
text-decoration: underline;
color: var(--text-normal);
}
/* Server List Scrollbar - https://github.com/kckarnige/server-scroll */
.none-2-_0dP {
scrollbar-width: auto !important;
overflow-y: scroll !important;
overflow-x: hidden !important;
margin-right: 2px;
}
.none-2-_0dP:hover::-webkit-scrollbar {
width: 0.29em !important;
border-radius: 25px;
height: 0px !important;
background: transparent !important;
}
.none-2-_0dP::-webkit-scrollbar-thumb {
background: var(--background-accent);
border-radius: 25px;
}

File diff suppressed because one or more lines are too long

View File

@ -4,8 +4,10 @@
:root {
--background-primary: #282b30;
--background-secondary: rgba(255, 255, 255, 0.1);
--background-modifier-hover: rgba(106, 116, 128, 0.16);
--brand-experiment: #7289da;
--header-primary: #fff;
--interactive-normal: #b9bbbe;
--interactive-hover: #dcddde;
--text-muted: #72767d;
--font-primary: "Whitney";
}
@ -20,14 +22,11 @@
html,
body {
overflow: hidden;
margin: 0;
padding-top: 30px;
width: 100%;
height: 100%;
background: var(--background-primary);
display: flex;
flex-direction: column;
justify-content: center;
@ -97,21 +96,20 @@ body {
flex-direction: row;
justify-content: center;
align-items: center;
content: var(--logo-svg);
width: 292px;
}
#logo p:first-child {
color: #7289da;
margin: 0;
font-weight: normal;
font-family: Helvetica, sans-serif;
font-size: 32px;
.titlebar #window-controls-container #maximize {
display: none;
}
#logo p:last-child {
color: white;
margin: 0;
font-weight: normal;
font-family: Discordinated;
font-size: 32px;
.titlebar #window-controls-container #spacer {
float: left;
height: 100%;
width: 33%;
}
/* }}} */
/* Buttons {{{ */
@ -121,19 +119,16 @@ body {
justify-content: center;
align-items: center;
gap: 1rem;
user-select: all !important;
margin-top: 10px;
margin-bottom: 10px;
}
button {
background: var(--brand-experiment);
color: var(--header-primary);
outline: none;
border: none;
border-radius: 4px;
padding: 8px 20px;
}
button:hover {

View File

@ -112,3 +112,7 @@ video {
color: var(--text-muted);
white-space: pre;
}
img.logo {
width: 272px;
}

View File

@ -1,10 +1,3 @@
@import url("https://armcord.smartfridge.space/logofont.css");
:root {
--window-buttons: var(--header-secondary);
--cord-color: var(--header-primary);
--armcord-color: #7289da;
--titlebar-color: var(--background-tertiary);
}
.tabs {
display: block;
top: 0;

View File

@ -1,10 +1,3 @@
@import url("https://armcord.smartfridge.space/logofont.css");
:root {
--window-buttons: var(--header-secondary);
--cord-color: var(--header-primary);
--armcord-color: #7289da;
--titlebar-color: var(--background-tertiary);
}
.titlebar {
display: block;
top: 0;
@ -18,7 +11,6 @@
clear: both;
height: 30px;
line-height: 30px;
background-color: #202225;
-webkit-app-region: drag;
width: 100%;
user-select: none;
@ -26,12 +18,10 @@
position: fixed;
z-index: 99999;
}
.titlebar #window-title {
width: 30%;
height: 100%;
line-height: 30px;
float: left;
padding: 0 0 0 1em;
.container-2RRFHK {
padding-top: 30px;
top: -30px;
}
.titlebar #window-controls-container {
@ -39,7 +29,6 @@
width: 150px;
height: 100%;
line-height: 30px;
background-color: #202225;
-webkit-app-region: no-drag;
}
@ -48,61 +37,115 @@
.titlebar #window-controls-container #quit {
float: left;
height: 100%;
width: 33%;
width: 33.1%;
text-align: center;
color: #f7f7f7;
color: var(--interactive-normal);
cursor: default;
}
.titlebar #window-controls-container #spacer {
pointer-events: none;
}
.titlebar #window-controls-container #minimize:hover {
/* ArmCord on Linux */
[armcord-platform="linux"] .titlebar #window-controls-container #minimize:hover {
background-color: #99aab5;
}
.titlebar #window-controls-container #maximize:hover {
[armcord-platform="linux"] .titlebar #window-controls-container #maximize:hover {
background-color: #99aab5;
}
.titlebar #window-controls-container #quit:hover {
[armcord-platform="linux"] .titlebar #window-controls-container #quit:hover {
background-color: #f04747;
}
.titlebar #window-controls-container #quit {
background-color: #f7f7f7;
/* ArmCord on Windows */
[armcord-platform="win32"] .titlebar #window-controls-container #minimize:hover {
background-color: var(--background-modifier-hover);
transition: 0.2s ease;
}
[armcord-platform="win32"] .titlebar #window-controls-container #maximize:hover {
background-color: var(--background-modifier-hover);
transition: 0.2s ease;
}
[armcord-platform="win32"] .titlebar #window-controls-container #minimize:hover #minimize-icon {
background-color: var(--interactive-hover);
transition: 0.2s ease;
}
[armcord-platform="win32"] .titlebar #window-controls-container #maximize:hover #maximize-icon {
background-color: var(--interactive-hover);
transition: 0.2s ease;
}
[armcord-platform="win32"] .titlebar #window-controls-container #quit:hover {
background-color: #e81123;
transition: 0.2s ease;
}
[armcord-platform="win32"] .titlebar #window-controls-container #quit:hover #quit-icon {
background-color: #ffffff;
transition: 0.1s ease;
}
[armcord-platform="win32"] .titlebar #window-controls-container #minimize {
background-color: transparent;
transition: 0.1s ease;
}
[armcord-platform="win32"] .titlebar #window-controls-container #maximize {
background-color: transparent;
transition: 0.1s ease;
}
[armcord-platform="win32"] .titlebar #window-controls-container #quit {
background-color: transparent;
transition: 0.1s ease;
}
[armcord-platform="win32"] .titlebar #window-controls-container #quit:active {
background-color: #f1707a;
transition: 0.1s ease;
}
[armcord-platform="win32"] .titlebar #window-controls-container #quit:active #quit-icon {
background-color: #000000cc;
transition: 0.1s ease;
}
.titlebar #window-controls-container #quit-icon {
background-color: var(--interactive-normal);
display: list-item;
-webkit-mask: url("data:image/svg+xml;charset=utf-8,%3Csvg width='11' height='11' viewBox='0 0 11 11' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6.279 5.5L11 10.221l-.779.779L5.5 6.279.779 11 0 10.221 4.721 5.5 0 .779.779 0 5.5 4.721 10.221 0 11 .779 6.279 5.5z' fill='%23000'/%3E%3C/svg%3E")
no-repeat 50% 50%;
mask: url("data:image/svg+xml;charset=utf-8,%3Csvg width='11' height='11' viewBox='0 0 11 11' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6.279 5.5L11 10.221l-.779.779L5.5 6.279.779 11 0 10.221 4.721 5.5 0 .779.779 0 5.5 4.721 10.221 0 11 .779 6.279 5.5z' fill='%23000'/%3E%3C/svg%3E")
no-repeat 50% 50%;
}
.titlebar #window-controls-container #minimize {
background-color: #f7f7f7;
.titlebar #window-controls-container #minimize-icon {
background-color: var(--interactive-normal);
display: list-item;
-webkit-mask: url("data:image/svg+xml;charset=utf-8,%3Csvg width='11' height='11' viewBox='0 0 11 11' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11 4.399V5.5H0V4.399h11z' fill='%23000'/%3E%3C/svg%3E")
no-repeat 50% 50%;
mask: url("data:image/svg+xml;charset=utf-8,%3Csvg width='11' height='11' viewBox='0 0 11 11' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11 4.399V5.5H0V4.399h11z' fill='%23000'/%3E%3C/svg%3E")
no-repeat 50% 50%;
}
.titlebar #window-controls-container #maximize {
background-color: #f7f7f7;
.titlebar #window-controls-container #maximize-icon {
background-color: var(--interactive-normal);
display: list-item;
-webkit-mask: url("data:image/svg+xml;charset=utf-8,%3Csvg width='11' height='11' viewBox='0 0 11 11' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11 0v11H0V0h11zM9.899 1.101H1.1V9.9h8.8V1.1z' fill='%23000'/%3E%3C/svg%3E")
no-repeat 50% 50%;
mask: url("data:image/svg+xml;charset=utf-8,%3Csvg width='11' height='11' viewBox='0 0 11 11' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11 0v11H0V0h11zM9.899 1.101H1.1V9.9h8.8V1.1z' fill='%23000'/%3E%3C/svg%3E")
no-repeat 50% 50%;
}
.window-title:after {
content: "Cord";
color: var(--cord-color) !important;
font-weight: normal;
font-size: 14px;
font-family: Discordinated;
}
.window-title:before {
content: "ARM";
color: var(--armcord-color);
font-weight: normal;
font-size: 14px;
font-family: Helvetica, sans-serif;
[isMaximized] .titlebar #window-controls-container #maximize-icon {
background-color: var(--interactive-normal);
display: list-item;
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30' width='11' height='11'%3E%3Cstyle%3E%3C/style%3E%3Cpath fill-rule='evenodd' d='m6 0h24v24h-6v6h-24v-24h6zm3 6h15v15h3v-18h-18zm-6 21h18v-18h-18z'/%3E%3C/svg%3E")
no-repeat 50% 50%;
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30' width='11' height='11'%3E%3Cstyle%3E%3C/style%3E%3Cpath fill-rule='evenodd' d='m6 0h24v24h-6v6h-24v-24h6zm3 6h15v15h3v-18h-18zm-6 21h18v-18h-18z'/%3E%3C/svg%3E")
no-repeat 50% 50%;
}
.window-title {
font-size: 0px !important;
margin-left: initial !important;
transform: translate(10px, 0px);
content: var(--wordmark-svg);
height: 10px;
margin-left: initial;
transform: translate(9px, 9.5px);
float: left;
padding: 0;
}
.withFrame-haYltI {
height: 30px !important;
}

View File

@ -15,10 +15,7 @@
<p>You appear to be offline. Please connect to the internet and restart ArmCord Setup.</p>
</div>
<div id="setup">
<div id="logo" class="hidden">
<p>ARM</p>
<p>Cord</p>
</div>
<div id="logo" class="hidden"></div>
<div id="page1" class="hidden">
<p>Select the type of setup you want to perform.</p>
<div id="buttons">
@ -58,7 +55,7 @@
<option value="flicker">Flicker (Heavily WIP)</option>
</select>
</div>
<p>
<p class="text-center">
Why not all of them? Having many client mods at the same time can cause issues. If you really
want to do it though, check our documentation ;)
</p>
@ -70,6 +67,9 @@
</div>
<script>
document.onload = function () {
ipcRenderer.send("win-unmaximize");
};
// Accessors {{{
let options = {};

View File

@ -14,7 +14,7 @@ export var tabs: boolean;
if (process.platform == "linux") {
if (process.env.$XDG_SESSION_TYPE == "wayland") {
console.log("Wayland specific patches applied.")
console.log("Wayland specific patches applied.");
app.commandLine.appendSwitch("ozone-platform=wayland");
if (process.env.$XDG_CURRENT_DESKTOP == "GNOME") {
app.commandLine.appendSwitch("enable-features=UseOzonePlatform,WaylandWindowDecorations");

View File

@ -7,6 +7,8 @@ import {injectTitlebar} from "./titlebar";
import {sleep, addStyle, injectJS} from "../utils";
import {ipcRenderer} from "electron";
import {injectTabs} from "./tabs";
var version = ipcRenderer.sendSync("get-app-version", "app-version");
declare global {
interface Window {
armcord: any;
@ -48,3 +50,17 @@ if (window.location.href.indexOf("splash.html") > -1) {
}
});
}
// Settings info version injection (Stolen and modified from OpenAsar, mwuh ha ha ha ha >:D)
setInterval(() => {
const host = document.getElementsByClassName("info-3pQQBb")[0];
if (!host || document.querySelector("#ac-ver")) return;
const el = document.createElement("span");
el.id = "ac-ver";
el.classList.add("text-xs-normal-3SiVjE", "line-18uChy");
el.textContent = `\nArmCord Version: ${version}`;
el.onclick = () => ipcRenderer.send("openSettingsWindow");
host.append(el);
}, 2000);

View File

@ -2,15 +2,17 @@ import {ipcRenderer} from "electron";
import {addStyle} from "../utils";
import * as fs from "fs";
import * as path from "path";
import {platform} from "node:process";
export function injectTitlebar() {
document.addEventListener("DOMContentLoaded", function (event) {
var elem = document.createElement("div");
elem.innerHTML = `<nav class="titlebar">
<div class="window-title" id="window-title"></div>
<div id="window-controls-container">
<div id="minimize"></div>
<div id="maximize"></div>
<div id="quit"></div>
<div id="spacer"></div>
<div id="minimize"><div id="minimize-icon"></div></div>
<div id="maximize"><div id="maximize-icon"></div></div>
<div id="quit"><div id="quit-icon"></div></div>
</div>
</nav>`;
elem.classList.add("withFrame-haYltI");
@ -19,8 +21,11 @@ export function injectTitlebar() {
} else {
document.getElementById("app-mount")!.prepend(elem);
}
const cssPath = path.join(__dirname, "../", "/content/css/titlebar.css");
addStyle(fs.readFileSync(cssPath, "utf8"));
const titlebarcssPath = path.join(__dirname, "../", "/content/css/titlebar.css");
const wordmarkcssPath = path.join(__dirname, "../", "/content/css/logos.css");
addStyle(fs.readFileSync(titlebarcssPath, "utf8"));
addStyle(fs.readFileSync(wordmarkcssPath, "utf8"));
document.body.setAttribute("armcord-platform", platform);
var minimize = document.getElementById("minimize");
var maximize = document.getElementById("maximize");
@ -33,8 +38,10 @@ export function injectTitlebar() {
maximize!.addEventListener("click", () => {
if (ipcRenderer.sendSync("win-isMaximized") == true) {
ipcRenderer.send("win-unmaximize");
document.body.removeAttribute("isMaximized");
} else {
ipcRenderer.send("win-maximize");
document.body.setAttribute("isMaximized", "");
}
});

View File

@ -118,65 +118,68 @@ export default async function startServer() {
["Discord PTB", new URL("https://ptb.discord.com/app")],
["Fosscord", new URL("https://dev.fosscord.com/app")]
] as const;
let wss = null, wsPort = 6463;
for(const port of range(6463, 6472)) {
let wss = null,
wsPort = 6463;
for (const port of range(6463, 6472)) {
wss = await getServer(port);
if(wss !== null) {
void wsLog("ArmCord is listening at " + (port.toString()));
if (wss !== null) {
void wsLog("ArmCord is listening at " + port.toString());
wsPort = port;
break;
}
}
if(wss === null) return;
if (wss === null) return;
let lock = false;
wss.on('connection', (wss, request) => {
const origin = request.headers.origin??'https://discord.com';
wss.on("connection", (wss, request) => {
const origin = request.headers.origin ?? "https://discord.com";
let known = false;
for(const instance of knownInstancesList) {
if(instance[1].origin === origin)
known = true;
for (const instance of knownInstancesList) {
if (instance[1].origin === origin) known = true;
}
if(!known) return;
if (!known) return;
wss.send(JSON.stringify(messages.handShake));
wss.once('message', (data, isBinary) => {
if(lock) return;
wss.once("message", (data, isBinary) => {
if (lock) return;
lock = true;
let parsedData:unknown = data;
if(!isBinary)
parsedData = data.toString();
if(isJsonSyntaxCorrect(parsedData as string))
parsedData = JSON.parse(parsedData as string);
if(isInviteResponse(parsedData)) {
let parsedData: unknown = data;
if (!isBinary) parsedData = data.toString();
if (isJsonSyntaxCorrect(parsedData as string)) parsedData = JSON.parse(parsedData as string);
if (isInviteResponse(parsedData)) {
// Replies to browser, so it finds the communication successful.
wss.send(JSON.stringify({
cmd: parsedData.cmd,
data: {
invite: null,
code: parsedData.args.code
},
evt: null,
nonce: parsedData.nonce
}));
createInviteWindow()
wss.send(
JSON.stringify({
cmd: parsedData.cmd,
data: {
invite: null,
code: parsedData.args.code
},
evt: null,
nonce: parsedData.nonce
})
);
createInviteWindow();
const child = inviteWindow;
if(child === undefined) return;
void child.loadURL(origin+'/invite/'+parsedData.args.code);
if (child === undefined) return;
void child.loadURL(origin + "/invite/" + parsedData.args.code);
child.webContents.once("did-finish-load", () => {
child.show();
});
child.webContents.once("will-navigate", () => {
lock = false;
child.close();
})
});
child.on("close", (e) => {
lock = false;
})
});
// Blocks requests to ArmCord's WS, to prevent loops.
child.webContents.session.webRequest.onBeforeRequest({
urls: ['ws://127.0.0.1:'+wsPort.toString()+'/*']
}, (_details,callback) => callback({cancel: true}));
child.webContents.session.webRequest.onBeforeRequest(
{
urls: ["ws://127.0.0.1:" + wsPort.toString() + "/*"]
},
(_details, callback) => callback({cancel: true})
);
}
})
})
});
});
}

View File

@ -1,11 +1,11 @@
import { app, Menu, Tray } from "electron";
import { mainWindow } from "./window";
import { getConfig } from "./utils";
import {app, Menu, Tray} from "electron";
import {mainWindow} from "./window";
import {getConfig} from "./utils";
import * as path from "path";
import { createSettingsWindow } from "./settings/main";
import {createSettingsWindow} from "./settings/main";
let tray: any = null;
app.whenReady().then(async () => {
if (await getConfig("windowStyle") == "discord") {
if ((await getConfig("windowStyle")) == "discord") {
tray = new Tray(path.join(__dirname, "../", "/assets/dsc-tray.png"));
const contextMenu = Menu.buildFromTemplate([
{
@ -28,7 +28,7 @@ app.whenReady().then(async () => {
tray = new Tray(path.join(__dirname, "../", "/assets/ac_plug.png"));
const contextMenu = Menu.buildFromTemplate([
{
label: "ArmCord",
label: "ArmCord"
},
{
type: "separator"

View File

@ -139,7 +139,7 @@ export async function checkIfConfigExists() {
contentPath = path.join(__dirname, "/ts-out/content/setup.html");
}
} else {
if (await getConfig("doneSetup") == false) {
if ((await getConfig("doneSetup")) == false) {
console.log("First run of the ArmCord. Starting setup.");
setup();
isSetup = true;

View File

@ -6,7 +6,7 @@ import {BrowserWindow, shell, app, ipcMain, dialog, clipboard} from "electron";
import path from "path";
import {checkIfConfigIsBroken, firstRun, getConfig, contentPath, isSetup} from "./utils";
import {registerIpc} from "./ipc";
import startServer from "./socket"
import startServer from "./socket";
import contextMenu from "electron-context-menu";
import os from "os";
export var icon: string;
@ -23,8 +23,7 @@ contextMenu({
async function doAfterDefiningTheWindow() {
checkIfConfigIsBroken();
registerIpc();
mainWindow.webContents.userAgent =
`Mozilla/5.0 (X11; ${os.type()} ${os.arch()}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36`; //fake useragent for screenshare to work
mainWindow.webContents.userAgent = `Mozilla/5.0 (X11; ${os.type()} ${os.arch()}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36`; //fake useragent for screenshare to work
mainWindow.webContents.setWindowOpenHandler(({url}) => {
shell.openExternal(url);
return {action: "deny"};
@ -43,10 +42,10 @@ async function doAfterDefiningTheWindow() {
}
});
console.log(contentPath);
if (await getConfig("inviteWebsocket") == true) {
startServer()
if ((await getConfig("inviteWebsocket")) == true) {
startServer();
}
try {
mainWindow.loadFile(contentPath);
if (isSetup) {
@ -191,5 +190,5 @@ export function createInviteWindow() {
spellcheck: true
}
});
inviteWindow.hide()
}
inviteWindow.hide();
}