Compare commits

..

20 commits

Author SHA1 Message Date
smartfrigde
50f9ded9e7 fix 2022-05-23 18:24:07 +02:00
smartfrigde
bde78e1924 ujgh 2022-05-23 18:15:19 +02:00
smartfrigde
aa76171d34 it turns out, it was powershell all along 2022-05-23 18:08:58 +02:00
smartfrigde
bfd874b9a9 Fix deleting unpacked builds in windowns 2022-05-23 18:03:15 +02:00
smartfrigde
e9afff1d92 Fix removing unpacked builds on Windows 2022-05-23 17:52:36 +02:00
smartfrigde
716cfea120 Burn in hell Bill Gates 2022-05-23 16:58:30 +02:00
smartfrigde
b9fb4837db Add release workflow (pls work) 2022-05-23 16:53:16 +02:00
smartfrigde
0ecabaeb36 v3.0.6 2022-05-23 16:08:49 +02:00
smartfrigde
e3b891e636 Correct the version in AC internals 2022-05-23 16:08:26 +02:00
smartfridge
cdfdbc5e2a
Add the release workflow 2022-05-23 16:07:22 +02:00
smartfrigde
af84a2a625 Add a license header for OpenAsar version settings/version info injection 2022-05-23 15:42:13 +02:00
smartfrigde
1489e213e5 Update Electron to 18.2.4 2022-05-23 15:37:27 +02:00
KayoticCarnige
31c5a88e94 Updated README.md 2022-05-22 12:14:54 -04:00
smartfrigde
b025948d90 Add the ability to pick the tray icon 2022-05-22 16:46:18 +02:00
smartfrigde
5e132564aa Include translations in the asar 2022-05-22 16:38:09 +02:00
KayoticCarnige
12c195a2fa Updated titlebar and a few other things 2022-05-22 07:52:26 -04:00
KayoticCarnige
b31d9d8d4a Updated .gitignore 2022-05-21 15:37:36 -04:00
smartfrigde
c848ad862c Fix clipboard bug 2022-05-21 13:00:04 +02:00
smartfridge
e70ef10dd6
Fix README build instructions 2022-05-21 12:17:28 +02:00
smartfridge
a40188ee43
Add Snaps to the readme 2022-05-21 12:11:55 +02:00
21 changed files with 459 additions and 6496 deletions

View file

