openvibers/openvibe.network Commits

Keep account comfort display preferences (#423)

OP OpenVibers committed 15 days ago · 589aebafa2 · 2 files, +13 −6

Changes

ddiff --git a/server/themes/routes.js b/server/themes/routes.js
iindex d46d8380..08aadd1a 100644
---- a/server/themes/routes.js
++++ b/server/themes/routes.js
@@@ -151,12 +151,16 @@ router.get('/me/active', (req, res, next) => {
res.json({ theme_id: prefs.theme_id, custom_variables: custom, display, override: false });
});
--// ── Display preferences (motion, text size) — follow the account to every site ──
++// ── Display preferences — follow the account to every site ──
// seasonal: the season's theme (openvibe-shared theme-loader Seasons: Pumpkin Night in October, Frost in December) in place
// of the default theme, unless 'off' (the owner, 2026-10-24: "users can opt out … and just want their normal default").
// scheme: 'manual' (the picked theme as it is) or 'auto' (its light or dark half, as the device is set; openvibe-shared
// theme-loader Light / Dark / Auto, 2026-10-25).
--const DISPLAY = { motion: ['auto', 'reduced'], text: ['100', '112', '125'], seasonal: ['on', 'off'], scheme: ['manual', 'auto'] };
++// contrast: increase contrast for easier reading.
++// font: use the readable typeface across sites.
++// colors: choose colors designed to be safe for color blindness.
++// oled: use pure black backgrounds on OLED displays.
++const DISPLAY = { motion: ['auto', 'reduced'], text: ['100', '112', '125'], seasonal: ['on', 'off'], scheme: ['manual', 'auto'], contrast: ['normal', 'more'], font: ['default', 'readable'], colors: ['default', 'cb-safe'], oled: ['off', 'on'] };
function cleanDisplay(d) {
if (!d || typeof d !== 'object') return null;
const out = {};
ddiff --git a/test/themes-review.test.js b/test/themes-review.test.js
iindex 5cffe407..3799ee76 100644
---- a/test/themes-review.test.js
++++ b/test/themes-review.test.js
@@@ -102,10 +102,13 @@ const token = async (id) => signToken(await db.prepare('SELECT * FROM users WHER
assert.deepStrictEqual([r.status, r.body.theme.slug], [200, 'ember'], 'followed, it is the ember theme');
assert.strictEqual((await call('GET', '/api/themes/no-such-theme')).status, 404, 'an unknown name is still a 404');
-- // ── Display preferences follow the account: text size, motion and seasonal themes (on|off), nothing else ──
-- r = await call('PUT', '/api/themes/me/display', { as: 2, body: { text: '112', motion: 'reduced', seasonal: 'off', colour: 'red' } });
-- assert.deepStrictEqual(r.body.display, { motion: 'reduced', text: '112', seasonal: 'off' }, 'seasonal is kept, an unknown key is not');
-- assert.deepStrictEqual((await call('GET', '/api/themes/me/active', { as: 2 })).body.display, { motion: 'reduced', text: '112', seasonal: 'off' });
++ // ── Display preferences follow the account; only known keys and values are kept ──
++ r = await call('PUT', '/api/themes/me/display', { as: 2, body: { text: '112', motion: 'reduced', seasonal: 'off', contrast: 'more', font: 'readable', colors: 'cb-safe', oled: 'on', colour: 'red' } });
++ const display = { motion: 'reduced', text: '112', seasonal: 'off', contrast: 'more', font: 'readable', colors: 'cb-safe', oled: 'on' };
++ assert.deepStrictEqual(r.body.display, display, 'comfort settings are kept, an unknown key is not');
++ assert.deepStrictEqual((await call('GET', '/api/themes/me/active', { as: 2 })).body.display, display, 'saved comfort settings follow the account');
++ r = await call('PUT', '/api/themes/me/display', { as: 2, body: { contrast: 'more', font: 'comic-sans' } });
++ assert.deepStrictEqual(r.body.display, { contrast: 'more' }, 'an invalid font is dropped');
r = await call('PUT', '/api/themes/me/display', { as: 2, body: { seasonal: 'maybe' } });
assert.ok(!('seasonal' in (r.body.display || {})), 'only on or off');
r = await call('PUT', '/api/themes/me/display', { as: 2, body: { scheme: 'auto' } });