From 8cc6a7e3debf882e4a6861087c7568eb84097ff6 Mon Sep 17 00:00:00 2001 From: Jack Greenlee Date: Wed, 17 Apr 2024 00:58:06 -0400 Subject: [PATCH 1/3] UserInputButton: before appConfig is defined, don't show default survey --- www/js/survey/enketo/UserInputButton.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/www/js/survey/enketo/UserInputButton.tsx b/www/js/survey/enketo/UserInputButton.tsx index 118b687f8..e3e629bda 100644 --- a/www/js/survey/enketo/UserInputButton.tsx +++ b/www/js/survey/enketo/UserInputButton.tsx @@ -34,6 +34,7 @@ const UserInputButton = ({ timelineEntry }: Props) => { // which survey will this button launch? const [surveyName, notFilledInLabel] = useMemo(() => { + if (!appConfig) return []; // no config loaded yet; show blank for now const tripLabelConfig = appConfig?.survey_info?.buttons?.['trip-label']; if (!tripLabelConfig) { // config doesn't specify; use default From 03673a40a511136cc07d8092c701804f21bb0905 Mon Sep 17 00:00:00 2001 From: Jack Greenlee Date: Wed, 17 Apr 2024 01:02:10 -0400 Subject: [PATCH 2/3] in updateUnprocessedBleScans, await call to getUnifiedDataForInterval Without the 'await' keyword here, execution would continue without the request being completed. This would cause the BLE scans to sometimes not be considered while rendering and evaluating conditional surveys. If the BLE scans took longer to load than the trips took to render, there would be no surveys prompted. Thus, we must 'await' to make sure the BLE scans are loaded first. --- www/js/diary/timelineHelper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/js/diary/timelineHelper.ts b/www/js/diary/timelineHelper.ts index d82adb4fb..6e82c0fbf 100644 --- a/www/js/diary/timelineHelper.ts +++ b/www/js/diary/timelineHelper.ts @@ -182,7 +182,7 @@ export async function updateUnprocessedBleScans(queryRange: TimestampRange) { endTs: queryRange.end_ts, }; const getMethod = window['cordova'].plugins.BEMUserCache.getSensorDataForInterval; - getUnifiedDataForInterval('background/bluetooth_ble', tq, getMethod).then( + await getUnifiedDataForInterval('background/bluetooth_ble', tq, getMethod).then( (bleScans: BEMData[]) => { logDebug(`Read ${bleScans.length} BLE scans`); unprocessedBleScans = bleScans; From d83f4d4a28744dc33a71f86b94014e32cd2c1219 Mon Sep 17 00:00:00 2001 From: Jack Greenlee Date: Wed, 17 Apr 2024 01:21:17 -0400 Subject: [PATCH 3/3] cacheResourcesFromConfig: reload the cache when config is downloaded We recently added the ability to refresh the config from inside the app. But whenever the config is downloaded for the first time, we cache the resources referenced in it by URL. Subsequent config downloads would still use the resources from the first time. fetchUrlCached now accepts options to pass through to the fetch API; if cache is 'reload', we will skip checking our localStorage cache for a previously stored value. This option will also cause the fetch API will also skip its own internal cache The result of this is that when we refresh the config, URL-referenced resources inside it will also be refreshed. --- www/js/config/dynamicConfig.ts | 4 ++-- www/js/services/commHelper.ts | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/www/js/config/dynamicConfig.ts b/www/js/config/dynamicConfig.ts index d9b9f3235..5843af3d2 100644 --- a/www/js/config/dynamicConfig.ts +++ b/www/js/config/dynamicConfig.ts @@ -92,11 +92,11 @@ function cacheResourcesFromConfig(config: AppConfig) { if (config.survey_info?.surveys) { Object.values(config.survey_info.surveys).forEach((survey) => { if (!survey?.['formPath']) throw new Error(i18next.t('config.survey-missing-formpath')); - fetchUrlCached(survey['formPath']); + fetchUrlCached(survey['formPath'], { cache: 'reload' }); }); } if (config.label_options) { - fetchUrlCached(config.label_options); + fetchUrlCached(config.label_options, { cache: 'reload' }); } } diff --git a/www/js/services/commHelper.ts b/www/js/services/commHelper.ts index 26dce8056..ec2ee9d97 100644 --- a/www/js/services/commHelper.ts +++ b/www/js/services/commHelper.ts @@ -5,17 +5,18 @@ import { TimestampRange } from '../types/diaryTypes'; /** * @param url URL endpoint for the request + * @param fetchOpts (optional) options for the fetch request. If 'cache' is set to 'reload', the cache will be ignored * @returns Promise of the fetched response (as text) or cached text from local storage */ -export async function fetchUrlCached(url) { +export async function fetchUrlCached(url: string, fetchOpts?: RequestInit) { const stored = localStorage.getItem(url); - if (stored) { + if (stored && fetchOpts?.cache != 'reload') { logDebug(`fetchUrlCached: found cached data for url ${url}, returning`); return Promise.resolve(stored); } try { - logDebug(`fetchUrlCached: found no cached data for url ${url}, fetching`); - const response = await fetch(url); + logDebug(`fetchUrlCached: cache had ${stored} for url ${url}, not using; fetching`); + const response = await fetch(url, fetchOpts); const text = await response.text(); localStorage.setItem(url, text); logDebug(`fetchUrlCached: fetched data for url ${url}, returning`);