@ -1,40 +1,194 @@
name: Build/release name: Release build
on: on:
push: push:
branches: branches:
- stable - stable
env:
FORCE_COLOR: true
jobs: jobs:
release: build-linux:
runs-on: ${{ matrix.os }} runs-on: ubuntu-latest
strategy: steps:
matrix: - uses: actions/setup-node@v3
os: [macos-latest, ubuntu-latest, windows-latest] with:
node-version: '18'
steps: - name: Checkout code
- name: Check out Git repository uses: actions/checkout@v2
uses: actions/checkout@v1
- name: Install Node.js, NPM and Yarn - name: Install Node dependencies
uses: actions/setup-node@v1 run: npm install
with:
node-version: 16
- name: Build/release Electron app - name: Install Electron-Builder
uses: samuelmeuli/action-electron-builder@v1 run: npm install -g electron-builder
with:
# GitHub token, automatically provided to the action - name: Build
# (No need to define this secret in the repo settings) run: npm run build && electron-builder --linux && electron-builder --arm64 --linux && electron-builder --armv7l --linux
github_token: ${{ secrets.github_token }} env:
# skip npm run build as there's no script like that GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
skip_build: false - name: Delete unpacked builds
# If the commit is tagged with a version (e.g. "v1.0.0"), run: rm -rf dist/linux-unpacked && rm -rf dist/linux-arm64-unpacked && rm -rf dist/linux-armv7l-unpacked
# release the app after building - name: Upload artifact
release: ${{ startsWith(github.ref, 'refs/tags/v') }} #disabled for now as it caused problems (nvm) uses: actions/upload-artifact@v2
- name: Archive production builds with:
uses: actions/upload-artifact@v2 name: ArmCordLinux
with: path: dist/
name: dist folder
path: dist/**
build-mac:
runs-on: macos-latest
steps:
- uses: actions/setup-node@v3
with:
node-version: '18'
- name: Checkout code
uses: actions/checkout@v2
- name: Install Node dependencies
run: npm install
- name: Install Electron-Builder
run: npm install -g electron-builder
- name: Build
run: npm run build && electron-builder --macos
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Delete unpacked builds
run: rm -rf dist/macos-unpacked
- name: Upload artifact
uses: actions/upload-artifact@v2
with:
name: ArmCordMac
path: dist/
build-windows:
runs-on: windows-latest
steps:
- uses: actions/setup-node@v3
with:
node-version: '18'
- name: Checkout code
uses: actions/checkout@v2
- name: Install Node dependencies
run: npm install
- name: Install Electron-Builder
run: npm install -g electron-builder
- name: Build
run: npm run build && electron-builder --windows
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Delete unpacked builds
run: Remove-Item -LiteralPath ".\dist\win-unpacked" -Force -Recurse
- name: Upload artifact
uses: actions/upload-artifact@v2
with:
name: ArmCordWindows
path: dist/
release:
runs-on: ubuntu-latest
needs: [build-linux, build-mac, build-windows]
steps:
- name: Checkout code
uses: actions/checkout@v2
- uses: actions/download-artifact@v2
with:
name: ArmCordMac
path: macos
- uses: actions/download-artifact@v2
with:
name: ArmCordWindows
path: windows
- uses: actions/download-artifact@v2
with:
name: ArmCordLinux
path: linux
- uses: actions/download-artifact@v2
with:
name: ArmCordLinuxArm64
path: linux
- name: Get some values needed for the release
id: vars
shell: bash
run: |
echo "::set-output name=releaseTag::$(git describe --tags --abbrev=0)"
- uses: dev-drprasad/delete-tag-and-release@v0.2.0
with:
delete_release: true
tag_name: ${{ steps.vars.outputs.releaseTag }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create Release
uses: actions/github-script@v2
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
console.log('environment', process.versions);
const fs = require('fs').promises;
const { repo: { owner, repo }, sha } = context;
console.log({ owner, repo, sha });
const release = await github.repos.createRelease({
owner, repo,
tag_name: process.env.releaseTag,
draft: true,
target_commitish: sha
});
console.log('created release', { release });
for (let file of await fs.readdir('linux')) {
// do whatever filtering you want here, I'm just uploading all the files
console.log('uploading', file);
await github.repos.uploadReleaseAsset({
owner, repo,
release_id: release.data.id,
name: file,
data: await fs.readFile(`./linux/${file}`)
});
}
for (let file of await fs.readdir('windows')) {
// do whatever filtering you want here, I'm just uploading all the files
console.log('uploading', file);
await github.repos.uploadReleaseAsset({
owner, repo,
release_id: release.data.id,
name: file,
data: await fs.readFile(`./windows/${file}`)
});
}
for (let file of await fs.readdir('macos')) {
// do whatever filtering you want here, I'm just uploading all the files
console.log('uploading', file);
await github.repos.uploadReleaseAsset({
owner, repo,
release_id: release.data.id,
name: file,
data: await fs.readFile(`./macos/${file}`)
});
}

3
.gitignore vendored
View file

@ -2,4 +2,5 @@ node_modules
out/ out/
dist dist
ts-out/ ts-out/
ts-out ts-out
package-lock.json

View file

@ -1,6 +1,6 @@
<div align="center"> <div align="center">
<img src="https://armcord.vercel.app/armcord_full_logo.png" width="720"> <img src="https://armcord.vercel.app/armcord_full_logo.png" width="520">
<br>ArmCord is a custom client designed to enhance your Discord experience while keeping everything lightweight. <br>ArmCord is a custom client designed to enhance your Discord experience while keeping everything lightweight.
</div> </div>
@ -35,17 +35,22 @@
Check releases tab for precompiled packages for Linux, Windows and Mac OS. Alternatively use our Sourceforge mirror. Check releases tab for precompiled packages for Linux, Windows and Mac OS. Alternatively use our Sourceforge mirror.
<a href="https://sourceforge.net/projects/armcord/files/latest/download"><img alt="Download ArmCord" src="https://a.fsdn.com/con/app/sf-download-button" width=276 height=48 srcset="https://a.fsdn.com/con/app/sf-download-button?button_size=2x 2x"></a> <a href="https://sourceforge.net/projects/armcord/files/latest/download"><img alt="Download ArmCord" src="https://a.fsdn.com/con/app/sf-download-button" width=276 height=48 srcset="https://a.fsdn.com/con/app/sf-download-button?button_size=2x 2x"></a>
### AUR Package ### AUR Package
Armcord is also available on the Arch User Repository (AUR) [here](https://aur.archlinux.org/packages/armcord-bin/). ArmCord is also available on the Arch User Repository (AUR) [here](https://aur.archlinux.org/packages/armcord-bin/).
Install it via an AUR helper tool like `yay`. Install it via an AUR helper tool like `yay`.
**Example:** `yay -S armcord-bin` **Example:** `yay -S armcord-bin`
### Snap package
ArmCord is also available on the Snap store [here](https://snapcraft.io/armcord).
<a href="https://snapcraft.io/armcord">
<img alt="Get it from the Snap Store" src="https://snapcraft.io/static/images/badges/en/snap-store-black.svg" />
</a>
### Manual: ### Manual:
Alternatively you can run ArmCord from source (npm, nodejs required): Alternatively you can run ArmCord from source (npm, nodejs required):
1. Clone ArmCord repo: `git clone https://github.com/ArmCord/ArmCord.git` 1. Clone ArmCord repo: `git clone https://github.com/ArmCord/ArmCord.git`
2. Run `npm install` to install dependencies 2. Run `npm install` to install dependencies
3. Compile/Package with `npm run package` 3. Build with `npm run build`
4. Compile/Package with `npm run package`
# FAQ # FAQ
@ -67,7 +72,8 @@ Install it via an AUR helper tool like `yay`.
[GooseMod Extension](https://github.com/GooseMod/extension) [GooseMod Extension](https://github.com/GooseMod/extension)
[electron-discord-webapp](https://github.com/SpacingBat3/electron-discord-webapp) [electron-discord-webapp](https://github.com/SpacingBat3/electron-discord-webapp)
[custom-electron-titlebar (css only)](https://github.com/AlexTorresSk/custom-electron-titlebar) [custom-electron-titlebar (css only)](https://github.com/AlexTorresSk/custom-electron-titlebar)
[electron-builder](https://electron.build) [electron-builder](https://electron.build)
[OpenAsar](https://github.com/GooseMod/OpenAsar)
# Sponsors # Sponsors
[![JetBrains supports ArmCord with free licenses to their software to core developers](https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg)](https://jb.gg/OpenSourceSupport) [![JetBrains supports ArmCord with free licenses to their software to core developers](https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.svg)](https://jb.gg/OpenSourceSupport)

View file

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

6313
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@
"description": "ArmCord is a custom client designed to enhance your Discord experience while keeping everything lightweight.", "description": "ArmCord is a custom client designed to enhance your Discord experience while keeping everything lightweight.",
"main": "ts-out/main.js", "main": "ts-out/main.js",
"scripts": { "scripts": {
"build": "tsc && copyfiles -u 1 src/**/*.html src/**/**/*.css ts-out/ && copyfiles package.json ts-out/ && copyfiles assets/** ts-out/", "build": "tsc && copyfiles -u 1 src/**/*.html src/**/**/*.css ts-out/ && copyfiles package.json ts-out/ && copyfiles assets/**/** ts-out/",
"watch": "tsc -w", "watch": "tsc -w",
"start": "npm run build && electron ./ts-out/main.js", "start": "npm run build && electron ./ts-out/main.js",
"package": "npm run build && electron-builder", "package": "npm run build && electron-builder",
@ -26,7 +26,7 @@
"@types/node": "^17.0.33", "@types/node": "^17.0.33",
"@types/ws": "^8.5.3", "@types/ws": "^8.5.3",
"copyfiles": "^2.4.1", "copyfiles": "^2.4.1",
"electron": "^18.2.3", "electron": "^18.2.4",
"electron-builder": "^23.0.3", "electron-builder": "^23.0.3",
"husky": "^8.0.1", "husky": "^8.0.1",
"prettier": "^2.5.1", "prettier": "^2.5.1",

View file

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

File diff suppressed because one or more lines are too long

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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