Compare commits

..

49 commits

Author SHA1 Message Date
smartfrigde
538bd10412 v3.0.7 2022-06-17 15:05:16 +02:00
smartfrigde
9efce82462 Add fallback to English 2022-06-17 09:37:18 +02:00
smartfrigde
a216475618 Add theme loader 2022-06-16 23:09:41 +02:00
smartfrigde
b7a0d1face formatting 2022-06-16 17:31:57 +02:00
smartfrigde
0b165e64bc Remove left over from tabs in armcord api 2022-06-16 17:31:57 +02:00
Hosted Weblate
8c62d9dd86
Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Translation: ArmCord/ArmCord
Translate-URL: https://hosted.weblate.org/projects/armcord/armcord/
2022-06-16 17:25:18 +02:00
smartfrigde
86f885c41f Add window state manager 2022-06-16 17:25:09 +02:00
dfa1665b19
Translated using Weblate (Thai)
Currently translated at 100.0% (28 of 28 strings)

Translation: ArmCord/ArmCord
Translate-URL: https://hosted.weblate.org/projects/armcord/armcord/th/
2022-06-16 17:19:39 +02:00
altinat
3957bb1c57
Translated using Weblate (Thai)
Currently translated at 100.0% (28 of 28 strings)

Translation: ArmCord/ArmCord
Translate-URL: https://hosted.weblate.org/projects/armcord/armcord/th/
2022-06-15 16:33:58 +02:00
Anonymous
31e3426ad1
Translated using Weblate (Thai)
Currently translated at 100.0% (0 of 0 strings)

Translation: ArmCord/ArmCord
Translate-URL: https://hosted.weblate.org/projects/armcord/armcord/th/
2022-06-15 12:58:55 +02:00
lukacchi
715afdd79d
Translated using Weblate (Spanish (Latin America))
Currently translated at 96.4% (27 of 28 strings)

Translation: ArmCord/ArmCord
Translate-URL: https://hosted.weblate.org/projects/armcord/armcord/es_419/
2022-06-15 12:58:54 +02:00
altinat
e7c6b2101d
Added translation using Weblate (Thai) 2022-06-15 12:58:51 +02:00
Anonymous
72c35cb2f3
Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (0 of 0 strings)

Translation: ArmCord/ArmCord
Translate-URL: https://hosted.weblate.org/projects/armcord/armcord/es_419/
2022-06-14 19:12:41 +02:00
smartfridge
4cf0187ef8
Added translation using Weblate (Spanish (Latin America)) 2022-06-14 19:12:34 +02:00
Hosted Weblate
f677b0e4fb
Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Translation: ArmCord/ArmCord
Translate-URL: https://hosted.weblate.org/projects/armcord/armcord/
2022-06-14 17:55:22 +02:00
smartfrigde
7f9b93dc79 Remove unused translation string 2022-06-14 17:55:14 +02:00
smartfrigde
a29cb2a6a5 Add translation loading to splash 2022-06-14 17:54:50 +02:00
smartfrigde
c979328aee Remove glasstron and tabs completely 2022-06-14 17:02:37 +02:00
smartfrigde
8d85591e1c Change default tray icon for macOS to avoid issues 2022-06-14 16:49:12 +02:00
smartfrigde
c6e2244ce8 Move attribute logic to main 2022-06-14 16:30:18 +02:00
smartfrigde
9ab08b16d8 Update dependencies 2022-06-14 16:07:33 +02:00
smartfrigde
e86b1a8924 Don't remove the getLang handler 2022-06-14 14:55:47 +02:00
smartfrigde
ef73af66c4 Move the getLang handler to main ipc module instead of storing it in settings 2022-06-14 14:54:34 +02:00
smartfrigde
bdb09bb912 Remove unwanted getLang handlers 2022-06-14 14:53:26 +02:00
smartfrigde
7f53710d6a Remove unused import 2022-06-12 22:17:09 +02:00
smartfrigde
0a7ec74b0f I forgot to uncomment a function 2022-06-12 21:03:58 +02:00
smartfrigde
86c3636a19 Add setup translation loading 2022-06-12 20:59:59 +02:00
smartfrigde
994ab5f5b0 Add fallback to English US if language doesn't exist 2022-06-12 13:32:54 +02:00
Phorcys
ade35473a8
Translated using Weblate (French)
Currently translated at 100.0% (30 of 30 strings)

Translation: ArmCord/ArmCord
Translate-URL: https://hosted.weblate.org/projects/armcord/armcord/fr/
2022-06-12 13:18:36 +02:00
smartfrigde
f9bfed7585 Add translation loading for settings 2022-06-12 13:18:31 +02:00
smartfridge
410c899c84
Translated using Weblate (Polish)
Currently translated at 100.0% (30 of 30 strings)

Translation: ArmCord/ArmCord
Translate-URL: https://hosted.weblate.org/projects/armcord/armcord/pl/
2022-06-12 00:15:32 +02:00
smartfrigde
fa24b7996f Add language detection from Discord 2022-06-11 22:14:33 +02:00
Anonymous
e518c0f04e
Translated using Weblate (Indonesian)
Currently translated at 0.0% (0 of 30 strings)

Translation: ArmCord/ArmCord
Translate-URL: https://hosted.weblate.org/projects/armcord/armcord/id/
2022-06-10 23:22:42 +02:00
Anonymous
113a693603
Translated using Weblate (Polish)
Currently translated at 76.6% (23 of 30 strings)

Translation: ArmCord/ArmCord
Translate-URL: https://hosted.weblate.org/projects/armcord/armcord/pl/
2022-06-10 23:22:41 +02:00
Anonymous
85dea97312
Translated using Weblate (Dutch)
Currently translated at 76.6% (23 of 30 strings)

Translation: ArmCord/ArmCord
Translate-URL: https://hosted.weblate.org/projects/armcord/armcord/nl/
2022-06-10 23:22:41 +02:00
Anonymous
00bf23667b
Translated using Weblate (Norwegian Bokmål)
Currently translated at 76.6% (23 of 30 strings)

Translation: ArmCord/ArmCord
Translate-URL: https://hosted.weblate.org/projects/armcord/armcord/nb_NO/
2022-06-10 23:22:41 +02:00
Anonymous
7f524b1559
Translated using Weblate (Italian)
Currently translated at 76.6% (23 of 30 strings)

Translation: ArmCord/ArmCord
Translate-URL: https://hosted.weblate.org/projects/armcord/armcord/it/
2022-06-10 23:22:41 +02:00
Anonymous
478c2da61a
Translated using Weblate (French)
Currently translated at 76.6% (23 of 30 strings)

Translation: ArmCord/ArmCord
Translate-URL: https://hosted.weblate.org/projects/armcord/armcord/fr/
2022-06-10 23:22:40 +02:00
smartfrigde
b43a992027 Tweak translations a bit 2022-06-10 23:22:32 +02:00
Anonymous
b8b1d04d24
Translated using Weblate (Indonesian)
Currently translated at 100.0% (0 of 0 strings)

