Compare commits

...

8 commits

Author SHA1 Message Date
dependabot[bot]
6662086397
Bump electron-context-menu from 3.0.0 to 3.1.1
Bumps [electron-context-menu](https://github.com/sindresorhus/electron-context-menu) from 3.0.0 to 3.1.1.
- [Release notes](https://github.com/sindresorhus/electron-context-menu/releases)
- [Commits](https://github.com/sindresorhus/electron-context-menu/compare/v3.0.0...v3.1.1)

---
updated-dependencies:
- dependency-name: electron-context-menu
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-07 14:17:55 +00:00
smartfridge
3fd237446f Merge branch 'main' of https://github.com/armcord/armcord 2021-11-07 15:12:44 +01:00
smartfridge
08b2b312f6 2.7.0 - Test 2021-11-07 15:12:42 +01:00
smartfridge
55a81d9543
Update some stuff in readme 2021-11-01 21:48:21 +01:00
smartfridge
d18504bc2f v2.6.1 2021-11-01 17:57:38 +01:00
smartfridge
6e12b1baa2 Fix cumcord bug 2021-11-01 17:57:03 +01:00
smartfridge
8c3abc8cf6 v2.6.0 2021-11-01 12:01:04 +01:00
smartfridge
0de7ca8f50 v1.2.3 2021-11-01 12:00:10 +01:00
11 changed files with 539 additions and 923 deletions

View file

@ -1,6 +1,6 @@
# ![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 [GooseMod](https://goosemod.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?
Check releases tab for precompiled packages for Linux, Windows and Mac OS (experimental).
@ -13,20 +13,20 @@ Alternatively you can run ArmCord from source (npm, nodejs required):
# FAQ
## 1.Will I get banned from using it?
-You are breaking Discord ToS since we are using GooseMod for themes and plugins. But no one ever got banned from using ArmCord or GooseMod as of now. If you wish to remove GooseMod, you can find it in your plugins folder.
-You are breaking Discord ToS since we are using Cumcord for themes and plugins. But no one ever got banned from using ArmCord or Cumcord. If you wish to remove Cumcord, you can find it in your mods folder.
## 2.How does this work?
-We are using official web app and adding GooseMod to it with some other tweaks.
-We are using official web app and adding Cumcord it with some other tweaks.
## 3.Can I use this on other architectures or operating systems?
-Yes! ArmCord should work normally under Windows, ~~Mac OS~~ (Mac OS is broken see [#48](https://github.com/ArmCord/ArmCord/issues/48)), Linux as long as it has NodeJS, npm and Electron support.
## 4.Code is big spaghetti.
-I'm aware. I'm slowly rewriting everything. This branch is mostly fixes only.
-I'm aware. I'm slowly rewriting everything.
# Credits
[ArmCord UI Elements and few features](https://github.com/kckarnige)
[GooseMod](https://github.com/GooseMod/GooseMod)
[Cumcord](https://github.com/Cumcord/Cumcord)
[GooseMod Extension](https://github.com/GooseMod/extension)
[electron-discord-webapp](https://github.com/SpacingBat3/electron-discord-webapp)
[custom-electron-titlebar](https://github.com/AlexTorresSk/custom-electron-titlebar)

View file

@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta charset="UTF-8"/>
<title>ArmCord</title>
<script>
window.onload = setTimeout(function() {
@ -90,15 +90,13 @@
display: none;
}
</style>
<style>
</style>
</head>
<body>
<div class="container">
<video autoplay loop class="logo">
<source src="https://discord.com/assets/0bdc0497eb3a19e66f2b1e3d5741634c.webm" type="video/webm">
<source src="https://discord.com/assets/3b0d96ed8113994f3d139088726cfecd.webm" type="video/webm">
</video>
<p>Loading...</p>
<h1></h1>

View file

@ -4,6 +4,7 @@ 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 {
@ -42,7 +43,6 @@ function createWindow() {
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
@ -81,6 +81,7 @@ function createWindow() {
mainWindow.show()
});
appIcon.setContextMenu(contextMenu);
// Emitted when the window is closed.

937
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{
"name": "ArmCord",
"version": "2.6.0",
"version": "2.7.0",
"description": "ArmCord is a Discord client made for ARM Linux that allows you to customize your experience.",
"main": "main.js",
"scripts": {
@ -9,21 +9,16 @@
"package": "electron-builder --dir",
"make": "electron-builder",
"linux-build": "electron-builder --linux deb tar.gz rpm AppImage",
"windows-build": "electron-builder --windows nsis portable zip appx"
"windows-build": "electron-builder --windows nsis portable zip"
},
"author": "smartfrigde <smartfridge1337@protonmail.com>",
"license": "OSL-3.0",
"dependencies": {
"@rollup/plugin-commonjs": "^21.0.1",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^13.0.6",
"custom-electron-titlebar": "3.2.7",
"electron-context-menu": "^3.0.0",
"electron-context-menu": "^3.1.1",
"electron-dl": "^3.2.1",
"electron-localshortcut": "^3.2.1",
"electron-store": "^8.0.0",
"rollup": "^2.58.0",
"rollup-plugin-terser": "^7.0.2",
"electron-updater": "^4.3.9",
"unzipper": "^0.10.1",
"v8-compile-cache": "^2.3.0"
},
@ -44,11 +39,21 @@
"appId": "com.smartfridge.armcord",
"productName": "ArmCord",
"mac": {
"category": "Network"
"category": "Network",
"extraResources": [
"./mods/cumcord/*"
]
},
"win": {
"extraResources": [
"./mods/cumcord/*"
]
},
"linux": {
"category": "Network",
"extraResources": ["./mods/cumcord/*"],
"extraResources": [
"./mods/cumcord/*"
],
"maintainer": "smartfridge1337@protonmail.com",
"target": [
"deb",

View file

@ -1,16 +1,14 @@
const { remote } = require("electron");
const currentWindow = remote.getCurrentWindow();
const customTitlebar = require("custom-electron-titlebar");
const electronLocalshortcut = require("electron-localshortcut");
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 {
new customTitlebar.Titlebar({
backgroundColor: customTitlebar.Color.fromHex("#202225"),
menu: false,
});}
if (require("./utils/ArmCord.js").Titlebar == "native") {console.log("Using native titlebar")} else {
//todo
}
electronLocalshortcut.register(currentWindow, "F5", () => {
location.reload();
@ -67,7 +65,7 @@ div.menubar[role="menubar"] {
.window-title {
font-size: 0px !important;
margin-left: initial !important;
transform: translate(10px, 2px);
transform: translate(10px, 0px);
}
.titlebar {
background: var(--titlebar-color) !important;

View file

@ -1,13 +1,19 @@
const { contextBridge, remote, desktopCapturer } = require("electron");
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(),
},
version: process.versions.electron,
desktopCapturer: desktopCapturer,
electron: process.versions.electron,
version: version,
ArmCord: ArmCord,
getDisplayMediaSelector: getDisplayMediaSelector,
});

View file

@ -1,164 +1,152 @@
// This desktop capturer has been taken from https://github.com/SpacingBat3/electron-discord-webapp
//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
const { desktopCapturer } = require('electron');
const CANCEL_ID = 'desktop-capturer-selection__cancel';
const ArmCord = require("./ArmCord.js");
async function getDisplayMediaSelector() {
const sources = await desktopCapturer.getSources({
types: ['screen', 'window'],
});
return `<div class="desktop-capturer-selection__scroller">
<ul class="desktop-capturer-selection__list">
${sources
.map(
({ id, name, thumbnail }) => `
<li class="desktop-capturer-selection__item">
<button class="desktop-capturer-selection__btn" data-id="${id}" title="${name}">
<img class="desktop-capturer-selection__thumbnail" src="${thumbnail.toDataURL()}" />
<span class="desktop-capturer-selection__name">${name}</span>
</button>
</li>
`,
)
.join('')}
<li class="desktop-capturer-selection__item">
<button class="desktop-capturer-selection__btn" data-id="${CANCEL_ID}" title="Cancel">
<span class="desktop-capturer-selection__name desktop-capturer-selection__name--cancel">Cancel</span>
</button>
</li>
</ul>
</div>`;
}
/*
* Thanks, @WesselKroos!
*/
/*function l10n(origin, locale){
if(originalString == 'Entire Screen') {
return locale;
} else {
return origin;
const screenShareCSS = `
.desktop-capturer-selection {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background: rgba(30,30,30,.75);
color: #FFFFFF;
z-index: 10000000;
display: flex;
align-items: center;
justify-content: center;
}
.desktop-capturer-selection__scroller {
width: 100%;
max-height: 100vh;
overflow-y: auto;
}
.desktop-capturer-selection__list {
max-width: calc(100% - 100px);
margin: 50px;
padding: 0;
display: flex;
flex-wrap: wrap;
list-style: none;
overflow: hidden;
justify-content: center;
}
.desktop-capturer-selection__item {
display: flex;
margin: 4px;
}
.desktop-capturer-selection__btn {
display: flex;
flex-direction: column;
align-items: stretch;
width: 145px;
margin: 0;
border: 0;
border-radius: 3px;
padding: 4px;
background: #2C2F33;
text-align: left;
@media (prefers-reduced-motion: no-preference) {
transition: background-color .15s, box-shadow .15s, color .15s;
}
}*/
const { desktopCapturer } = require("electron");
color: #dedede;
}
.desktop-capturer-selection__btn:hover,
.desktop-capturer-selection__btn:focus {
background: #7289DA;
box-shadow: 0 0 4px rgba(0,0,0,0.45), 0 0 2px rgba(0,0,0,0.25);
color: #fff;
}
.desktop-capturer-selection__thumbnail {
width: 100%;
height: 81px;
object-fit: cover;
}
.desktop-capturer-selection__name {
margin: 6px 0;
white-space: nowrap;
color: white;
text-overflow: ellipsis;
text-align: center;
overflow: hidden;
}
.desktop-capturer-selection__name--cancel {
margin: auto 0;
}
`;
navigator.mediaDevices.getDisplayMedia = () => {
return new Promise(async (resolve, reject) => {
try {
const sources = await desktopCapturer.getSources({
types: ["screen", "window"],
});
const selectionElem = document.createElement("div");
selectionElem.setAttribute("class", "desktop-capturer-selection");
selectionElem.innerHTML = `
<style>
.desktop-capturer-selection {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background: rgba(30,30,30,.75);
color: #fff;
z-index: 10000000;
display: flex;
align-items: center;
justify-content: center;
}
.desktop-capturer-selection__scroller {
width: 100%;
max-height: 100vh;
overflow-y: auto;
}
.desktop-capturer-selection__list {
max-width: calc(100% - 100px);
margin: 50px;
padding: 0;
display: flex;
flex-wrap: wrap;
list-style: none;
overflow: hidden;
justify-content: center;
}
.desktop-capturer-selection__item {
display: flex;
margin: 4px;
}
.desktop-capturer-selection__btn {
display: flex;
flex-direction: column;
align-items: stretch;
width: 145px;
margin: 0;
border: 0;
border-radius: 3px;
padding: 4px;
color: #FFFFFF;
background: #36393F;
text-align: left;
transition: background-color .15s, box-shadow .15s;
}
.desktop-capturer-selection__btn:hover,
.desktop-capturer-selection__btn:focus {
background: #7289DA;
}
.desktop-capturer-selection__thumbnail {
width: 100%;
height: 81px;
object-fit: cover;
}
.desktop-capturer-selection__name {
margin: 6px 0 6px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.desktop-capturer-close {
background-color: #36393F;
position: fixed;
top: 50%;
transform: translateY(-50%);
right: 15px;
padding-top: 5px;
transition: background-color .15s;
}
.desktop-capturer-close:hover {
background-color: #823A3A;
}
</style>
<div class="desktop-capturer-selection__scroller">
<ul class="desktop-capturer-selection__list">
${sources
.map(
({ id, name, thumbnail }) => `
<li class="desktop-capturer-selection__item">
<button class="desktop-capturer-selection__btn" data-id="${id}" title="${name}">
<img class="desktop-capturer-selection__thumbnail" src="${thumbnail.toDataURL()}" />
<span class="desktop-capturer-selection__name">${name}</span>
</button>
</li>
`
)
.join("")}
</ul>
<button class="desktop-capturer-close">
<svg viewBox="0 0 10 10" height=20px>
<line x1="0" y1="10" x2="10" y2="0" stroke="white" />
<line x1="0" y1="0" x2="10" y2="10" stroke="white" />
</svg>
</button>
</div>
`;
document.body.appendChild(selectionElem);
document
.querySelectorAll(".desktop-capturer-selection__btn")
.forEach((button) => {
button.addEventListener("click", async () => {
try {
const id = button.getAttribute("data-id");
const source = sources.find((source) => source.id === id);
if (!source) {
throw new Error(`Source with id ${id} does not exist`);
}
const stream = await navigator.mediaDevices.getUserMedia({
const screenShareJS = `
window.navigator.mediaDevices.getDisplayMedia = () => new Promise(async (resolve, reject) => {
try {
const selectionElem = document.createElement('div');
selectionElem.classList = ['desktop-capturer-selection'];
selectionElem.innerHTML = await window.electron.getDisplayMediaSelector();
document.body.appendChild(selectionElem);
document
.querySelectorAll('.desktop-capturer-selection__btn')
.forEach((button) => {
button.addEventListener('click', async () => {
try {
const id = button.getAttribute('data-id');
if (id === '${CANCEL_ID}') {
reject(new Error('Cancelled by user'));
} else {
const stream = await window.navigator.mediaDevices.getUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: "desktop",
chromeMediaSourceId: source.id,
chromeMediaSource: 'desktop',
chromeMediaSourceId: id,
},
},
});
resolve(stream);
selectionElem.remove();
} catch (err) {
console.error("Error selecting desktop capture source:", err);
reject(err);
}
});
});
document.querySelectorAll(".desktop-capturer-close").forEach((button) => {
button.addEventListener("click", () => {
selectionElem.remove();
} catch (err) {
reject(err);
} finally {
selectionElem.remove();
}
});
});
} catch (err) {
console.error("Error displaying desktop capture sources:", err);
reject(err);
}
});
};
console.log("Desktop capturer has been preloaded 🎉️");
} catch (err) {
reject(err);
}
});
`;
document.addEventListener("DOMContentLoaded", function(event) {
ArmCord.addScript(screenShareJS);
ArmCord.addStyle(screenShareCSS);
});
exports.getDisplayMediaSelector = getDisplayMediaSelector;

View file

@ -1,6 +1,5 @@
const fs = require("fs");
const { app, session } = require("electron");
const electron = require("electron");
const path = require ('path');
const execPath = path.dirname (process.execPath);
app.whenReady().then(() => {

138
utils/titlebar.js Normal file
View file

@ -0,0 +1,138 @@
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();
});
});

22
utils/updater.js Normal file
View file

@ -0,0 +1,22 @@
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)
})