Fix: Save Themes inside "AppData"

This commit is contained in:
MasterAcnolo
2026-04-13 21:49:19 +02:00
parent d879a5eb1d
commit 238d4ea717
4 changed files with 74 additions and 11 deletions

View File

@@ -6,6 +6,7 @@ const { configFeatures, featuresPath } = require("../config");
const { getThemes, reloadThemes } = require("./themeManager"); const { getThemes, reloadThemes } = require("./themeManager");
const config = require("../config"); const config = require("../config");
const { validateDownloadPath, getDefaultDownloadPath } = require("./pathValidator"); const { validateDownloadPath, getDefaultDownloadPath } = require("./pathValidator");
const { userThemesPath } = require("../server/helpers/path.helpers");
const FEATURE_WHITELIST = new Set([ const FEATURE_WHITELIST = new Set([
"autoUpdate", "autoUpdate",
@@ -24,9 +25,7 @@ const FEATURE_WHITELIST = new Set([
const configFolderPath = featuresPath; const configFolderPath = featuresPath;
const themeFolderPath = config.localMode const themeFolderPath = userThemesPath;
? path.join(__dirname, "..", "theme")
: path.join(process.resourcesPath, "theme");
function registerIpcHandlers(getMainWindow) { function registerIpcHandlers(getMainWindow) {

View File

@@ -24,6 +24,7 @@ const { checkNativeDependencies } = require("./app/dependencyCheck");
const { updateYtDlp } = require("./app/ytDlpUpdater"); const { updateYtDlp } = require("./app/ytDlpUpdater");
const { createMainWindow, getMainWindow } = require("./app/windowManager"); const { createMainWindow, getMainWindow } = require("./app/windowManager");
const { registerIpcHandlers } = require("./app/ipcHandlers"); const { registerIpcHandlers } = require("./app/ipcHandlers");
const { userThemesPath, initUserThemes } = require("./server/helpers/path.helpers");
app.setName("Freedom Loader"); app.setName("Freedom Loader");
app.setAppUserModelId("com.masteracnolo.freedomloader"); app.setAppUserModelId("com.masteracnolo.freedomloader");
@@ -56,13 +57,9 @@ app.whenReady().then(async () => {
setSplashProgress(1); // Starting server setSplashProgress(1); // Starting server
registerIpcHandlers(getMainWindow); registerIpcHandlers(getMainWindow);
const themeFolderPath = config.localMode
? path.join(__dirname, "theme")
: path.join(process.resourcesPath, "theme");
setSplashProgress(2); // Loading themes setSplashProgress(2); // Loading themes
await initThemes(themeFolderPath); initUserThemes();
await initThemes(userThemesPath);
setSplashProgress(3); // Almost ready setSplashProgress(3); // Almost ready
await createMainWindow(); await createMainWindow();

View File

@@ -39,7 +39,8 @@
"files": [ "files": [
"**/*", "**/*",
"node_modules/**/*", "node_modules/**/*",
"!config/config.dev.json" "!config/config.dev.json",
"!theme/**/*"
], ],
"directories": { "directories": {
"buildResources": "build" "buildResources": "build"

View File

@@ -50,8 +50,74 @@ const binaryPaths = {
deno: path.join(resourcesPath, "binaries", "deno.exe") deno: path.join(resourcesPath, "binaries", "deno.exe")
}; };
// Theme paths - themes stored in AppData to survive updates
const userThemesPath = path.join(app.getPath("userData"), "themes");
const defaultThemesSourcePath = path.join(resourcesPath, "theme");
function initUserThemes() {
try {
if (!fs.existsSync(userThemesPath)) {
fs.mkdirSync(userThemesPath, { recursive: true });
// Ensure folder is writable
fs.chmodSync(userThemesPath, 0o777);
logger.info("Created user themes directory");
}
// Copy default themes from resources to user directory if they don't exist
if (fs.existsSync(defaultThemesSourcePath)) {
const defaultThemes = fs.readdirSync(defaultThemesSourcePath);
for (const theme of defaultThemes) {
const srcPath = path.join(defaultThemesSourcePath, theme);
const destPath = path.join(userThemesPath, theme);
if (!fs.existsSync(destPath)) {
try {
copyDirectory(srcPath, destPath);
fs.chmodSync(destPath, 0o777);
logger.info(`Copied default theme: ${theme}`);
} catch (copyErr) {
logger.warn(`Failed to copy theme ${theme}: ${copyErr.message}. Theme folder will be created, add theme files manually.`);
try {
fs.mkdirSync(destPath, { recursive: true });
fs.chmodSync(destPath, 0o777);
} catch (mkdirErr) {
logger.warn(`Could not create theme directory ${theme}: ${mkdirErr.message}`);
}
}
}
}
} else {
logger.warn(`Default themes source path not found: ${defaultThemesSourcePath}`);
}
} catch (err) {
logger.error(`Failed to initialize user themes: ${err.message}`);
}
}
function copyDirectory(src, dest) {
try {
if (!fs.existsSync(dest)) {
fs.mkdirSync(dest, { recursive: true, mode: 0o777 });
}
const files = fs.readdirSync(src);
for (const file of files) {
const srcFile = path.join(src, file);
const destFile = path.join(dest, file);
if (fs.statSync(srcFile).isDirectory()) {
copyDirectory(srcFile, destFile);
} else {
fs.copyFileSync(srcFile, destFile);
}
}
} catch (err) {
throw new Error(`Copy error: ${err.message}`);
}
}
if (!userYtDlp){ logger.error("Missing YT-DLP")} if (!userYtDlp){ logger.error("Missing YT-DLP")}
if (!ffmpegPath){ logger.error("Missing FFMPEG")} if (!ffmpegPath){ logger.error("Missing FFMPEG")}
if (!denoPath){ logger.error("Missing DENO")} if (!denoPath){ logger.error("Missing DENO")}
module.exports = { userYtDlp, ffmpegPath, denoPath, iconPaths, binaryPaths, resourcesPath, defaultDownloadFolder }; module.exports = { userYtDlp, ffmpegPath, denoPath, iconPaths, binaryPaths, resourcesPath, defaultDownloadFolder, userThemesPath, initUserThemes };