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:
@@ -47,6 +47,10 @@ interface TelegramWebApp {
|
||||
onClick?: (cb: () => void) => void;
|
||||
offClick?: (cb: () => void) => void;
|
||||
};
|
||||
CloudStorage?: {
|
||||
getItem?: (key: string, cb: (err: string | null, value?: string) => void) => void;
|
||||
setItem?: (key: string, value: string, cb?: (err: string | null, ok?: boolean) => void) => void;
|
||||
};
|
||||
}
|
||||
|
||||
function webApp(): TelegramWebApp | undefined {
|
||||
@@ -312,6 +316,37 @@ export function telegramShowSettingsButton(handler: () => void): void {
|
||||
b.show();
|
||||
}
|
||||
|
||||
/** telegramCloudAvailable reports whether Telegram CloudStorage (Bot API 6.9) is usable. */
|
||||
export function telegramCloudAvailable(): boolean {
|
||||
return !!webApp()?.CloudStorage?.getItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* telegramCloudGet reads a value from Telegram CloudStorage, resolving null when the key is absent,
|
||||
* CloudStorage is unavailable (outside Telegram / a client predating Bot API 6.9), or the read
|
||||
* errors — so the caller can fall back to the local value.
|
||||
*/
|
||||
export function telegramCloudGet(key: string): Promise<string | null> {
|
||||
const cs = webApp()?.CloudStorage;
|
||||
if (!cs?.getItem) return Promise.resolve(null);
|
||||
return new Promise((resolve) => {
|
||||
cs.getItem!(key, (err, value) => resolve(err ? null : (value ?? null)));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* telegramCloudSet writes a value to Telegram CloudStorage, resolving once the write settles. It is
|
||||
* best-effort: a no-op outside Telegram / on an older client, and it swallows write errors, since
|
||||
* the local store remains the source of truth.
|
||||
*/
|
||||
export function telegramCloudSet(key: string, value: string): Promise<void> {
|
||||
const cs = webApp()?.CloudStorage;
|
||||
if (!cs?.setItem) return Promise.resolve();
|
||||
return new Promise((resolve) => {
|
||||
cs.setItem!(key, value, () => resolve());
|
||||
});
|
||||
}
|
||||
|
||||
/** Haptic is the set of feedbacks the app triggers. */
|
||||
export type Haptic = 'select' | 'success' | 'error' | 'warning' | 'light' | 'medium' | 'heavy';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user