From aa863dd77031d42db0696727d699de54cba145ef Mon Sep 17 00:00:00 2001 From: faraoman Date: Wed, 8 Oct 2025 19:54:30 +0200 Subject: [PATCH 1/3] feat: add Recipe pool interval configuration --- src/models/Service.ts | 2 ++ src/stores/ServicesStore.ts | 13 ++++++++++--- src/webview/lib/RecipeWebview.ts | 7 ++++++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/models/Service.ts b/src/models/Service.ts index 6b664a4c70..b037484d70 100644 --- a/src/models/Service.ts +++ b/src/models/Service.ts @@ -126,6 +126,8 @@ export default class Service { @observable lastHibernated: number | null = null; // timestamp + @observable pollDelay: number = 2000; // interval for Recipe Polling + @observable lastPoll: number = Date.now(); @observable lastPollAnswer: number = Date.now(); diff --git a/src/stores/ServicesStore.ts b/src/stores/ServicesStore.ts index 58c6b2a87c..20aa93203f 100644 --- a/src/stores/ServicesStore.ts +++ b/src/stores/ServicesStore.ts @@ -983,6 +983,15 @@ export default class ServicesStore extends TypedStore { break; } + case 'set-loop-delay': { + debug('Received set-loop-delay request from', serviceId); + const defaultDelay = ms('2s'); + let parsedData = ms(`${args[0]}`); + if (parsedData < defaultDelay) parsedData = defaultDelay; + + service.pollDelay = parsedData; + break; + } // No default } } @@ -1440,8 +1449,6 @@ export default class ServicesStore extends TypedStore { _initRecipePolling(serviceId: string) { const service = this.one(serviceId); - const delay = ms('2s'); - if (service) { if (service.timer !== null) { clearTimeout(service.timer); @@ -1452,7 +1459,7 @@ export default class ServicesStore extends TypedStore { service.webview.send('poll'); - service.timer = setTimeout(loop, delay); + service.timer = setTimeout(loop, service.pollDelay); service.lastPoll = Date.now(); }; diff --git a/src/webview/lib/RecipeWebview.ts b/src/webview/lib/RecipeWebview.ts index 2e967a7914..e745e5cc28 100644 --- a/src/webview/lib/RecipeWebview.ts +++ b/src/webview/lib/RecipeWebview.ts @@ -58,8 +58,13 @@ class RecipeWebview { * Initialize the loop * * @param {Function} Function that will be executed + * @param {String} Interval which drive the loop in `ms` library format */ - loop(fn) { + loop(fn, interval) { + if (interval && typeof interval === 'string') { + ipcRenderer.sendToHost('set-loop-delay', interval); + } + this.loopFunc = fn; } From 3928af3bd27bcfda33847f7477e628f78d6705f4 Mon Sep 17 00:00:00 2001 From: faraoman Date: Wed, 8 Oct 2025 19:54:30 +0200 Subject: [PATCH 2/3] feat: add Recipe pool interval configuration --- src/models/Service.ts | 2 ++ src/stores/ServicesStore.ts | 13 ++++++++++--- src/webview/lib/RecipeWebview.ts | 7 ++++++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/models/Service.ts b/src/models/Service.ts index 6b664a4c70..b037484d70 100644 --- a/src/models/Service.ts +++ b/src/models/Service.ts @@ -126,6 +126,8 @@ export default class Service { @observable lastHibernated: number | null = null; // timestamp + @observable pollDelay: number = 2000; // interval for Recipe Polling + @observable lastPoll: number = Date.now(); @observable lastPollAnswer: number = Date.now(); diff --git a/src/stores/ServicesStore.ts b/src/stores/ServicesStore.ts index 58c6b2a87c..20aa93203f 100644 --- a/src/stores/ServicesStore.ts +++ b/src/stores/ServicesStore.ts @@ -983,6 +983,15 @@ export default class ServicesStore extends TypedStore { break; } + case 'set-loop-delay': { + debug('Received set-loop-delay request from', serviceId); + const defaultDelay = ms('2s'); + let parsedData = ms(`${args[0]}`); + if (parsedData < defaultDelay) parsedData = defaultDelay; + + service.pollDelay = parsedData; + break; + } // No default } } @@ -1440,8 +1449,6 @@ export default class ServicesStore extends TypedStore { _initRecipePolling(serviceId: string) { const service = this.one(serviceId); - const delay = ms('2s'); - if (service) { if (service.timer !== null) { clearTimeout(service.timer); @@ -1452,7 +1459,7 @@ export default class ServicesStore extends TypedStore { service.webview.send('poll'); - service.timer = setTimeout(loop, delay); + service.timer = setTimeout(loop, service.pollDelay); service.lastPoll = Date.now(); }; diff --git a/src/webview/lib/RecipeWebview.ts b/src/webview/lib/RecipeWebview.ts index 2e967a7914..e745e5cc28 100644 --- a/src/webview/lib/RecipeWebview.ts +++ b/src/webview/lib/RecipeWebview.ts @@ -58,8 +58,13 @@ class RecipeWebview { * Initialize the loop * * @param {Function} Function that will be executed + * @param {String} Interval which drive the loop in `ms` library format */ - loop(fn) { + loop(fn, interval) { + if (interval && typeof interval === 'string') { + ipcRenderer.sendToHost('set-loop-delay', interval); + } + this.loopFunc = fn; } From 54c07db1ec7213a33d08eaf35cb652dc9fb6d015 Mon Sep 17 00:00:00 2001 From: faraoman Date: Sat, 18 Oct 2025 16:05:19 +0200 Subject: [PATCH 3/3] feat: refactoring on previous implementation in favour of configuration tied to recipe --- src/config.ts | 1 + src/models/Recipe.ts | 5 +++++ src/models/Service.ts | 8 ++++++-- src/stores/ServicesStore.ts | 10 +--------- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/config.ts b/src/config.ts index 538cf3ff66..da312c7849 100644 --- a/src/config.ts +++ b/src/config.ts @@ -651,6 +651,7 @@ export const DEFAULT_SERVICE_SETTINGS = { darkReaderBrightness: 100, darkReaderContrast: 90, darkReaderSepia: 10, + pollDelay: 2000 /* 2000ms */, }; export const DEFAULT_SHORTCUTS = { diff --git a/src/models/Recipe.ts b/src/models/Recipe.ts index 87043693bc..df729b2038 100644 --- a/src/models/Recipe.ts +++ b/src/models/Recipe.ts @@ -25,6 +25,7 @@ interface RecipeData { local?: boolean; message?: string; allowFavoritesDelineationInUnreadCount?: boolean; + pollDelay?: number; }; defaultIcon: string; } @@ -51,6 +52,7 @@ export interface IRecipe { partition: string; local: boolean; defaultIcon: string; + pollDelay: number; readonly overrideUserAgent?: () => string; @@ -113,6 +115,8 @@ export default class Recipe implements IRecipe { partition = ''; + pollDelay = DEFAULT_SERVICE_SETTINGS.pollDelay; + // TODO: Is this being used? local = false; @@ -188,6 +192,7 @@ export default class Recipe implements IRecipe { data.config.allowFavoritesDelineationInUnreadCount, this.allowFavoritesDelineationInUnreadCount, ); + this.pollDelay = ifUndefined(data.config.pollDelay, this.pollDelay); // computed this.path = data.path; diff --git a/src/models/Service.ts b/src/models/Service.ts index b037484d70..fbff7418d5 100644 --- a/src/models/Service.ts +++ b/src/models/Service.ts @@ -126,7 +126,7 @@ export default class Service { @observable lastHibernated: number | null = null; // timestamp - @observable pollDelay: number = 2000; // interval for Recipe Polling + @observable pollDelay: number = DEFAULT_SERVICE_SETTINGS.pollDelay; // interval for Recipe Polling @observable lastPoll: number = Date.now(); @@ -239,7 +239,11 @@ export default class Service { data.isWakeUpEnabled, this.isWakeUpEnabled, ); - + this.pollDelay = ifUndefined( + recipe.pollDelay <= data.pollDelay ? data.pollDelay : recipe.pollDelay, + this.pollDelay, + ); + // console.log('ctor-recipe', recipe); // Check if "Hibernate on Startup" is enabled and hibernate all services except active one const { hibernateOnStartup } = window['ferdium'].stores.settings.app; // The service store is probably not loaded yet so we need to use localStorage data to get active service diff --git a/src/stores/ServicesStore.ts b/src/stores/ServicesStore.ts index 20aa93203f..1c49c8b699 100644 --- a/src/stores/ServicesStore.ts +++ b/src/stores/ServicesStore.ts @@ -480,6 +480,7 @@ export default class ServicesStore extends TypedStore { spellcheckerLanguage: SPELLCHECKER_LOCALES[this.stores.settings.app.spellcheckerLanguage], userAgentPref: '', + pollDelay: DEFAULT_SERVICE_SETTINGS.pollDelay, ...serviceData, }; @@ -983,15 +984,6 @@ export default class ServicesStore extends TypedStore { break; } - case 'set-loop-delay': { - debug('Received set-loop-delay request from', serviceId); - const defaultDelay = ms('2s'); - let parsedData = ms(`${args[0]}`); - if (parsedData < defaultDelay) parsedData = defaultDelay; - - service.pollDelay = parsedData; - break; - } // No default } }