fix(settings): keep the language and save settings one after the other

This commit is contained in:
lobo committed 2026-09-29 13:27:31 +02:00
1 parent 14dd59f9e0
commit f605917874
25 files changed
+423 -98

No files matched your search

+30 -10
View File
@@ -4,11 +4,13 @@ import {
applyAppearance,
cacheAppearance,
DEFAULT_APPEARANCE,
loadAppearance,
loadPreferences,
normalizeAppearance,
readCachedAppearance,
saveAppearance,
} from '../utils/appearance.js';
import {hasSession} from '../utils/auth.js';
import {LANGUAGES, saveSettings} from '../utils/settings.js';
const DARK_MODE_STORAGE_KEY = 'tbp_dark_mode';
// The --background of style.css; the installed app paints its title bar in this color.
@@ -51,21 +53,29 @@ export function PreferencesProvider({children}) {
cacheAppearance(appearance);
}, [appearance]);
const syncAppearance = useCallback(() => {
// Grows on every language pick, so a load that started before does not undo it.
const languagePicks = useRef(0);
const syncPreferences = useCallback(() => {
const started = generation.current;
const picksBefore = languagePicks.current;
syncing.current = (async () => {
try {
const loaded = await loadAppearance();
if (loaded && generation.current === started) {
savedAppearance.current = loaded;
setAppearanceState(normalizeAppearance({...loaded, ...pendingChanges.current}));
const loaded = await loadPreferences();
if (loaded?.appearance && generation.current === started) {
savedAppearance.current = loaded.appearance;
setAppearanceState(normalizeAppearance({...loaded.appearance, ...pendingChanges.current}));
}
if (LANGUAGES.includes(loaded?.language) && languagePicks.current === picksBefore
&& loaded.language !== i18n.language) {
i18n.changeLanguage(loaded.language);
}
} catch (err) {
console.error('Appearance load error:', err);
console.error('Preferences load error:', err);
}
})();
return syncing.current;
}, []);
}, [i18n]);
/**
* Applies the changed fields at once, then saves them to Auth after a running load and after the saves before
@@ -114,7 +124,17 @@ export function PreferencesProvider({children}) {
setAppearanceState(DEFAULT_APPEARANCE);
}, []);
const setLanguage = (lang) => i18n.changeLanguage(lang);
/**
* Applies the language at once and saves it to Auth while logged in.
*
* @return the fetch response, or null when logged out; rejects on a network error
*/
const setLanguage = (lang) => {
languagePicks.current += 1;
i18n.changeLanguage(lang);
if (!hasSession()) return Promise.resolve(null);
return saveSettings({language: lang});
};
return (
<PreferencesContext.Provider
@@ -125,7 +145,7 @@ export function PreferencesProvider({children}) {
setLanguage,
appearance,
changeAppearance,
syncAppearance,
syncPreferences,
resetAppearance,
}}
>