diff --git a/README.md b/README.md index 1c5c7dd..7b17232 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ # Installer -CLI installation tool that automates the installation, removal and maintenance of themes. +GUI/CLI installation tool that automates the installation, removal and maintenance of themes. diff --git a/discord.ps1 b/cli/discord.ps1 similarity index 100% rename from discord.ps1 rename to cli/discord.ps1 diff --git a/steam.ps1 b/cli/steam.ps1 similarity index 100% rename from steam.ps1 rename to cli/steam.ps1 diff --git a/gui/main.js b/gui/main.js new file mode 100644 index 0000000..dd4112b --- /dev/null +++ b/gui/main.js @@ -0,0 +1,244 @@ +const { app, BrowserWindow, ipcMain } = require('electron'); +const path = require('path'); +const fs = require('fs'); +const https = require('https'); +const AdmZip = require('adm-zip'); + +function createWindow() { + const win = new BrowserWindow({ + width: 750, + height: 500, + webPreferences: { + nodeIntegration: true, + contextIsolation: false, + preload: path.join(__dirname, 'src/preload.js') + }, + icon: path.join(__dirname, 'src/assets/logo.png'), + frame: false, + transparent: true, + backgroundColor: '#00000000', + autoHideMenuBar: true, + resizable: false + }); + + win.loadFile('src/index.html'); +} + +const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); + +ipcMain.on('start-installation', async (event, data) => { + const appData = process.env.APPDATA; + + function sendLog(message) { + console.log('Debug:', message); + event.reply('installation-logs', [message]); + } + + sendLog('Preparing installation...'); + await delay(1000); + + if (data.theme === 'DiscordTheme') { + const betterDiscordPath = path.join(appData, 'BetterDiscord', 'themes'); + const vencordPath = path.join(appData, 'Vencord', 'themes'); + const vencordThemePath = path.join(vencordPath, 'SpaceTheme.theme.css'); + const betterDiscordThemePath = path.join(betterDiscordPath, 'SpaceTheme.theme.css'); + const themeUrl = 'https://raw.githubusercontent.com/SpaceTheme/Discord/refs/heads/main/SpaceTheme.theme.css'; + + async function installTheme(themePath, clientName) { + try { + if (!fs.existsSync(themePath)) { + fs.mkdirSync(themePath, { recursive: true }); + sendLog(`Created directory for ${clientName}`); + } + + const themeFile = path.join(themePath, 'SpaceTheme.theme.css'); + const file = fs.createWriteStream(themeFile); + + return new Promise((resolve, reject) => { + sendLog(`Downloading theme for ${clientName}...`); + https.get(themeUrl, response => { + response.pipe(file); + file.on('finish', () => { + sendLog(`SpaceTheme.theme.css downloaded successfully in ${themePath}`); + file.close(); + sendLog(`SpaceTheme installed successfully for ${clientName}`); + resolve(); + }); + }).on('error', error => { + sendLog(`Error downloading theme for ${clientName}: ${error.message}`); + reject(error); + }); + }); + } catch (error) { + sendLog(`Error installing theme for ${clientName}: ${error.message}`); + throw error; + } + } + + try { + if (data.option === 'uninstall-theme') { + let uninstalled = false; + if (fs.existsSync(vencordThemePath)) { + fs.unlinkSync(vencordThemePath); + sendLog('SpaceTheme uninstalled successfully from Vencord'); + uninstalled = true; + } + if (fs.existsSync(betterDiscordThemePath)) { + fs.unlinkSync(betterDiscordThemePath); + sendLog('SpaceTheme uninstalled successfully from BetterDiscord'); + uninstalled = true; + } + if (!uninstalled) { + sendLog('Discord theme not found in any supported client'); + } + return; + } + + if (data.option === 'reset-theme') { + sendLog('Starting theme reset process...'); + if (fs.existsSync(vencordThemePath)) { + fs.unlinkSync(vencordThemePath); + sendLog('Removed existing Vencord theme'); + } + if (fs.existsSync(betterDiscordThemePath)) { + fs.unlinkSync(betterDiscordThemePath); + sendLog('Removed existing BetterDiscord theme'); + } + } + + let installed = false; + if (fs.existsSync(betterDiscordPath)) { + await installTheme(betterDiscordPath, 'BetterDiscord'); + installed = true; + } + if (fs.existsSync(vencordPath)) { + await installTheme(vencordPath, 'Vencord'); + installed = true; + } + if (!installed) { + sendLog('Neither BetterDiscord nor Vencord is installed. Please install one of them first.'); + } + } catch (error) { + sendLog(`Installation failed: ${error.message}`); + } + + } else if (data.theme === 'SteamTheme') { + await delay(1000); + + const skinsFolder = 'C:\\Program Files (x86)\\Steam\\steamui\\skins'; + const destinationFolder = path.join(skinsFolder, 'SpaceTheme for Steam'); + const tempPath = path.join(process.env.TEMP, 'SpaceTheme_for_Steam.zip'); + const extractedFolderPath = path.join(skinsFolder, 'Steam-main'); + + function cleanup() { + try { + if (fs.existsSync(tempPath)) { + fs.unlinkSync(tempPath); + } + if (fs.existsSync(extractedFolderPath)) { + fs.rmSync(extractedFolderPath, { recursive: true, force: true }); + } + } catch (error) { + sendLog(`Cleanup error: ${error.message}`); + } + } + + try { + if (data.option === 'uninstall-theme') { + sendLog('Starting Steam theme uninstallation...'); + sendLog('Trying to see if you have SteamTheme installed...'); + if (fs.existsSync(destinationFolder)) { + fs.rmSync(destinationFolder, { recursive: true, force: true }); + sendLog('SteamTheme path was found and deleted!'); + sendLog('SpaceTheme uninstalled successfully for Steam.'); + } else { + sendLog('Steam theme not found'); + } + return; + } + + if (data.option === 'reset-theme') { + sendLog('Starting Steam theme reset...'); + if (fs.existsSync(destinationFolder)) { + fs.rmSync(destinationFolder, { recursive: true, force: true }); + sendLog('Removed existing Steam theme installation'); + sendLog('Starting installation...'); + } else { + sendLog('No existing Steam theme found, proceeding with installation...'); + } + } + + if (!fs.existsSync(skinsFolder)) { + sendLog('Steam skins folder not found. Please install Steam first.'); + return; + } + + sendLog('Downloading SpaceTheme for Steam...'); + const file = fs.createWriteStream(tempPath); + + await new Promise((resolve, reject) => { + sendLog('Checking website availability...'); + https.get('https://github.com/SpaceTheme/Steam/archive/refs/heads/main.zip', response => { + if (response.statusCode === 302 || response.statusCode === 301) { + https.get(response.headers.location, redirectResponse => { + if (redirectResponse.statusCode !== 200) { + reject(new Error(`Download failed with status ${redirectResponse.statusCode}`)); + return; + } + redirectResponse.pipe(file); + file.on('finish', () => { + file.close(); + resolve(); + }); + }).on('error', reject); + } else if (response.statusCode === 200) { + response.pipe(file); + file.on('finish', () => { + file.close(); + resolve(); + }); + } else { + reject(new Error(`Unexpected status code: ${response.statusCode}`)); + } + }).on('error', reject); + }); + + sendLog('Website is available for you!'); + sendLog(`SpaceTheme for Steam was successfully installed in ${tempPath} folder.`); + sendLog('Extracting files... '); + const zip = new AdmZip(tempPath); + zip.extractAllTo(skinsFolder, true); + sendLog(`SpaceTheme for Steam was successfully extracted to ${skinsFolder} folder.`); + + if (fs.existsSync(extractedFolderPath)) { + fs.renameSync(extractedFolderPath, destinationFolder); + sendLog('SpaceTheme installed successfully for Steam.'); + } else { + throw new Error('Failed to extract theme files'); + } + } catch (error) { + sendLog(`Error during Steam theme operation: ${error.message}`); + } finally { + cleanup(); + } + } +}); + +ipcMain.on('close-window', () => { + const win = BrowserWindow.getFocusedWindow(); + if (win) win.close(); +}); + +app.whenReady().then(createWindow); + +app.on('window-all-closed', () => { + if (process.platform !== 'darwin') { + app.quit(); + } +}); + +app.on('activate', () => { + if (BrowserWindow.getAllWindows().length === 0) { + createWindow(); + } +}); diff --git a/gui/package.json b/gui/package.json new file mode 100644 index 0000000..5baf538 --- /dev/null +++ b/gui/package.json @@ -0,0 +1,36 @@ +{ + "name": "spacetheme-installer", + "private": true, + "version": "1.0.1", + "main": "main.js", + "scripts": { + "start": "electron .", + "build": "electron-builder" + }, + "dependencies": { + "adm-zip": "^0.5.16" + }, + "keywords": [], + "author": "", + "license": "MIT", + "description": "", + "build": { + "appId": "com.noxy.st-installer", + "productName": "SpaceTheme-Installer", + "copyright": "Copyright © 2024 SpaceTheme", + "win": { + "target": [ + "nsis", + "portable" + ], + "icon": "src/assets/logo.png" + }, + "directories": { + "buildResources": "public" + } + }, + "devDependencies": { + "electron": "^29.1.0", + "electron-builder": "^25.1.8" + } +} diff --git a/gui/src/assets/arrow-left-disabled.svg b/gui/src/assets/arrow-left-disabled.svg new file mode 100644 index 0000000..e5ef17e --- /dev/null +++ b/gui/src/assets/arrow-left-disabled.svg @@ -0,0 +1,7 @@ + diff --git a/gui/src/assets/arrow-left.svg b/gui/src/assets/arrow-left.svg new file mode 100644 index 0000000..741a6e0 --- /dev/null +++ b/gui/src/assets/arrow-left.svg @@ -0,0 +1,7 @@ + diff --git a/gui/src/assets/arrow-right-disabled.svg b/gui/src/assets/arrow-right-disabled.svg new file mode 100644 index 0000000..e7f8ad5 --- /dev/null +++ b/gui/src/assets/arrow-right-disabled.svg @@ -0,0 +1,7 @@ + diff --git a/gui/src/assets/arrow-right.svg b/gui/src/assets/arrow-right.svg new file mode 100644 index 0000000..b01f107 --- /dev/null +++ b/gui/src/assets/arrow-right.svg @@ -0,0 +1,7 @@ + diff --git a/gui/src/assets/checkmark.svg b/gui/src/assets/checkmark.svg new file mode 100644 index 0000000..3e6cba5 --- /dev/null +++ b/gui/src/assets/checkmark.svg @@ -0,0 +1,7 @@ + diff --git a/gui/src/assets/close-icon.svg b/gui/src/assets/close-icon.svg new file mode 100644 index 0000000..ade0b03 --- /dev/null +++ b/gui/src/assets/close-icon.svg @@ -0,0 +1,8 @@ + diff --git a/gui/src/assets/discord.svg b/gui/src/assets/discord.svg new file mode 100644 index 0000000..8e68cbd --- /dev/null +++ b/gui/src/assets/discord.svg @@ -0,0 +1,7 @@ + diff --git a/gui/src/assets/donate.svg b/gui/src/assets/donate.svg new file mode 100644 index 0000000..4136659 --- /dev/null +++ b/gui/src/assets/donate.svg @@ -0,0 +1,7 @@ + diff --git a/gui/src/assets/github.svg b/gui/src/assets/github.svg new file mode 100644 index 0000000..1731e64 --- /dev/null +++ b/gui/src/assets/github.svg @@ -0,0 +1,7 @@ + diff --git a/gui/src/assets/installation-icon.svg b/gui/src/assets/installation-icon.svg new file mode 100644 index 0000000..f4f0e94 --- /dev/null +++ b/gui/src/assets/installation-icon.svg @@ -0,0 +1,7 @@ + diff --git a/gui/src/assets/installdone-disabled.svg b/gui/src/assets/installdone-disabled.svg new file mode 100644 index 0000000..6e5a7bf --- /dev/null +++ b/gui/src/assets/installdone-disabled.svg @@ -0,0 +1,7 @@ + diff --git a/gui/src/assets/installdone.svg b/gui/src/assets/installdone.svg new file mode 100644 index 0000000..6e5a7bf --- /dev/null +++ b/gui/src/assets/installdone.svg @@ -0,0 +1,7 @@ + diff --git a/gui/src/assets/logo.ico b/gui/src/assets/logo.ico new file mode 100644 index 0000000..a00e712 Binary files /dev/null and b/gui/src/assets/logo.ico differ diff --git a/gui/src/assets/logo.png b/gui/src/assets/logo.png new file mode 100644 index 0000000..09fbdd1 Binary files /dev/null and b/gui/src/assets/logo.png differ diff --git a/gui/src/assets/minimize-icon.svg b/gui/src/assets/minimize-icon.svg new file mode 100644 index 0000000..cb3aeaa --- /dev/null +++ b/gui/src/assets/minimize-icon.svg @@ -0,0 +1,7 @@ + diff --git a/gui/src/assets/mit-icon.svg b/gui/src/assets/mit-icon.svg new file mode 100644 index 0000000..f3a0bad --- /dev/null +++ b/gui/src/assets/mit-icon.svg @@ -0,0 +1,7 @@ + diff --git a/gui/src/assets/website.svg b/gui/src/assets/website.svg new file mode 100644 index 0000000..3a3aab9 --- /dev/null +++ b/gui/src/assets/website.svg @@ -0,0 +1,7 @@ + diff --git a/gui/src/index.html b/gui/src/index.html new file mode 100644 index 0000000..22203f6 --- /dev/null +++ b/gui/src/index.html @@ -0,0 +1,150 @@ + + +
+ + +