mirror of
https://github.com/smartfrigde/armcord.git
synced 2024-08-14 23:56:58 +00:00
Initial source code upload
This commit is contained in:
parent
3fd237446f
commit
101bc63651
41 changed files with 1117 additions and 6272 deletions
2
.gitattributes
vendored
2
.gitattributes
vendored
|
@ -1,2 +0,0 @@
|
||||||
# Auto detect text files and perform LF normalization
|
|
||||||
* text=auto
|
|
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -1,3 +0,0 @@
|
||||||
[submodule "mods/goosemod"]
|
|
||||||
path = mods/goosemod
|
|
||||||
url = https://github.com/GooseMod/Extension
|
|
172
LICENSE
172
LICENSE
|
@ -1,172 +0,0 @@
|
||||||
Open Software License ("OSL") v. 3.0
|
|
||||||
|
|
||||||
This Open Software License (the "License") applies to any original work of
|
|
||||||
authorship (the "Original Work") whose owner (the "Licensor") has placed the
|
|
||||||
following licensing notice adjacent to the copyright notice for the Original
|
|
||||||
Work:
|
|
||||||
|
|
||||||
Licensed under the Open Software License version 3.0
|
|
||||||
|
|
||||||
1) Grant of Copyright License. Licensor grants You a worldwide, royalty-free,
|
|
||||||
non-exclusive, sublicensable license, for the duration of the copyright, to do
|
|
||||||
the following:
|
|
||||||
|
|
||||||
a) to reproduce the Original Work in copies, either alone or as part of a
|
|
||||||
collective work;
|
|
||||||
|
|
||||||
b) to translate, adapt, alter, transform, modify, or arrange the Original
|
|
||||||
Work, thereby creating derivative works ("Derivative Works") based upon the
|
|
||||||
Original Work;
|
|
||||||
|
|
||||||
c) to distribute or communicate copies of the Original Work and Derivative
|
|
||||||
Works to the public, with the proviso that copies of Original Work or
|
|
||||||
Derivative Works that You distribute or communicate shall be licensed under
|
|
||||||
this Open Software License;
|
|
||||||
|
|
||||||
d) to perform the Original Work publicly; and
|
|
||||||
|
|
||||||
e) to display the Original Work publicly.
|
|
||||||
|
|
||||||
2) Grant of Patent License. Licensor grants You a worldwide, royalty-free,
|
|
||||||
non-exclusive, sublicensable license, under patent claims owned or controlled
|
|
||||||
by the Licensor that are embodied in the Original Work as furnished by the
|
|
||||||
Licensor, for the duration of the patents, to make, use, sell, offer for sale,
|
|
||||||
have made, and import the Original Work and Derivative Works.
|
|
||||||
|
|
||||||
3) Grant of Source Code License. The term "Source Code" means the preferred
|
|
||||||
form of the Original Work for making modifications to it and all available
|
|
||||||
documentation describing how to modify the Original Work. Licensor agrees to
|
|
||||||
provide a machine-readable copy of the Source Code of the Original Work along
|
|
||||||
with each copy of the Original Work that Licensor distributes. Licensor
|
|
||||||
reserves the right to satisfy this obligation by placing a machine-readable
|
|
||||||
copy of the Source Code in an information repository reasonably calculated to
|
|
||||||
permit inexpensive and convenient access by You for as long as Licensor
|
|
||||||
continues to distribute the Original Work.
|
|
||||||
|
|
||||||
4) Exclusions From License Grant. Neither the names of Licensor, nor the names
|
|
||||||
of any contributors to the Original Work, nor any of their trademarks or
|
|
||||||
service marks, may be used to endorse or promote products derived from this
|
|
||||||
Original Work without express prior permission of the Licensor. Except as
|
|
||||||
expressly stated herein, nothing in this License grants any license to
|
|
||||||
Licensor's trademarks, copyrights, patents, trade secrets or any other
|
|
||||||
intellectual property. No patent license is granted to make, use, sell, offer
|
|
||||||
for sale, have made, or import embodiments of any patent claims other than the
|
|
||||||
licensed claims defined in Section 2. No license is granted to the trademarks
|
|
||||||
of Licensor even if such marks are included in the Original Work. Nothing in
|
|
||||||
this License shall be interpreted to prohibit Licensor from licensing under
|
|
||||||
terms different from this License any Original Work that Licensor otherwise
|
|
||||||
would have a right to license.
|
|
||||||
|
|
||||||
5) External Deployment. The term "External Deployment" means the use,
|
|
||||||
distribution, or communication of the Original Work or Derivative Works in any
|
|
||||||
way such that the Original Work or Derivative Works may be used by anyone
|
|
||||||
other than You, whether those works are distributed or communicated to those
|
|
||||||
persons or made available as an application intended for use over a network.
|
|
||||||
As an express condition for the grants of license hereunder, You must treat
|
|
||||||
any External Deployment by You of the Original Work or a Derivative Work as a
|
|
||||||
distribution under section 1(c).
|
|
||||||
|
|
||||||
6) Attribution Rights. You must retain, in the Source Code of any Derivative
|
|
||||||
Works that You create, all copyright, patent, or trademark notices from the
|
|
||||||
Source Code of the Original Work, as well as any notices of licensing and any
|
|
||||||
descriptive text identified therein as an "Attribution Notice." You must cause
|
|
||||||
the Source Code for any Derivative Works that You create to carry a prominent
|
|
||||||
Attribution Notice reasonably calculated to inform recipients that You have
|
|
||||||
modified the Original Work.
|
|
||||||
|
|
||||||
7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that
|
|
||||||
the copyright in and to the Original Work and the patent rights granted herein
|
|
||||||
by Licensor are owned by the Licensor or are sublicensed to You under the
|
|
||||||
terms of this License with the permission of the contributor(s) of those
|
|
||||||
copyrights and patent rights. Except as expressly stated in the immediately
|
|
||||||
preceding sentence, the Original Work is provided under this License on an "AS
|
|
||||||
IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without
|
|
||||||
limitation, the warranties of non-infringement, merchantability or fitness for
|
|
||||||
a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK
|
|
||||||
IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this
|
|
||||||
License. No license to the Original Work is granted by this License except
|
|
||||||
under this disclaimer.
|
|
||||||
|
|
||||||
8) Limitation of Liability. Under no circumstances and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise, shall the
|
|
||||||
Licensor be liable to anyone for any indirect, special, incidental, or
|
|
||||||
consequential damages of any character arising as a result of this License or
|
|
||||||
the use of the Original Work including, without limitation, damages for loss
|
|
||||||
of goodwill, work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses. This limitation of liability shall not
|
|
||||||
apply to the extent applicable law prohibits such limitation.
|
|
||||||
|
|
||||||
9) Acceptance and Termination. If, at any time, You expressly assented to this
|
|
||||||
License, that assent indicates your clear and irrevocable acceptance of this
|
|
||||||
License and all of its terms and conditions. If You distribute or communicate
|
|
||||||
copies of the Original Work or a Derivative Work, You must make a reasonable
|
|
||||||
effort under the circumstances to obtain the express assent of recipients to
|
|
||||||
the terms of this License. This License conditions your rights to undertake
|
|
||||||
the activities listed in Section 1, including your right to create Derivative
|
|
||||||
Works based upon the Original Work, and doing so without honoring these terms
|
|
||||||
and conditions is prohibited by copyright law and international treaty.
|
|
||||||
Nothing in this License is intended to affect copyright exceptions and
|
|
||||||
limitations (including "fair use" or "fair dealing"). This License shall
|
|
||||||
terminate immediately and You may no longer exercise any of the rights granted
|
|
||||||
to You by this License upon your failure to honor the conditions in Section
|
|
||||||
1(c).
|
|
||||||
|
|
||||||
10) Termination for Patent Action. This License shall terminate automatically
|
|
||||||
and You may no longer exercise any of the rights granted to You by this
|
|
||||||
License as of the date You commence an action, including a cross-claim or
|
|
||||||
counterclaim, against Licensor or any licensee alleging that the Original Work
|
|
||||||
infringes a patent. This termination provision shall not apply for an action
|
|
||||||
alleging patent infringement by combinations of the Original Work with other
|
|
||||||
software or hardware.
|
|
||||||
|
|
||||||
11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this
|
|
||||||
License may be brought only in the courts of a jurisdiction wherein the
|
|
||||||
Licensor resides or in which Licensor conducts its primary business, and under
|
|
||||||
the laws of that jurisdiction excluding its conflict-of-law provisions. The
|
|
||||||
application of the United Nations Convention on Contracts for the
|
|
||||||
International Sale of Goods is expressly excluded. Any use of the Original
|
|
||||||
Work outside the scope of this License or after its termination shall be
|
|
||||||
subject to the requirements and penalties of copyright or patent law in the
|
|
||||||
appropriate jurisdiction. This section shall survive the termination of this
|
|
||||||
License.
|
|
||||||
|
|
||||||
12) Attorneys' Fees. In any action to enforce the terms of this License or
|
|
||||||
seeking damages relating thereto, the prevailing party shall be entitled to
|
|
||||||
recover its costs and expenses, including, without limitation, reasonable
|
|
||||||
attorneys' fees and costs incurred in connection with such action, including
|
|
||||||
any appeal of such action. This section shall survive the termination of this
|
|
||||||
License.
|
|
||||||
|
|
||||||
13) Miscellaneous. If any provision of this License is held to be
|
|
||||||
unenforceable, such provision shall be reformed only to the extent necessary
|
|
||||||
to make it enforceable.
|
|
||||||
|
|
||||||
14) Definition of "You" in This License. "You" throughout this License,
|
|
||||||
whether in upper or lower case, means an individual or a legal entity
|
|
||||||
exercising rights under, and complying with all of the terms of, this License.
|
|
||||||
For legal entities, "You" includes any entity that controls, is controlled by,
|
|
||||||
or is under common control with you. For purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the direction or
|
|
||||||
management of such entity, whether by contract or otherwise, or (ii) ownership
|
|
||||||
of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial
|
|
||||||
ownership of such entity.
|
|
||||||
|
|
||||||
15) Right to Use. You may use the Original Work in all ways not otherwise
|
|
||||||
restricted or conditioned by this License or by law, and Licensor promises not
|
|
||||||
to interfere with or be responsible for such uses by You.
|
|
||||||
|
|
||||||
16) Modification of This License. This License is Copyright © 2005 Lawrence
|
|
||||||
Rosen. Permission is granted to copy, distribute, or communicate this License
|
|
||||||
without modification. Nothing in this License permits You to modify this
|
|
||||||
License as applied to the Original Work or to Derivative Works. However, You
|
|
||||||
may modify the text of this License and copy, distribute or communicate your
|
|
||||||
modified version (the "Modified License") and apply it to other original works
|
|
||||||
of authorship subject to the following conditions: (i) You may not indicate in
|
|
||||||
any way that your Modified License is the "Open Software License" or "OSL" and
|
|
||||||
you may not use those names in the name of your Modified License; (ii) You
|
|
||||||
must replace the notice specified in the first paragraph above with the notice
|
|
||||||
"Licensed under <insert your license name here>" or with a notice of your own
|
|
||||||
that is not confusingly similar to the notice in this License; and (iii) You
|
|
||||||
may not claim that your original works are open source software unless your
|
|
||||||
Modified License has been approved by Open Source Initiative (OSI) and You
|
|
||||||
comply with its license review and certification process.
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
### THIS IS EXPERIMENTAL REWRITE CODE
|
||||||
|
<h1 align="center">
|
||||||
|
<img src="https://armcord.vercel.app/armcord_full_logo.png" width="720">
|
||||||
|
</h1>
|
||||||
|
|
||||||
# ![Arm with a Cord](https://raw.githubusercontent.com/kckarnige/armcord/main/arm-with-a-cord.svg)
|
|
||||||
ArmCord is a custom alternative Discord client made for people on lower-end devices and ARM architecture that want custom Discord experience. It uses [Cumcord](https://cumcord.com) for custom themes and plugins!
|
ArmCord is a custom alternative Discord client made for people on lower-end devices and ARM architecture that want custom Discord experience. It uses [Cumcord](https://cumcord.com) for custom themes and plugins!
|
||||||
|
|
||||||
# How to run/install it?
|
# How to run/install it?
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 81 KiB |
BIN
ac_plug.ico
BIN
ac_plug.ico
Binary file not shown.
Before Width: | Height: | Size: 107 KiB |
BIN
ac_plug.png
BIN
ac_plug.png
Binary file not shown.
Before Width: | Height: | Size: 38 KiB |
2
build.sh
2
build.sh
|
@ -1,2 +0,0 @@
|
||||||
npm run package
|
|
||||||
./dist/linux-unpacked/armcord
|
|
BIN
build/icon.ico
BIN
build/icon.ico
Binary file not shown.
Before Width: | Height: | Size: 107 KiB |
BIN
build/icon.png
BIN
build/icon.png
Binary file not shown.
Before Width: | Height: | Size: 38 KiB |
108
index.html
108
index.html
|
@ -1,108 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8"/>
|
|
||||||
<title>ArmCord</title>
|
|
||||||
<script>
|
|
||||||
window.onload = setTimeout(function() {
|
|
||||||
if (document.getElementById("ac-channel").innerHTML == "stable") {
|
|
||||||
window.location.href = "https://discord.com/app";
|
|
||||||
} else if (document.getElementById("ac-channel").innerHTML == "canary") {
|
|
||||||
window.location.href = "https://canary.discord.com/app";
|
|
||||||
} else if (document.getElementById("ac-channel").innerHTML == "ptb") {
|
|
||||||
window.location.href = "https://ptb.discord.com/app";
|
|
||||||
} else if (document.getElementById("ac-channel").innerHTML == "foss") {
|
|
||||||
window.location.href = "https://dev.fosscord.com/app";
|
|
||||||
} else {
|
|
||||||
window.location.href = "https://discord.com/app";
|
|
||||||
};
|
|
||||||
}, 3000);
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
@import url("https://kckarnige.github.io/femboi_owo/discord-font.css");
|
|
||||||
|
|
||||||
:root {
|
|
||||||
background-color: #2c2f33;
|
|
||||||
--header-secondary: #b9bbbe;
|
|
||||||
--header-primary: #fff;
|
|
||||||
--background-tertiary: #202225;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
color: #8e9297;
|
|
||||||
text-align: center;
|
|
||||||
font-weight: 100;
|
|
||||||
transform: translateY(-185%);
|
|
||||||
font-family: Whitney,Helvetica Neue,Helvetica,Arial,sans-serif;
|
|
||||||
text-rendering: optimizeLegibility;
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 0px;
|
|
||||||
text-align: center;
|
|
||||||
transform: translateY(-105%);
|
|
||||||
}
|
|
||||||
|
|
||||||
h1:before {
|
|
||||||
content: "ARM";
|
|
||||||
color: #7289da;
|
|
||||||
font-weight: normal;
|
|
||||||
font-family: Helvetica, sans-serif;
|
|
||||||
font-size: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1:after {
|
|
||||||
content: "Cord";
|
|
||||||
color: #ffffff;
|
|
||||||
font-weight: normal;
|
|
||||||
font-family: Discordinated;
|
|
||||||
font-size: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
span {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
display: block;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
max-height: 204px;
|
|
||||||
max-width: 204px;
|
|
||||||
transform: translateY(5%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
position: fixed;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
color: #fff;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ac-channel {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
<video autoplay loop class="logo">
|
|
||||||
<source src="https://discord.com/assets/3b0d96ed8113994f3d139088726cfecd.webm" type="video/webm">
|
|
||||||
</video>
|
|
||||||
<p>Loading...</p>
|
|
||||||
<h1></h1>
|
|
||||||
<p id="ac-channel"></p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
141
main.js
141
main.js
|
@ -1,141 +0,0 @@
|
||||||
// Modules to control application life and create native browser window
|
|
||||||
const { app, BrowserWindow, session, Tray, Menu } = require("electron");
|
|
||||||
const path = require("path");
|
|
||||||
const contextMenu = require("electron-context-menu");
|
|
||||||
const os = require("os");
|
|
||||||
require("v8-compile-cache");
|
|
||||||
require("./utils/updater.js")
|
|
||||||
if (require("./utils/ArmCord.js").Titlebar === "native") {
|
|
||||||
var frame = true
|
|
||||||
} else {
|
|
||||||
var frame = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (os.type() == 'Linux'){
|
|
||||||
var iconformat = __dirname + "/ac_icon_transparent.png"
|
|
||||||
} else {
|
|
||||||
console.log("Running Non-Linux")
|
|
||||||
var iconformat = __dirname + "/ac_plug.ico";
|
|
||||||
}
|
|
||||||
|
|
||||||
contextMenu({
|
|
||||||
prepend: (defaultActions, parameters, browserWindow) => [
|
|
||||||
{
|
|
||||||
label: "Image",
|
|
||||||
// Only show it when right-clicking images
|
|
||||||
visible: parameters.mediaType === "image",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
contextMenu.showSearchWithGoogle = false;
|
|
||||||
|
|
||||||
let mainWindow;
|
|
||||||
function createWindow() {
|
|
||||||
mainWindow = new BrowserWindow({
|
|
||||||
width: 800,
|
|
||||||
height: 600,
|
|
||||||
icon: iconformat,
|
|
||||||
title: "ArmCord",
|
|
||||||
frame: frame,
|
|
||||||
webPreferences: {
|
|
||||||
preload: path.join(__dirname, "preload.js"),
|
|
||||||
enableRemoteModule: true,
|
|
||||||
nodeIntegration: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
var appIcon = new Tray(iconformat);
|
|
||||||
mainWindow.webContents.userAgent =
|
|
||||||
"Mozilla/5.0 (X12; Linux x86) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"; //fake useragent
|
|
||||||
mainWindow.loadFile("index.html");
|
|
||||||
mainWindow.focus();
|
|
||||||
mainWindow.webContents.on("new-window", function (e, url) {
|
|
||||||
e.preventDefault();
|
|
||||||
require("electron").shell.openExternal(url);
|
|
||||||
});
|
|
||||||
// Open the DevTools.
|
|
||||||
// mainWindow.webContents.openDevTools()
|
|
||||||
var contextMenu = Menu.buildFromTemplate([
|
|
||||||
{
|
|
||||||
label: "Show App",
|
|
||||||
click: function () {
|
|
||||||
mainWindow.show();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Support Discord Server",
|
|
||||||
click: function () {
|
|
||||||
mainWindow.show();
|
|
||||||
mainWindow.loadURL("https://discord.gg/F25bc4RYDt");
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Quit",
|
|
||||||
click: function () {
|
|
||||||
mainWindow.destroy();
|
|
||||||
app.isQuiting = true;
|
|
||||||
app.quit();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
appIcon.on("click", () => {
|
|
||||||
mainWindow.show()
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
appIcon.setContextMenu(contextMenu);
|
|
||||||
|
|
||||||
// Emitted when the window is closed.
|
|
||||||
mainWindow.on("close", function (event) {
|
|
||||||
event.preventDefault();
|
|
||||||
mainWindow.hide();
|
|
||||||
});
|
|
||||||
|
|
||||||
mainWindow.on("show", function () {
|
|
||||||
//temporary fix
|
|
||||||
try {
|
|
||||||
appIcon();
|
|
||||||
} catch (error) {
|
|
||||||
//console.error(error);
|
|
||||||
// expected output: TypeError: appIcon is not a function
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// This method will be called when Electron has finished
|
|
||||||
// initialization and is ready to create browser windows.
|
|
||||||
// Some APIs can only be used after this event occurs.
|
|
||||||
app.whenReady().then(() => {
|
|
||||||
createWindow();
|
|
||||||
require("./utils/mod.js");
|
|
||||||
require("./utils/plugin.js");
|
|
||||||
session
|
|
||||||
.fromPartition("some-partition")
|
|
||||||
.setPermissionRequestHandler((webContents, permission, callback) => {
|
|
||||||
const url = webContents.getURL(); //unused?
|
|
||||||
|
|
||||||
if (permission === "notifications") {
|
|
||||||
// Approves the permissions request
|
|
||||||
callback(true);
|
|
||||||
}
|
|
||||||
if (permission === "microphone") {
|
|
||||||
// Approves the permissions request
|
|
||||||
callback(true);
|
|
||||||
}
|
|
||||||
if (!url.startsWith("discord://")) {
|
|
||||||
// Denies the permissions request
|
|
||||||
return callback(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
app.on("activate", function () {
|
|
||||||
// On macOS it's common to re-create a window in the app when the
|
|
||||||
// dock icon is clicked and there are no other windows open.
|
|
||||||
if (BrowserWindow.getAllWindows().length === 0) createWindow();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Quit when all windows are closed, except on macOS. There, it's common
|
|
||||||
// for applications and their menu bar to stay active until the user quits
|
|
||||||
// explicitly with Cmd + Q.
|
|
||||||
app.on("window-all-closed", function () {
|
|
||||||
if (process.platform !== "darwin") app.quit();
|
|
||||||
});
|
|
161
manager.css
161
manager.css
|
@ -1,161 +0,0 @@
|
||||||
@import url("https://kckarnige.github.io/femboi_owo/discord-font.css");
|
|
||||||
|
|
||||||
:root {
|
|
||||||
background-color: #2f3136;
|
|
||||||
user-select: none;
|
|
||||||
--header-secondary: #b9bbbe;
|
|
||||||
--header-primary: #fff;
|
|
||||||
--background-tertiary: #202225;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 0;
|
|
||||||
text-align: center;
|
|
||||||
transform: translateY(-105%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo:before {
|
|
||||||
content: "ARM";
|
|
||||||
color: #7289da;
|
|
||||||
font-weight: normal;
|
|
||||||
font-family: Helvetica, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
span {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
color: #ffffff;
|
|
||||||
font-weight: normal;
|
|
||||||
font-family: Discordinated;
|
|
||||||
font-size: 32px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.disabled {
|
|
||||||
text-align: center;
|
|
||||||
font-weight: normal;
|
|
||||||
font-family: Helvetica, sans-serif;
|
|
||||||
}
|
|
||||||
.container {
|
|
||||||
position: fixed;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
color: #fff;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
button.back-btn {
|
|
||||||
position: absolute;
|
|
||||||
background-color: #7289da;
|
|
||||||
font-family: Whitney, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
||||||
color: #ffffff;
|
|
||||||
padding: 4px;
|
|
||||||
border-radius: 5px;
|
|
||||||
width: 105px;
|
|
||||||
height: 25px;
|
|
||||||
margin-top: 5px;
|
|
||||||
margin-left: 5px;
|
|
||||||
left: 0;
|
|
||||||
text-align: center;
|
|
||||||
border-style: none;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
button.back-btn:hover {
|
|
||||||
background-color: #687dc6;
|
|
||||||
border-style: none;
|
|
||||||
outline: none;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
button.back-btn:active {
|
|
||||||
background-color: #5c6fb1;
|
|
||||||
}
|
|
||||||
|
|
||||||
button#open-themes-btn {
|
|
||||||
position: absolute;
|
|
||||||
background-color: #7289da;
|
|
||||||
font-family: Whitney, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
||||||
color: #ffffff;
|
|
||||||
padding: 4px;
|
|
||||||
border-radius: 5px;
|
|
||||||
width: 105px;
|
|
||||||
height: 25px;
|
|
||||||
margin-top: 5px;
|
|
||||||
margin-right: 5px;
|
|
||||||
right: 0;
|
|
||||||
text-align: center;
|
|
||||||
border-style: none;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
button#open-themes-btn:hover {
|
|
||||||
background-color: #687dc6;
|
|
||||||
border-style: none;
|
|
||||||
outline: none;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
button#open-themes-btn:active {
|
|
||||||
background-color: #5c6fb1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tm-list {
|
|
||||||
position: absolute;
|
|
||||||
top: 100px;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
#tm-disabled {
|
|
||||||
position: absolute;
|
|
||||||
top: 100px;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
#tm-list-item {
|
|
||||||
background: #23272a;
|
|
||||||
font-family: Whitney, Helvetica Neue, Helvetica, Arial, sans-serif;
|
|
||||||
width: 100%;
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 10px 10px 18px;
|
|
||||||
width: 420px;
|
|
||||||
max-width: 820px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#theme-name {
|
|
||||||
color: #7289da;
|
|
||||||
font-weight: 400;
|
|
||||||
font-size: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#theme-author {
|
|
||||||
color: #99aab5;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#theme-description {
|
|
||||||
color: #b9bbbe;
|
|
||||||
font-size: 15px;
|
|
||||||
position: relative;
|
|
||||||
top: 8px;
|
|
||||||
width: 75%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ac-channel {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
|
||||||
width: 0.4em;
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
|
||||||
background: #202225;
|
|
||||||
border-radius: 25px;
|
|
||||||
}
|
|
18
manager.html
18
manager.html
|
@ -1,18 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title>ArmCord Manager</title>
|
|
||||||
<link rel="stylesheet" href="manager.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<button class="back-btn">Back to Discord</button>
|
|
||||||
<button id="open-themes-btn">Themes Folder</button>
|
|
||||||
<p class="logo">Cord Manager</p>
|
|
||||||
<div id="tm-list"></div>
|
|
||||||
<p class="disabled">Disabled Themes:</p>
|
|
||||||
<div id="tm-disabled"></div>
|
|
||||||
<p id="ac-channel"></p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,42 +0,0 @@
|
||||||
const cspAllowAll = [
|
|
||||||
'connect-src',
|
|
||||||
'style-src',
|
|
||||||
'img-src',
|
|
||||||
'font-src'
|
|
||||||
];
|
|
||||||
const corsAllowUrls = [
|
|
||||||
'https://github.com/GooseMod/GooseMod/releases/download/dev/index.js',
|
|
||||||
'https://github-releases.githubusercontent.com/',
|
|
||||||
'https://api.goosemod.com/inject.js',
|
|
||||||
'https://raw.githubusercontent.com/Cumcord/Cumcord/stable/dist/build.js'
|
|
||||||
];
|
|
||||||
|
|
||||||
chrome.webRequest.onHeadersReceived.addListener(({ responseHeaders, url }) => {
|
|
||||||
let csp = responseHeaders.find((x) => x.name === 'content-security-policy');
|
|
||||||
|
|
||||||
if (csp) {
|
|
||||||
for (let p of cspAllowAll) {
|
|
||||||
csp.value = csp.value.replace(`${p}`, `${p} * blob: data:`); // * does not include data: URIs
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix Discord's broken CSP which disallows unsafe-inline due to having a nonce (which they don't even use?)
|
|
||||||
csp.value = csp.value.replace(/'nonce-.*?' /, '');
|
|
||||||
}
|
|
||||||
if (corsAllowUrls.some((x) => url.startsWith(x))) {
|
|
||||||
let cors = responseHeaders.find((x) => x.name === 'access-control-allow-origin');
|
|
||||||
cors.value = '*';
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
responseHeaders
|
|
||||||
};
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
urls: [
|
|
||||||
'*://*.discord.com/*'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
['blocking', 'responseHeaders']
|
|
||||||
);
|
|
|
@ -1,9 +0,0 @@
|
||||||
const load = async () => {
|
|
||||||
console.log("[CCExt] Loading Cumcord...");
|
|
||||||
const response = await fetch("https://raw.githubusercontent.com/Cumcord/Cumcord/stable/dist/build.js");
|
|
||||||
const text = await response.text()
|
|
||||||
eval(text);
|
|
||||||
}
|
|
||||||
const el = document.createElement('script');
|
|
||||||
el.appendChild(document.createTextNode(`(${load.toString()})();`));
|
|
||||||
document.body.appendChild(el);
|
|
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"name": "Cumcord for Web",
|
|
||||||
"description": "A heavy, throbbing, and easy to use cum expeller; now in your browser.",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"author": "Drake",
|
|
||||||
"background": {
|
|
||||||
"scripts": [
|
|
||||||
"background.js"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
"content_scripts": [
|
|
||||||
{
|
|
||||||
"matches": ["*://*.discord.com/*"],
|
|
||||||
"js": ["content.js"]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"permissions": [
|
|
||||||
"storage",
|
|
||||||
"webRequest",
|
|
||||||
"webRequestBlocking",
|
|
||||||
"*://*.discord.com/*"
|
|
||||||
],
|
|
||||||
"manifest_version": 2
|
|
||||||
}
|
|
5560
package-lock.json
generated
5560
package-lock.json
generated
File diff suppressed because it is too large
Load diff
85
package.json
85
package.json
|
@ -1,71 +1,32 @@
|
||||||
{
|
{
|
||||||
"name": "ArmCord",
|
"name": "armcord",
|
||||||
"version": "2.7.0",
|
"version": "3.0.0",
|
||||||
"description": "ArmCord is a Discord client made for ARM Linux that allows you to customize your experience.",
|
"description": "ArmCord is a custom client designed to enhance your Discord experience while keeping everything lightweight.",
|
||||||
"main": "main.js",
|
"main": "src/index.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "./build.sh",
|
"build": "tsc",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"watch": "tsc -w",
|
||||||
"package": "electron-builder --dir",
|
"start": "npm run build && npm run copy-files && electron ./dist/main.js",
|
||||||
"make": "electron-builder",
|
"copy-files": "copyfiles -u 1 src/**/*.html src/**/*.css dist/ && copyfiles package.json dist/"
|
||||||
"linux-build": "electron-builder --linux deb tar.gz rpm AppImage",
|
|
||||||
"windows-build": "electron-builder --windows nsis portable zip"
|
|
||||||
},
|
|
||||||
"author": "smartfrigde <smartfridge1337@protonmail.com>",
|
|
||||||
"license": "OSL-3.0",
|
|
||||||
"dependencies": {
|
|
||||||
"electron-context-menu": "^3.0.0",
|
|
||||||
"electron-dl": "^3.2.1",
|
|
||||||
"electron-localshortcut": "^3.2.1",
|
|
||||||
"electron-store": "^8.0.0",
|
|
||||||
"electron-updater": "^4.3.9",
|
|
||||||
"unzipper": "^0.10.1",
|
|
||||||
"v8-compile-cache": "^2.3.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"electron": "^13.3.0",
|
|
||||||
"electron-builder": "^22.11.7"
|
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/smartfrigde/armcord.git"
|
"url": "git+https://github.com/armcord/armcord.git"
|
||||||
},
|
|
||||||
"keywords": [
|
|
||||||
"arm",
|
|
||||||
"discord",
|
|
||||||
"electron"
|
|
||||||
],
|
|
||||||
"build": {
|
|
||||||
"appId": "com.smartfridge.armcord",
|
|
||||||
"productName": "ArmCord",
|
|
||||||
"mac": {
|
|
||||||
"category": "Network",
|
|
||||||
"extraResources": [
|
|
||||||
"./mods/cumcord/*"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"win": {
|
|
||||||
"extraResources": [
|
|
||||||
"./mods/cumcord/*"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"linux": {
|
|
||||||
"category": "Network",
|
|
||||||
"extraResources": [
|
|
||||||
"./mods/cumcord/*"
|
|
||||||
],
|
|
||||||
"maintainer": "smartfridge1337@protonmail.com",
|
|
||||||
"target": [
|
|
||||||
"deb",
|
|
||||||
"tar.gz",
|
|
||||||
"rpm",
|
|
||||||
"AppImage"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
"author": "smartfrigde",
|
||||||
|
"license": "OSL-3.0",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/smartfrigde/armcord/issues",
|
"url": "https://github.com/armcord/armcord/issues"
|
||||||
"email": "smartfridge1337@protonmail.com"
|
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/smartfrigde/armcord#readme"
|
"homepage": "https://github.com/armcord/armcord#readme",
|
||||||
|
"devDependencies": {
|
||||||
|
"electron": "^16.0.5"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/electron-json-storage": "^4.5.0",
|
||||||
|
"@types/node": "^14.18.2",
|
||||||
|
"copyfiles": "^2.4.1",
|
||||||
|
"electron-json-storage": "^4.5.0",
|
||||||
|
"typescript": "^4.5.4"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
97
preload.js
97
preload.js
|
@ -1,97 +0,0 @@
|
||||||
const { remote } = require("electron");
|
|
||||||
const currentWindow = remote.getCurrentWindow();
|
|
||||||
const ArmCord = require("./utils/ArmCord.js");
|
|
||||||
const electronLocalshortcut = require("electron-localshortcut");
|
|
||||||
require("./utils/theme.js");
|
|
||||||
require("./utils/bridge.js")
|
|
||||||
require('./utils/titlebar')
|
|
||||||
window.addEventListener("DOMContentLoaded", () => {
|
|
||||||
if (require("./utils/ArmCord.js").Titlebar == "native") {console.log("Using native titlebar")} else {
|
|
||||||
//todo
|
|
||||||
}
|
|
||||||
|
|
||||||
electronLocalshortcut.register(currentWindow, "F5", () => {
|
|
||||||
location.reload();
|
|
||||||
});
|
|
||||||
electronLocalshortcut.register(currentWindow, "F12", () => {
|
|
||||||
currentWindow.webContents.openDevTools();
|
|
||||||
});
|
|
||||||
electronLocalshortcut.register(currentWindow, "F1", () => {
|
|
||||||
require("shell").openExternal("https://support.discord.com/");
|
|
||||||
});
|
|
||||||
electronLocalshortcut.register(currentWindow, "F2", () => {
|
|
||||||
window.location.href = "https://discord.gg/invite/F25bc4RYDt";
|
|
||||||
});
|
|
||||||
electronLocalshortcut.register(currentWindow, "F4", () => {
|
|
||||||
currentWindow.loadFile("./manager.html");
|
|
||||||
});
|
|
||||||
require("./utils/capturer.js");
|
|
||||||
|
|
||||||
ArmCord.addStyle(`
|
|
||||||
@import url("https://kckarnige.github.io/femboi_owo/discord-font.css");
|
|
||||||
:root {
|
|
||||||
--window-buttons: var(--header-secondary);
|
|
||||||
--cord-color: var(--header-primary);
|
|
||||||
--armcord-color: #7289da;
|
|
||||||
--titlebar-color: var(--background-tertiary);
|
|
||||||
}
|
|
||||||
.base-3dtUhz, .sidebar-2K8pFh {
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
-webkit-box-direction: normal;
|
|
||||||
-ms-flex-direction: column;
|
|
||||||
overflow: hidden;
|
|
||||||
border-top-left-radius: 8px;
|
|
||||||
}
|
|
||||||
div.menubar[role="menubar"] {
|
|
||||||
width: 0px;
|
|
||||||
}
|
|
||||||
.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;
|
|
||||||
}
|
|
||||||
.window-title {
|
|
||||||
font-size: 0px !important;
|
|
||||||
margin-left: initial !important;
|
|
||||||
transform: translate(10px, 0px);
|
|
||||||
}
|
|
||||||
.titlebar {
|
|
||||||
background: var(--titlebar-color) !important;
|
|
||||||
font-family: Verdana, Geneva, Tahoma, sans-serif;
|
|
||||||
}
|
|
||||||
.titlebar .window-controls-container .window-icon {
|
|
||||||
background: var(--window-buttons) !important;
|
|
||||||
}
|
|
||||||
.notice-3bPHh-.colorDefault-22HBa0 {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
|
|
||||||
ArmCord.addStyle(
|
|
||||||
`.info-1VyQPT:last-child:before {
|
|
||||||
content: "ArmCord Version: ` +
|
|
||||||
ArmCord.Version +
|
|
||||||
`";
|
|
||||||
height: auto;
|
|
||||||
line-height: 16px;
|
|
||||||
text-align: center;
|
|
||||||
color: var(--text-muted);
|
|
||||||
font-size: 12px;
|
|
||||||
text-transform: none;
|
|
||||||
}`
|
|
||||||
);
|
|
||||||
|
|
||||||
document.getElementById("ac-channel").innerHTML = ArmCord.Channel;
|
|
||||||
});
|
|
85
src/content/css/setup.css
Normal file
85
src/content/css/setup.css
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
/*CSS ONLY FOR INTERNAL USE (setup and loading)*/
|
||||||
|
@import url("https://kckarnige.github.io/femboi_owo/discord-font.css");
|
||||||
|
|
||||||
|
:root {
|
||||||
|
background-color: #2c2f33;
|
||||||
|
--header-secondary: #b9bbbe;
|
||||||
|
--header-primary: #fff;
|
||||||
|
--background-tertiary: #202225;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: #8e9297;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 100;
|
||||||
|
transform: translateY(-185%);
|
||||||
|
font-family: Whitney, Helvetica Neue, Helvetica, Arial, sans-serif;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
font-size: 0px;
|
||||||
|
text-align: center;
|
||||||
|
transform: translateY(-105%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo:before {
|
||||||
|
content: "ARM";
|
||||||
|
color: #7289da;
|
||||||
|
font-weight: normal;
|
||||||
|
font-family: Helvetica, sans-serif;
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo:after {
|
||||||
|
content: "Cord";
|
||||||
|
color: #ffffff;
|
||||||
|
font-weight: normal;
|
||||||
|
font-family: Discordinated;
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
max-height: 204px;
|
||||||
|
max-width: 204px;
|
||||||
|
transform: translateY(5%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
color: #fff;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background-color: #7289da;
|
||||||
|
font-family: Whitney, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 4px;
|
||||||
|
border-radius: 5px;
|
||||||
|
left: 0;
|
||||||
|
text-align: center;
|
||||||
|
border-style: none;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background-color: #687dc6;
|
||||||
|
border-style: none;
|
||||||
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
114
src/content/css/splash.css
Normal file
114
src/content/css/splash.css
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
/*MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 GooseMod
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.*/
|
||||||
|
:root {
|
||||||
|
--background-primary: #282b30;
|
||||||
|
--background-secondary: rgba(255, 255, 255, 0.1);
|
||||||
|
--brand-experiment: #5865f2;
|
||||||
|
--header-primary: #fff;
|
||||||
|
--text-muted: #72767d;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: Whitney;
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
src: url(https://armcord.smartfridge.space/whitney_400.woff) format("woff");
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
-webkit-app-region: drag;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
background: var(--background-primary);
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
font-family: "Whitney", sans-serif;
|
||||||
|
|
||||||
|
box-sizing: border-box;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
video {
|
||||||
|
width: 200px;
|
||||||
|
height: 150px;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
#text {
|
||||||
|
font-size: 7vw;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
color: var(--header-primary);
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 16px;
|
||||||
|
|
||||||
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bar-container,
|
||||||
|
#bar-fill {
|
||||||
|
width: 180px;
|
||||||
|
height: 8px;
|
||||||
|
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bar-container {
|
||||||
|
background-color: var(--background-secondary);
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bar-fill {
|
||||||
|
background-color: var(--brand-experiment);
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#debug {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 6px;
|
||||||
|
right: 6px;
|
||||||
|
|
||||||
|
text-align: right;
|
||||||
|
font-size: 10px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
white-space: pre;
|
||||||
|
}
|
123
src/content/css/titlebar.css
Normal file
123
src/content/css/titlebar.css
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
@import url("https://kckarnige.github.io/femboi_owo/discord-font.css");
|
||||||
|
:root {
|
||||||
|
--window-buttons: var(--header-secondary);
|
||||||
|
--cord-color: var(--header-primary);
|
||||||
|
--armcord-color: #7289da;
|
||||||
|
--titlebar-color: var(--background-tertiary);
|
||||||
|
}
|
||||||
|
.titleebar {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 13px;
|
||||||
|
padding: 0 16px;
|
||||||
|
overflow: hidden;
|
||||||
|
flex-shrink: 0;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
user-select: none;
|
||||||
|
zoom: 1;
|
||||||
|
line-height: 22px;
|
||||||
|
height: 22px;
|
||||||
|
display: flex;
|
||||||
|
z-index: 99999;
|
||||||
|
}
|
||||||
|
.titlebar {
|
||||||
|
display: block;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
zoom: 1;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
clear:both;
|
||||||
|
height: 30px;
|
||||||
|
line-height: 30px;
|
||||||
|
background-color: #202225;
|
||||||
|
-webkit-app-region: drag;
|
||||||
|
width: 100%;
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 99999;
|
||||||
|
|
||||||
|
}
|
||||||
|
.appMount-3lHmkl{
|
||||||
|
|
||||||
|
}
|
||||||
|
.titlebar #window-title {
|
||||||
|
width: 30%;
|
||||||
|
height: 100%;
|
||||||
|
line-height: 30px;
|
||||||
|
float: left;
|
||||||
|
padding: 0 0 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.titlebar #window-controls-container {
|
||||||
|
float: right;
|
||||||
|
width: 150px;
|
||||||
|
height: 100%;
|
||||||
|
line-height: 30px;
|
||||||
|
background-color: #202225;
|
||||||
|
-webkit-app-region: no-drag;
|
||||||
|
}
|
||||||
|
|
||||||
|
.titlebar #window-controls-container #minimize,
|
||||||
|
.titlebar #window-controls-container #maximize,
|
||||||
|
.titlebar #window-controls-container #quit {
|
||||||
|
float: left;
|
||||||
|
height: 100%;
|
||||||
|
width: 33%;
|
||||||
|
text-align: center;
|
||||||
|
color: #f7f7f7;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.titlebar #window-controls-container #minimize:hover {
|
||||||
|
background-color: #99AAB5;
|
||||||
|
}
|
||||||
|
.titlebar #window-controls-container #maximize:hover {
|
||||||
|
background-color: #99AAB5;
|
||||||
|
}
|
||||||
|
.titlebar #window-controls-container #quit:hover {
|
||||||
|
background-color: #F04747;
|
||||||
|
}
|
||||||
|
.titlebar #window-controls-container #quit {
|
||||||
|
background-color: #f7f7f7;
|
||||||
|
-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;
|
||||||
|
-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;
|
||||||
|
-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;
|
||||||
|
}
|
||||||
|
.window-title {
|
||||||
|
font-size: 0px !important;
|
||||||
|
margin-left: initial !important;
|
||||||
|
transform: translate(10px, 0px);
|
||||||
|
}
|
50
src/content/index.html
Normal file
50
src/content/index.html
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>ArmCord</title>
|
||||||
|
<style>
|
||||||
|
@import url("css/splash.css");
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<video autoplay loop class="logo">
|
||||||
|
<source
|
||||||
|
src="https://armcord.smartfridge.space/discord_loading.webm"
|
||||||
|
type="video/webm"
|
||||||
|
/>
|
||||||
|
</video>
|
||||||
|
<p id="text"></p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<script>
|
||||||
|
const text = document.getElementById("text");
|
||||||
|
if (window.navigator.onLine === false) {
|
||||||
|
text.innerHTML =
|
||||||
|
"You appear to be offline. Please connect to the internet and try again.";
|
||||||
|
} else {
|
||||||
|
text.innerHTML = "Starting ArmCord...";
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
window.armcord.splashEnd();
|
||||||
|
switch (window.armcord.channel) {
|
||||||
|
case "stable":
|
||||||
|
window.location.href = "https://discord.com/app";
|
||||||
|
break;
|
||||||
|
case "canary":
|
||||||
|
window.location.href = "https://canary.discord.com/app";
|
||||||
|
break;
|
||||||
|
case "ptb":
|
||||||
|
window.location.href = "https://ptb.discord.com/app";
|
||||||
|
break;
|
||||||
|
case "foss":
|
||||||
|
window.location.href = "https://dev.fosscord.com/app";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
window.location.href = "https://discord.com/app";
|
||||||
|
}}, 5000);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</html>
|
24
src/content/setup.html
Normal file
24
src/content/setup.html
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8"/>
|
||||||
|
<title>ArmCord Setup</title>
|
||||||
|
<style>
|
||||||
|
@import url("css/setup.css");
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="logo"></h1>
|
||||||
|
<h2>Welcome to ArmCord!</h2>
|
||||||
|
<p>Select what kind of setup you want to perform:</p>
|
||||||
|
<button id="express">Express setup</button>
|
||||||
|
<button id="full">Full setup</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
26
src/extensions/plugin.ts
Normal file
26
src/extensions/plugin.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import { app, session } from 'electron';
|
||||||
|
const userDataPath = app.getPath("userData");
|
||||||
|
const pluginFolder = userDataPath + "/plugins/";
|
||||||
|
if (!fs.existsSync(pluginFolder)) {
|
||||||
|
fs.mkdirSync(pluginFolder);
|
||||||
|
console.log("Created missing plugin folder");
|
||||||
|
}
|
||||||
|
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}`);
|
||||||
|
console.log(
|
||||||
|
`%cLoaded ${pluginFile.name} made by ${pluginFile.author}`,
|
||||||
|
"color:red"
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
0
src/extensions/themes.ts
Normal file
0
src/extensions/themes.ts
Normal file
92
src/main.ts
Normal file
92
src/main.ts
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
// Modules to control application life and create native browser window
|
||||||
|
import { app, BrowserWindow, ipcMain, shell } from "electron";
|
||||||
|
import * as path from "path";
|
||||||
|
import * as storage from 'electron-json-storage';
|
||||||
|
import {setup} from './utils';
|
||||||
|
import './extensions/plugin';
|
||||||
|
var isSetup = null;
|
||||||
|
var contentPath:string = "null";
|
||||||
|
var frame:boolean;
|
||||||
|
|
||||||
|
storage.keys(function(error, keys) {
|
||||||
|
if (error) throw error;
|
||||||
|
|
||||||
|
for (var key of keys) {
|
||||||
|
console.log('There is a key called: ' + key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
storage.has('firstRun', function(error, hasKey) {
|
||||||
|
if (error) throw error;
|
||||||
|
|
||||||
|
if (!hasKey) {
|
||||||
|
console.log('First run of the ArmCord. Starting setup.');
|
||||||
|
isSetup = true;
|
||||||
|
setup();
|
||||||
|
contentPath = __dirname + '/content/setup.html'
|
||||||
|
} else {
|
||||||
|
console.log('ArmCord has been run before. Skipping setup.');
|
||||||
|
isSetup = false;
|
||||||
|
contentPath = __dirname + '/content/index.html'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
storage.get('settings', function(error, data:any) {
|
||||||
|
if (error) throw error;
|
||||||
|
console.log(data);
|
||||||
|
frame = data.customTitlebar;
|
||||||
|
console.log(frame)
|
||||||
|
});
|
||||||
|
function createWindow () {
|
||||||
|
const mainWindow = new BrowserWindow({
|
||||||
|
width: 300,
|
||||||
|
height: 300,
|
||||||
|
title: "ArmCord",
|
||||||
|
frame: frame,
|
||||||
|
webPreferences: {
|
||||||
|
preload: path.join(__dirname, 'preload/preload.js')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
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-show", (event, arg) => {
|
||||||
|
mainWindow.show();
|
||||||
|
});
|
||||||
|
ipcMain.on("win-hide", (event, arg) => {
|
||||||
|
mainWindow.hide();
|
||||||
|
});
|
||||||
|
ipcMain.on("get-app-version", (event) => {
|
||||||
|
event.returnValue = process.env.npm_package_version;
|
||||||
|
})
|
||||||
|
ipcMain.on("splashEnd", (event, arg) => {
|
||||||
|
mainWindow.setSize(800, 600);
|
||||||
|
});
|
||||||
|
ipcMain.on("channel", (event) => {
|
||||||
|
event.returnValue = storage.getSync('channel');
|
||||||
|
})
|
||||||
|
mainWindow.loadFile(contentPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
app.whenReady().then(() => {
|
||||||
|
createWindow()
|
||||||
|
|
||||||
|
app.on('activate', function () {
|
||||||
|
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
app.on('window-all-closed', function () {
|
||||||
|
if (process.platform !== 'darwin') app.quit()
|
||||||
|
})
|
17
src/preload/bridge.ts
Normal file
17
src/preload/bridge.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
|
||||||
|
import { contextBridge, ipcRenderer } from 'electron';
|
||||||
|
import {getDisplayMediaSelector} from './capturer';
|
||||||
|
|
||||||
|
contextBridge.exposeInMainWorld("armcord", {
|
||||||
|
window: {
|
||||||
|
show: () => ipcRenderer.sendSync('win-show'),
|
||||||
|
hide: () => ipcRenderer.sendSync('win-hide'),
|
||||||
|
minimize: () => ipcRenderer.sendSync('win-minimize'),
|
||||||
|
maximize: () => ipcRenderer.sendSync('win-maximize'),
|
||||||
|
},
|
||||||
|
electron: process.versions.electron,
|
||||||
|
version: ipcRenderer.sendSync('get-app-version', 'app-version'),
|
||||||
|
getDisplayMediaSelector: getDisplayMediaSelector,
|
||||||
|
splashEnd: () => ipcRenderer.sendSync('splashEnd'),
|
||||||
|
channel: ipcRenderer.sendSync('channel')
|
||||||
|
});
|
|
@ -1,9 +1,11 @@
|
||||||
//Fixed context isolation version https://github.com/getferdi/ferdi/blob/develop/src/webview/screenshare.ts
|
//Fixed context isolation version https://github.com/getferdi/ferdi/blob/develop/src/webview/screenshare.ts
|
||||||
//original https://github.com/electron/electron/issues/16513#issuecomment-602070250
|
//original https://github.com/electron/electron/issues/16513#issuecomment-602070250
|
||||||
const { desktopCapturer } = require('electron');
|
import { desktopCapturer } from 'electron';
|
||||||
|
import {addStyle, addScript} from '../utils';
|
||||||
|
|
||||||
const CANCEL_ID = 'desktop-capturer-selection__cancel';
|
const CANCEL_ID = 'desktop-capturer-selection__cancel';
|
||||||
const ArmCord = require("./ArmCord.js");
|
|
||||||
async function getDisplayMediaSelector() {
|
export async function getDisplayMediaSelector() {
|
||||||
const sources = await desktopCapturer.getSources({
|
const sources = await desktopCapturer.getSources({
|
||||||
types: ['screen', 'window'],
|
types: ['screen', 'window'],
|
||||||
});
|
});
|
||||||
|
@ -144,9 +146,7 @@ window.navigator.mediaDevices.getDisplayMedia = () => new Promise(async (resolve
|
||||||
`;
|
`;
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", function(event) {
|
document.addEventListener("DOMContentLoaded", function(event) {
|
||||||
ArmCord.addScript(screenShareJS);
|
addScript(screenShareJS);
|
||||||
ArmCord.addStyle(screenShareCSS);
|
addStyle(screenShareCSS);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
exports.getDisplayMediaSelector = getDisplayMediaSelector;
|
|
5
src/preload/preload.ts
Normal file
5
src/preload/preload.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import './capturer'
|
||||||
|
import './bridge'
|
||||||
|
import {injectTitlebar} from './titlebar';
|
||||||
|
injectTitlebar();
|
||||||
|
console.log("ArmCord");
|
46
src/preload/titlebar.ts
Normal file
46
src/preload/titlebar.ts
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import { ipcRenderer } from 'electron';
|
||||||
|
import {addStyle} from '../utils'
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
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>
|
||||||
|
</nav>`;
|
||||||
|
document.body.appendChild(elem);
|
||||||
|
const cssPath = path.join(__dirname, '../', '/content/css/titlebar.css');
|
||||||
|
addStyle(fs.readFileSync(
|
||||||
|
cssPath,
|
||||||
|
"utf8"
|
||||||
|
));
|
||||||
|
|
||||||
|
var minimize = document.querySelector("#minimize");
|
||||||
|
var maximize = document.querySelector("#maximize");
|
||||||
|
var quit = document.querySelector("#quit");
|
||||||
|
|
||||||
|
minimize!.addEventListener("click", () => {
|
||||||
|
ipcRenderer.sendSync('win-minimize')
|
||||||
|
});
|
||||||
|
|
||||||
|
maximize!.addEventListener("click", () => {
|
||||||
|
if (ipcRenderer.sendSync('win-isMaximized') == true) {
|
||||||
|
ipcRenderer.sendSync('win-minimize')
|
||||||
|
} else {
|
||||||
|
ipcRenderer.sendSync('win-maximize')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
quit!.addEventListener("click", () => {
|
||||||
|
ipcRenderer.sendSync('win-hide')
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
export function removeTitlebar() {
|
||||||
|
document.querySelector('#titlebar')!.remove();
|
||||||
|
}
|
24
src/utils.ts
Normal file
24
src/utils.ts
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import * as storage from 'electron-json-storage';
|
||||||
|
//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) {
|
||||||
|
const style = document.createElement('style');
|
||||||
|
style.textContent = styleString;
|
||||||
|
document.head.append(style);
|
||||||
|
};
|
||||||
|
|
||||||
|
export function addScript(scriptString: string) {
|
||||||
|
var script = document.createElement("script");
|
||||||
|
script.textContent = scriptString;
|
||||||
|
document.body.append(script);
|
||||||
|
};
|
||||||
|
export function setup(){
|
||||||
|
console.log("Setting up ArmCord settings.");
|
||||||
|
storage.set('settings', { customTitlebar: true, channel: 'stable', firstRun: 'done' }, function(error) {
|
||||||
|
if (error) throw error;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
export interface settingsStructure {
|
||||||
|
channel: string,
|
||||||
|
customTitlebar: boolean,
|
||||||
|
firstRun: string,
|
||||||
|
}
|
35
tsconfig.json
Normal file
35
tsconfig.json
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// Reference: https://www.typescriptlang.org/tsconfig
|
||||||
|
{
|
||||||
|
"include": ["src/**/*"], // This makes it so that the compiler won't compile anything outside of "src".
|
||||||
|
//"exclude": ["src/**/*.test.ts"], // Exclude .test.ts files since they're for Jest only.
|
||||||
|
"compilerOptions": {
|
||||||
|
// Project Structure //
|
||||||
|
"rootDir": "src", // rootDir only affects the STRUCTURE of the folders, not what gets compiled. For extra measure, make sure the structure conforms to "src".
|
||||||
|
"outDir": "dist", // Likewise, outDir only chooses which folder to compile to. Prevent the compiler from creating JS files right next to source files.
|
||||||
|
"moduleResolution": "node", // Specify how the compiler resolves modules, like going for node_modules first then searching elsewhere. The official docs just say to use this instead of classic.
|
||||||
|
|
||||||
|
// Type Settings //
|
||||||
|
"strict": true, // Enables all strict checks possible.
|
||||||
|
"noImplicitReturns": false, // Makes sure you don't accidentally return something + undefined.
|
||||||
|
"noFallthroughCasesInSwitch": true, // Prevents accidentally forgetting to break every switch case. Of course, if you know what you're doing, feel free to add a @ts-ignore, which also signals that it's not a mistake.
|
||||||
|
"forceConsistentCasingInFileNames": true, // Make import paths case-sensitive. "./tEst" is no longer the same as "./test".
|
||||||
|
"esModuleInterop": true, // Enables compatibility with Node.js' module system since the entire export can be whatever you want. allowSyntheticDefaultImports doesn't address runtime issues and is made redundant by this setting.
|
||||||
|
"resolveJsonModule": true, // Allows you to import JSON files just like how you can require() them. Do note that if you're accessing any JSON files outside of src, it'll mess up dist.
|
||||||
|
"lib": ["ES2020", "DOM"], // Specifies what common libraries you have access to. If you're working in Node.js, you'll want to leave out the DOM library. But do make sure to include "@types/node" because otherwise, variables like "console" won't be defined.
|
||||||
|
|
||||||
|
// Output //
|
||||||
|
"module": "CommonJS", // Compiles ES6 imports to require() syntax.
|
||||||
|
"removeComments": false,
|
||||||
|
"sourceMap": true, // Used for displaying the original source when debugging in webpack. Allows you to set breakpoints directly on TypeScript code for VSCode's debugger.
|
||||||
|
|
||||||
|
// Library Building //
|
||||||
|
"declaration": false, // Exports declaration files in addition, used for exporting a module.
|
||||||
|
"declarationMap": false, // Allows the user to go to the source file when hitting a go-to-implementation key like F12 in VSCode for example.
|
||||||
|
//"declarationDir": "typings", // declarationDir allows you to separate the compiled code from the declaration files, used in conjunction with package.json's "types" property.
|
||||||
|
|
||||||
|
// Web Compatibility //
|
||||||
|
"target": "ES2020", // ES2017 supports async/await, reducing the amount of compiled code, especially for async-heavy projects. ES2020 is from the Node 14 base (https://github.com/tsconfig/bases/blob/master/bases/node14.json)
|
||||||
|
"downlevelIteration": false, // This flag adds extra support when targeting ES3, but adds extra bloat otherwise.
|
||||||
|
"importHelpers": false // Reduce the amount of bloat that comes from downlevelIteration (when polyfills are redeclared).
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,24 +0,0 @@
|
||||||
exports.Version = require("../package.json").version;
|
|
||||||
const fs = require("fs");
|
|
||||||
const electron = require("electron");
|
|
||||||
const userDataPath = (electron.app || electron.remote.app).getPath("userData");
|
|
||||||
const settingsFile= userDataPath + "/settings.json";
|
|
||||||
if (!fs.existsSync(settingsFile)) {
|
|
||||||
fs.writeFile(settingsFile, "{}", (err) => {
|
|
||||||
if (err) throw err;
|
|
||||||
});
|
|
||||||
console.log("Created settings.json file");
|
|
||||||
}
|
|
||||||
exports.Channel = require(settingsFile).channel;
|
|
||||||
exports.Titlebar = require(settingsFile).titlebar;
|
|
||||||
exports.addStyle = function(styleString) {
|
|
||||||
const style = document.createElement('style');
|
|
||||||
style.textContent = styleString;
|
|
||||||
document.head.append(style);
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.addScript = function (scriptString) {
|
|
||||||
var script = document.createElement("script");
|
|
||||||
script.textContent = scriptString;
|
|
||||||
document.body.append(script);
|
|
||||||
};
|
|
|
@ -1,19 +0,0 @@
|
||||||
const { contextBridge, remote } = require("electron");
|
|
||||||
const currentWindow = remote.getCurrentWindow();
|
|
||||||
const {getDisplayMediaSelector} = require('./capturer')
|
|
||||||
const ArmCord = require("./ArmCord.js");
|
|
||||||
const version = require("../package.json").version;
|
|
||||||
contextBridge.exposeInMainWorld("electron", {
|
|
||||||
window: {
|
|
||||||
show: () => currentWindow.show(),
|
|
||||||
hide: () => currentWindow.hide(),
|
|
||||||
minimize: () => currentWindow.minimize(),
|
|
||||||
maximize: () => currentWindow.maximize(),
|
|
||||||
on : () => currentWindow.on(),
|
|
||||||
},
|
|
||||||
electron: process.versions.electron,
|
|
||||||
version: version,
|
|
||||||
ArmCord: ArmCord,
|
|
||||||
getDisplayMediaSelector: getDisplayMediaSelector,
|
|
||||||
|
|
||||||
});
|
|
22
utils/mod.js
22
utils/mod.js
|
@ -1,22 +0,0 @@
|
||||||
const fs = require("fs");
|
|
||||||
const { app, session } = require("electron");
|
|
||||||
const path = require ('path');
|
|
||||||
const execPath = path.dirname (process.execPath);
|
|
||||||
app.whenReady().then(() => {
|
|
||||||
fs.readdirSync(`${execPath}/resources/mods/`).forEach((file) => {
|
|
||||||
try {
|
|
||||||
const manifest = fs.readFileSync(
|
|
||||||
`${execPath}/resources/mods/${file}/manifest.json`,
|
|
||||||
"utf8"
|
|
||||||
);
|
|
||||||
var pluginFile = JSON.parse(manifest);
|
|
||||||
session.defaultSession.loadExtension(`${execPath}/resources/mods/${file}`);
|
|
||||||
console.log(
|
|
||||||
`%cLoaded ${pluginFile.name} made by ${pluginFile.author}`,
|
|
||||||
"color:red"
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,24 +0,0 @@
|
||||||
const fs = require("fs");
|
|
||||||
const { app, session } = require("electron");
|
|
||||||
const electron = require("electron");
|
|
||||||
const userDataPath = (electron.app || electron.remote.app).getPath("userData");
|
|
||||||
const pluginFolder = userDataPath + "/plugins/";
|
|
||||||
|
|
||||||
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}`);
|
|
||||||
console.log(
|
|
||||||
`%cLoaded ${pluginFile.name} made by ${pluginFile.author}`,
|
|
||||||
"color:red"
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,53 +0,0 @@
|
||||||
const fs = require("fs");
|
|
||||||
const {shell} = require('electron');
|
|
||||||
const electron = require("electron");
|
|
||||||
const ArmCord = require("./ArmCord.js");
|
|
||||||
const userDataPath = (electron.app || electron.remote.app).getPath("userData");
|
|
||||||
const themeFolder = userDataPath + "/themes/";
|
|
||||||
if (!fs.existsSync(themeFolder)) {
|
|
||||||
fs.mkdirSync(themeFolder);
|
|
||||||
console.log("Created theme folder");
|
|
||||||
}
|
|
||||||
window.addEventListener("DOMContentLoaded", () => {
|
|
||||||
console.log("Theme Module Loaded"); // I KNOW THIS IS A MESS BUT IT'S WORKING MESS, XOXO
|
|
||||||
fs.readdirSync(themeFolder).forEach((file) => {
|
|
||||||
try {
|
|
||||||
if (file.includes('DISABLED')) {
|
|
||||||
console.log(`Skipping ${file}.`)
|
|
||||||
const manifest = fs.readFileSync(`${userDataPath}/themes/${file}/manifest.json`, "utf8");
|
|
||||||
var themeFile = JSON.parse(manifest);
|
|
||||||
var html = `<div id="tm-list-item"><div id="theme-name">${themeFile.name}</div><div id="theme-author">By ${themeFile.author}</div><div id="theme-description">${themeFile.description}</div></div><br><br>`;
|
|
||||||
document.getElementById("tm-disabled").innerHTML = html + document.getElementById("tm-disabled").innerHTML;
|
|
||||||
}
|
|
||||||
const manifest = fs.readFileSync(`${userDataPath}/themes/${file}/manifest.json`, "utf8");
|
|
||||||
var themeFile = JSON.parse(manifest);
|
|
||||||
const theme = fs.readFileSync(`${userDataPath}/themes/${file}/${themeFile.theme}`, "utf8");
|
|
||||||
if (themeFile.theme.endsWith(".scss")) {
|
|
||||||
console.log(
|
|
||||||
`%cCouldn't load ${themeFile.name} made by ${themeFile.author}. ArmCord doesn't support SCSS files! If you want to have this theme ported, feel free to reach out https://discord.gg/F25bc4RYDt `,
|
|
||||||
"color:red; font-weight: bold; font-size: 50px;color: red;"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
ArmCord.addStyle(theme);
|
|
||||||
var html = `<div id="tm-list-item"><div id="theme-name">${themeFile.name}</div><div id="theme-author">By ${themeFile.author}</div><div id="theme-description">${themeFile.description}</div></div><br><br>`;
|
|
||||||
document.getElementById("tm-list").innerHTML = html + document.getElementById("tm-list").innerHTML;
|
|
||||||
console.log(`%cLoaded ${themeFile.name} made by ${themeFile.author}`, "color:red");
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
document.getElementById("open-themes-btn").onclick = function () {shell.openPath(`${userDataPath}/themes`);};
|
|
||||||
document.getElementsByClassName("back-btn")[0].onclick = function () {
|
|
||||||
if (document.getElementById("ac-channel").innerHTML == "stable") {
|
|
||||||
window.location.href = "https://discord.com/app";
|
|
||||||
} else if (document.getElementById("ac-channel").innerHTML == "canary") {
|
|
||||||
window.location.href = "https://canary.discord.com/app";
|
|
||||||
} else if (document.getElementById("ac-channel").innerHTML == "ptb") {
|
|
||||||
window.location.href = "https://ptb.discord.com/app";
|
|
||||||
} else if (document.getElementById("ac-channel").innerHTML == "foss") {
|
|
||||||
window.location.href = "https://dev.fosscord.com/app";
|
|
||||||
} else {
|
|
||||||
window.location.href = "https://discord.com/app";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,138 +0,0 @@
|
||||||
const { remote } = require("electron");
|
|
||||||
var win = remote.BrowserWindow.getFocusedWindow();
|
|
||||||
const ArmCord = require("./ArmCord.js");
|
|
||||||
const css = `
|
|
||||||
.titleebar {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
width: 100%;
|
|
||||||
font-size: 13px;
|
|
||||||
padding: 0 16px;
|
|
||||||
overflow: hidden;
|
|
||||||
flex-shrink: 0;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
user-select: none;
|
|
||||||
zoom: 1;
|
|
||||||
line-height: 22px;
|
|
||||||
height: 22px;
|
|
||||||
display: flex;
|
|
||||||
z-index: 99999;
|
|
||||||
}
|
|
||||||
.titlebar {
|
|
||||||
display: block;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
zoom: 1;
|
|
||||||
box-sizing: border-box;
|
|
||||||
width: 100%;
|
|
||||||
clear:both;
|
|
||||||
height: 30px;
|
|
||||||
line-height: 30px;
|
|
||||||
background-color: #202225;
|
|
||||||
-webkit-app-region: drag;
|
|
||||||
width: 100%;
|
|
||||||
user-select: none;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
position: fixed;
|
|
||||||
z-index: 99999;
|
|
||||||
|
|
||||||
}
|
|
||||||
.appMount-3lHmkl{
|
|
||||||
|
|
||||||
}
|
|
||||||
.titlebar #window-title {
|
|
||||||
width: 30%;
|
|
||||||
height: 100%;
|
|
||||||
line-height: 30px;
|
|
||||||
float: left;
|
|
||||||
padding: 0 0 0 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.titlebar #window-controls-container {
|
|
||||||
float: right;
|
|
||||||
width: 150px;
|
|
||||||
height: 100%;
|
|
||||||
line-height: 30px;
|
|
||||||
background-color: #202225;
|
|
||||||
-webkit-app-region: no-drag;
|
|
||||||
}
|
|
||||||
|
|
||||||
.titlebar #window-controls-container #minimize,
|
|
||||||
.titlebar #window-controls-container #maximize,
|
|
||||||
.titlebar #window-controls-container #quit {
|
|
||||||
float: left;
|
|
||||||
height: 100%;
|
|
||||||
width: 33%;
|
|
||||||
text-align: center;
|
|
||||||
color: #f7f7f7;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
.titlebar #window-controls-container #minimize:hover {
|
|
||||||
background-color: #99AAB5;
|
|
||||||
}
|
|
||||||
.titlebar #window-controls-container #maximize:hover {
|
|
||||||
background-color: #99AAB5;
|
|
||||||
}
|
|
||||||
.titlebar #window-controls-container #quit:hover {
|
|
||||||
background-color: #F04747;
|
|
||||||
}
|
|
||||||
.titlebar #window-controls-container #quit {
|
|
||||||
background-color: #f7f7f7;
|
|
||||||
-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;
|
|
||||||
-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;
|
|
||||||
-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%;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
`;
|
|
||||||
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>
|
|
||||||
</nav>`;
|
|
||||||
document.body.appendChild(elem);
|
|
||||||
|
|
||||||
ArmCord.addStyle(css);
|
|
||||||
|
|
||||||
var minimize = document.querySelector("#minimize");
|
|
||||||
var maximize = document.querySelector("#maximize");
|
|
||||||
var quit = document.querySelector("#quit");
|
|
||||||
|
|
||||||
minimize.addEventListener("click", () => {
|
|
||||||
win.minimize();
|
|
||||||
});
|
|
||||||
|
|
||||||
maximize.addEventListener("click", () => {
|
|
||||||
if (win.isMaximized() == true) {
|
|
||||||
win.unmaximize();
|
|
||||||
} else {
|
|
||||||
win.maximize();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
quit.addEventListener("click", () => {
|
|
||||||
win.close();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,22 +0,0 @@
|
||||||
const { app, autoUpdater } = require('electron')
|
|
||||||
const server = "https://download.smartfridge.space"
|
|
||||||
const url = `${server}/update/${process.platform}/${app.getVersion()}`
|
|
||||||
|
|
||||||
autoUpdater.setFeedURL({ url })
|
|
||||||
autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => {
|
|
||||||
const dialogOpts = {
|
|
||||||
type: 'info',
|
|
||||||
buttons: ['Restart', 'Later'],
|
|
||||||
title: 'ArmCord Update',
|
|
||||||
message: process.platform === 'win32' ? releaseNotes : releaseName,
|
|
||||||
detail: 'A new version has been downloaded. Restart the application to apply the updates.'
|
|
||||||
}
|
|
||||||
|
|
||||||
dialog.showMessageBox(dialogOpts).then((returnValue) => {
|
|
||||||
if (returnValue.response === 0) autoUpdater.quitAndInstall()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
autoUpdater.on('error', message => {
|
|
||||||
console.error('There was a problem updating the application')
|
|
||||||
console.error(message)
|
|
||||||
})
|
|
Loading…
Reference in a new issue