fix: auto-create swap subdirs, add folder buttons, fix CSS theme injection
This commit is contained in:
+21
-3
@@ -229,6 +229,12 @@ async function launchApp(): Promise<void> {
|
|||||||
// ── Resource swapper ──
|
// ── Resource swapper ──
|
||||||
const swapperConfig = config.get('swapper');
|
const swapperConfig = config.get('swapper');
|
||||||
const swapDir = swapperConfig.path || join(app.getPath('userData'), 'Krunker Civilian Client', 'swapper');
|
const swapDir = swapperConfig.path || join(app.getPath('userData'), 'Krunker Civilian Client', 'swapper');
|
||||||
|
// Ensure swap subdirectories exist (themes/, backgrounds/)
|
||||||
|
for (const sub of ['themes', 'backgrounds']) {
|
||||||
|
const dir = join(swapDir, sub);
|
||||||
|
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
const swapper = swapperConfig.enabled ? new ResourceSwapper(swapDir) : null;
|
const swapper = swapperConfig.enabled ? new ResourceSwapper(swapDir) : null;
|
||||||
electronLog.log(`[KCC] Resource swapper: ${swapper ? 'enabled' : 'disabled'} (${swapDir})`);
|
electronLog.log(`[KCC] Resource swapper: ${swapper ? 'enabled' : 'disabled'} (${swapDir})`);
|
||||||
|
|
||||||
@@ -510,10 +516,20 @@ async function launchApp(): Promise<void> {
|
|||||||
win.webContents.insertCSS(ALL_CLIENT_CSS),
|
win.webContents.insertCSS(ALL_CLIENT_CSS),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Inject user CSS theme
|
// Inject user CSS theme via <style> tag so @import rules work
|
||||||
const uiConf = config.get('ui');
|
const uiConf = config.get('ui');
|
||||||
const themeCSS = getThemeCSS(uiConf?.cssTheme || 'disabled', swapDir);
|
const themeId = uiConf?.cssTheme || 'disabled';
|
||||||
if (themeCSS) cssInjections.push(win.webContents.insertCSS(themeCSS));
|
const themeCSS = getThemeCSS(themeId, swapDir);
|
||||||
|
electronLog.log(`[KCC] CSS theme: id=${themeId}, css=${themeCSS ? themeCSS.length + ' chars' : 'none'}`);
|
||||||
|
if (themeCSS) {
|
||||||
|
const escaped = themeCSS.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$/g, '\\$');
|
||||||
|
win.webContents.executeJavaScript(`(() => {
|
||||||
|
const s = document.createElement('style');
|
||||||
|
s.id = 'kcc-user-theme';
|
||||||
|
s.textContent = \`${escaped}\`;
|
||||||
|
document.head.appendChild(s);
|
||||||
|
})()`).catch((err) => electronLog.warn('[KCC] Theme inject failed:', err));
|
||||||
|
}
|
||||||
|
|
||||||
// Inject loading screen background
|
// Inject loading screen background
|
||||||
const loadingCSS = getLoadingScreenCSS(uiConf?.loadingTheme || 'disabled', uiConf?.backgroundUrl || '', swapDir);
|
const loadingCSS = getLoadingScreenCSS(uiConf?.loadingTheme || 'disabled', uiConf?.backgroundUrl || '', swapDir);
|
||||||
@@ -607,6 +623,8 @@ async function launchApp(): Promise<void> {
|
|||||||
});
|
});
|
||||||
ipcMain.handle('get-swap-dir', () => swapDir);
|
ipcMain.handle('get-swap-dir', () => swapDir);
|
||||||
ipcMain.handle('open-swap-folder', () => shell.openPath(swapDir));
|
ipcMain.handle('open-swap-folder', () => shell.openPath(swapDir));
|
||||||
|
ipcMain.handle('open-themes-folder', () => shell.openPath(join(swapDir, 'themes')));
|
||||||
|
ipcMain.handle('open-backgrounds-folder', () => shell.openPath(join(swapDir, 'backgrounds')));
|
||||||
|
|
||||||
// ── Ping regions IPC handler (TCP connect timing, cached 60s) ──
|
// ── Ping regions IPC handler (TCP connect timing, cached 60s) ──
|
||||||
ipcMain.handle('ping-regions', async () => {
|
ipcMain.handle('ping-regions', async () => {
|
||||||
|
|||||||
+14
-2
@@ -707,7 +707,7 @@ function buildSwapperSection(body: HTMLElement, swapperConf: any, uiConfRaw: any
|
|||||||
|
|
||||||
// ── CSS Theme selector (populated from swap/themes/) ──
|
// ── CSS Theme selector (populated from swap/themes/) ──
|
||||||
const themeRow = document.createElement('div');
|
const themeRow = document.createElement('div');
|
||||||
themeRow.className = 'setting settName safety-0 sel';
|
themeRow.className = 'setting settName safety-0 sel has-button';
|
||||||
themeRow.innerHTML =
|
themeRow.innerHTML =
|
||||||
'<span class="setting-title">CSS Theme</span>' +
|
'<span class="setting-title">CSS Theme</span>' +
|
||||||
'<div class="setting-desc-new">Load a custom CSS theme from swap/themes/</div>';
|
'<div class="setting-desc-new">Load a custom CSS theme from swap/themes/</div>';
|
||||||
@@ -715,6 +715,12 @@ function buildSwapperSection(body: HTMLElement, swapperConf: any, uiConfRaw: any
|
|||||||
themeSelect.className = 's-update inputGrey2';
|
themeSelect.className = 's-update inputGrey2';
|
||||||
themeSelect.innerHTML = '<option value="disabled">Loading...</option>';
|
themeSelect.innerHTML = '<option value="disabled">Loading...</option>';
|
||||||
themeRow.appendChild(themeSelect);
|
themeRow.appendChild(themeSelect);
|
||||||
|
const themeFolderBtn = document.createElement('div');
|
||||||
|
themeFolderBtn.className = 'settingsBtn';
|
||||||
|
themeFolderBtn.title = 'Open Themes Folder';
|
||||||
|
themeFolderBtn.innerHTML = '<span class="material-icons">folder</span>';
|
||||||
|
themeFolderBtn.addEventListener('click', () => ipcRenderer.invoke('open-themes-folder'));
|
||||||
|
themeRow.appendChild(themeFolderBtn);
|
||||||
body.appendChild(themeRow);
|
body.appendChild(themeRow);
|
||||||
|
|
||||||
ipcRenderer.invoke('list-themes').then((themes: Array<{ id: string; label: string }>) => {
|
ipcRenderer.invoke('list-themes').then((themes: Array<{ id: string; label: string }>) => {
|
||||||
@@ -736,7 +742,7 @@ function buildSwapperSection(body: HTMLElement, swapperConf: any, uiConfRaw: any
|
|||||||
|
|
||||||
// ── Loading Screen Background ──
|
// ── Loading Screen Background ──
|
||||||
const bgRow = document.createElement('div');
|
const bgRow = document.createElement('div');
|
||||||
bgRow.className = 'setting settName safety-0 sel';
|
bgRow.className = 'setting settName safety-0 sel has-button';
|
||||||
bgRow.innerHTML =
|
bgRow.innerHTML =
|
||||||
'<span class="setting-title">Loading Background</span>' +
|
'<span class="setting-title">Loading Background</span>' +
|
||||||
'<div class="setting-desc-new">Custom background image for the loading screen (swap/backgrounds/)</div>';
|
'<div class="setting-desc-new">Custom background image for the loading screen (swap/backgrounds/)</div>';
|
||||||
@@ -744,6 +750,12 @@ function buildSwapperSection(body: HTMLElement, swapperConf: any, uiConfRaw: any
|
|||||||
bgSelect.className = 's-update inputGrey2';
|
bgSelect.className = 's-update inputGrey2';
|
||||||
bgSelect.innerHTML = '<option value="disabled">Loading...</option>';
|
bgSelect.innerHTML = '<option value="disabled">Loading...</option>';
|
||||||
bgRow.appendChild(bgSelect);
|
bgRow.appendChild(bgSelect);
|
||||||
|
const bgFolderBtn = document.createElement('div');
|
||||||
|
bgFolderBtn.className = 'settingsBtn';
|
||||||
|
bgFolderBtn.title = 'Open Backgrounds Folder';
|
||||||
|
bgFolderBtn.innerHTML = '<span class="material-icons">folder</span>';
|
||||||
|
bgFolderBtn.addEventListener('click', () => ipcRenderer.invoke('open-backgrounds-folder'));
|
||||||
|
bgRow.appendChild(bgFolderBtn);
|
||||||
body.appendChild(bgRow);
|
body.appendChild(bgRow);
|
||||||
|
|
||||||
ipcRenderer.invoke('list-loading-themes').then((themes: Array<{ id: string; label: string }>) => {
|
ipcRenderer.invoke('list-loading-themes').then((themes: Array<{ id: string; label: string }>) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user