feat(widgets): make goal countdown movable and resizable
This commit is contained in:
1 parent
248e1639a3
commit
6089059dbc
6 files changed
+96
-7
No files matched your search
+3
-3
@@ -7,7 +7,7 @@ const meta = new URL("../dist/.openai/", import.meta.url);
|
||||
|
||||
await rm(dist, { recursive: true, force: true });
|
||||
await Promise.all([mkdir(server, { recursive: true }), mkdir(meta, { recursive: true })]);
|
||||
const [rawIndexHtml, addonsJs, bootGuardJs, i18nJs, tasksJs, calendarJs, i18nRenderersJs, desktopPersonalizationJs, manifest, serviceWorker, icon, localeEn, localeZh] = await Promise.all([text("index.html"), text("addons.js"), text("boot-guard.js"), text("i18n.js"), text("tasks.js"), text("calendar.js"), text("i18n-renderers.js"), text("desktop-personalization.js"), text("manifest.webmanifest"), text("service-worker.js"), text("life-os-icon.svg"), readFile(new URL("../public/locales/en.json", import.meta.url), "utf8"), readFile(new URL("../public/locales/zh-CN.json", import.meta.url), "utf8")]);
|
||||
const [rawIndexHtml, addonsJs, bootGuardJs, i18nJs, tasksJs, calendarJs, i18nRenderersJs, desktopPersonalizationJs, desktopWidgetsJs, manifest, serviceWorker, icon, localeEn, localeZh] = await Promise.all([text("index.html"), text("addons.js"), text("boot-guard.js"), text("i18n.js"), text("tasks.js"), text("calendar.js"), text("i18n-renderers.js"), text("desktop-personalization.js"), text("desktop-widgets.js"), text("manifest.webmanifest"), text("service-worker.js"), text("life-os-icon.svg"), readFile(new URL("../public/locales/en.json", import.meta.url), "utf8"), readFile(new URL("../public/locales/zh-CN.json", import.meta.url), "utf8")]);
|
||||
const release = "1.7.0";
|
||||
const localeEnJs = `window.LifeOSLocales=window.LifeOSLocales||{};window.LifeOSLocales.en=${localeEn};`;
|
||||
const localeZhJs = `window.LifeOSLocales=window.LifeOSLocales||{};window.LifeOSLocales['zh-CN']=${localeZh};`;
|
||||
@@ -15,13 +15,13 @@ let indexHtml = rawIndexHtml.replace('src="addons.js"', `src="addons.js?v=${rele
|
||||
for (const [src, code] of [
|
||||
['boot-guard.js', bootGuardJs], ['locales/en.js', localeEnJs], ['locales/zh-CN.js', localeZhJs],
|
||||
['i18n.js', i18nJs], ['tasks.js', tasksJs], ['calendar.js', calendarJs],
|
||||
['addons.js', addonsJs], ['i18n-renderers.js', i18nRenderersJs], ['desktop-personalization.js', desktopPersonalizationJs]
|
||||
['addons.js', addonsJs], ['i18n-renderers.js', i18nRenderersJs], ['desktop-personalization.js', desktopPersonalizationJs], ['desktop-widgets.js', desktopWidgetsJs]
|
||||
]) {
|
||||
const tag = `<script src="${src}${src === 'boot-guard.js' ? '' : `?v=${release}`}"></script>`;
|
||||
if (!indexHtml.includes(tag)) throw new Error(`Missing Life OS script: ${src}`);
|
||||
indexHtml = indexHtml.replace(tag, `<script>${code.replace(/<\/script/gi, '<\\/script')}</script>`);
|
||||
}
|
||||
await writeFile(new URL("assets.js", server), `export const indexHtml=${JSON.stringify(indexHtml)};\nexport const addonsJs=${JSON.stringify(addonsJs)};\nexport const bootGuardJs=${JSON.stringify(bootGuardJs)};\nexport const i18nJs=${JSON.stringify(i18nJs)};\nexport const localeEn=JSON.parse(${JSON.stringify(localeEn)});\nexport const localeZh=JSON.parse(${JSON.stringify(localeZh)});\nexport const localeEnJs=${JSON.stringify(localeEnJs)};\nexport const localeZhJs=${JSON.stringify(localeZhJs)};\nexport const tasksJs=${JSON.stringify(tasksJs)};\nexport const calendarJs=${JSON.stringify(calendarJs)};\nexport const i18nRenderersJs=${JSON.stringify(i18nRenderersJs)};\nexport const desktopPersonalizationJs=${JSON.stringify(desktopPersonalizationJs)};\nexport const manifest=${JSON.stringify(manifest)};\nexport const serviceWorker=${JSON.stringify(serviceWorker)};\nexport const icon=${JSON.stringify(icon)};\n`);
|
||||
await writeFile(new URL("assets.js", server), `export const indexHtml=${JSON.stringify(indexHtml)};\nexport const addonsJs=${JSON.stringify(addonsJs)};\nexport const bootGuardJs=${JSON.stringify(bootGuardJs)};\nexport const i18nJs=${JSON.stringify(i18nJs)};\nexport const localeEn=JSON.parse(${JSON.stringify(localeEn)});\nexport const localeZh=JSON.parse(${JSON.stringify(localeZh)});\nexport const localeEnJs=${JSON.stringify(localeEnJs)};\nexport const localeZhJs=${JSON.stringify(localeZhJs)};\nexport const tasksJs=${JSON.stringify(tasksJs)};\nexport const calendarJs=${JSON.stringify(calendarJs)};\nexport const i18nRenderersJs=${JSON.stringify(i18nRenderersJs)};\nexport const desktopPersonalizationJs=${JSON.stringify(desktopPersonalizationJs)};\nexport const desktopWidgetsJs=${JSON.stringify(desktopWidgetsJs)};\nexport const manifest=${JSON.stringify(manifest)};\nexport const serviceWorker=${JSON.stringify(serviceWorker)};\nexport const icon=${JSON.stringify(icon)};\n`);
|
||||
await copyFile(new URL("../worker/index.js", import.meta.url), new URL("index.js", server));
|
||||
await copyFile(new URL("../.openai/hosting.json", import.meta.url), new URL("hosting.json", meta));
|
||||
console.log("Built Life OS Worker artifact");
|
||||
@@ -20,7 +20,7 @@ const flatten = (value, prefix = "") => Object.entries(value).flatMap(([key, chi
|
||||
const enKeys = flatten(assets.localeEn), zhKeys = flatten(assets.localeZh);
|
||||
assert.deepEqual(enKeys, zhKeys, "English and Chinese locale keys must match");
|
||||
const resolveKey = (locale, key) => key.split(".").reduce((value, part) => value?.[part], locale);
|
||||
for (const script of [assets.i18nRenderersJs, assets.desktopPersonalizationJs, assets.addonsJs, source]) {
|
||||
for (const script of [assets.i18nRenderersJs, assets.desktopPersonalizationJs, assets.desktopWidgetsJs, assets.addonsJs, source]) {
|
||||
for (const match of script.matchAll(/(?:\bt|LifeI18n\.t)\(['"`]([A-Za-z][\w.]+)['"`]/g)) {
|
||||
assert.notEqual(resolveKey(assets.localeEn, match[1]), undefined, `Missing locale key: ${match[1]}`);
|
||||
assert.notEqual(resolveKey(assets.localeZh, match[1]), undefined, `Missing Chinese locale key: ${match[1]}`);
|
||||
@@ -45,11 +45,11 @@ assert.doesNotMatch(assets.indexHtml, /setTimeout\(applyLanguage\s*,/);
|
||||
assert.doesNotMatch(assets.addonsJs, /(?<![\w.])applyLanguage\s*\(/, "add-on actions must not call a missing global locale function");
|
||||
assert.match(assets.indexHtml, /window\.renderIcons=renderIcons;window\.renderAll=renderAll/, "shared renderers are explicitly exposed to locale scripts");
|
||||
const shippedScripts = [...assets.indexHtml.matchAll(/<script>([\s\S]*?)<\/script>/g)].map(match => match[1]);
|
||||
assert.equal(shippedScripts.length, 11, "the complete desktop script chain is present in the served HTML");
|
||||
assert.equal(shippedScripts.length, 12, "the complete desktop script chain is present in the served HTML");
|
||||
assert.doesNotMatch(assets.indexHtml, /<script\s+src=/, "the desktop cannot silently fall back when an app script fails to load");
|
||||
assert.ok(assets.indexHtml.indexOf('window.systemApp =') < assets.indexHtml.lastIndexOf("window.init()"), "locale renderers run before desktop initialization");
|
||||
for (const script of shippedScripts) new vm.Script(script);
|
||||
for (const script of [assets.i18nJs, assets.tasksJs, assets.calendarJs, assets.i18nRenderersJs, assets.desktopPersonalizationJs, assets.addonsJs]) new vm.Script(script);
|
||||
for (const script of [assets.i18nJs, assets.tasksJs, assets.calendarJs, assets.i18nRenderersJs, assets.desktopPersonalizationJs, assets.desktopWidgetsJs, assets.addonsJs]) new vm.Script(script);
|
||||
assert.doesNotMatch(source, /Version 0\.1|Schema v1/);
|
||||
const makeStorage = initial => {
|
||||
const values = new Map(Object.entries(initial || {}));
|
||||
|
||||
Reference in new issue
Block a user