feat(log): auto-persist fallback path into settings

When the configured log path isn't writable and we fall back to
Desktop/userData, the working fallback now gets saved into
globalSettings.logFilePath automatically. Benefits:

  - Next session writes directly to the known-working path, no
    fallback ladder, no recurring toast warning.
  - The Settings input reflects the actual path in use, so users
    don't stay confused about where their uploads are being logged.
  - Live update via IPC — if the Settings view is currently open,
    the input value updates without needing a view switch.

Daily-log mode is handled: we strip the -YYYY-MM-DD suffix before
persisting so tomorrow's auto-rotation doesn't double-date the
filename.
This commit is contained in:
Administrator 2026-04-19 23:30:14 +02:00
parent 90ba69d1b0
commit f6b1ef96b7
3 changed files with 45 additions and 3 deletions

32
main.js
View File

@ -290,6 +290,10 @@ function _flushUploadLog() {
debugLog(`uploadLog append failed: ${err.message}`); debugLog(`uploadLog append failed: ${err.message}`);
} else if (target.isFallback && !_uploadLogFallbackWarned) { } else if (target.isFallback && !_uploadLogFallbackWarned) {
_uploadLogFallbackWarned = true; _uploadLogFallbackWarned = true;
// Auto-persist the working fallback into the user's config so the
// next session writes here directly (no more fallback ladder) and
// the Settings input reflects reality.
_persistFallbackLogPath(target.path);
if (mainWindow && !mainWindow.isDestroyed()) { if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.webContents.send('upload-log-fallback', { fallbackPath: target.path }); mainWindow.webContents.send('upload-log-fallback', { fallbackPath: target.path });
} }
@ -298,6 +302,34 @@ function _flushUploadLog() {
}); });
} }
function _persistFallbackLogPath(workingPath) {
try {
const cfg = configStore.load();
const gs = cfg.globalSettings || {};
// If daily-log is on, workingPath has a date suffix (fileuploader-YYYY-MM-DD.log).
// Strip that before saving so the base path rolls forward to tomorrow's
// file correctly — otherwise the next day's getLogFilePath would append
// another date onto the already-dated base.
let toSave = workingPath;
if (gs.sessionLog) {
const dir = path.dirname(workingPath);
const base = path.basename(workingPath);
const stripped = base.replace(/-\d{4}-\d{2}-\d{2}(\.[^.]+)$/, '$1');
toSave = path.join(dir, stripped);
}
if (gs.logFilePath === toSave) return;
gs.logFilePath = toSave;
cfg.globalSettings = gs;
configStore.save({ globalSettings: gs }).catch(() => {});
_invalidateUploadLogTargetCache();
if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.webContents.send('log-path-auto-updated', { logFilePath: toSave });
}
} catch (err) {
debugLog(`persist fallback logpath failed: ${err.message}`);
}
}
function appendUploadLog(hoster, link, fileName) { function appendUploadLog(hoster, link, fileName) {
const now = new Date(); const now = new Date();
const pad = (n) => String(n).padStart(2, '0'); const pad = (n) => String(n).padStart(2, '0');

View File

@ -108,6 +108,9 @@ contextBridge.exposeInMainWorld('api', {
ipcRenderer.on('account-rotation-log', (_event, data) => callback(data)); ipcRenderer.on('account-rotation-log', (_event, data) => callback(data));
}, },
openLogFolder: () => ipcRenderer.invoke('open-log-folder'), openLogFolder: () => ipcRenderer.invoke('open-log-folder'),
onLogPathAutoUpdated: (callback) => {
ipcRenderer.on('log-path-auto-updated', (_event, data) => callback(data));
},
// Remote Control // Remote Control
remoteGetSettings: () => ipcRenderer.invoke('remote:get-settings'), remoteGetSettings: () => ipcRenderer.invoke('remote:get-settings'),
remoteSaveSettings: (settings) => ipcRenderer.invoke('remote:save-settings', settings), remoteSaveSettings: (settings) => ipcRenderer.invoke('remote:save-settings', settings),

View File

@ -118,12 +118,19 @@ async function init() {
}); });
window.api.onShutdownCountdown(handleShutdownCountdown); window.api.onShutdownCountdown(handleShutdownCountdown);
window.api.onUploadLogFallback((data) => { window.api.onUploadLogFallback((data) => {
// Non-blocking toast instead of alert() — alert() in Electron halts the
// entire renderer main thread (including the upload table) until the user
// clicks OK. During a big batch that freezes everything.
const path = data && data.fallbackPath ? data.fallbackPath : '(Fallback)'; const path = data && data.fallbackPath ? data.fallbackPath : '(Fallback)';
showCopyToast(`Log-Pfad nicht beschreibbar — schreibe nach: ${path}`, 8000); showCopyToast(`Log-Pfad nicht beschreibbar — schreibe nach: ${path}`, 8000);
}); });
window.api.onLogPathAutoUpdated((data) => {
if (!data || !data.logFilePath) return;
// Keep the in-memory config and the visible Settings input in sync so
// the user sees the path that's actually being written to, and the
// next save from the UI doesn't revert it.
if (config && config.globalSettings) config.globalSettings.logFilePath = data.logFilePath;
const input = document.getElementById('logFilePathInput');
if (input) input.value = data.logFilePath;
showCopyToast(`Log-Pfad automatisch auf funktionierenden Ordner gesetzt`, 5000);
});
window.api.onAccountRotationLog((entry) => { window.api.onAccountRotationLog((entry) => {
// Surface only the user-visible rotation events as toasts; full detail // Surface only the user-visible rotation events as toasts; full detail
// goes to account-rotation.log. Keep it quiet otherwise. // goes to account-rotation.log. Keep it quiet otherwise.