Translation: ArmCord/ArmCord
Translate-URL: https://hosted.weblate.org/projects/armcord/armcord/id/
2022-06-10 22:38:33 +02:00
Ufal Salman
465a072e67
Added translation using Weblate (Indonesian) 2022-06-10 22:38:33 +02:00
smartfrigde
0f6f650be2 Add 16x16 icon 2022-06-10 22:38:27 +02:00
smartfrigde
a12463877a Add macOS tray icon potential fix 2022-06-10 22:29:43 +02:00
smartfrigde
98f88f4609 Fix icon loading 2022-06-10 20:46:30 +02:00
smartfrigde
81377d3657 Add performance mode 2022-06-10 20:27:37 +02:00
KayoticCarnige
40d743d0e2 Fixed "null" bug
Fixed "null" bug, where on Windows, Discord wouldn't recognize the OS (Only tested onw Windows 10)
2022-06-03 12:05:28 -04:00
smartfrigde
54b1481a4e Update WindowOpenHandler to be much more secure 2022-06-03 15:18:36 +02:00
smartfrigde
12352e3536 Fix icon generating on Debian 2022-06-02 14:28:42 +02:00
smartfrigde
13eb57d17d Add the stable release workflow onto dev 2022-06-02 14:27:29 +02:00
28 changed files with 531 additions and 322 deletions

View file

@ -138,7 +138,7 @@ jobs:
- uses: dev-drprasad/delete-tag-and-release@v0.2.0
with:
delete_release: true
tag_name: v3.0.6
tag_name: v3.0.7
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create Release
@ -193,4 +193,4 @@ jobs:
});
}
env:
releaseTag: ${{ steps.vars.outputs.releaseTag }}
releaseTag: ${{ steps.vars.outputs.releaseTag }}

View file

@ -1,5 +0,0 @@
{
"yaml.schemas": {
"https://json.schemastore.org/github-workflow.json": "file:///home/smartfridge/Documents/ArmCord/.github/workflows/build.yml"
}
}

View file

@ -12,17 +12,19 @@
"no": "No",
"next": "Next",
"setup_question4": "Select a client mod you want to install:",
"setup_question4_clientmodnotice": "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.",
"settings-theme": "ArmCord Theme:",
"settings-theme-glasstron": "Glasstron (experimental)",
"settings-theme-tabs": "Tabs (experimental)",
"setup_question4_clientmodnotice": "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 Discord.",
"settings-theme": "ArmCord theme:",
"settings-theme-default": "Default",
"settings-theme-native": "Native",
"settings-tray": "Minimize to tray",
"settings-patches": "Automatic Patches",
"settings-channel": "Discord channel:",
"settings-invitewebsocket": "discord.gg support",
"settings-invitewebsocket": "Invite Websocket",
"settings-mod": "Client mod:",
"settings-prfmMode": "Performance mode:",
"settings-prfmMode-performance": "Performance",
"settings-prfmMode-battery": "Battery",
"settings-none": "None",
"settings-save": "Save settings",
"settings-updater": "Check for updates"
}

30
assets/lang/es-419.json Normal file
View file

@ -0,0 +1,30 @@
{
"loading_screen_start": "Cargando ArmCord…",
"loading_screen_offline": "Parece que no estás conectado a la Internet. Por favor conectate e intentalo de nuevo.",
"loading_screen_update": "Una nueva version de ArmCord está disponible. Por favor actualiza a la última version.",
"setup_question1": "Escoge que tipo de instalación quieres hacer:",
"yes": "Sí",
"setup_question2": "Escoge tu version de Discord:",
"setup_question3": "Dejar que ArmCord se encargue de la instalacion de modificaciones?",
"setup_question1_answer1": "Instalación rápida",
"setup_question1_answer2": "Instalación completa",
"setup_offline": "Parece que no estás conectado a la Internet. Por favor conectate a la Internet e reinicia el instalador de ArmCord.",
"no": "No",
"next": "Siguiente",
"setup_question4": "Selecciona una modificación que te gustaría instalar:",
"setup_question4_clientmodnotice": "Por qué no instalar todas las modificaciones? Tener varias modificaciones a la vez puede causar problemas. Si realmente quieres hacerlo, puedes unirte a nuestro Discord.",
"settings-theme": "Tema de ArmCord:",
"settings-theme-default": "Por Defecto",
"settings-theme-native": "Nativa",
"settings-tray": "Minimizar a la barra de tareas",
"settings-patches": "Automatizar Parches",
"settings-channel": "Version de Discord:",
"settings-invitewebsocket": "Websocket de Invitación",
"settings-mod": "Modificación:",
"settings-prfmMode": "Modo de Rendimiento:",
"settings-prfmMode-performance": "Rendimiento",
"settings-prfmMode-battery": "Batería",
"settings-none": "Ninguna",
"settings-save": "Guardar ajustes",
"settings-updater": "Buscar una actualización"
}

View file

@ -1,6 +1,6 @@
{
"loading_screen_start": "Démarrage d'ArmCord…",
"loading_screen_update": "Une nouvelle version de ArmCord est disponible. Veuillez mettre à jour la dernière version.",
"loading_screen_update": "Une nouvelle version d'ArmCord est disponible. Veuillez mettre à jour vers la dernière version.",
"setup_question1": "Sélectionnez le type de configuration que vous souhaitez effectuer :",
"setup_question1_answer1": "Configuration express",
"setup_question1_answer2": "Configuration complète",
@ -10,19 +10,21 @@
"no": "Non",
"next": "Suivant",
"setup_question4": "Sélectionnez le mod client que vous souhaitez installer :",
"setup_question4_clientmodnotice": "Pourquoi pas tous ? Le fait d'avoir plusieurs mods clients en même temps peut causer des problèmes. Si vous voulez vraiment le faire, consultez notre documentation.",
"setup_question4_clientmodnotice": "Pourquoi pas tous ? Le fait d'avoir plusieurs clients mods en même temps peut causer des problèmes. Si vous voulez vraiment le faire, consultez notre Discord.",
"loading_screen_offline": "Vous semblez être hors ligne. Veuillez vous connecter à internet et réessayer.",
"setup_offline": "Vous semblez être hors ligne. Veuillez vous connecter à internet et redémarrer ArmCord Setup.",
"setup_offline": "Vous semblez être hors ligne. Veuillez vous connecter à internet et redémarrer l'installateur ArmCord.",
"settings-tray": "Minimize to tray",
"settings-channel": "Discord channel:",
"settings-mod": "Client mod:",
"settings-save": "Save settings",
"settings-updater": "Check for updates",
"settings-theme": "ArmCord Theme:",
"settings-theme-tabs": "Tabs (experimental)",
"settings-theme": "Thème ArmCord :",
"settings-theme-default": "Default",
"settings-theme-glasstron": "Glasstron (experimental)",
"settings-theme-native": "Native",
"settings-patches": "Automatic Patches",
"settings-invitewebsocket": "discord.gg support"
"settings-invitewebsocket": "Lien discord.gg",
"settings-prfmMode": "Mode performance :",
"settings-prfmMode-performance": "Performance",
"settings-prfmMode-battery": "Batterie",
"settings-none": "Aucun"
}

30
assets/lang/id-ID.json Normal file
View file

@ -0,0 +1,30 @@
{
"loading_screen_start": "Starting ArmCord…",
"loading_screen_offline": "You appear to be offline. Please connect to the Internet and try again.",
"loading_screen_update": "A new version of ArmCord is available. Please update to the latest version.",
"setup_question1": "Select what kind of setup you want to perform:",
"setup_question1_answer1": "Express setup",
"setup_question1_answer2": "Full setup",
"setup_question2": "Choose your Discord channel/instance:",
"setup_offline": "You appear to be offline. Please connect to the Internet and restart the ArmCord setup.",
"setup_question3": "Should ArmCord handle client mods installation?",
"yes": "Yes",
"no": "No",
"next": "Next",
"setup_question4": "Select a client mod you want to install:",
"setup_question4_clientmodnotice": "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.",
"settings-theme": "ArmCord Theme:",
"settings-theme-default": "Default",
"settings-theme-native": "Native",
"settings-tray": "Minimize to tray",
"settings-patches": "Automatic Patches",
"settings-channel": "Discord channel:",
"settings-invitewebsocket": "discord.gg support",
"settings-mod": "Client mod:",
"settings-save": "Save settings",
"settings-updater": "Check for updates",
"settings-prfmMode": "Performance mode:",
"settings-prfmMode-performance": "Performance",
"settings-prfmMode-battery": "Battery",
"settings-none": "None"
}

