- Webhooks for automations: per-job secret, Gitea/GitHub HMAC signatures, payload appended to the instructions; settings on the automations page - Service worker gets a new file name per build (proxies that cache *.js served a stale worker, which broke updates and Android installation); /sw.js is a kill switch that removes old workers - Push: devices re-register their subscription with the server on start and before a test; the test reports why a push service rejected a message Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
40 lines
1.5 KiB
TypeScript
40 lines
1.5 KiB
TypeScript
import { get, put } from "./api";
|
|
import { getLang, onLangChange, setLang } from "./i18n";
|
|
import { applyTheme, getTheme, getThemeMode, onThemeChange, THEMES, type Theme, type ThemeMode } from "./theme";
|
|
|
|
/**
|
|
* Theme and language are stored per device (localStorage) and mirrored to the
|
|
* server, so the command line client uses the same colours and language and a
|
|
* new device starts with your settings.
|
|
*/
|
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
let started = false;
|
|
|
|
function push() {
|
|
clearTimeout(timer);
|
|
timer = setTimeout(() => {
|
|
void put("/account/prefs", { theme: getTheme(), theme_mode: getThemeMode(), lang: getLang() }).catch(() => undefined);
|
|
}, 800);
|
|
}
|
|
|
|
export async function startPrefsSync() {
|
|
if (started) return;
|
|
started = true;
|
|
// A device without own settings takes the server's.
|
|
const fresh = !localStorage.getItem("codecraft.theme") && !localStorage.getItem("codecraft.themeMode");
|
|
try {
|
|
const p = await get<{ theme?: string; theme_mode?: string; lang?: string }>("/account/prefs");
|
|
if (fresh && p.theme && THEMES.some((t) => t.id === p.theme)) {
|
|
applyTheme(p.theme as Theme, (p.theme_mode as ThemeMode) ?? "auto");
|
|
}
|
|
if (fresh && p.lang) setLang(p.lang);
|
|
if (!p.theme) push();
|
|
} catch {
|
|
/* offline or old server */
|
|
}
|
|
// Push subscription of this device: make sure the server has it.
|
|
void import("./push").then((m) => m.syncPush()).catch(() => undefined);
|
|
onThemeChange(push);
|
|
onLangChange(push);
|
|
}
|