support syncing the settings autoUpdateExchangeRatesData, showAddTransactionButtonInDesktopNavbar, mapCacheExpiration, and exchangeRatesDataCacheExpiration
This commit is contained in:
@@ -16,6 +16,9 @@ const (
|
||||
var ALL_ALLOWED_CLOUD_SYNC_APP_SETTING_KEY_TYPES = map[string]UserApplicationCloudSettingType{
|
||||
// Basic Settings
|
||||
"showAccountBalance": USER_APPLICATION_CLOUD_SETTING_TYPE_BOOLEAN,
|
||||
"autoUpdateExchangeRatesData": USER_APPLICATION_CLOUD_SETTING_TYPE_BOOLEAN,
|
||||
// Navigation Bar
|
||||
"showAddTransactionButtonInDesktopNavbar": USER_APPLICATION_CLOUD_SETTING_TYPE_BOOLEAN,
|
||||
// Overview Page
|
||||
"showAmountInHomePage": USER_APPLICATION_CLOUD_SETTING_TYPE_BOOLEAN,
|
||||
"timezoneUsedForStatisticsInHomePage": USER_APPLICATION_CLOUD_SETTING_TYPE_NUMBER,
|
||||
@@ -41,6 +44,9 @@ var ALL_ALLOWED_CLOUD_SYNC_APP_SETTING_KEY_TYPES = map[string]UserApplicationClo
|
||||
"hideCategoriesWithoutAccounts": USER_APPLICATION_CLOUD_SETTING_TYPE_BOOLEAN,
|
||||
// Exchange Rates Data Page
|
||||
"currencySortByInExchangeRatesPage": USER_APPLICATION_CLOUD_SETTING_TYPE_NUMBER,
|
||||
// Browser Cache Management
|
||||
"mapCacheExpiration": USER_APPLICATION_CLOUD_SETTING_TYPE_NUMBER,
|
||||
"exchangeRatesDataCacheExpiration": USER_APPLICATION_CLOUD_SETTING_TYPE_NUMBER,
|
||||
// Statistics Settings
|
||||
"statistics.defaultChartDataType": USER_APPLICATION_CLOUD_SETTING_TYPE_NUMBER,
|
||||
"statistics.defaultTimezoneType": USER_APPLICATION_CLOUD_SETTING_TYPE_NUMBER,
|
||||
|
||||
+4
-16
@@ -78,16 +78,6 @@ onMounted(() => {
|
||||
const languageInfo = getCurrentLanguageInfo();
|
||||
initMapProvider(languageInfo?.alternativeLanguageTag);
|
||||
});
|
||||
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.addEventListener('controllerchange', () => {
|
||||
updateMapCacheExpiration(settingsStore.appSettings.mapCacheExpiration);
|
||||
});
|
||||
|
||||
if (navigator.serviceWorker.controller) {
|
||||
updateMapCacheExpiration(settingsStore.appSettings.mapCacheExpiration);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
watch(currentNotificationContent, (newValue) => {
|
||||
@@ -114,7 +104,6 @@ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', fun
|
||||
|
||||
let localeDefaultSettings = initLocale(userStore.currentUserLanguage, settingsStore.appSettings.timeZone);
|
||||
settingsStore.updateLocalizedDefaultSettings(localeDefaultSettings);
|
||||
exchangeRatesStore.removeExpiredExchangeRates(true);
|
||||
|
||||
setExpenseAndIncomeAmountColor(userStore.currentUserExpenseAmountColor, userStore.currentUserIncomeAmountColor);
|
||||
|
||||
@@ -132,12 +121,11 @@ if (isUserLogined() && initialRoutePath !== '/verify_email' && initialRoutePath
|
||||
rootStore.setNotificationContent(response.notificationContent);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// auto refresh exchange rates data
|
||||
if (settingsStore.appSettings.autoUpdateExchangeRatesData) {
|
||||
exchangeRatesStore.getLatestExchangeRates({ silent: true, force: false });
|
||||
}
|
||||
updateMapCacheExpiration(settingsStore.appSettings.mapCacheExpiration);
|
||||
exchangeRatesStore.removeExpiredExchangeRates(true);
|
||||
exchangeRatesStore.autoUpdateExchangeRatesData();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-16
@@ -181,16 +181,6 @@ onMounted(() => {
|
||||
const languageInfo = getCurrentLanguageInfo();
|
||||
initMapProvider(languageInfo?.alternativeLanguageTag);
|
||||
});
|
||||
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.addEventListener('controllerchange', () => {
|
||||
updateMapCacheExpiration(settingsStore.appSettings.mapCacheExpiration);
|
||||
});
|
||||
|
||||
if (navigator.serviceWorker.controller) {
|
||||
updateMapCacheExpiration(settingsStore.appSettings.mapCacheExpiration);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
watch(currentNotificationContent, (newValue) => {
|
||||
@@ -221,7 +211,6 @@ watch(currentNotificationContent, (newValue) => {
|
||||
|
||||
let localeDefaultSettings = initLocale(userStore.currentUserLanguage, settingsStore.appSettings.timeZone);
|
||||
settingsStore.updateLocalizedDefaultSettings(localeDefaultSettings);
|
||||
exchangeRatesStore.removeExpiredExchangeRates(true);
|
||||
|
||||
setExpenseAndIncomeAmountColor(userStore.currentUserExpenseAmountColor, userStore.currentUserIncomeAmountColor);
|
||||
|
||||
@@ -239,12 +228,11 @@ if (isUserLogined()) {
|
||||
rootStore.setNotificationContent(response.notificationContent);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// auto refresh exchange rates data
|
||||
if (settingsStore.appSettings.autoUpdateExchangeRatesData) {
|
||||
exchangeRatesStore.getLatestExchangeRates({ silent: true, force: false });
|
||||
}
|
||||
updateMapCacheExpiration(settingsStore.appSettings.mapCacheExpiration);
|
||||
exchangeRatesStore.removeExpiredExchangeRates(true);
|
||||
exchangeRatesStore.autoUpdateExchangeRatesData();
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
+8
-2
@@ -62,7 +62,7 @@ export interface ApplicationSettings extends BaseApplicationSetting {
|
||||
hideCategoriesWithoutAccounts: boolean;
|
||||
// Exchange Rates Data Page
|
||||
currencySortByInExchangeRatesPage: number;
|
||||
// Browser Cache Settings
|
||||
// Browser Cache Management
|
||||
mapCacheExpiration: number,
|
||||
exchangeRatesDataCacheExpiration: number,
|
||||
// Statistics Settings
|
||||
@@ -110,6 +110,9 @@ export interface WebAuthnConfig {
|
||||
export const ALL_ALLOWED_CLOUD_SYNC_APP_SETTING_KEY_TYPES: Record<string, UserApplicationCloudSettingType> = {
|
||||
// Basic Settings
|
||||
'showAccountBalance': UserApplicationCloudSettingType.Boolean,
|
||||
'autoUpdateExchangeRatesData': UserApplicationCloudSettingType.Boolean,
|
||||
// Navigation Bar
|
||||
'showAddTransactionButtonInDesktopNavbar': UserApplicationCloudSettingType.Boolean,
|
||||
// Overview Page
|
||||
'showAmountInHomePage': UserApplicationCloudSettingType.Boolean,
|
||||
'timezoneUsedForStatisticsInHomePage': UserApplicationCloudSettingType.Number,
|
||||
@@ -135,6 +138,9 @@ export const ALL_ALLOWED_CLOUD_SYNC_APP_SETTING_KEY_TYPES: Record<string, UserAp
|
||||
'hideCategoriesWithoutAccounts': UserApplicationCloudSettingType.Boolean,
|
||||
// Exchange Rates Data Page
|
||||
'currencySortByInExchangeRatesPage': UserApplicationCloudSettingType.Number,
|
||||
// Browser Cache Management
|
||||
'mapCacheExpiration': UserApplicationCloudSettingType.Number,
|
||||
'exchangeRatesDataCacheExpiration': UserApplicationCloudSettingType.Number,
|
||||
// Statistics Settings
|
||||
'statistics.defaultChartDataType': UserApplicationCloudSettingType.Number,
|
||||
'statistics.defaultTimezoneType': UserApplicationCloudSettingType.Number,
|
||||
@@ -190,7 +196,7 @@ export const DEFAULT_APPLICATION_SETTINGS: ApplicationSettings = {
|
||||
hideCategoriesWithoutAccounts: false,
|
||||
// Exchange Rates Data Page
|
||||
currencySortByInExchangeRatesPage: CurrencySortingType.Default.type,
|
||||
// Browser Cache Settings
|
||||
// Browser Cache Management
|
||||
mapCacheExpiration: -1,
|
||||
exchangeRatesDataCacheExpiration: 0,
|
||||
// Statistics Settings
|
||||
|
||||
+52
-35
@@ -18,6 +18,8 @@ import { isFunction, isObject, isNumber } from './common.ts';
|
||||
import services from './services.ts';
|
||||
import logger from './logger.ts';
|
||||
|
||||
let controllerchangeListenerAdded: boolean = false;
|
||||
|
||||
function findFirstCacheName(prefix: string): Promise<string> {
|
||||
if (!window.caches) {
|
||||
logger.error('caches API is not supported in this browser');
|
||||
@@ -35,6 +37,46 @@ function findFirstCacheName(prefix: string): Promise<string> {
|
||||
});
|
||||
}
|
||||
|
||||
function doUpdateMapCacheExpiration(expireSeconds: number): Promise<void> {
|
||||
const config: SWMapCacheConfig = {
|
||||
enabled: expireSeconds >= 0,
|
||||
patterns: services.getMapProxyTileImageAndAnnotationImageUrlPatterns(),
|
||||
maxEntries: MAP_CACHE_MAX_ENTRIES,
|
||||
maxAgeMilliseconds: expireSeconds * 1000
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!navigator.serviceWorker || !navigator.serviceWorker.controller) {
|
||||
reject(new Error('Service worker is not supported or not active'));
|
||||
return;
|
||||
}
|
||||
|
||||
const controller = navigator.serviceWorker.controller;
|
||||
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
const messageChannel = new MessageChannel();
|
||||
|
||||
messageChannel.port1.onmessage = (event) => {
|
||||
if (event.data && event.data.type === SW_MESSAGE_TYPE_UPDATE_MAP_CACHE_CONFIG_RESPONSE) {
|
||||
logger.info('Map cache config updated successfully in service worker: ' + JSON.stringify(event.data.payload));
|
||||
resolve();
|
||||
} else {
|
||||
logger.error('cannot update map cache config, invalid response from service worker', event);
|
||||
reject(new Error('Invalid response from service worker'));
|
||||
}
|
||||
};
|
||||
|
||||
controller.postMessage({
|
||||
type: SW_MESSAGE_TYPE_UPDATE_MAP_CACHE_CONFIG,
|
||||
payload: config
|
||||
}, [messageChannel.port2]);
|
||||
}).catch(error => {
|
||||
logger.error('failed to update map cache config', error);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function getCacheTotalSize(cacheName: string): Promise<number> {
|
||||
if (!window.caches) {
|
||||
logger.error('caches API is not supported in this browser');
|
||||
@@ -118,44 +160,19 @@ export function loadBrowserCacheStatistics(): Promise<BrowserCacheStatistics> {
|
||||
});
|
||||
}
|
||||
|
||||
export function updateMapCacheExpiration(expireSeconds: number): Promise<void> {
|
||||
const config: SWMapCacheConfig = {
|
||||
enabled: expireSeconds >= 0,
|
||||
patterns: services.getMapProxyTileImageAndAnnotationImageUrlPatterns(),
|
||||
maxEntries: MAP_CACHE_MAX_ENTRIES,
|
||||
maxAgeMilliseconds: expireSeconds * 1000
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!navigator.serviceWorker || !navigator.serviceWorker.controller) {
|
||||
reject(new Error('Service worker is not supported or not active'));
|
||||
return;
|
||||
export function updateMapCacheExpiration(expireSeconds: number): void {
|
||||
if ('serviceWorker' in navigator) {
|
||||
if (!controllerchangeListenerAdded) {
|
||||
navigator.serviceWorker.addEventListener('controllerchange', () => {
|
||||
doUpdateMapCacheExpiration(expireSeconds);
|
||||
});
|
||||
controllerchangeListenerAdded = true;
|
||||
}
|
||||
|
||||
const controller = navigator.serviceWorker.controller;
|
||||
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
const messageChannel = new MessageChannel();
|
||||
|
||||
messageChannel.port1.onmessage = (event) => {
|
||||
if (event.data && event.data.type === SW_MESSAGE_TYPE_UPDATE_MAP_CACHE_CONFIG_RESPONSE) {
|
||||
logger.info('Map cache config updated successfully in service worker: ' + JSON.stringify(event.data.payload));
|
||||
resolve();
|
||||
} else {
|
||||
logger.error('cannot update map cache config, invalid response from service worker', event);
|
||||
reject(new Error('Invalid response from service worker'));
|
||||
if (navigator.serviceWorker.controller) {
|
||||
doUpdateMapCacheExpiration(expireSeconds);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
controller.postMessage({
|
||||
type: SW_MESSAGE_TYPE_UPDATE_MAP_CACHE_CONFIG,
|
||||
payload: config
|
||||
}, [messageChannel.port2]);
|
||||
}).catch(error => {
|
||||
logger.error('failed to update map cache config', error);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function clearMapDataCache(): Promise<void> {
|
||||
|
||||
@@ -169,6 +169,12 @@ export const useExchangeRatesStore = defineStore('exchangeRates', () => {
|
||||
clearExchangeRatesFromLocalStorage();
|
||||
}
|
||||
|
||||
function autoUpdateExchangeRatesData(): void {
|
||||
if (settingsStore.appSettings.autoUpdateExchangeRatesData) {
|
||||
getLatestExchangeRates({ silent: true, force: false });
|
||||
}
|
||||
}
|
||||
|
||||
function getLatestExchangeRates({ silent, force }: { silent: boolean, force: boolean }): Promise<LatestExchangeRateResponse> {
|
||||
const currentExchangeRateData = latestExchangeRates.value;
|
||||
const now = getCurrentUnixTime();
|
||||
@@ -331,6 +337,7 @@ export const useExchangeRatesStore = defineStore('exchangeRates', () => {
|
||||
getExchangeRatesCacheSize,
|
||||
removeExpiredExchangeRates,
|
||||
resetLatestExchangeRates,
|
||||
autoUpdateExchangeRatesData,
|
||||
getLatestExchangeRates,
|
||||
updateUserCustomExchangeRate,
|
||||
deleteUserCustomExchangeRate,
|
||||
|
||||
@@ -152,6 +152,7 @@ export const useSettingsStore = defineStore('settings', () => {
|
||||
function setAutoUpdateExchangeRatesData(value: boolean): void {
|
||||
updateApplicationSettingsValue('autoUpdateExchangeRatesData', value);
|
||||
appSettings.value.autoUpdateExchangeRatesData = value;
|
||||
updateUserApplicationCloudSettingValue('autoUpdateExchangeRatesData', value);
|
||||
}
|
||||
|
||||
function setShowAccountBalance(value: boolean): void {
|
||||
@@ -185,6 +186,7 @@ export const useSettingsStore = defineStore('settings', () => {
|
||||
function setShowAddTransactionButtonInDesktopNavbar(value: boolean): void {
|
||||
updateApplicationSettingsValue('showAddTransactionButtonInDesktopNavbar', value);
|
||||
appSettings.value.showAddTransactionButtonInDesktopNavbar = value;
|
||||
updateUserApplicationCloudSettingValue('showAddTransactionButtonInDesktopNavbar', value);
|
||||
}
|
||||
|
||||
// Overview Page
|
||||
@@ -310,15 +312,17 @@ export const useSettingsStore = defineStore('settings', () => {
|
||||
updateUserApplicationCloudSettingValue('currencySortByInExchangeRatesPage', value);
|
||||
}
|
||||
|
||||
// Browser Cache Settings
|
||||
// Browser Cache Management
|
||||
function setMapCacheExpiration(value: number): void {
|
||||
updateApplicationSettingsValue('mapCacheExpiration', value);
|
||||
appSettings.value.mapCacheExpiration = value;
|
||||
updateUserApplicationCloudSettingValue('mapCacheExpiration', value);
|
||||
}
|
||||
|
||||
function setExchangeRatesDataCacheExpiration(value: number): void {
|
||||
updateApplicationSettingsValue('exchangeRatesDataCacheExpiration', value);
|
||||
appSettings.value.exchangeRatesDataCacheExpiration = value;
|
||||
updateUserApplicationCloudSettingValue('exchangeRatesDataCacheExpiration', value);
|
||||
}
|
||||
|
||||
// Statistics Settings
|
||||
@@ -542,7 +546,7 @@ export const useSettingsStore = defineStore('settings', () => {
|
||||
setHideCategoriesWithoutAccounts,
|
||||
// -- Exchange Rates Data Page
|
||||
setCurrencySortByInExchangeRatesPage,
|
||||
// -- Browser Cache Settings
|
||||
// -- Browser Cache Management
|
||||
setMapCacheExpiration,
|
||||
setExchangeRatesDataCacheExpiration,
|
||||
// -- Statistics Settings
|
||||
|
||||
@@ -8,6 +8,7 @@ import { useExchangeRatesStore } from '@/stores/exchangeRates.ts';
|
||||
|
||||
import type { AuthResponse } from '@/models/auth_response.ts';
|
||||
|
||||
import { updateMapCacheExpiration } from '@/lib/cache.ts';
|
||||
import { getOAuth2Provider, getOIDCCustomDisplayNames, getLoginPageTips } from '@/lib/server_settings.ts';
|
||||
import { getClientDisplayVersion } from '@/lib/version.ts';
|
||||
import { setExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts';
|
||||
@@ -54,9 +55,9 @@ export function useLoginPageBase(platform: 'mobile' | 'desktop') {
|
||||
setExpenseAndIncomeAmountColor(authResponse.user.expenseAmountColor, authResponse.user.incomeAmountColor);
|
||||
}
|
||||
|
||||
if (settingsStore.appSettings.autoUpdateExchangeRatesData) {
|
||||
exchangeRatesStore.getLatestExchangeRates({ silent: true, force: false });
|
||||
}
|
||||
updateMapCacheExpiration(settingsStore.appSettings.mapCacheExpiration);
|
||||
exchangeRatesStore.removeExpiredExchangeRates(true);
|
||||
exchangeRatesStore.autoUpdateExchangeRatesData();
|
||||
|
||||
if (authResponse.notificationContent) {
|
||||
rootStore.setNotificationContent(authResponse.notificationContent);
|
||||
|
||||
@@ -10,6 +10,8 @@ import { useExchangeRatesStore } from '@/stores/exchangeRates.ts';
|
||||
import { CategoryType } from '@/core/category.ts';
|
||||
import type { RegisterResponse } from '@/models/auth_response.ts';
|
||||
import type { User } from '@/models/user.ts';
|
||||
|
||||
import { updateMapCacheExpiration } from '@/lib/cache.ts';
|
||||
import { setExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts';
|
||||
|
||||
export function useSignupPageBase() {
|
||||
@@ -114,9 +116,9 @@ export function useSignupPageBase() {
|
||||
setExpenseAndIncomeAmountColor(response.user.expenseAmountColor, response.user.incomeAmountColor);
|
||||
}
|
||||
|
||||
if (settingsStore.appSettings.autoUpdateExchangeRatesData) {
|
||||
exchangeRatesStore.getLatestExchangeRates({ silent: true, force: false });
|
||||
}
|
||||
updateMapCacheExpiration(settingsStore.appSettings.mapCacheExpiration);
|
||||
exchangeRatesStore.removeExpiredExchangeRates(true);
|
||||
exchangeRatesStore.autoUpdateExchangeRatesData();
|
||||
|
||||
if (response.notificationContent) {
|
||||
rootStore.setNotificationContent(response.notificationContent);
|
||||
|
||||
@@ -11,6 +11,7 @@ import { useExchangeRatesStore } from '@/stores/exchangeRates.ts';
|
||||
|
||||
import { isWebAuthnSupported } from '@/lib/webauthn.ts';
|
||||
import { hasWebAuthnConfig } from '@/lib/userstate.ts';
|
||||
import { updateMapCacheExpiration } from '@/lib/cache.ts';
|
||||
import { getClientDisplayVersion } from '@/lib/version.ts';
|
||||
import { setExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts';
|
||||
|
||||
@@ -48,14 +49,14 @@ export function useUnlockPageBase() {
|
||||
setExpenseAndIncomeAmountColor(response.user.expenseAmountColor, response.user.incomeAmountColor);
|
||||
}
|
||||
|
||||
updateMapCacheExpiration(settingsStore.appSettings.mapCacheExpiration);
|
||||
exchangeRatesStore.removeExpiredExchangeRates(true);
|
||||
exchangeRatesStore.autoUpdateExchangeRatesData();
|
||||
|
||||
if (response.notificationContent) {
|
||||
rootStore.setNotificationContent(response.notificationContent);
|
||||
}
|
||||
});
|
||||
|
||||
if (settingsStore.appSettings.autoUpdateExchangeRatesData) {
|
||||
exchangeRatesStore.getLatestExchangeRates({ silent: true, force: false });
|
||||
}
|
||||
}
|
||||
|
||||
function doRelogin(): void {
|
||||
|
||||
@@ -23,7 +23,14 @@ export const ALL_APPLICATION_CLOUD_SETTINGS: CategorizedApplicationCloudSettingI
|
||||
{
|
||||
categoryName: 'Basic Settings',
|
||||
items: [
|
||||
{ settingKey: 'showAccountBalance', settingName: 'Show Account Balance', mobile: true, desktop: true }
|
||||
{ settingKey: 'showAccountBalance', settingName: 'Show Account Balance', mobile: true, desktop: true },
|
||||
{ settingKey: 'autoUpdateExchangeRatesData', settingName: 'Auto-update Exchange Rates Data', mobile: true, desktop: true }
|
||||
]
|
||||
},
|
||||
{
|
||||
categoryName: 'Navigation Bar',
|
||||
items: [
|
||||
{ settingKey: 'showAddTransactionButtonInDesktopNavbar', settingName: 'Show Add Transaction Button', mobile: false, desktop: true }
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -78,6 +85,13 @@ export const ALL_APPLICATION_CLOUD_SETTINGS: CategorizedApplicationCloudSettingI
|
||||
{ settingKey: 'currencySortByInExchangeRatesPage', settingName: 'Sort by', mobile: true, desktop: true }
|
||||
]
|
||||
},
|
||||
{
|
||||
categoryName: 'Browser Cache Management',
|
||||
items: [
|
||||
{ settingKey: 'mapCacheExpiration', settingName: 'Cache Expiration for Map Data', mobile: true, desktop: true },
|
||||
{ settingKey: 'exchangeRatesDataCacheExpiration', settingName: 'Cache Expiration for Exchange Rates Data', mobile: true, desktop: true }
|
||||
]
|
||||
},
|
||||
{
|
||||
categoryName: 'Statistics Settings',
|
||||
categorySubName: 'Common Settings',
|
||||
|
||||
Reference in New Issue
Block a user