View file

@ -19,10 +19,12 @@
"settings-updater": "Controlla gli aggiornamenti",
"settings-mod": "Client mod:",
"settings-theme": "ArmCord Theme:",
"settings-theme-glasstron": "Glasstron (experimental)",
"settings-theme-tabs": "Tabs (experimental)",
"settings-theme-default": "Default",
"settings-theme-native": "Native",
"settings-patches": "Automatic Patches",
"settings-invitewebsocket": "discord.gg support"
"settings-invitewebsocket": "discord.gg support",
"settings-prfmMode": "Performance mode:",
"settings-prfmMode-performance": "Performance",
"settings-prfmMode-battery": "Battery",
"settings-none": "None"
}

View file

@ -19,10 +19,12 @@
"settings-save": "Save settings",
"settings-updater": "Check for updates",
"settings-theme": "ArmCord Theme:",
"settings-theme-glasstron": "Glasstron (experimental)",
"settings-theme-tabs": "Tabs (experimental)",
"settings-theme-default": "Default",
"settings-theme-native": "Native",
"settings-patches": "Automatic Patches",
"settings-invitewebsocket": "discord.gg support"
"settings-invitewebsocket": "discord.gg support",
"settings-prfmMode": "Performance mode:",
"settings-prfmMode-performance": "Performance",
"settings-prfmMode-battery": "Battery",
"settings-none": "None"
}

View file

@ -20,9 +20,11 @@
"settings-updater": "Check voor updates",
"settings-patches": "Automatische Patches",
"settings-theme": "ArmCord Thema:",
"settings-theme-glasstron": "Glasstron (experimenteel)",
"settings-theme-tabs": "Tabs (experimenteel)",
"settings-theme-default": "Standaard",
"settings-theme-native": "Native",
"settings-invitewebsocket": "discord.gg support"
"settings-invitewebsocket": "discord.gg support",
"settings-none": "None",
"settings-prfmMode": "Performance mode:",
"settings-prfmMode-performance": "Performance",
"settings-prfmMode-battery": "Battery"
}

View file

@ -7,7 +7,7 @@
"no": "Nie",
"next": "Dalej",
"setup_question4": "Wybierz modyfikację klienta którą chcesz zainstalować:",
"setup_question4_clientmodnotice": "Dlaczego nie wszystkie na raz? Posiadanie wielu modyfikacji może spowodować wiele błędów. Jeśli jednak nalegasz możesz sprawdzić naszą dokumentację.",
"setup_question4_clientmodnotice": "Dlaczego nie wszystkie na raz? Posiadanie wielu modyfikacji może spowodować wiele błędów. Jeśli jednak nalegasz możesz sprawdzić naszego Discorda.",
"loading_screen_start": "Ładowanie ArmCord…",
"loading_screen_offline": "Wydaje nam się, że nie jesteś połączony z Internetem. Połącz się z internetem i spróbuj ponownie.",
"setup_question1_answer1": "Ekspresowa konfiguracja",
@ -19,10 +19,12 @@
"settings-save": "Zapisz ustawienia",
"settings-mod": "Modyfikacja klienta:",
"settings-theme": "Motyw ArmCord:",
"settings-theme-glasstron": "Glasstron (eksperymentalne)",
"settings-theme-tabs": "Karty (eksperymentalne)",
"settings-theme-default": "Domyślny",
"settings-theme-native": "Natywny",
"settings-patches": "Automatyczne łatki",
"settings-invitewebsocket": "Wsparcie linków discord.gg"
"settings-invitewebsocket": "Websocket dla zaproszeń",
"settings-prfmMode": "Tryb wydajności:",
"settings-prfmMode-performance": "Wydajny",
"settings-prfmMode-battery": "Bateria",
"settings-none": "Nic/Brak"
}

30
assets/lang/th-TH.json Normal file
View file

@ -0,0 +1,30 @@
{
"loading_screen_start": "เริ่มต้น ArmCord…",
"loading_screen_offline": "ดูเหมือนว่าคุณออฟไลน์อยู่ โปรดเชื่อมต่ออินเทอร์เน็ตและลองใหม่อีกครั้ง",
"loading_screen_update": "ArmCord เวอร์ชันใหม่พร้อมใช้งานแล้ว โปรดอัปเดตเป็นเวอร์ชันล่าสุด",
"setup_question1": "เลือกประเภทการติดตั้งที่คุณต้องการ:",
"setup_question1_answer1": "ติดตั้งแบบรวดเร็ว",
"setup_question1_answer2": "การตั้งค่าเต็มรูปแบบ",
"setup_offline": "ดูเหมือนว่าคุณออฟไลน์อยู่ โปรดเชื่อมต่ออินเทอร์เน็ตและลองใหม่อีกครั้ง",
"setup_question2": "เลือกช่อง/อินสแตนส์ Discord:",
"setup_question3": "ต้องการให้ ArmCord จัดการการติดตั้งมอดของไคลเอนต์หรือไม่?",
"yes": "ใช่",
"no": "ไม่",
"next": "ถัดไป",
"setup_question4": "เลือกไคลเอนต์มอดที่ต้องการติดตั้ง:",
"settings-prfmMode-battery": "แบตเตอรี่",
"setup_question4_clientmodnotice": "ทำไมไม่ใช้ทั้งหมดล่ะ? การมีไคลเอนต์มอดหลายตัวพร้อมกันอาจทำให้เกิดปัญหาได้ หากต้องการที่จะทำจริงๆ ให้ไปดูใน Discord ของเรา",
"settings-theme": "ธีม ArmCord:",
"settings-theme-default": "ค่าเริ่มต้น",
"settings-theme-native": "ดั้งเดิม",
"settings-tray": "ย่อลงไปในถาดงาน",
"settings-patches": "แพทช์อัตโนมัติ",
"settings-channel": "ช่อง Discord:",
"settings-invitewebsocket": "ใช้ Websocket สำหรับการเชิญ",
"settings-prfmMode": "โหมดประสิทธิภาพ:",
"settings-prfmMode-performance": "ประสิทธิภาพ",
"settings-mod": "ไคลแอนต์มอด:",
"settings-none": "ไม่มี",
"settings-save": "บันทึกการตั้งค่า",
"settings-updater": "ตรวจหาการอัปเดต"
}

