diff --git a/main.js b/main.js
index 152683b..46f9270 100644
--- a/main.js
+++ b/main.js
@@ -65,10 +65,10 @@ app.on('window-all-closed', () => {
}
})
+///////////////// SAVING AND LOADING /////////////////
ipcMain.handle('save-path', (event, path) => {
saveSilksongPath(path)
});
-
function saveSilksongPath(path) {
silksongPath = path;
bepinexFolderPath = `${silksongPath}/BepInEx`
@@ -84,19 +84,6 @@ ipcMain.handle('load-path', () => {
return silksongPath;
});
-ipcMain.handle('load-nexus-api', () => {
- nexusAPI = store.get('nexus-api');
- if (nexusAPI == undefined) {
- return "";
- }
- return nexusAPI;
-});
-
-ipcMain.handle('save-nexus-api', (event, api) => {
- nexusAPI = api;
- createNexus()
- store.set('nexus-api', nexusAPI);
-});
function saveBepinexVersion(version) {
bepinexVersion = version;
@@ -107,6 +94,12 @@ function saveBepinexVersion(version) {
store.set('bepinex-version', version);
};
+ipcMain.handle('load-bepinex-version', () => {
+ bepinexVersion = store.get('bepinex-version');
+ return bepinexVersion;
+});
+
+
function saveBepinexBackupVersion(version) {
bepinexBackupVersion = version;
if (bepinexBackupVersion == undefined) {
@@ -116,15 +109,40 @@ function saveBepinexBackupVersion(version) {
store.set('bepinex-backup-version', version);
};
-ipcMain.handle('load-bepinex-version', () => {
- bepinexVersion = store.get('bepinex-version');
- return bepinexVersion;
-});
-
ipcMain.handle('load-bepinex-backup-version', () => {
bepinexBackupVersion = store.get('bepinex-backup-version');
return bepinexBackupVersion;
});
+
+ipcMain.handle('save-nexus-api', (event, api) => {
+ nexusAPI = api;
+ createNexus()
+ store.set('nexus-api', nexusAPI);
+});
+
+ipcMain.handle('load-nexus-api', () => {
+ nexusAPI = store.get('nexus-api');
+ if (nexusAPI == undefined) {
+ return "";
+ }
+ return nexusAPI;
+});
+
+
+ipcMain.handle('save-theme', (event, theme) => {
+ store.set('theme', theme);
+});
+
+ipcMain.handle('load-theme', () => {
+ theme = store.get('theme');
+ if (theme == undefined) {
+ return "Silksong";
+ }
+ return theme;
+});
+
+//////////////////////////////////////////////////////
+/////////////////// DATA HANDLING ////////////////////
async function fileExists(filePath) {
try {
@@ -135,15 +153,17 @@ async function fileExists(filePath) {
}
}
-ipcMain.handle('file-exists', async (_, filePath) => {
- return await fileExists(filePath);
-});
-
ipcMain.handle('delete-data', async () => {
- await fs.unlink(dataPath)
+ if (await fileExists(dataPath)) {
+ await fs.unlink(dataPath)
+ }
});
ipcMain.handle('export-data', async () => {
+ if (!await fileExists(dataPath)) {
+ return
+ }
+
const { canceled, filePath } = await dialog.showSaveDialog({
title: 'Export Data',
defaultPath: 'config.json',
@@ -173,31 +193,8 @@ ipcMain.handle('import-data', async () => {
return true
})
-ipcMain.handle('open-link', async (event, link) => {
- await shell.openExternal(link)
-})
-
-ipcMain.handle('launch-game', async (event, mode) => {
- const silksongExecutablePath = `${silksongPath}/Hollow Knight Silksong.exe`
- if (mode === "modded"){
- if (await fileExists(bepinexFolderPath)) {
- await shell.openExternal(silksongExecutablePath)
- }
- else {
- await installBepinex()
- await shell.openExternal(silksongExecutablePath)
- }
- }
- if (mode === "vanilla"){
- if (await fileExists(bepinexFolderPath)) {
- await backupBepinex()
- await shell.openExternal(silksongExecutablePath)
- }
- else {
- await shell.openExternal(silksongExecutablePath)
- }
- }
-})
+//////////////////////////////////////////////////////
+////////////////////// BEPINEX ///////////////////////
async function installBepinex() {
if (await fileExists(bepinexBackupPath)) {
@@ -308,6 +305,9 @@ ipcMain.handle('delete-bepinex-backup', async () => {
}
})
+//////////////////////////////////////////////////////
+/////////////////////// NEXUS ////////////////////////
+
async function createNexus() {
if (nexusAPI == undefined) {
return
@@ -366,6 +366,9 @@ ipcMain.handle('download-mod', async (event, link) => {
nexusWindow.loadURL(link)
})
+//////////////////////////////////////////////////////
+//////////////////// UNCATEGORIZE ////////////////////
+
ipcMain.handle('auto-detect-game-path', async () => {
const defaultsSilksongPaths = [
":/Program Files (x86)/Steam/steamapps/common/Hollow Knight Silksong",
@@ -384,4 +387,30 @@ ipcMain.handle('auto-detect-game-path', async () => {
ipcMain.handle('load-main-page', () => {
mainWindow.loadFile("renderer/index.html")
-})
\ No newline at end of file
+})
+
+ipcMain.handle('open-link', async (event, link) => {
+ await shell.openExternal(link)
+})
+
+ipcMain.handle('launch-game', async (event, mode) => {
+ const silksongExecutablePath = `${silksongPath}/Hollow Knight Silksong.exe`
+ if (mode === "modded"){
+ if (await fileExists(bepinexFolderPath)) {
+ await shell.openExternal(silksongExecutablePath)
+ }
+ else {
+ await installBepinex()
+ await shell.openExternal(silksongExecutablePath)
+ }
+ }
+ if (mode === "vanilla"){
+ if (await fileExists(bepinexFolderPath)) {
+ await backupBepinex()
+ await shell.openExternal(silksongExecutablePath)
+ }
+ else {
+ await shell.openExternal(silksongExecutablePath)
+ }
+ }
+})
diff --git a/preload.js b/preload.js
index 309c112..86667da 100644
--- a/preload.js
+++ b/preload.js
@@ -7,7 +7,6 @@ contextBridge.exposeInMainWorld('versions', {
});
contextBridge.exposeInMainWorld('files', {
- fileExists: (path) => ipcRenderer.invoke('file-exists', path),
delete: () => ipcRenderer.invoke('delete-data'),
export: () => ipcRenderer.invoke('export-data'),
import: () => ipcRenderer.invoke('import-data'),
@@ -18,7 +17,9 @@ contextBridge.exposeInMainWorld('files', {
loadBepinexVersion: () => ipcRenderer.invoke('load-bepinex-version'),
loadBepinexBackupVersion: () => ipcRenderer.invoke('load-bepinex-backup-version'),
saveNexusAPI: (api) => ipcRenderer.invoke('save-nexus-api', api),
- loadNexusAPI: () => ipcRenderer.invoke('load-nexus-api')
+ loadNexusAPI: () => ipcRenderer.invoke('load-nexus-api'),
+ saveTheme: (theme) => ipcRenderer.invoke('save-theme', theme),
+ loadTheme: () => ipcRenderer.invoke('load-theme')
});
contextBridge.exposeInMainWorld('electronAPI', {
diff --git a/renderer/assets/background.mp4 b/renderer/assets/background/Silksong.mp4
similarity index 100%
rename from renderer/assets/background.mp4
rename to renderer/assets/background/Silksong.mp4
diff --git a/renderer/index.html b/renderer/index.html
index 62fbd14..62effc7 100644
--- a/renderer/index.html
+++ b/renderer/index.html
@@ -9,42 +9,40 @@
-
+
+
BepInEx
diff --git a/renderer/renderer.js b/renderer/renderer.js
index 39cd823..21c63e7 100644
--- a/renderer/renderer.js
+++ b/renderer/renderer.js
@@ -9,7 +9,12 @@ const modTemplate = document.getElementById("mod-template");
const versionText = HomeTemplate.content.getElementById("version-text");
-navigate("home")
+on_startup()
+
+async function on_startup() {
+ changeTheme(await files.loadTheme())
+ navigate("home")
+}
async function navigate(page) {
view.replaceChildren()
@@ -105,17 +110,18 @@ async function navigate(page) {
silksongPathInput.value = await files.loadSilksongPath()
silksongPathInput.addEventListener('input', async function(event) {
let silksongPath = silksongPathInput.value
- await files.saveSilksongPath(silksongPath)
+ files.saveSilksongPath(silksongPath)
});
nexusAPIInput.value = await files.loadNexusAPI()
nexusAPIInput.addEventListener('input', async function(event) {
let nexusAPI = nexusAPIInput.value
- await files.saveNexusAPI(nexusAPI)
+ files.saveNexusAPI(nexusAPI)
});
view.appendChild(settingsTemplateCopy)
setBepinexVersion()
+ setThemeButton()
verifyNexusAPI()
break;
}
@@ -135,6 +141,8 @@ async function autoDetectGamePath() {
}
async function deleteData() {
+ changeTheme("Silksong")
+ toggleThemesMenu()
await files.delete()
document.getElementById("silksong-path-input").value = await files.loadSilksongPath()
document.getElementById("nexus-api-input").value = await files.loadNexusAPI()
@@ -148,6 +156,8 @@ async function importData() {
await files.import()
document.getElementById("silksong-path-input").value = await files.loadSilksongPath()
document.getElementById("nexus-api-input").value = await files.loadNexusAPI()
+ changeTheme(await files.loadTheme())
+ toggleThemesMenu()
}
async function installBepinex() {
@@ -205,4 +215,43 @@ async function verifyNexusAPI() {
else {
nexusCheckImage.src = "assets/cross.svg"
}
+}
+
+function toggleThemesMenu() {
+ const themesMenu = document.getElementById("themes-menu")
+ if (themesMenu) {
+ themesMenu.classList.toggle("show")
+ }
+}
+
+async function setThemeButton() {
+ const themesButton = document.getElementById("themes-button")
+ if (themesButton) {
+ themesButton.textContent = await files.loadTheme()
+ }
+}
+
+function changeTheme(theme) {
+ files.saveTheme(theme)
+
+ setThemeButton()
+
+ const themesColors = {
+ "var": ["--primary-color", "--secondary-color", "--background-color"],
+ "Silksong": ["rgba(255, 25, 0, 0.3)", "#ff6b6b", "rgba(255, 72, 0, 0.2)"],
+ "Citadel of song": ["rgba(160, 116, 89, 0.3)", "#d3ba91", "rgba(123, 102, 93, 0.2)"],
+ "Cradle": ["rgba(123, 136, 255, 0.3)", "#7c9fea", "rgba(61, 88, 150, 0.2)"],
+ "Abyss": ["rgba(255, 255, 255, 0.3)", "#ececec", "rgba(255, 255, 255, 0.2)"],
+ "Greyroot": ["rgba(181, 255, 180, 0.3)", "#c1ffcd", "rgba(90, 165, 130, 0.2)"],
+ "Surface": ["rgba(75, 120, 255, 0.3)", "#87c3ff", "rgba(42, 107, 203, 0.2)"],
+ "Steel": ["rgba(164, 164, 164, 0.3)", "#c5b9b9", "rgba(255, 255, 255, 0.2)"]
+ }
+ for(let i = 0; i < 3; i++) {
+ document.documentElement.style.setProperty(themesColors.var[i], themesColors[theme][i])
+ }
+
+ const backgroundVideo = document.getElementById("background-video")
+ backgroundVideo.src = `assets/background/${theme}.mp4`
+
+ toggleThemesMenu()
}
\ No newline at end of file
diff --git a/renderer/style.css b/renderer/style.css
index e0ed64e..a615bde 100644
--- a/renderer/style.css
+++ b/renderer/style.css
@@ -1,11 +1,21 @@
* {
margin: 0;
- padding: 0;
box-sizing: border-box;
font-family: "Segoe UI", sans-serif;
cursor: url("assets/cursor.png") 0 0, auto !important;
}
+:root {
+ --primary-color: rgba(255, 25, 0, 0.3);
+ --secondary-color: #ff6b6b;
+ --background-color: rgba(255, 72, 0, 0.2);
+
+ --text-color: #eee;
+ --transparent-black: rgba(0, 0, 0, 0.4);
+ --darker-transparent-black: rgba(0, 0, 0, 0.8);
+ --transparent-grey: rgba(30, 30, 30, 0.8)
+}
+
body {
background: black;
color: #eee;
@@ -18,7 +28,7 @@ body {
height: 100vh;
}
-.background_video {
+.background-video {
position: fixed;
top: 0;
left: 0;
@@ -31,8 +41,8 @@ body {
.sidebar {
width: 280px;
- background: rgba(0, 0, 0, 0.8);
- border-right: 1px solid rgba(255, 0, 0, 0.15);
+ background: var(--darker-transparent-black);
+ border-right: 1px solid var(--background-color);
display: flex;
flex-direction: column;
}
@@ -43,18 +53,16 @@ body {
align-items: center;
justify-content: center;
font-size: 32px;
- cursor: pointer;
- border-bottom: 1px solid rgba(255, 72, 0, 0.2);
- transition: background 0.2s;
+ border-bottom: 1px solid var(--background-color);
+ transition: background 0.2s ease;
}
.logo:hover {
- background: rgba(255, 0, 0, 0.08);
+ background: var(--background-color);
}
-.logo_img {
+.logo-img {
height: 50px;
- width: auto;
}
.nav {
@@ -70,11 +78,11 @@ body {
font-size: 13px;
text-transform: uppercase;
letter-spacing: 1px;
- color: #fff;
+ color: var(--text-color);
margin-bottom: 10px;
padding: 0 4px 4px;
- border-bottom: 1px solid #ff6b6b;
+ border-bottom: 1px solid var(--secondary-color);
}
.nav button {
@@ -82,17 +90,16 @@ body {
padding: 10px 14px;
margin-bottom: 8px;
background: transparent;
- border: 1px solid black;
+ border: 1px solid transparent;
border-radius: 4px;
- color: #eee;
- cursor: pointer;
+ color: var(--text-color);
text-align: left;
transition: all 0.2s ease;
}
.nav button:hover {
- background: rgba(255, 72, 0, 0.2);
- border-color: rgba(255, 25, 0, 0.3);
+ background: var(--background-color);
+ border-color: var(--primary-color);
}
.content {
@@ -103,7 +110,7 @@ body {
.content h1 {
font-size: 28px;
margin-bottom: 20px;
- color: #ffffff;
+ color: var(--text-color);
display: flex;
justify-content: center;
}
@@ -111,19 +118,18 @@ body {
.content h2 {
font-size: 24px;
margin-bottom: 20px;
- color: #ffffff;
+ color: var(--text-color);
padding: 0 4px 4px;
- border-bottom: 1px solid #ff6b6b;
+ border-bottom: 1px solid var(--secondary-color);
}
.view {
- width: 100%;
- background: rgba(0, 0, 0, 0.8);
+ background: var(--darker-transparent-black);
border-radius: 12px;
padding: 40px;
position: relative;
z-index: 0;
- box-shadow: 0 0 50px rgba(0, 0, 0, 0.15);
+ box-shadow: 0 0 50px var(--darker-transparent-black);
overflow: auto;
height: 90%;
}
@@ -139,35 +145,33 @@ body {
flex: 1;
height: 30px;
padding: 0 12px;
- background: rgba(0, 0, 0, 0.4);
- border: 1px solid #ff6b6b;
+ background: var(--transparent-black);
+ border: 1px solid var(--secondary-color);
border-radius: 4px;
- color: #eee;
+ color: var(--text-color);
font-size: 13px;
outline: none;
transition: all 0.2s ease;
}
.input:hover {
- background: rgba(0, 0, 0, 0.55);
- border-color: rgba(255, 25, 0, 0.3);
+ background: var(--darker-transparent-black);
+ border-color: var(--primary-color);
}
.input:focus {
- background: rgba(0, 0, 0, 0.65);
- border-color: rgba(255, 25, 0, 0.3);
- box-shadow: 0 0 0 1px rgba(255, 25, 0, 0.2);
+ background: var(--darker-transparent-black);
+ border-color: var(--primary-color);
+ box-shadow: 0 0 0 1px var(--primary-color);
}
.default-button {
width: 120px;
height: 40px;
- padding: 2px;
- background: rgba(0, 0, 0, 0.4);
- border: 1px solid #ff6b6b;
+ background: var(--transparent-black);
+ border: 1px solid var(--secondary-color);
border-radius: 4px;
- color: #eee;
- cursor: pointer;
+ color: var(--text-color);
font-size: 16px;
transition: all 0.2s ease;
display: flex;
@@ -176,19 +180,17 @@ body {
}
.default-button:hover {
- background: rgba(255, 72, 0, 0.2);
- border-color: rgba(255, 25, 0, 0.3);
+ background: var(--background-color);
+ border-color: var(--primary-color);
}
.important-button {
width: 120px;
height: 40px;
- padding: 2px;
background: rgba(100, 0, 0, 0.4);
border: 1px solid rgba(200, 25, 0);
border-radius: 4px;
- color: #eee;
- cursor: pointer;
+ color: var(--text-color);
font-size: 16px;
transition: all 0.2s ease;
display: flex;
@@ -208,6 +210,10 @@ body {
font-size: 32px;
}
+.longer-button {
+ width: 240px;
+}
+
.search-container {
position: absolute;
left: 50%;
@@ -221,7 +227,7 @@ body {
border: none;
border-radius: 50px;
background-color: rgba(255, 255, 255, 0.15);
- color: #fff;
+ color: var(--text-color);
outline: none;
transition: background 0.3s, width 0.3s;
}
@@ -238,20 +244,15 @@ body {
transform: translateY(-50%);
background: none;
border: none;
- color: #fff;
+ color: var(--text-color);
font-size: 18px;
cursor: pointer;
}
.mods-container {
- width: 100%;
height: 80%;
transform: translateY(50px);
- background: rgba(30, 30, 30, 0.8);
- border-radius: 12px;
padding: 20px;
- position: relative;
- box-shadow: 0 0 50px rgba(30, 30, 30, 0.15);
overflow: auto;
}
@@ -262,12 +263,10 @@ body {
display: flex;
align-items: center;
justify-content: space-between;
-
}
.mod-container:not(:last-child) {
- border-bottom: 1px solid rgba(150, 25, 0, 0.5);
-
+ border-bottom: 1px solid var(--secondary-color);
}
.mod-text {
@@ -275,17 +274,10 @@ body {
flex-direction: column;
}
-.mod-actions {
- margin-top: 12px;
- display: flex;
- gap: 20px;
-}
-
.mod-icon {
width: 128px;
height: 128px;
object-fit: contain;
- opacity: 0.9;
}
::-webkit-scrollbar {
@@ -293,16 +285,17 @@ body {
}
::-webkit-scrollbar-track {
- background: #101010;
+ background: var(--transparent-grey);
+ border-radius: 5px;
}
::-webkit-scrollbar-thumb {
- background: rgb(120, 25, 0);
- border-radius: 7px;
+ background: var(--primary-color);
+ border-radius: 5px;
}
::-webkit-scrollbar-thumb:hover {
- background: rgb(170, 25, 0);
+ background: var(--secondary-color);
}
.transparent-text {
@@ -316,10 +309,36 @@ body {
}
.link {
- color: #ffffff;
+ color: var(--text-color);
transition: all 0.2s ease;
}
.link:hover {
- color: #ff6b6b;
+ color: var(--secondary-color);
+}
+
+.themes-div {
+ position: relative;
+}
+
+.themes-menu {
+ display: none;
+ position: absolute;
+ background: var(--darker-transparent-black);
+ border: 1px solid var(--secondary-color);
+ border-radius: 4px;
+}
+
+.themes-menu.show {
+ display: block;
+}
+
+.themes-menu li {
+ padding: 6px;
+ display: flex;
+ justify-content: center;
+}
+
+.themes-menu li:hover {
+ background: var(--background-color);
}
\ No newline at end of file
diff --git a/renderer/welcome.css b/renderer/welcome.css
index c6ce0df..e192f4e 100644
--- a/renderer/welcome.css
+++ b/renderer/welcome.css
@@ -1,17 +1,15 @@
.welcome-div {
display: flex;
flex-direction: column;
- height: 100%;
flex: 1;
padding: 0 60px;
}
.title {
display: flex;
- flex: 1;
font-size: 60px;
margin-bottom: 60px;
- color: #ffffff;
+ color: #eee;
justify-content: center;
}
@@ -20,6 +18,4 @@
flex: 2;
align-items: center;
justify-content: space-between;
- margin-top: 8px;
- gap: 40px;
}
\ No newline at end of file
diff --git a/renderer/welcome.html b/renderer/welcome.html
index 6b36dc0..e31f174 100644
--- a/renderer/welcome.html
+++ b/renderer/welcome.html
@@ -8,9 +8,7 @@
-
+
@@ -59,6 +57,21 @@
Chose the theme of the app
+
diff --git a/renderer/welcome.js b/renderer/welcome.js
index bce1e88..4cf3731 100644
--- a/renderer/welcome.js
+++ b/renderer/welcome.js
@@ -109,4 +109,43 @@ async function importData() {
if (res) {
electronAPI.loadMainPage()
}
+}
+
+function toggleThemesMenu() {
+ const themesMenu = document.getElementById("themes-menu")
+ if (themesMenu) {
+ themesMenu.classList.toggle("show")
+ }
+}
+
+async function setThemeButton() {
+ const themesButton = document.getElementById("themes-button")
+ if (themesButton) {
+ themesButton.textContent = await files.loadTheme()
+ }
+}
+
+function changeTheme(theme) {
+ files.saveTheme(theme)
+
+ setThemeButton()
+
+ const themesColors = {
+ "var": ["--primary-color", "--secondary-color", "--background-color"],
+ "Silksong": ["rgba(255, 25, 0, 0.3)", "#ff6b6b", "rgba(255, 72, 0, 0.2)"],
+ "Citadel of song": ["rgba(160, 116, 89, 0.3)", "#d3ba91", "rgba(123, 102, 93, 0.2)"],
+ "Cradle": ["rgba(123, 136, 255, 0.3)", "#7c9fea", "rgba(61, 88, 150, 0.2)"],
+ "Abyss": ["rgba(255, 255, 255, 0.3)", "#ececec", "rgba(255, 255, 255, 0.2)"],
+ "Greyroot": ["rgba(181, 255, 180, 0.3)", "#c1ffcd", "rgba(90, 165, 130, 0.2)"],
+ "Surface": ["rgba(75, 120, 255, 0.3)", "#87c3ff", "rgba(42, 107, 203, 0.2)"],
+ "Steel": ["rgba(164, 164, 164, 0.3)", "#c5b9b9", "rgba(255, 255, 255, 0.2)"]
+ }
+ for(let i = 0; i < 3; i++) {
+ document.documentElement.style.setProperty(themesColors.var[i], themesColors[theme][i])
+ }
+
+ const backgroundVideo = document.getElementById("background-video")
+ backgroundVideo.src = `assets/background/${theme}.mp4`
+
+ toggleThemesMenu()
}
\ No newline at end of file