Skip to content
This repository was archived by the owner on Mar 9, 2025. It is now read-only.

Commit 883de5e

Browse files
authored
Merge pull request #6 from noxygalaxy/main
add: GUI Installer
2 parents 96a7e15 + fbb5887 commit 883de5e

27 files changed

+1382
-1
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# Installer
2-
CLI installation tool that automates the installation, removal and maintenance of themes.
2+
GUI/CLI installation tool that automates the installation, removal and maintenance of themes.

discord.ps1 cli/discord.ps1

File renamed without changes.

steam.ps1 cli/steam.ps1

File renamed without changes.

gui/main.js

+244
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
const { app, BrowserWindow, ipcMain } = require('electron');
2+
const path = require('path');
3+
const fs = require('fs');
4+
const https = require('https');
5+
const AdmZip = require('adm-zip');
6+
7+
function createWindow() {
8+
const win = new BrowserWindow({
9+
width: 750,
10+
height: 500,
11+
webPreferences: {
12+
nodeIntegration: true,
13+
contextIsolation: false,
14+
preload: path.join(__dirname, 'src/preload.js')
15+
},
16+
icon: path.join(__dirname, 'src/assets/logo.png'),
17+
frame: false,
18+
transparent: true,
19+
backgroundColor: '#00000000',
20+
autoHideMenuBar: true,
21+
resizable: false
22+
});
23+
24+
win.loadFile('src/index.html');
25+
}
26+
27+
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
28+
29+
ipcMain.on('start-installation', async (event, data) => {
30+
const appData = process.env.APPDATA;
31+
32+
function sendLog(message) {
33+
console.log('Debug:', message);
34+
event.reply('installation-logs', [message]);
35+
}
36+
37+
sendLog('Preparing installation...');
38+
await delay(1000);
39+
40+
if (data.theme === 'DiscordTheme') {
41+
const betterDiscordPath = path.join(appData, 'BetterDiscord', 'themes');
42+
const vencordPath = path.join(appData, 'Vencord', 'themes');
43+
const vencordThemePath = path.join(vencordPath, 'SpaceTheme.theme.css');
44+
const betterDiscordThemePath = path.join(betterDiscordPath, 'SpaceTheme.theme.css');
45+
const themeUrl = 'https://raw.githubusercontent.com/SpaceTheme/Discord/refs/heads/main/SpaceTheme.theme.css';
46+
47+
async function installTheme(themePath, clientName) {
48+
try {
49+
if (!fs.existsSync(themePath)) {
50+
fs.mkdirSync(themePath, { recursive: true });
51+
sendLog(`Created directory for ${clientName}`);
52+
}
53+
54+
const themeFile = path.join(themePath, 'SpaceTheme.theme.css');
55+
const file = fs.createWriteStream(themeFile);
56+
57+
return new Promise((resolve, reject) => {
58+
sendLog(`Downloading theme for ${clientName}...`);
59+
https.get(themeUrl, response => {
60+
response.pipe(file);
61+
file.on('finish', () => {
62+
sendLog(`SpaceTheme.theme.css downloaded successfully in ${themePath}`);
63+
file.close();
64+
sendLog(`SpaceTheme installed successfully for ${clientName}`);
65+
resolve();
66+
});
67+
}).on('error', error => {
68+
sendLog(`Error downloading theme for ${clientName}: ${error.message}`);
69+
reject(error);
70+
});
71+
});
72+
} catch (error) {
73+
sendLog(`Error installing theme for ${clientName}: ${error.message}`);
74+
throw error;
75+
}
76+
}
77+
78+
try {
79+
if (data.option === 'uninstall-theme') {
80+
let uninstalled = false;
81+
if (fs.existsSync(vencordThemePath)) {
82+
fs.unlinkSync(vencordThemePath);
83+
sendLog('SpaceTheme uninstalled successfully from Vencord');
84+
uninstalled = true;
85+
}
86+
if (fs.existsSync(betterDiscordThemePath)) {
87+
fs.unlinkSync(betterDiscordThemePath);
88+
sendLog('SpaceTheme uninstalled successfully from BetterDiscord');
89+
uninstalled = true;
90+
}
91+
if (!uninstalled) {
92+
sendLog('Discord theme not found in any supported client');
93+
}
94+
return;
95+
}
96+
97+
if (data.option === 'reset-theme') {
98+
sendLog('Starting theme reset process...');
99+
if (fs.existsSync(vencordThemePath)) {
100+
fs.unlinkSync(vencordThemePath);
101+
sendLog('Removed existing Vencord theme');
102+
}
103+
if (fs.existsSync(betterDiscordThemePath)) {
104+
fs.unlinkSync(betterDiscordThemePath);
105+
sendLog('Removed existing BetterDiscord theme');
106+
}
107+
}
108+
109+
let installed = false;
110+
if (fs.existsSync(betterDiscordPath)) {
111+
await installTheme(betterDiscordPath, 'BetterDiscord');
112+
installed = true;
113+
}
114+
if (fs.existsSync(vencordPath)) {
115+
await installTheme(vencordPath, 'Vencord');
116+
installed = true;
117+
}
118+
if (!installed) {
119+
sendLog('Neither BetterDiscord nor Vencord is installed. Please install one of them first.');
120+
}
121+
} catch (error) {
122+
sendLog(`Installation failed: ${error.message}`);
123+
}
124+
125+
} else if (data.theme === 'SteamTheme') {
126+
await delay(1000);
127+
128+
const skinsFolder = 'C:\\Program Files (x86)\\Steam\\steamui\\skins';
129+
const destinationFolder = path.join(skinsFolder, 'SpaceTheme for Steam');
130+
const tempPath = path.join(process.env.TEMP, 'SpaceTheme_for_Steam.zip');
131+
const extractedFolderPath = path.join(skinsFolder, 'Steam-main');
132+
133+
function cleanup() {
134+
try {
135+
if (fs.existsSync(tempPath)) {
136+
fs.unlinkSync(tempPath);
137+
}
138+
if (fs.existsSync(extractedFolderPath)) {
139+
fs.rmSync(extractedFolderPath, { recursive: true, force: true });
140+
}
141+
} catch (error) {
142+
sendLog(`Cleanup error: ${error.message}`);
143+
}
144+
}
145+
146+
try {
147+
if (data.option === 'uninstall-theme') {
148+
sendLog('Starting Steam theme uninstallation...');
149+
sendLog('Trying to see if you have SteamTheme installed...');
150+
if (fs.existsSync(destinationFolder)) {
151+
fs.rmSync(destinationFolder, { recursive: true, force: true });
152+
sendLog('SteamTheme path was found and deleted!');
153+
sendLog('SpaceTheme uninstalled successfully for Steam.');
154+
} else {
155+
sendLog('Steam theme not found');
156+
}
157+
return;
158+
}
159+
160+
if (data.option === 'reset-theme') {
161+
sendLog('Starting Steam theme reset...');
162+
if (fs.existsSync(destinationFolder)) {
163+
fs.rmSync(destinationFolder, { recursive: true, force: true });
164+
sendLog('Removed existing Steam theme installation');
165+
sendLog('Starting installation...');
166+
} else {
167+
sendLog('No existing Steam theme found, proceeding with installation...');
168+
}
169+
}
170+
171+
if (!fs.existsSync(skinsFolder)) {
172+
sendLog('Steam skins folder not found. Please install Steam first.');
173+
return;
174+
}
175+
176+
sendLog('Downloading SpaceTheme for Steam...');
177+
const file = fs.createWriteStream(tempPath);
178+
179+
await new Promise((resolve, reject) => {
180+
sendLog('Checking website availability...');
181+
https.get('https://github.com/SpaceTheme/Steam/archive/refs/heads/main.zip', response => {
182+
if (response.statusCode === 302 || response.statusCode === 301) {
183+
https.get(response.headers.location, redirectResponse => {
184+
if (redirectResponse.statusCode !== 200) {
185+
reject(new Error(`Download failed with status ${redirectResponse.statusCode}`));
186+
return;
187+
}
188+
redirectResponse.pipe(file);
189+
file.on('finish', () => {
190+
file.close();
191+
resolve();
192+
});
193+
}).on('error', reject);
194+
} else if (response.statusCode === 200) {
195+
response.pipe(file);
196+
file.on('finish', () => {
197+
file.close();
198+
resolve();
199+
});
200+
} else {
201+
reject(new Error(`Unexpected status code: ${response.statusCode}`));
202+
}
203+
}).on('error', reject);
204+
});
205+
206+
sendLog('Website is available for you!');
207+
sendLog(`SpaceTheme for Steam was successfully installed in ${tempPath} folder.`);
208+
sendLog('Extracting files... ');
209+
const zip = new AdmZip(tempPath);
210+
zip.extractAllTo(skinsFolder, true);
211+
sendLog(`SpaceTheme for Steam was successfully extracted to ${skinsFolder} folder.`);
212+
213+
if (fs.existsSync(extractedFolderPath)) {
214+
fs.renameSync(extractedFolderPath, destinationFolder);
215+
sendLog('SpaceTheme installed successfully for Steam.');
216+
} else {
217+
throw new Error('Failed to extract theme files');
218+
}
219+
} catch (error) {
220+
sendLog(`Error during Steam theme operation: ${error.message}`);
221+
} finally {
222+
cleanup();
223+
}
224+
}
225+
});
226+
227+
ipcMain.on('close-window', () => {
228+
const win = BrowserWindow.getFocusedWindow();
229+
if (win) win.close();
230+
});
231+
232+
app.whenReady().then(createWindow);
233+
234+
app.on('window-all-closed', () => {
235+
if (process.platform !== 'darwin') {
236+
app.quit();
237+
}
238+
});
239+
240+
app.on('activate', () => {
241+
if (BrowserWindow.getAllWindows().length === 0) {
242+
createWindow();
243+
}
244+
});