BIN
assets/macos.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -1,6 +1,6 @@
{
"name": "ArmCord",
"version": "3.0.6",
"version": "3.0.7",
"description": "ArmCord is a custom client designed to enhance your Discord experience while keeping everything lightweight.",
"main": "ts-out/main.js",
"scripts": {
@ -23,19 +23,20 @@
},
"homepage": "https://github.com/armcord/armcord#readme",
"devDependencies": {
"@types/node": "^17.0.33",
"@types/node": "^17.0.42",
"@types/ws": "^8.5.3",
"copyfiles": "^2.4.1",
"electron": "^18.2.4",
"electron": "^19.0.4",
"electron-builder": "^23.0.3",
"husky": "^8.0.1",
"prettier": "^2.5.1",
"typescript": "^4.6.3"
"prettier": "^2.7.0",
"typescript": "^4.7.3"
},
"dependencies": {
"electron-context-menu": "github:ArmCord/electron-context-menu",
"os-locale": "^6.0.2",
"v8-compile-cache": "^2.3.0",
"ws": "^8.6.0"
"ws": "^8.8.0"
},
"build": {
"appId": "com.smartfridge.armcord",

View file

@ -1,46 +0,0 @@
.tabs {
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;
}
.tabs #tabs-controls-container {
float: left;
width: 150px;
height: 100%;
line-height: 30px;
background-color: #202225;
-webkit-app-region: no-drag;
}
.tabs-buttons {
color: white;
background-color: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
transition: 0.3s;
font-size: 20px;
}
.tabs-buttons:hover {
background-color: #4e515a;
}
.withFrame-haYltI {
height: 30px !important;
}

View file

@ -12,12 +12,14 @@
<body>
<div class="container">
<div id="warning" class="hidden">
<p>You appear to be offline. Please connect to the internet and restart ArmCord Setup.</p>
<p id="setup_offline">
You appear to be offline. Please connect to the internet and restart ArmCord Setup.
</p>
</div>
<div id="setup">
<div id="logo" class="hidden"></div>
<div id="page1" class="hidden">
<p>Select the type of setup you want to perform.</p>
<p id="setup_question1">Select the type of setup you want to perform.</p>
<div id="buttons">
<button id="express" class="center">Express</button>
<button id="full" class="center">Full</button>
@ -25,7 +27,7 @@
</div>
<div id="page2" class="hidden">
<p class="text-center setup-ask">Choose your Discord channel/instance:</p>
<p class="text-center setup-ask" id="setup_question2">Choose your Discord channel/instance:</p>
<div class="center">
<select name="channel" id="channel" class="dropdown-button">
<option value="stable">Stable</option>
@ -34,7 +36,9 @@
<option value="foss">Fosscord</option>
</select>
</div>
<p class="text-center setup-ask">Should ArmCord handle client mods installation?</p>
<p class="text-center setup-ask" id="setup_question3">
Should ArmCord handle client mods installation?
</p>
<div class="center">
<select name="csp" id="csp" class="dropdown-button">
<option value="true">Yes</option>
@ -47,7 +51,7 @@
</div>
<div id="page3" class="hidden">
<p class="text-center setup-ask">Select a client mod you want to install:</p>
<p class="text-center setup-ask" id="setup_question4">Select a client mod you want to install:</p>
<div class="center">
<select name="mod" id="mod" class="dropdown-button">
<option value="cumcord">Cumcord</option>
@ -55,9 +59,9 @@
<option value="flicker">Flicker (Heavily WIP)</option>
</select>
</div>
<p class="text-center">
<p class="text-center" id="setup_question4_clientmodnotice">
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 Discord ;)
</p>
<div id="buttons">
<button id="next" class="center">Next</button>
@ -65,7 +69,25 @@
</div>
</div>
</div>
<script>
async function loadLang() {
document.getElementById("next").innerHTML = await armcord.getLang("next");
document.getElementById("setup_offline").innerHTML = await armcord.getLang("setup_offline");
document.getElementById("setup_question1").innerHTML = await armcord.getLang("setup_question1");
document.getElementById("express").innerHTML = await armcord.getLang("setup_question1_answer1");
document.getElementById("full").innerHTML = await armcord.getLang("setup_question1_answer2");
document.getElementById("setup_question2").innerHTML = await armcord.getLang("setup_question2");
document.getElementById("setup_question3").innerHTML = await armcord.getLang("setup_question3");
document.getElementById("setup_question4").innerHTML = await armcord.getLang("setup_question4");
document.getElementById("setup_question4_clientmodnotice").innerHTML = await armcord.getLang(
"setup_question4_clientmodnotice"
);
//select stuff1
document.getElementById("csp").options[1].text = await armcord.getLang("no");
document.getElementById("csp").options[0].text = await armcord.getLang("yes");
}
loadLang();
</script>
<script>
document.onload = function () {
ipcRenderer.send("win-unmaximize");
@ -101,7 +123,7 @@
automaticPatches: false,
mods: "cumcord",
inviteWebsocket: true,
blurType: "acrylic"
performanceMode: "none"
});
setTimeout(() => window.armcordinternal.restart(), 5000);
});
@ -130,9 +152,9 @@
autoLaunch: true,
minimizeToTray: true,
automaticPatches: false,
performanceMode: "none",
mods: options.mod,
inviteWebsocket: true,
blurType: "acrylic"
inviteWebsocket: true
});
setTimeout(() => window.armcordinternal.restart(), 500);
});
@ -145,8 +167,8 @@
automaticPatches: false,
autoLaunch: true,
mods: "none",
inviteWebsocket: true,
blurType: "acrylic"
performanceMode: "none",
inviteWebsocket: true
});
setTimeout(() => window.armcordinternal.restart(), 500);
}

View file

