fix(sync): run watched sync when a scheduled --sync hits the running instance #12

Merged
debont80 merged 1 commits from fix/scheduled-sync-running-instance into main 2026-07-09 15:48:32 -04:00
5 changed files with 26 additions and 2 deletions
+9
View File
@@ -260,6 +260,15 @@ if (isPrimaryInstance) {
// link it carried and hand it to the window we already have. // link it carried and hand it to the window we already have.
app.on('second-instance', (_e, argv) => { app.on('second-instance', (_e, argv) => {
if (!mainWindow) return if (!mainWindow) return
// A scheduled `--sync` relaunch (Task Scheduler) hit the already-running instance:
// run the watched-source sync in this window instead of no-opping. Without this the
// daily auto-download never fires while AeroFetch is open — e.g. minimize-to-tray
// users. Deliberately does NOT focus the window, so the daily sync stays unobtrusive
// (mirrors the fresh-launch `--sync` showInactive path in createWindow).
if (isSyncLaunch(argv)) {
mainWindow.webContents.send(IpcChannels.runWatchedSync)
return
}
focusWindow(mainWindow) focusWindow(mainWindow)
const incomingUrl = extractIncomingUrl(argv) const incomingUrl = extractIncomingUrl(argv)
if (incomingUrl) mainWindow.webContents.send(IpcChannels.externalUrl, incomingUrl) if (incomingUrl) mainWindow.webContents.send(IpcChannels.externalUrl, incomingUrl)
+8
View File
@@ -279,6 +279,14 @@ const api = {
return () => ipcRenderer.removeListener(IpcChannels.indexProgress, listener) return () => ipcRenderer.removeListener(IpcChannels.indexProgress, listener)
}, },
/** Subscribe to the "run watched-source sync now" nudge a scheduled `--sync` relaunch
* sends when it hits the already-running instance. Returns an unsubscribe function. */
onRunWatchedSync: (cb: () => void): (() => void) => {
const listener = (): void => cb()
ipcRenderer.on(IpcChannels.runWatchedSync, listener)
return () => ipcRenderer.removeListener(IpcChannels.runWatchedSync, listener)
},
// --- Built-in yt-dlp terminal (Phase N) --- // --- Built-in yt-dlp terminal (Phase N) ---
/** Run the bundled yt-dlp with raw args; output streams via onTerminalOutput. */ /** Run the bundled yt-dlp with raw args; output streams via onTerminalOutput. */
+1
View File
@@ -271,6 +271,7 @@ export const mockApi: Api = {
onSystemThemeUpdate: () => () => {}, onSystemThemeUpdate: () => () => {},
openHighContrastSettings: async () => {}, openHighContrastSettings: async () => {},
onExternalUrl: () => () => {}, onExternalUrl: () => () => {},
onRunWatchedSync: () => () => {},
// Media-manager sources — a seeded channel so the (Phase H) Library view has // Media-manager sources — a seeded channel so the (Phase H) Library view has
// demo data in this browser-only preview. // demo data in this browser-only preview.
listSources: async () => [ listSources: async () => [
+5 -2
View File
@@ -485,13 +485,16 @@ if (!PREVIEW) {
.listSources() .listSources()
.then((sources) => { .then((sources) => {
useSources.setState({ sources }) useSources.setState({ sources })
// If any source is watched, kick off a sync shortly after launch (covers the // If any source is watched, kick off a sync shortly after launch (covers a fresh
// scheduled `--sync` launch and a normal launch alike). // `--sync` launch and a normal launch alike).
if (sources.some((s) => s.watched)) { if (sources.some((s) => s.watched)) {
setTimeout(() => useSources.getState().syncWatched(), 1500) setTimeout(() => useSources.getState().syncWatched(), 1500)
} }
}) })
.catch(logError('startup listSources')) .catch(logError('startup listSources'))
// A scheduled `--sync` relaunch that hit the already-running instance nudges us here,
// so the daily sync fires even when AeroFetch was already open (e.g. tray mode).
window.api.onRunWatchedSync?.(() => useSources.getState().syncWatched())
window.api.onIndexProgress((p: IndexProgress) => { window.api.onIndexProgress((p: IndexProgress) => {
useSources.setState({ useSources.setState({
indexing: { indexing: {
+3
View File
@@ -105,6 +105,9 @@ export const IpcChannels = {
scheduledSyncSet: 'sources:scheduled-sync-set', scheduledSyncSet: 'sources:scheduled-sync-set',
/** main → renderer push channel for live indexing progress */ /** main → renderer push channel for live indexing progress */
indexProgress: 'sources:index-progress', indexProgress: 'sources:index-progress',
/** main → renderer: a scheduled `--sync` relaunch hit the running instance — run the
* watched-source sync here instead of no-opping (Phase J) */
runWatchedSync: 'sources:run-sync',
// --- Built-in yt-dlp terminal (Phase N) --- // --- Built-in yt-dlp terminal (Phase N) ---
terminalRun: 'terminal:run', terminalRun: 'terminal:run',
terminalCancel: 'terminal:cancel', terminalCancel: 'terminal:cancel',