gui/package.json

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"name": "spacetheme-installer",
3+
"private": true,
4+
"version": "1.0.1",
5+
"main": "main.js",
6+
"scripts": {
7+
"start": "electron .",
8+
"build": "electron-builder"
9+
},
10+
"dependencies": {
11+
"adm-zip": "^0.5.16"
12+
},
13+
"keywords": [],
14+
"author": "",
15+
"license": "MIT",
16+
"description": "",
17+
"build": {
18+
"appId": "com.noxy.st-installer",
19+
"productName": "SpaceTheme-Installer",
20+
"copyright": "Copyright © 2024 SpaceTheme",
21+
"win": {
22+
"target": [
23+
"nsis",
24+
"portable"
25+
],
26+
"icon": "src/assets/logo.png"
27+
},
28+
"directories": {
29+
"buildResources": "public"
30+
}
31+
},
32+
"devDependencies": {
33+
"electron": "^29.1.0",
34+
"electron-builder": "^25.1.8"
35+
}
36+
}
+7
Loading

gui/src/assets/arrow-left.svg

+7
Loading
+7
Loading

gui/src/assets/arrow-right.svg

+7
Loading

gui/src/assets/checkmark.svg

+7
Loading

gui/src/assets/close-icon.svg

+8
Loading

gui/src/assets/discord.svg

+7
Loading

gui/src/assets/donate.svg

+7
Loading

gui/src/assets/github.svg

+7
Loading

gui/src/assets/installation-icon.svg

+7
Loading
+7
Loading

0 commit comments

Comments
 (0)