@ -17,52 +17,53 @@
</div>
</body>
<script>
const text = document.getElementById("text-splashscreen");
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...";
if (window.armcord.version === "DEV") {
console.log("Running a development build of ArmCord. Skipping updater.");
async function loadLang() {
const text = document.getElementById("text-splashscreen");
if (window.navigator.onLine === false) {
text.innerHTML = await armcord.getLang("loading_screen_offline");
} else {
fetch("https://armcord.xyz/latest.json")
.then((response) => response.json())
.then((data) => {
if (data.version !== window.armcord.version) {
var elem = document.createElement("img");
elem.classList.add("logo");
elem.src = "https://armcord.smartfridge.space/update.webp";
document.body.prepend(elem);
document.getElementById("splashscreen-armcord").remove();
text.innerHTML =
"A new version of ArmCord is available. Please update to the latest version.";
} else {
console.log("ArmCord is up to date.");
}
});
}
setTimeout(() => {
window.armcordinternal.splashEnd();
switch (window.armcord.channel) {
case "stable":
window.location.replace("https://discord.com/app");
break;
case "canary":
window.location.replace("https://canary.discord.com/app");
break;
case "ptb":
window.location.replace("https://ptb.discord.com/app");
break;
case "foss":
window.location.replace("https://dev.fosscord.com/app");
break;
case undefined:
window.location.replace("https://discord.com/app");
break;
default:
window.location.replace("https://discord.com/app");
text.innerHTML = await armcord.getLang("loading_screen_start");
if (window.armcord.version === "DEV") {
console.log("Running a development build of ArmCord. Skipping updater.");
} else {
const response = await fetch("https://armcord.xyz/latest.json");
const data = await response.json();
if (data.version !== window.armcord.version) {
var elem = document.createElement("img");
elem.classList.add("logo");
elem.src = "https://armcord.smartfridge.space/update.webp";
document.body.prepend(elem);
document.getElementById("splashscreen-armcord").remove();
text.innerHTML = await armcord.getLang("loading_screen_update");
} else {
console.log("ArmCord is up to date.");
}
}
}, 5000);
setTimeout(() => {
window.armcordinternal.splashEnd();
switch (window.armcord.channel) {
case "stable":
window.location.replace("https://discord.com/app");
break;
case "canary":
window.location.replace("https://canary.discord.com/app");
break;
case "ptb":
window.location.replace("https://ptb.discord.com/app");
break;
case "foss":
window.location.replace("https://dev.fosscord.com/app");
break;
case undefined:
window.location.replace("https://discord.com/app");
break;
default:
window.location.replace("https://discord.com/app");
}
}, 5000);
}
}
loadLang();
</script>
</html>

View file

@ -1,15 +1,18 @@
//ipc stuff
import {app, ipcMain, shell, desktopCapturer} from "electron";
import {createTabsGuest, mainWindow} from "./window";
import {setConfigBulk, getVersion, getConfig} from "./utils";
import {customTitlebar, tabs} from "./main";
import {mainWindow} from "./window";
import {setConfigBulk, getVersion, getConfig, setLang, getLang, getWindowState} from "./utils";
import {customTitlebar} from "./main";
import {createSettingsWindow} from "./settings/main";
export function registerIpc() {
ipcMain.on("get-app-path", (event, arg) => {
event.reply("app-path", app.getAppPath());
});
ipcMain.on("openTab", (event, number: number) => {
createTabsGuest(number);
ipcMain.on("setLang", (event, lang: string) => {
setLang(lang);
});
ipcMain.handle("getLang", (event, toGet: string) => {
return getLang(toGet);
});
ipcMain.on("open-external-link", (event, href: string) => {
shell.openExternal(href);
@ -38,8 +41,22 @@ export function registerIpc() {
ipcMain.on("get-app-version", (event) => {
event.returnValue = getVersion();
});
ipcMain.on("splashEnd", (event, arg) => {
mainWindow.setSize(800, 600);
ipcMain.on("splashEnd", async (event, arg) => {
try {
var width = await getWindowState("width") ?? 800;
var height= await getWindowState("height") ?? 600;
var isMaximized = await getWindowState("isMaximized") ?? false;
} catch (e) {
console.log("No window state file found. Fallbacking to default values.")
mainWindow.setSize(800, 600);
}
if (isMaximized) {
mainWindow.setSize(800, 600); //just so the whole thing doesn't cover whole screen
mainWindow.maximize()
} else {
mainWindow.setSize(width, height);
console.log("Not maximized.")
}
});
ipcMain.on("restart", (event, arg) => {
app.relaunch();
@ -60,9 +77,6 @@ export function registerIpc() {
ipcMain.on("titlebar", (event, arg) => {
event.returnValue = customTitlebar;
});
ipcMain.on("tabs", (event, arg) => {
event.returnValue = tabs;
});
ipcMain.on("shouldPatch", async (event, arg) => {
event.returnValue = await getConfig("automaticPatches");
});

View file

@ -1,16 +1,15 @@
// Modules to control application life and create native browser window
import {app, BrowserWindow, session, dialog} from "electron";
import {app, BrowserWindow, session} from "electron";
import "v8-compile-cache";
import {getConfig, setup, checkIfConfigExists} from "./utils";
import {getConfig, checkIfConfigExists, injectElectronFlags} from "./utils";
import "./extensions/mods";
import "./extensions/plugin";
import "./tray";
import {createCustomWindow, createNativeWindow, createTabsHost} from "./window";
import {createCustomWindow, createNativeWindow} from "./window";
import "./shortcuts";
export var settings: any;
export var customTitlebar: boolean;
export var tabs: boolean;
if (process.platform == "linux") {
if (process.env.$XDG_SESSION_TYPE == "wayland") {
@ -24,7 +23,7 @@ if (process.platform == "linux") {
}
}
checkIfConfigExists();
injectElectronFlags();
app.whenReady().then(async () => {
switch (await getConfig("windowStyle")) {
case "default":
@ -37,17 +36,6 @@ app.whenReady().then(async () => {
case "discord":
createNativeWindow();
break;
case "glasstron":
dialog.showErrorBox(
"Glasstron is unsupported.",
"This build doesn't include Glasstron functionality, please edit windowStyle value in your settings.json to something different (default for example)"
);
app.quit();
break;
case "tabs":
createTabsHost();
tabs = true;
break;
default:
createCustomWindow();
customTitlebar = true;
@ -72,16 +60,8 @@ app.whenReady().then(async () => {
case "native":
createNativeWindow();
break;
case "glasstron":
dialog.showErrorBox(
"Glasstron is unsupported.",
"This build doesn't include Glasstron functionality, please edit windowStyle value in your settings.json to something different (default for example)"
);
app.quit();
break;
case "tabs":
createTabsHost();
tabs = true;
case "discord":
createNativeWindow();
break;
default:
createCustomWindow();

View file

@ -15,7 +15,11 @@ contextBridge.exposeInMainWorld("armcord", {
},
electron: process.versions.electron,
channel: ipcRenderer.sendSync("channel"),
openTab: (number: number) => ipcRenderer.sendSync("openTab", number),
setLang: (lang: string) => ipcRenderer.send("setLang", lang),
getLang: (toGet: string) =>
ipcRenderer.invoke("getLang", toGet).then((result) => {
return result;
}),
version: ipcRenderer.sendSync("get-app-version", "app-version"),
getDisplayMediaSelector: getDisplayMediaSelector,
openSettingsWindow: () => ipcRenderer.send("openSettingsWindow")

View file

@ -4,11 +4,18 @@ import "./patch";
import * as fs from "fs";
import * as path from "path";
import {injectTitlebar} from "./titlebar";
import {sleep, addStyle, injectJS} from "../utils";
import {sleep, addStyle, injectJS, addScript} from "../utils";
import {ipcRenderer} from "electron";
import {injectTabs} from "./tabs";
var version = ipcRenderer.sendSync("get-app-version", "app-version");
async function updateLang() {
if (window.location.href.indexOf("setup.html") > -1) {
console.log("Setup, skipping lang update");
} else {
addScript(`function getDiscordLang() {
{const _w=webpackChunkdiscord_app;let lang;_w.push([[Symbol()],{},e=>{for(const k in e.c){const m=e.c[k].exports;const mDef=m?.default&&m.__esModule?m.default:m;if(mDef?._chosenLocale&&!lang)lang=mDef}}]);_w.pop();window.armcord.setLang(lang._chosenLocale);return lang._chosenLocale;void 0}}
getDiscordLang();`);
}
}
declare global {
interface Window {
armcord: any;
@ -21,16 +28,16 @@ const clientMods = {
};
console.log("ArmCord");
ipcRenderer.on("themeLoader", (event, message) => {
addStyle(message);
});
if (window.location.href.indexOf("splash.html") > -1) {
console.log("Skipping titlebar injection and client mod injection.");
} else {
if (ipcRenderer.sendSync("titlebar")) {
injectTitlebar();
}
if (ipcRenderer.sendSync("tabs")) {
injectTabs();
}
sleep(5000).then(() => {
sleep(5000).then(async () => {
const cssPath = path.join(__dirname, "../", "/content/css/discord.css");
addStyle(fs.readFileSync(cssPath, "utf8"));
@ -38,14 +45,17 @@ if (window.location.href.indexOf("splash.html") > -1) {
case "goosemod":
injectJS(clientMods.goosemod);
console.log("Loading GooseMod...");
await updateLang();
break;
case "cumcord":
injectJS(clientMods.cumcord);
console.log("Loading Cumcord...");
await updateLang();
break;
case "flicker":
injectJS(clientMods.flicker);
console.log("Loading FlickerMod...");
await updateLang();
break;
}
});

View file

@ -1,26 +0,0 @@
import {addStyle} from "../utils";
import * as fs from "fs";
import * as path from "path";
export function injectTabs() {
document.addEventListener("DOMContentLoaded", function (event) {
var elem = document.createElement("div");
elem.innerHTML = `<nav class="tabs">
<div id="tabs-controls-container">
<button class="tabs-buttons" onclick="armcord.openTab(1)">1</button>
<button class="tabs-buttons" onclick="armcord.openTab(2)">2</button>
<button class="tabs-buttons" onclick="armcord.openTab(3)">3</button>
<button class="tabs-buttons" onclick="armcord.openTab(4)">4</button>
<button class="tabs-buttons" onclick="armcord.openTab(5)">5</button>
<p class="experimental">Experimental</p>
</div>
</nav>`;
elem.classList.add("withFrame-haYltI");
if (document.getElementById("app-mount") == null) {
document.body.appendChild(elem);
} else {
document.getElementById("app-mount")!.prepend(elem);
}
const cssPath = path.join(__dirname, "../", "/content/css/tabs.css");
addStyle(fs.readFileSync(cssPath, "utf8"));
});
}

View file

@ -38,10 +38,8 @@ export function injectTitlebar() {
maximize!.addEventListener("click", () => {
if (ipcRenderer.sendSync("win-isMaximized") == true) {
ipcRenderer.send("win-unmaximize");
document.body.removeAttribute("isMaximized");
} else {
ipcRenderer.send("win-maximize");
document.body.setAttribute("isMaximized", "");
}
});
@ -54,6 +52,3 @@ export function injectTitlebar() {
});
});
}
export function removeTitlebar() {
document.querySelector("#titlebar")!.remove();
}

View file

@ -1,5 +1,5 @@
import {BrowserWindow, shell, ipcMain} from "electron";
import {getConfig, setConfigBulk, Settings} from "../utils";
import {getConfig, setConfigBulk, Settings, getLang} from "../utils";
import path from "path";
var settingsWindow: BrowserWindow;
var instance: number = 0;

View file

@ -2,6 +2,10 @@ import {contextBridge, ipcRenderer} from "electron";
console.log("ArmCord Settings");
contextBridge.exposeInMainWorld("settings", {
save: (...args: any) => ipcRenderer.send("saveSettings", ...args),
getLang: (toGet: string) =>
ipcRenderer.invoke("getLang", toGet).then((result) => {
return result;
}),
get: (toGet: string) =>
ipcRenderer.invoke("getSetting", toGet).then((result) => {
return result;

View file

@ -14,7 +14,7 @@
<option value="default">Default</option>
<option value="native">Native</option>
</select>
<p class="header">ArmCord theme:</p>
<p class="header" id="settings-theme">ArmCord theme:</p>
</div>
<br />
<div class="switch">
@ -24,19 +24,19 @@
</div>
<br />
<div class="switch">
<label class="header">Minimize to tray</label>
<label class="header" id="settings-tray">Minimize to tray</label>
<input class="tgl tgl-light left" id="tray" type="checkbox" />
<label class="tgl-btn left" for="tray"></label>
</div>
<br />
<div class="switch">
<label class="header">Automatic Patches</label>
<label class="header" id="settings-patches">Automatic Patches</label>
<input class="tgl tgl-light left" id="patches" type="checkbox" />
<label class="tgl-btn left" for="patches"></label>
</div>
<br />
<div class="switch">
<label class="header">Invite Websocket</label>
<label class="header" id="settings-invitewebsocket">Invite Websocket</label>
<input class="tgl tgl-light left" id="websocket" type="checkbox" />
<label class="tgl-btn left" for="websocket"></label>
</div>
@ -47,7 +47,7 @@
<option value="ptb">PTB</option>
<option value="foss">Fosscord</option>
</select>
<p class="header">Discord channel:</p>
<p class="header" id="settings-channel">Discord channel:</p>
</div>
<div class="switch">
<select name="mod" id="mod" class="left">
@ -56,12 +56,41 @@
<option value="flicker">Flicker</option>
<option value="none">None</option>
</select>
<p class="header">Client mod:</p>
<p class="header" id="settings-mod">Client mod:</p>
</div>
<button id="save" class="center">Save settings</button>
<div class="switch">
<select name="prfmMode" id="prfmMode" class="left">
<option value="performance">Performance</option>
<option value="battery">Battery</option>
<option value="none">None</option>
</select>
<p class="header" id="settings-prfmMode">Performance mode:</p>
</div>
<button id="settings-save" class="center">Save settings</button>
</body>
<script>
async function loadLang() {
document.getElementById("settings-save").innerHTML = await settings.getLang("settings-save");
document.getElementById("settings-mod").innerHTML = await settings.getLang("settings-mod");
document.getElementById("settings-channel").innerHTML = await settings.getLang("settings-channel");
document.getElementById("settings-invitewebsocket").innerHTML = await settings.getLang(
"settings-invitewebsocket"
);
document.getElementById("settings-patches").innerHTML = await settings.getLang("settings-patches");
document.getElementById("settings-tray").innerHTML = await settings.getLang("settings-tray");
document.getElementById("settings-theme").innerHTML = await settings.getLang("settings-theme");
//select stuff
document.getElementById("mod").options[3].text = await settings.getLang("settings-none");
document.getElementById("prfmMode").options[2].text = await settings.getLang("settings-none");
document.getElementById("prfmMode").options[1].text = await settings.getLang("settings-prfmMode-battery");
document.getElementById("prfmMode").options[0].text = await settings.getLang(
"settings-prfmMode-performance"
);
document.getElementById("theme").options[1].text = await settings.getLang("settings-theme-native");
document.getElementById("theme").options[0].text = await settings.getLang("settings-theme-default");
}
loadLang();
</script>
<script>
async function loadSettings() {
document.getElementById("csp").checked = await settings.get("armcordCSP");
@ -71,10 +100,10 @@
document.getElementById("mod").value = await settings.get("mods");
document.getElementById("channel").value = await settings.get("channel");
document.getElementById("theme").value = await settings.get("windowStyle");
document.getElementById("prfmMode").value = await settings.get("performanceMode");
}
loadSettings();
document.getElementById("save").addEventListener("click", function () {
//function saveSettings(windowStyle: string, channelSetting: string, armcordCSPSetting: boolean, minimizeToTray: boolean, automaticPatches: boolean,modsSetting: string, blurType: string)
document.getElementById("settings-save").addEventListener("click", function () {
settings.save({
windowStyle: document.getElementById("theme").value,
channel: document.getElementById("channel").value,
@ -82,8 +111,8 @@
minimizeToTray: document.getElementById("tray").checked,
automaticPatches: document.getElementById("patches").checked,
mods: document.getElementById("mod").value,
blurType: "acrylic",
inviteWebsocket: document.getElementById("websocket").checked,
performanceMode: document.getElementById("prfmMode").value,
doneSetup: true
});
});

View file

@ -1,10 +1,15 @@
import {app, Menu, Tray} from "electron";
import {mainWindow} from "./window";
import {getConfig} from "./utils";
import { app, Menu, Tray } from "electron";
import { mainWindow } from "./window";
import { getConfig, setWindowState } from "./utils";
import * as path from "path";
import {createSettingsWindow} from "./settings/main";
import { createSettingsWindow } from "./settings/main";
import { platform } from "process";
let tray: any = null;
let defaultIcon = "ac_plug_colored";
app.whenReady().then(async () => {
if (platform == "darwin") {
defaultIcon = "macos"
}
if ((await getConfig("windowStyle")) == "discord") {
tray = new Tray(path.join(__dirname, "../", "/assets/dsc-tray.png"));
const contextMenu = Menu.buildFromTemplate([
@ -17,6 +22,12 @@ app.whenReady().then(async () => {
{
label: "Quit ArmCord",
click: function () {
let [width, height] = mainWindow.getSize()
setWindowState({
width: width,
height: height,
isMaximized: mainWindow.isMaximized()
})
app.quit();
}
}
@ -25,7 +36,7 @@ app.whenReady().then(async () => {
tray.setToolTip("Discord");
tray.setContextMenu(contextMenu);
} else {
var trayIcon = (await getConfig("trayIcon")) ?? "ac_plug_colored";
var trayIcon = (await getConfig("trayIcon")) ?? defaultIcon;
tray = new Tray(path.join(__dirname, "../", `/assets/${trayIcon}.png`));
const contextMenu = Menu.buildFromTemplate([
{
@ -59,6 +70,12 @@ app.whenReady().then(async () => {
{
label: "Quit ArmCord",
click: function () {
let [width, height] = mainWindow.getSize()
setWindowState({
width: width,
height: height,
isMaximized: mainWindow.isMaximized()
})
app.quit();
}
}

View file

@ -1,6 +1,7 @@
import * as fs from "fs";
import {app, dialog} from "electron";
import { app, dialog } from "electron";
import path from "path";
import { defaultMaxListeners } from "events";
export var firstRun: boolean;
export var isSetup: boolean;
export var contentPath: string;
@ -41,7 +42,7 @@ export function setup() {
minimizeToTray: true,
automaticPatches: false,
mods: "cumcord",
blurType: "acrylic",
performanceMode: "none",
inviteWebsocket: true,
doneSetup: false
};
@ -52,7 +53,7 @@ export function setup() {
export function getVersion() {
//to-do better way of doing this
return "3.0.6";
return "3.0.7";
}
export async function injectJS(inject: string) {
const js = await (await fetch(`${inject}`)).text();
@ -63,7 +64,111 @@ export async function injectJS(inject: string) {
document.body.appendChild(el);
}
export async function injectElectronFlags() {
// 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.
const presets = {
performance: `--enable-gpu-rasterization --enable-zero-copy --ignore-gpu-blocklist --enable-hardware-overlays=single-fullscreen,single-on-top,underlay --enable-features=EnableDrDc,CanvasOopRasterization,BackForwardCache:TimeToLiveInBackForwardCacheInSeconds/300/should_ignore_blocklists/true/enable_same_site/true,ThrottleDisplayNoneAndVisibilityHiddenCrossOriginIframes,UseSkiaRenderer,WebAssemblyLazyCompilation --disable-features=Vulkan --force_high_performance_gpu`, // Performance
battery: "--enable-features=TurnOffStreamingMediaCachingOnBattery --force_low_power_gpu" // Known to have better battery life for Chromium?
};
switch (await getConfig("performanceMode")) {
case "performance":
console.log("Performance mode enabled");
app.commandLine.appendSwitch(presets.performance);
break;
case "battery":
console.log("Battery mode enabled");
app.commandLine.appendSwitch(presets.battery);
break;
default:
console.log("No performance modes set");
}
}
export async function setLang(language: string) {
const userDataPath = app.getPath("userData");
const storagePath = path.join(userDataPath, "/storage/");
const langConfigFile = storagePath + "lang.json";
if (!fs.existsSync(langConfigFile)) {
fs.writeFileSync(langConfigFile, "{}", "utf-8");
}
let rawdata = fs.readFileSync(langConfigFile, "utf-8");
let parsed = JSON.parse(rawdata);
parsed["lang"] = language;
let toSave = JSON.stringify(parsed);
fs.writeFileSync(langConfigFile, toSave, "utf-8");
}
var language: string;
export async function getLang(object: string) {
if (language == undefined) {
try {
const userDataPath = app.getPath("userData");
const storagePath = path.join(userDataPath, "/storage/");
const langConfigFile = storagePath + "lang.json";
let rawdata = fs.readFileSync(langConfigFile, "utf-8");
let parsed = JSON.parse(rawdata);
language = parsed["lang"];
} catch (e) {
console.log("Language config file doesn't exist. Fallback to English.")
language = "en-US"
}
}
if (language.length == 2) {
language = language + "-" + language.toUpperCase();
}
var langPath = path.join(__dirname, "../", "/assets/lang/" + language + ".json");
if (!fs.existsSync(langPath)) {
langPath = path.join(__dirname, "../", "/assets/lang/en-US.json");
}
let rawdata = fs.readFileSync(langPath, "utf-8");
let parsed = JSON.parse(rawdata);
return parsed[object];
}
//ArmCord Window State manager
export interface WindowState {
width: number;
height: number;
isMaximized: boolean;
}
export async function setWindowState(object: WindowState) {
const userDataPath = app.getPath("userData");
const storagePath = path.join(userDataPath, "/storage/");
const saveFile = storagePath + "window.json";
if (!fs.existsSync(saveFile)) {
fs.writeFileSync(saveFile, "{}", "utf-8");
}
let toSave = JSON.stringify(object);
fs.writeFileSync(saveFile, toSave, "utf-8");
}
export async function getWindowState(object: string) {
const userDataPath = app.getPath("userData");
const storagePath = path.join(userDataPath, "/storage/");
const settingsFile = storagePath + "window.json";
let rawdata = fs.readFileSync(settingsFile, "utf-8");
let returndata = JSON.parse(rawdata);
console.log(object + ": " + returndata[object]);
return returndata[object];
}
//ArmCord Settings/Storage manager
export interface Settings {
@ -73,7 +178,7 @@ export interface Settings {
minimizeToTray: boolean;
automaticPatches: boolean;
mods: string;
blurType: string;
performanceMode: string;
inviteWebsocket: boolean;
doneSetup: boolean;
}

View file

@ -2,17 +2,18 @@
// I had to add most of the window creation code here to split both into seperete functions
// WHY? Because I can't use the same code for both due to annoying bug with value `frame` not responding to variables
// I'm sorry for this mess but I'm not sure how to fix it.
import {BrowserWindow, shell, app, ipcMain, dialog, clipboard} from "electron";
import { BrowserWindow, shell, app, dialog } from "electron";
import path from "path";
import {checkIfConfigIsBroken, firstRun, getConfig, contentPath, isSetup} from "./utils";
import {registerIpc} from "./ipc";
import { checkIfConfigIsBroken, firstRun, getConfig, contentPath, isSetup, setConfig, setLang, setWindowState } from "./utils";
import { registerIpc } from "./ipc";
import * as fs from "fs";
import startServer from "./socket";
import contextMenu from "electron-context-menu";
import os from "os";
export var icon: string;
export let mainWindow: BrowserWindow;
export let inviteWindow: BrowserWindow;
let guestWindows: BrowserWindow[] = [];
var osType = os.type()
contextMenu({
showSaveImageAs: true,
@ -21,18 +22,82 @@ contextMenu({
});
async function doAfterDefiningTheWindow() {
var ignoreProtocolWarning = await getConfig("ignoreProtocolWarning");
checkIfConfigIsBroken();
registerIpc();
mainWindow.webContents.userAgent = `Mozilla/5.0 (X11; ${os.type()} ${os.arch()}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36`; //fake useragent for screenshare to work
mainWindow.webContents.setWindowOpenHandler(({url}) => {
shell.openExternal(url);
return {action: "deny"};
// A little sloppy but it works :p
if (osType == 'Windows_NT') {
osType = "Windows " + os.release().split('.')[0] + " (" + os.release() + ")";
}
mainWindow.webContents.userAgent = `Mozilla/5.0 (X11; ${osType} ${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 }) => {
if (url.startsWith("https:" || url.startsWith("http:") || url.startsWith("mailto:"))) {
shell.openExternal(url);
} else {
if (ignoreProtocolWarning) {
shell.openExternal(url);
} else {
const options = {
type: "question",
buttons: ["Yes, please", "No, I don't"],
defaultId: 1,
title: url,
message: `Do you want to open ${url}?`,
detail: "This url was detected to not use normal browser protocols. It could mean that this url leads to a local program on your computer. Please check if you recognise it, before proceeding!",
checkboxLabel: "Remember my answer and ignore this warning for future sessions",
checkboxChecked: false
};
dialog.showMessageBox(mainWindow, options).then(({ response, checkboxChecked }) => {
console.log(response, checkboxChecked);
if (checkboxChecked) {
if (response == 0) {
setConfig("ignoreProtocolWarning", true);
} else {
setConfig("ignoreProtocolWarning", false);
}
}
if (response == 0) {
shell.openExternal(url);
} else {
return;
}
});
}
}
return { action: "deny" };
});
mainWindow.webContents.session.webRequest.onBeforeRequest((details, callback) => {
if (/api\/v\d\/science$/g.test(details.url)) return callback({cancel: true});
if (/api\/v\d\/science$/g.test(details.url)) return callback({ cancel: true });
return callback({});
});
const userDataPath = app.getPath("userData");
const themesFolder = userDataPath + "/themes/";
if (!fs.existsSync(themesFolder)) {
fs.mkdirSync(themesFolder);
console.log("Created missing theme folder");
}
mainWindow.webContents.on('did-finish-load', () => {
fs.readdirSync(themesFolder).forEach((file) => {
try {
const manifest = fs.readFileSync(`${themesFolder}/${file}/manifest.json`, "utf8");
var themeFile = JSON.parse(manifest);
mainWindow.webContents.send("themeLoader", fs.readFileSync(`${themesFolder}/${file}/${themeFile.theme}`, "utf-8"))
console.log(`%cLoaded ${themeFile.name} made by ${themeFile.author}`, "color:red");
} catch (err) {
console.error(err);
}
});
});
mainWindow.on("close", async (e) => {
let [width, height] = mainWindow.getSize()
setWindowState({
width: width,
height: height,
isMaximized: mainWindow.isMaximized()
})
if (await getConfig("minimizeToTray")) {
e.preventDefault();
mainWindow.hide();
@ -41,14 +106,20 @@ async function doAfterDefiningTheWindow() {
app.quit();
}
});
mainWindow.on('maximize', () => {
mainWindow.webContents.executeJavaScript(`document.body.setAttribute("isMaximized", "");`)
})
mainWindow.on('unmaximize', () => {
mainWindow.webContents.executeJavaScript(`document.body.removeAttribute("isMaximized");`)
})
console.log(contentPath);
if ((await getConfig("inviteWebsocket")) == true) {
startServer();
}
try {
mainWindow.loadFile(contentPath);
if (isSetup) {
await setLang(Intl.DateTimeFormat().resolvedOptions().locale)
mainWindow.setSize(390, 470);
}
} catch (e) {
@ -58,6 +129,7 @@ async function doAfterDefiningTheWindow() {
console.log(process.platform);
if (process.platform === "win32") {
if (firstRun) {
await setLang(Intl.DateTimeFormat().resolvedOptions().locale)
mainWindow.setSize(390, 470);
mainWindow.loadURL(`file://${__dirname}/content/setup.html`);
} else {
@ -65,6 +137,7 @@ async function doAfterDefiningTheWindow() {
}
} else {
if (firstRun) {
await setLang(Intl.DateTimeFormat().resolvedOptions().locale)
mainWindow.setSize(390, 470);
mainWindow.loadURL(`file://${__dirname}/ts-out/content/setup.html`);
} else {
@ -79,7 +152,7 @@ export function createCustomWindow() {
height: 350,
title: "ArmCord",
darkTheme: true,
icon: path.join(__dirname, "/assets/icon_transparent.png"),
icon: path.join(__dirname, "../", "/assets/ac_icon_transparent.png"),
frame: false,
autoHideMenuBar: true,
webPreferences: {
@ -95,7 +168,7 @@ export function createNativeWindow() {
height: 350,
title: "ArmCord",
darkTheme: true,
icon: path.join(__dirname, "/assets/icon_transparent.png"),
icon: path.join(__dirname, "../", "/assets/ac_icon_transparent.png"),
frame: true,
autoHideMenuBar: true,
webPreferences: {
@ -106,84 +179,13 @@ export function createNativeWindow() {
doAfterDefiningTheWindow();
}
export function createTabsHost() {
dialog.showErrorBox(
"READ THIS BEFORE USING THE APP",
"ArmCord Tabs are highly experimental and should be only used for strict testing purposes. Please don't ask for support, however you can still report bugs!"
);
guestWindows[1] = mainWindow;
mainWindow = new BrowserWindow({
width: 300,
height: 350,
title: "ArmCord",
darkTheme: true,
icon: path.join(__dirname, "/assets/icon_transparent.png"),
frame: true,
autoHideMenuBar: true,
webPreferences: {
preload: path.join(__dirname, "preload/preload.js")
}
});
doAfterDefiningTheWindow();
}
export function createTabsGuest(number: number) {
console.log(guestWindows);
if (guestWindows[number] !== undefined || null) {
try {
console.log("Showing Guest Window " + number);
mainWindow.hide();
guestWindows[number].show();
mainWindow = guestWindows[number];
} catch (e) {
console.error(e);
}
} else {
console.log("Creating Guest Window " + number);
mainWindow.hide();
guestWindows[number] = new BrowserWindow({
width: 800,
height: 600,
title: "ArmCord Guest Window " + number,
darkTheme: true,
icon: path.join(__dirname, "/assets/icon_transparent.png"),
frame: true,
autoHideMenuBar: true,
webPreferences: {
preload: path.join(__dirname, "preload/preload.js")
}
});
mainWindow = guestWindows[number];
ipcMain.on("tab" + number, (event) => {
event.returnValue = true; //return true so we know the tab exists
});
guestWindows[number].webContents.userAgent =
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36"; //fake useragent for screenshare to work
guestWindows[number].webContents.setWindowOpenHandler(({url}) => {
shell.openExternal(url);
return {action: "deny"};
});
guestWindows[number].webContents.session.webRequest.onBeforeRequest(
(details: {url: string}, callback: (arg0: {cancel?: boolean}) => any) => {
if (/api\/v\d\/science$/g.test(details.url)) return callback({cancel: true});
return callback({});
}
);
guestWindows[number].loadURL("https://discord.com/app");
}
}
export function createInviteWindow() {
inviteWindow = new BrowserWindow({
width: 800,
height: 600,
title: "ArmCord Invite Manager",
darkTheme: true,
icon: path.join(__dirname, "/assets/icon_transparent.png"),
icon: path.join(__dirname, "../", "/assets/ac_icon_transparent.png"),
frame: true,
autoHideMenuBar: true,
webPreferences: {