feat(telegram): sync client display prefs via CloudStorage
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 56s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m20s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 56s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m20s
Theme, reduce-motion and board labels lived only in local IndexedDB/localStorage, so they did not follow the user across devices and could be lost when the Telegram WebView cleared storage. Mirror these three device-independent prefs to Telegram CloudStorage (Bot API 6.9) from the single local-persist point (persistPrefs), and reconcile them from CloudStorage in the background on launch (reconcileCloudPrefs) so a change made on another device follows the user here. The local store stays the instant-render cache; the interface language is intentionally excluded (it syncs via the durable account). Pure encode/decode extracted to cloudprefs.ts with unit tests; the CloudStorage transport wrappers are added to telegram.ts. No-op outside Telegram or on a client predating CloudStorage.
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { CLOUD_PREFS_KEY, decodeClientPrefs, encodeClientPrefs } from './cloudprefs';
|
||||
|
||||
describe('cloudprefs', () => {
|
||||
it('round-trips the synced client prefs', () => {
|
||||
const p = { theme: 'dark', reduceMotion: true, boardLabels: 'classic' } as const;
|
||||
expect(decodeClientPrefs(encodeClientPrefs(p))).toEqual(p);
|
||||
});
|
||||
|
||||
it('never encodes the locale (it syncs via the durable account instead)', () => {
|
||||
const raw = encodeClientPrefs({ theme: 'light', reduceMotion: false, boardLabels: 'none' });
|
||||
expect(raw).not.toContain('locale');
|
||||
});
|
||||
|
||||
it('returns an empty partial for missing or malformed input', () => {
|
||||
expect(decodeClientPrefs(null)).toEqual({});
|
||||
expect(decodeClientPrefs(undefined)).toEqual({});
|
||||
expect(decodeClientPrefs('')).toEqual({});
|
||||
expect(decodeClientPrefs('not json')).toEqual({});
|
||||
expect(decodeClientPrefs('[1,2,3]')).toEqual({});
|
||||
});
|
||||
|
||||
it('keeps only valid fields and drops unknown or mistyped ones', () => {
|
||||
const raw = JSON.stringify({ theme: 'neon', reduceMotion: 'yes', boardLabels: 'classic', locale: 'ru' });
|
||||
expect(decodeClientPrefs(raw)).toEqual({ boardLabels: 'classic' });
|
||||
});
|
||||
|
||||
it('exposes the CloudStorage key', () => {
|
||||
expect(CLOUD_PREFS_KEY).toBe('prefs');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user