@glassly/engine 0.3.5-dev.751 → 0.3.5-dev.754
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/generated/releaseMetadata.js +3 -3
- package/build/generated/releaseMetadata.js.map +1 -1
- package/build/services/SceneRenderer.d.ts.map +1 -1
- package/build/services/SceneRenderer.js +3 -1
- package/build/services/SceneRenderer.js.map +1 -1
- package/build/services/settingsBridge.d.ts +4 -4
- package/build/services/settingsBridge.d.ts.map +1 -1
- package/build/services/settingsBridge.js +9 -4
- package/build/services/settingsBridge.js.map +1 -1
- package/build/stores/bluetoothSettingKeys.d.ts +2 -0
- package/build/stores/bluetoothSettingKeys.d.ts.map +1 -1
- package/build/stores/bluetoothSettingKeys.js +17 -0
- package/build/stores/bluetoothSettingKeys.js.map +1 -1
- package/build/stores/settings.d.ts.map +1 -1
- package/build/stores/settings.js +23 -2
- package/build/stores/settings.js.map +1 -1
- package/build/utils/display/scene/index.d.ts +1 -1
- package/build/utils/display/scene/index.d.ts.map +1 -1
- package/build/utils/display/scene/index.js.map +1 -1
- package/build/utils/display/scene/process.d.ts.map +1 -1
- package/build/utils/display/scene/process.js +20 -1
- package/build/utils/display/scene/process.js.map +1 -1
- package/build/utils/display/scene/types.d.ts +1 -1
- package/build/utils/display/scene/types.d.ts.map +1 -1
- package/build/utils/display/scene/types.js.map +1 -1
- package/package.json +7 -7
- package/src/generated/releaseMetadata.ts +3 -3
- package/src/services/SceneRenderer.ts +3 -1
- package/src/services/settingsBridge.ts +9 -4
- package/src/stores/bluetoothSettingKeys.ts +20 -0
- package/src/stores/settings.ts +25 -2
- package/src/utils/display/scene/index.ts +1 -0
- package/src/utils/display/scene/process.ts +17 -1
- package/src/utils/display/scene/types.ts +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process.js","sourceRoot":"","sources":["../../../../src/utils/display/scene/process.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Scene processing — validate → clamp → budget → wrap. Everything here is\n * generic; device variation enters only through the capabilities block and the\n * display profile (data, not code). Spec §5.\n *\n * Never rejects a frame: offending elements are dropped per-element and\n * reported via `dropped` / `degraded` (design doc §3.4.6; spec §4 refines the\n * design doc's image \"reject\" to per-element drop).\n */\n\nimport {compileSvgPath} from \"./svgPath\"\nimport {TextMeasurer} from \"../measurer/TextMeasurer\"\nimport {TextWrapper} from \"../wrapper/TextWrapper\"\nimport type {DisplayProfile} from \"../profiles/types\"\nimport type {DiffableElement} from \"./differ\"\nimport type {\n SceneBox,\n SceneBoxInput,\n SceneDisplayCapabilities,\n SceneElementInput,\n ScenePoint,\n SceneTextStyle,\n SceneTransition,\n} from \"./types\"\nimport {MAX_SCENE_DEPTH, POINT_SHAPE_ARITY, POINT_SHAPE_TYPES, elementContentHash} from \"./types\"\n\nexport interface ProcessedScene {\n elements: DiffableElement[]\n degraded: boolean\n dropped: string[]\n}\n\n/** Reporting id for an element the app may not have named. */\nfunction reportId(el: SceneElementInput, index: number): string {\n return el.id ?? `${el.type}[${index}]`\n}\n\nfunction clampBox(box: SceneBox, width: number, height: number): SceneBox | null {\n const x1 = Math.max(0, Math.floor(box.x))\n const y1 = Math.max(0, Math.floor(box.y))\n const x2 = Math.min(width, Math.floor(box.x) + Math.max(0, Math.floor(box.w)))\n const y2 = Math.min(height, Math.floor(box.y) + Math.max(0, Math.floor(box.h)))\n if (x2 <= x1 || y2 <= y1) return null\n return {x: x1, y: y1, w: x2 - x1, h: y2 - y1}\n}\n\nconst isFinite = (n: unknown): n is number => typeof n === \"number\" && Number.isFinite(n)\n\n/** Integer points, or null when the count/values are invalid for the type. */\nfunction validPoints(el: SceneElementInput): ScenePoint[] | null {\n const raw = (el as {points?: unknown}).points\n if (!Array.isArray(raw) || !(POINT_SHAPE_ARITY[el.type] ?? []).includes(raw.length)) return null\n const points: ScenePoint[] = []\n for (const p of raw) {\n if (!p || typeof p !== \"object\" || !isFinite((p as ScenePoint).x) || !isFinite((p as ScenePoint).y)) return null\n points.push({x: Math.floor((p as ScenePoint).x), y: Math.floor((p as ScenePoint).y)})\n }\n return points\n}\n\nfunction pointsBox(points: ScenePoint[]): SceneBox {\n const xs = points.map((p) => p.x)\n const ys = points.map((p) => p.y)\n const x = Math.min(...xs)\n const y = Math.min(...ys)\n return {x, y, w: Math.max(...xs) - x + 1, h: Math.max(...ys) - y + 1}\n}\n\nfunction validTransition(t: unknown): SceneTransition | undefined {\n if (!t || typeof t !== \"object\") return undefined\n const {durationMs, easing} = t as SceneTransition\n if (!isFinite(durationMs) || durationMs <= 0) return undefined\n return easing ? {durationMs, easing} : {durationMs}\n}\n\nfunction boxShrunk(orig: SceneBox, clamped: SceneBox): boolean {\n return (\n clamped.x !== Math.floor(orig.x) ||\n clamped.y !== Math.floor(orig.y) ||\n clamped.w !== Math.floor(orig.w) ||\n clamped.h !== Math.floor(orig.h)\n )\n}\n\n/**\n * Line height for box-height→line-count math — ONLY when the profile declares\n * a calibrated `lineHeightPx`. Deriving one from full-canvas numbers proved\n * wrong on hardware (288/8=36px clipped the G2 nav instruction to one line;\n * the real container line height is smaller). Without calibration we return\n * null and the wrap step skips host-side height clipping entirely — text wraps\n * to the box WIDTH and the firmware clips vertically in-box, which is exactly\n * the legacy behavior.\n */\nexport function profileLineHeightPx(profile: DisplayProfile, _canvasHeight: number): number | null {\n return profile.lineHeightPx ?? null\n}\n\n/**\n * Process a raw scene against a device's capabilities + profile. Output is\n * diff-ready (text pre-wrapped, boxes clamped, content hashed) and reflects\n * exactly what will be sent — the diff baseline is post-processed by design\n * (spec §4).\n */\nexport function processScene(\n input: readonly SceneElementInput[],\n caps: SceneDisplayCapabilities,\n profile: DisplayProfile,\n): ProcessedScene {\n const dropped: string[] = []\n let degraded = false\n\n const measurer = new TextMeasurer(profile)\n const wrapper = new TextWrapper(measurer)\n const lineHeight = profileLineHeightPx(profile, caps.height)\n\n // Validate + dedupe explicit ids (first occurrence wins; dupes are dev error).\n const seenIds = new Set<string>()\n const valid: {el: SceneElementInput; index: number; box: SceneBoxInput; points?: ScenePoint[]}[] = []\n input.forEach((raw, index) => {\n if (!raw || typeof raw !== \"object\") {\n dropped.push(reportId(raw ?? ({type: \"text\"} as SceneElementInput), index))\n degraded = true\n return\n }\n let points: ScenePoint[] | undefined\n if (POINT_SHAPE_TYPES.includes(raw.type)) {\n const valid = validPoints(raw)\n if (!valid) {\n dropped.push(reportId(raw, index))\n degraded = true\n return\n }\n points = valid\n raw = {...raw, box: pointsBox(valid)} as SceneElementInput\n }\n if (!raw.box) {\n dropped.push(reportId(raw, index))\n degraded = true\n return\n }\n // Non-finite box numbers (NaN/±Infinity/non-number) would survive the\n // Math.* clamp below and poison the frame all the way to native ints.\n const b = raw.box\n if (![b.x, b.y, b.w, b.h].every(isFinite)) {\n dropped.push(reportId(raw, index))\n degraded = true\n return\n }\n if ((raw.type === \"arc\" || raw.type === \"pie\") && !(isFinite(raw.startDeg) && isFinite(raw.endDeg))) {\n dropped.push(reportId(raw, index))\n degraded = true\n return\n }\n // Leading \"~\" is the differ's synthetic-id namespace — an app id there\n // would never match across frames (re-created every push). Normalize by\n // stripping; the rewrite is deterministic, so diffing stays stable.\n const el = raw.id?.startsWith(\"~\") ? {...raw, id: raw.id.replace(/^~+/, \"\") || undefined} : raw\n if (el.id) {\n const key = `${el.type}:${el.id}`\n if (seenIds.has(key)) {\n dropped.push(reportId(el, index))\n degraded = true\n return\n }\n seenIds.add(key)\n }\n valid.push({el, index, box: el.box as SceneBoxInput, points})\n })\n\n // Clamp + per-type limits, then budget in array order.\n let textBudget = caps.maxTextElements\n let imageBudget = caps.maxImageElements\n const out: DiffableElement[] = []\n let pathEdges = 0\n\n for (const {el, index, box, points} of valid) {\n const transition = validTransition((el as {transition?: unknown}).transition)\n const transform: {rotation?: number; pivot?: ScenePoint} = {}\n if (el.rotation !== undefined || el.pivot !== undefined) {\n const angle = el.rotation ?? 0\n const pivot = el.pivot ?? {x: box.x + box.w / 2, y: box.y + box.h / 2}\n if (\n !isFinite(angle) ||\n Math.abs(angle) > 36000 ||\n !isFinite(pivot.x) ||\n !isFinite(pivot.y) ||\n Math.abs(pivot.x) > 32767 ||\n Math.abs(pivot.y) > 32767 ||\n !caps.rotation ||\n el.type === \"image\" ||\n el.type === \"text\"\n ) {\n dropped.push(reportId(el, index))\n degraded = true\n continue\n }\n transform.rotation = Math.round(angle * 256) / 256\n transform.pivot = {x: Math.round(pivot.x), y: Math.round(pivot.y)}\n if (transition) transition.durationMs = Math.min(65535, transition.durationMs)\n }\n const transformHash =\n transform.rotation === undefined ? undefined : `${transform.rotation}:${transform.pivot?.x}:${transform.pivot?.y}`\n // Depth is a lens disparity, not content: devices without it draw the\n // element flat instead of dropping it. A non-number is still a dev error.\n let depth: number | undefined\n if (el.depth !== undefined) {\n if (!isFinite(el.depth)) {\n dropped.push(reportId(el, index))\n degraded = true\n continue\n }\n const d = Math.max(-MAX_SCENE_DEPTH, Math.min(MAX_SCENE_DEPTH, Math.round(el.depth)))\n if (caps.depth && d !== 0) depth = d\n }\n const plane = depth === undefined ? {} : {depth}\n const clamped = clampBox(box, caps.width, caps.height)\n if (!clamped) {\n dropped.push(reportId(el, index))\n degraded = true\n continue\n }\n const shrunk = boxShrunk(box, clamped)\n if (shrunk) degraded = true\n\n if (el.type === \"svg\") {\n try {\n if (!caps.shapes.includes(\"svg\") || textBudget <= 0 || shrunk)\n throw new Error(\"SVG unavailable or out of bounds\")\n const scale = el.scale ?? 1\n if (\n !isFinite(scale) ||\n scale < 0 ||\n scale > 8 ||\n (el.fillRule !== undefined && el.fillRule !== \"evenodd\" && el.fillRule !== \"nonzero\")\n )\n throw new Error(\"Invalid SVG scale or fill rule\")\n const compiled = compileSvgPath(el.d)\n if (pathEdges + compiled.edges > 4096) throw new Error(\"SVG scene exceeds the edge budget\")\n pathEdges += compiled.edges\n textBudget--\n out.push({\n id: el.id,\n type: \"svg\",\n box: clamped,\n d: el.d,\n path: compiled.commands,\n pathScale: Math.round(scale * 256),\n fillRule: el.fillRule ?? \"nonzero\",\n style: el.style,\n ...transform,\n ...plane,\n ...(transition ? {transition} : {}),\n contentHash: elementContentHash({\n type: \"svg\",\n data: `${el.d}:${scale}:${el.fillRule}:${transformHash}`,\n style: el.style,\n depth,\n }),\n })\n } catch {\n dropped.push(reportId(el, index))\n degraded = true\n }\n continue\n }\n\n if (el.type !== \"text\" && el.type !== \"image\" && el.type !== \"rect\") {\n // Vector shapes: only devices that draw them get them; the device clips\n // point shapes itself, so an off-canvas point is not a drop.\n if (!caps.shapes.includes(el.type) || textBudget <= 0) {\n dropped.push(reportId(el, index))\n degraded = true\n continue\n }\n textBudget--\n const angles = el.type === \"arc\" || el.type === \"pie\" ? {startDeg: el.startDeg, endDeg: el.endDeg} : {}\n out.push({\n id: el.id,\n type: el.type,\n box: clamped,\n style: el.style,\n ...(points ? {points} : {}),\n ...angles,\n ...(transition ? {transition} : {}),\n ...transform,\n ...plane,\n contentHash: elementContentHash({\n type: el.type,\n style: el.style,\n points,\n ...angles,\n data: transformHash,\n depth,\n }),\n })\n continue\n }\n\n if (el.type === \"image\") {\n // Images: a shrunk box can't be honored (we don't crop pixels host-side)\n // and per-image device limits are box-level (the firmware allocates the\n // component from the box). SGCs scale pixels to the box (phone-side\n // scaling — never on glasses).\n if (shrunk) {\n dropped.push(reportId(el, index))\n continue\n }\n if (caps.maxImagePx && (clamped.w > caps.maxImagePx.width || clamped.h > caps.maxImagePx.height)) {\n dropped.push(reportId(el, index))\n degraded = true\n continue\n }\n if (imageBudget <= 0) {\n dropped.push(reportId(el, index))\n degraded = true\n continue\n }\n imageBudget--\n out.push({\n id: el.id,\n type: \"image\",\n box: clamped,\n data: el.data,\n ...(el.style ? {style: el.style} : {}),\n ...(transition ? {transition} : {}),\n ...plane,\n contentHash: elementContentHash({type: \"image\", data: el.data, style: el.style, depth}),\n })\n continue\n }\n\n // text + rect share the text-container budget (design doc §3.4.6).\n if (textBudget <= 0) {\n dropped.push(reportId(el, index))\n degraded = true\n continue\n }\n textBudget--\n\n if (el.type === \"rect\") {\n out.push({\n id: el.id,\n type: \"rect\",\n box: clamped,\n style: el.style,\n ...(transition ? {transition} : {}),\n ...transform,\n ...plane,\n contentHash: elementContentHash({type: \"rect\", style: el.style, data: transformHash, depth}),\n })\n continue\n }\n\n // Text: wrap on the phone into the (clamped) box. The box then carries\n // pre-wrapped text; firmware in-box wrap is a fallback, not the mechanism.\n // Height clipping only applies with a CALIBRATED line height — otherwise\n // the firmware clips vertically in-box (legacy behavior).\n const style: SceneTextStyle = el.style ?? {}\n if (style.font === \"mono\" || style.font === \"builtin\") {\n // Grid text is laid out by the app (cols × rows) and builtin text by the\n // glasses' own font engine; the host's proportional wrap metrics don't\n // apply to either. Pass lines through and let the device clip.\n const monoText = el.text ?? \"\"\n out.push({\n id: el.id,\n type: \"text\",\n box: clamped,\n text: monoText,\n style: el.style,\n ...(transition ? {transition} : {}),\n ...plane,\n contentHash: elementContentHash({type: \"text\", text: monoText, style: el.style, depth}),\n })\n continue\n }\n const maxLines = lineHeight ? Math.max(1, Math.floor(clamped.h / lineHeight)) : profile.maxLines\n const result = wrapper.wrap(el.text ?? \"\", {\n maxWidthPx: clamped.w,\n maxLines,\n ...(style.breakMode ? {breakMode: style.breakMode} : {}),\n })\n let lines = result.lines\n if (result.truncated) {\n degraded = true\n if (style.overflow === \"ellipsis\" && lines.length > 0) {\n // Trim the last line until it fits WITH the ellipsis appended —\n // otherwise the extra glyph can overflow the clamped box width.\n let last = lines[lines.length - 1]\n while (last.length > 0 && !measurer.fitsInWidth(`${last}…`, clamped.w)) {\n last = last.slice(0, -1)\n }\n // A box narrower than the ellipsis glyph itself gets an empty line —\n // never emit a line wider than the clamped box.\n const ellipsized = last.length > 0 || measurer.fitsInWidth(\"…\", clamped.w) ? `${last}…` : \"\"\n lines = [...lines.slice(0, -1), ellipsized]\n }\n }\n const wrappedText = lines.join(\"\\n\")\n out.push({\n id: el.id,\n type: \"text\",\n box: clamped,\n text: wrappedText,\n style: el.style,\n ...(transition ? {transition} : {}),\n ...plane,\n contentHash: elementContentHash({type: \"text\", text: wrappedText, style: el.style, depth}),\n })\n }\n\n return {elements: out, degraded, dropped}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"process.js","sourceRoot":"","sources":["../../../../src/utils/display/scene/process.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Scene processing — validate → clamp → budget → wrap. Everything here is\n * generic; device variation enters only through the capabilities block and the\n * display profile (data, not code). Spec §5.\n *\n * Never rejects a frame: offending elements are dropped per-element and\n * reported via `dropped` / `degraded` (design doc §3.4.6; spec §4 refines the\n * design doc's image \"reject\" to per-element drop).\n */\n\nimport {compileSvgPath} from \"./svgPath\"\nimport {TextMeasurer} from \"../measurer/TextMeasurer\"\nimport {TextWrapper} from \"../wrapper/TextWrapper\"\nimport type {DisplayProfile} from \"../profiles/types\"\nimport type {DiffableElement} from \"./differ\"\nimport type {\n SceneBox,\n SceneBoxInput,\n SceneDisplayCapabilities,\n SceneElementInput,\n ScenePoint,\n SceneTextStyle,\n SceneTransition,\n SceneTransitionEdge,\n} from \"./types\"\nimport {MAX_SCENE_DEPTH, POINT_SHAPE_ARITY, POINT_SHAPE_TYPES, elementContentHash} from \"./types\"\n\nexport interface ProcessedScene {\n elements: DiffableElement[]\n degraded: boolean\n dropped: string[]\n}\n\n/** Reporting id for an element the app may not have named. */\nfunction reportId(el: SceneElementInput, index: number): string {\n return el.id ?? `${el.type}[${index}]`\n}\n\nfunction clampBox(box: SceneBox, width: number, height: number): SceneBox | null {\n const x1 = Math.max(0, Math.floor(box.x))\n const y1 = Math.max(0, Math.floor(box.y))\n const x2 = Math.min(width, Math.floor(box.x) + Math.max(0, Math.floor(box.w)))\n const y2 = Math.min(height, Math.floor(box.y) + Math.max(0, Math.floor(box.h)))\n if (x2 <= x1 || y2 <= y1) return null\n return {x: x1, y: y1, w: x2 - x1, h: y2 - y1}\n}\n\nconst isFinite = (n: unknown): n is number => typeof n === \"number\" && Number.isFinite(n)\n\n/** Integer points, or null when the count/values are invalid for the type. */\nfunction validPoints(el: SceneElementInput): ScenePoint[] | null {\n const raw = (el as {points?: unknown}).points\n if (!Array.isArray(raw) || !(POINT_SHAPE_ARITY[el.type] ?? []).includes(raw.length)) return null\n const points: ScenePoint[] = []\n for (const p of raw) {\n if (!p || typeof p !== \"object\" || !isFinite((p as ScenePoint).x) || !isFinite((p as ScenePoint).y)) return null\n points.push({x: Math.floor((p as ScenePoint).x), y: Math.floor((p as ScenePoint).y)})\n }\n return points\n}\n\nfunction pointsBox(points: ScenePoint[]): SceneBox {\n const xs = points.map((p) => p.x)\n const ys = points.map((p) => p.y)\n const x = Math.min(...xs)\n const y = Math.min(...ys)\n return {x, y, w: Math.max(...xs) - x + 1, h: Math.max(...ys) - y + 1}\n}\n\nfunction validEdge(e: unknown): SceneTransitionEdge | undefined {\n if (!e || typeof e !== \"object\") return undefined\n const dx = Math.round(Number((e as SceneTransitionEdge).dx ?? 0))\n const dy = Math.round(Number((e as SceneTransitionEdge).dy ?? 0))\n if (!isFinite(dx) || !isFinite(dy) || Math.abs(dx) > 1024 || Math.abs(dy) > 1024) return undefined\n return {dx, dy}\n}\n\nfunction validTransition(t: unknown): SceneTransition | undefined {\n if (!t || typeof t !== \"object\") return undefined\n const {durationMs, easing} = t as SceneTransition\n if (!isFinite(durationMs) || durationMs <= 0) return undefined\n const out: SceneTransition = easing ? {durationMs, easing} : {durationMs}\n const enter = validEdge((t as SceneTransition).enter)\n const exit = validEdge((t as SceneTransition).exit)\n if (enter) out.enter = enter\n if (exit) out.exit = exit\n return out\n}\n\nfunction boxShrunk(orig: SceneBox, clamped: SceneBox): boolean {\n return (\n clamped.x !== Math.floor(orig.x) ||\n clamped.y !== Math.floor(orig.y) ||\n clamped.w !== Math.floor(orig.w) ||\n clamped.h !== Math.floor(orig.h)\n )\n}\n\n/**\n * Line height for box-height→line-count math — ONLY when the profile declares\n * a calibrated `lineHeightPx`. Deriving one from full-canvas numbers proved\n * wrong on hardware (288/8=36px clipped the G2 nav instruction to one line;\n * the real container line height is smaller). Without calibration we return\n * null and the wrap step skips host-side height clipping entirely — text wraps\n * to the box WIDTH and the firmware clips vertically in-box, which is exactly\n * the legacy behavior.\n */\nexport function profileLineHeightPx(profile: DisplayProfile, _canvasHeight: number): number | null {\n return profile.lineHeightPx ?? null\n}\n\n/**\n * Process a raw scene against a device's capabilities + profile. Output is\n * diff-ready (text pre-wrapped, boxes clamped, content hashed) and reflects\n * exactly what will be sent — the diff baseline is post-processed by design\n * (spec §4).\n */\nexport function processScene(\n input: readonly SceneElementInput[],\n caps: SceneDisplayCapabilities,\n profile: DisplayProfile,\n): ProcessedScene {\n const dropped: string[] = []\n let degraded = false\n\n const measurer = new TextMeasurer(profile)\n const wrapper = new TextWrapper(measurer)\n const lineHeight = profileLineHeightPx(profile, caps.height)\n\n // Validate + dedupe explicit ids (first occurrence wins; dupes are dev error).\n const seenIds = new Set<string>()\n const valid: {el: SceneElementInput; index: number; box: SceneBoxInput; points?: ScenePoint[]}[] = []\n input.forEach((raw, index) => {\n if (!raw || typeof raw !== \"object\") {\n dropped.push(reportId(raw ?? ({type: \"text\"} as SceneElementInput), index))\n degraded = true\n return\n }\n let points: ScenePoint[] | undefined\n if (POINT_SHAPE_TYPES.includes(raw.type)) {\n const valid = validPoints(raw)\n if (!valid) {\n dropped.push(reportId(raw, index))\n degraded = true\n return\n }\n points = valid\n raw = {...raw, box: pointsBox(valid)} as SceneElementInput\n }\n if (!raw.box) {\n dropped.push(reportId(raw, index))\n degraded = true\n return\n }\n // Non-finite box numbers (NaN/±Infinity/non-number) would survive the\n // Math.* clamp below and poison the frame all the way to native ints.\n const b = raw.box\n if (![b.x, b.y, b.w, b.h].every(isFinite)) {\n dropped.push(reportId(raw, index))\n degraded = true\n return\n }\n if ((raw.type === \"arc\" || raw.type === \"pie\") && !(isFinite(raw.startDeg) && isFinite(raw.endDeg))) {\n dropped.push(reportId(raw, index))\n degraded = true\n return\n }\n // Leading \"~\" is the differ's synthetic-id namespace — an app id there\n // would never match across frames (re-created every push). Normalize by\n // stripping; the rewrite is deterministic, so diffing stays stable.\n const el = raw.id?.startsWith(\"~\") ? {...raw, id: raw.id.replace(/^~+/, \"\") || undefined} : raw\n if (el.id) {\n const key = `${el.type}:${el.id}`\n if (seenIds.has(key)) {\n dropped.push(reportId(el, index))\n degraded = true\n return\n }\n seenIds.add(key)\n }\n valid.push({el, index, box: el.box as SceneBoxInput, points})\n })\n\n // Clamp + per-type limits, then budget in array order.\n let textBudget = caps.maxTextElements\n let imageBudget = caps.maxImageElements\n const out: DiffableElement[] = []\n let pathEdges = 0\n\n for (const {el, index, box, points} of valid) {\n const transition = validTransition((el as {transition?: unknown}).transition)\n // Leaving elements only exist to tween away; a device that jumps never shows them.\n if (transition?.exit && !caps.animation) continue\n const transform: {rotation?: number; pivot?: ScenePoint} = {}\n if (el.rotation !== undefined || el.pivot !== undefined) {\n const angle = el.rotation ?? 0\n const pivot = el.pivot ?? {x: box.x + box.w / 2, y: box.y + box.h / 2}\n if (\n !isFinite(angle) ||\n Math.abs(angle) > 36000 ||\n !isFinite(pivot.x) ||\n !isFinite(pivot.y) ||\n Math.abs(pivot.x) > 32767 ||\n Math.abs(pivot.y) > 32767 ||\n !caps.rotation ||\n el.type === \"image\" ||\n el.type === \"text\"\n ) {\n dropped.push(reportId(el, index))\n degraded = true\n continue\n }\n transform.rotation = Math.round(angle * 256) / 256\n transform.pivot = {x: Math.round(pivot.x), y: Math.round(pivot.y)}\n if (transition) transition.durationMs = Math.min(65535, transition.durationMs)\n }\n const transformHash =\n transform.rotation === undefined ? undefined : `${transform.rotation}:${transform.pivot?.x}:${transform.pivot?.y}`\n // Depth is a lens disparity, not content: devices without it draw the\n // element flat instead of dropping it. A non-number is still a dev error.\n let depth: number | undefined\n if (el.depth !== undefined) {\n if (!isFinite(el.depth)) {\n dropped.push(reportId(el, index))\n degraded = true\n continue\n }\n const d = Math.max(-MAX_SCENE_DEPTH, Math.min(MAX_SCENE_DEPTH, Math.round(el.depth)))\n if (caps.depth && d !== 0) depth = d\n }\n const plane = depth === undefined ? {} : {depth}\n const clamped = clampBox(box, caps.width, caps.height)\n if (!clamped) {\n dropped.push(reportId(el, index))\n degraded = true\n continue\n }\n const shrunk = boxShrunk(box, clamped)\n if (shrunk) degraded = true\n\n if (el.type === \"svg\") {\n try {\n if (!caps.shapes.includes(\"svg\") || textBudget <= 0 || shrunk)\n throw new Error(\"SVG unavailable or out of bounds\")\n const scale = el.scale ?? 1\n if (\n !isFinite(scale) ||\n scale < 0 ||\n scale > 8 ||\n (el.fillRule !== undefined && el.fillRule !== \"evenodd\" && el.fillRule !== \"nonzero\")\n )\n throw new Error(\"Invalid SVG scale or fill rule\")\n const compiled = compileSvgPath(el.d)\n if (pathEdges + compiled.edges > 4096) throw new Error(\"SVG scene exceeds the edge budget\")\n pathEdges += compiled.edges\n textBudget--\n out.push({\n id: el.id,\n type: \"svg\",\n box: clamped,\n d: el.d,\n path: compiled.commands,\n pathScale: Math.round(scale * 256),\n fillRule: el.fillRule ?? \"nonzero\",\n style: el.style,\n ...transform,\n ...plane,\n ...(transition ? {transition} : {}),\n contentHash: elementContentHash({\n type: \"svg\",\n data: `${el.d}:${scale}:${el.fillRule}:${transformHash}`,\n style: el.style,\n depth,\n }),\n })\n } catch {\n dropped.push(reportId(el, index))\n degraded = true\n }\n continue\n }\n\n if (el.type !== \"text\" && el.type !== \"image\" && el.type !== \"rect\") {\n // Vector shapes: only devices that draw them get them; the device clips\n // point shapes itself, so an off-canvas point is not a drop.\n if (!caps.shapes.includes(el.type) || textBudget <= 0) {\n dropped.push(reportId(el, index))\n degraded = true\n continue\n }\n textBudget--\n const angles = el.type === \"arc\" || el.type === \"pie\" ? {startDeg: el.startDeg, endDeg: el.endDeg} : {}\n out.push({\n id: el.id,\n type: el.type,\n box: clamped,\n style: el.style,\n ...(points ? {points} : {}),\n ...angles,\n ...(transition ? {transition} : {}),\n ...transform,\n ...plane,\n contentHash: elementContentHash({\n type: el.type,\n style: el.style,\n points,\n ...angles,\n data: transformHash,\n depth,\n }),\n })\n continue\n }\n\n if (el.type === \"image\") {\n // Images: a shrunk box can't be honored (we don't crop pixels host-side)\n // and per-image device limits are box-level (the firmware allocates the\n // component from the box). SGCs scale pixels to the box (phone-side\n // scaling — never on glasses).\n if (shrunk) {\n dropped.push(reportId(el, index))\n continue\n }\n if (caps.maxImagePx && (clamped.w > caps.maxImagePx.width || clamped.h > caps.maxImagePx.height)) {\n dropped.push(reportId(el, index))\n degraded = true\n continue\n }\n if (imageBudget <= 0) {\n dropped.push(reportId(el, index))\n degraded = true\n continue\n }\n imageBudget--\n out.push({\n id: el.id,\n type: \"image\",\n box: clamped,\n data: el.data,\n ...(el.style ? {style: el.style} : {}),\n ...(transition ? {transition} : {}),\n ...plane,\n contentHash: elementContentHash({type: \"image\", data: el.data, style: el.style, depth}),\n })\n continue\n }\n\n // text + rect share the text-container budget (design doc §3.4.6).\n if (textBudget <= 0) {\n dropped.push(reportId(el, index))\n degraded = true\n continue\n }\n textBudget--\n\n if (el.type === \"rect\") {\n out.push({\n id: el.id,\n type: \"rect\",\n box: clamped,\n style: el.style,\n ...(transition ? {transition} : {}),\n ...transform,\n ...plane,\n contentHash: elementContentHash({type: \"rect\", style: el.style, data: transformHash, depth}),\n })\n continue\n }\n\n // Text: wrap on the phone into the (clamped) box. The box then carries\n // pre-wrapped text; firmware in-box wrap is a fallback, not the mechanism.\n // Height clipping only applies with a CALIBRATED line height — otherwise\n // the firmware clips vertically in-box (legacy behavior).\n const style: SceneTextStyle = el.style ?? {}\n if (style.font === \"mono\" || style.font === \"builtin\") {\n // Grid text is laid out by the app (cols × rows) and builtin text by the\n // glasses' own font engine; the host's proportional wrap metrics don't\n // apply to either. Pass lines through and let the device clip.\n const monoText = el.text ?? \"\"\n out.push({\n id: el.id,\n type: \"text\",\n box: clamped,\n text: monoText,\n style: el.style,\n ...(transition ? {transition} : {}),\n ...plane,\n contentHash: elementContentHash({type: \"text\", text: monoText, style: el.style, depth}),\n })\n continue\n }\n const maxLines = lineHeight ? Math.max(1, Math.floor(clamped.h / lineHeight)) : profile.maxLines\n const result = wrapper.wrap(el.text ?? \"\", {\n maxWidthPx: clamped.w,\n maxLines,\n ...(style.breakMode ? {breakMode: style.breakMode} : {}),\n })\n let lines = result.lines\n if (result.truncated) {\n degraded = true\n if (style.overflow === \"ellipsis\" && lines.length > 0) {\n // Trim the last line until it fits WITH the ellipsis appended —\n // otherwise the extra glyph can overflow the clamped box width.\n let last = lines[lines.length - 1]\n while (last.length > 0 && !measurer.fitsInWidth(`${last}…`, clamped.w)) {\n last = last.slice(0, -1)\n }\n // A box narrower than the ellipsis glyph itself gets an empty line —\n // never emit a line wider than the clamped box.\n const ellipsized = last.length > 0 || measurer.fitsInWidth(\"…\", clamped.w) ? `${last}…` : \"\"\n lines = [...lines.slice(0, -1), ellipsized]\n }\n }\n const wrappedText = lines.join(\"\\n\")\n out.push({\n id: el.id,\n type: \"text\",\n box: clamped,\n text: wrappedText,\n style: el.style,\n ...(transition ? {transition} : {}),\n ...plane,\n contentHash: elementContentHash({type: \"text\", text: wrappedText, style: el.style, depth}),\n })\n }\n\n return {elements: out, degraded, dropped}\n}\n"]}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export type { FrameElement, SceneAnchor, SceneBox, SceneBoxInput, SceneBreakMode, SceneChange, SceneDisplayCapabilities, SceneElementInput, SceneElementType, SceneFrame, SceneImageStyle, ScenePoint, SceneProcessResult, SceneRectStyle, SceneShapeStyle, SceneStrokeStyle, SceneTextStyle, SceneTransition, } from "@glassly/miniapp/display";
|
|
1
|
+
export type { FrameElement, SceneAnchor, SceneBox, SceneBoxInput, SceneBreakMode, SceneChange, SceneDisplayCapabilities, SceneElementInput, SceneElementType, SceneFrame, SceneImageStyle, ScenePoint, SceneProcessResult, SceneRectStyle, SceneShapeStyle, SceneStrokeStyle, SceneTextStyle, SceneTransition, SceneTransitionEdge, } from "@glassly/miniapp/display";
|
|
2
2
|
export { boxesEqual, contentHash, elementContentHash, MAX_SCENE_DEPTH, POINT_SHAPE_ARITY, POINT_SHAPE_TYPES, } from "@glassly/miniapp/display";
|
|
3
3
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/utils/display/scene/types.ts"],"names":[],"mappings":"AACA,YAAY,EACV,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,aAAa,EACb,cAAc,EACd,WAAW,EACX,wBAAwB,EACxB,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,UAAU,EACV,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,eAAe,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/utils/display/scene/types.ts"],"names":[],"mappings":"AACA,YAAY,EACV,YAAY,EACZ,WAAW,EACX,QAAQ,EACR,aAAa,EACb,cAAc,EACd,WAAW,EACX,wBAAwB,EACxB,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,eAAe,EACf,UAAU,EACV,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,mBAAmB,GACpB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EACL,UAAU,EACV,WAAW,EACX,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,0BAA0B,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/utils/display/scene/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/utils/display/scene/types.ts"],"names":[],"mappings":"AAsBA,OAAO,EACL,UAAU,EACV,WAAW,EACX,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,0BAA0B,CAAA","sourcesContent":["// Moved into the SDK (@glassly/miniapp/display) so miniapps lay text out the way the host measures it; this path re-exports it for the engine.\nexport type {\n FrameElement,\n SceneAnchor,\n SceneBox,\n SceneBoxInput,\n SceneBreakMode,\n SceneChange,\n SceneDisplayCapabilities,\n SceneElementInput,\n SceneElementType,\n SceneFrame,\n SceneImageStyle,\n ScenePoint,\n SceneProcessResult,\n SceneRectStyle,\n SceneShapeStyle,\n SceneStrokeStyle,\n SceneTextStyle,\n SceneTransition,\n SceneTransitionEdge,\n} from \"@glassly/miniapp/display\"\nexport {\n boxesEqual,\n contentHash,\n elementContentHash,\n MAX_SCENE_DEPTH,\n POINT_SHAPE_ARITY,\n POINT_SHAPE_TYPES,\n} from \"@glassly/miniapp/display\"\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glassly/engine",
|
|
3
|
-
"version": "0.3.5-dev.
|
|
3
|
+
"version": "0.3.5-dev.754",
|
|
4
4
|
"description": "Glassly Engine — miniapp registry, WebView bridge, and miniapp store",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"react-native": "src/index.ts",
|
|
@@ -97,17 +97,17 @@
|
|
|
97
97
|
"registry": "https://registry.npmjs.org/"
|
|
98
98
|
},
|
|
99
99
|
"dependencies": {
|
|
100
|
-
"@glassly/bluetooth-sdk": "0.3.5-dev.
|
|
101
|
-
"@glassly/cloud-client": "0.3.5-dev.
|
|
102
|
-
"@glassly/cloud-protocol": "0.3.5-dev.
|
|
103
|
-
"@glassly/crust": "0.3.5-dev.
|
|
104
|
-
"@glassly/miniapp": "0.3.5-dev.
|
|
100
|
+
"@glassly/bluetooth-sdk": "0.3.5-dev.754",
|
|
101
|
+
"@glassly/cloud-client": "0.3.5-dev.754",
|
|
102
|
+
"@glassly/cloud-protocol": "0.3.5-dev.754",
|
|
103
|
+
"@glassly/crust": "0.3.5-dev.754",
|
|
104
|
+
"@glassly/miniapp": "0.3.5-dev.754",
|
|
105
105
|
"buffer": "^6.0.3",
|
|
106
106
|
"events": "^3.3.0",
|
|
107
107
|
"react-native-marked": "8.1.1",
|
|
108
108
|
"semver": "^7.7.4",
|
|
109
109
|
"typesafe-ts": "^1.7.1",
|
|
110
|
-
"@glassly/llm-providers": "0.3.5-dev.
|
|
110
|
+
"@glassly/llm-providers": "0.3.5-dev.754",
|
|
111
111
|
"@huggingface/jinja": "^0.5.9",
|
|
112
112
|
"jsonrepair": "^3.12.0"
|
|
113
113
|
},
|
|
@@ -12,9 +12,9 @@ export interface EngineReleaseMetadata {
|
|
|
12
12
|
export const ENGINE_RELEASE_METADATA: Readonly<EngineReleaseMetadata> = Object.freeze({
|
|
13
13
|
"schemaVersion": 1,
|
|
14
14
|
"familyBaseVersion": "0.3.5",
|
|
15
|
-
"releaseIdentity": "0.3.5-dev.
|
|
16
|
-
"releaseSetId": "glassly-0.3.5-dev.
|
|
17
|
-
"sourceCommit": "
|
|
15
|
+
"releaseIdentity": "0.3.5-dev.754",
|
|
16
|
+
"releaseSetId": "glassly-0.3.5-dev.754",
|
|
17
|
+
"sourceCommit": "95e2c4abed0771eaa4d67276bea31bfd80c7b320",
|
|
18
18
|
"otaManifestUrl": null,
|
|
19
19
|
"otaManifestSha256": null
|
|
20
20
|
})
|
|
@@ -66,7 +66,9 @@ const MAX_SETTLE_MS = 255 * 33
|
|
|
66
66
|
function settleTimeOf(elements: FrameElement[]): number {
|
|
67
67
|
let ms = 0
|
|
68
68
|
for (const el of elements) {
|
|
69
|
-
|
|
69
|
+
// Entering and leaving elements tween too, from or to their offset.
|
|
70
|
+
const edge = el.transition?.exit !== undefined || (el.change === "created" && el.transition?.enter !== undefined)
|
|
71
|
+
if (el.change !== "updated" && el.change !== "moved" && !edge) continue
|
|
70
72
|
const t = el.transition?.durationMs ?? 0
|
|
71
73
|
// Rotation has its own millisecond clock, beyond the geometry frame limit.
|
|
72
74
|
const duration = Math.min(t, el.rotation !== undefined ? 65535 : MAX_SETTLE_MS)
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
* be tested without the native import surface the runtime pulls in.
|
|
7
7
|
*
|
|
8
8
|
* A dashboard miniapp is the usual consumer: it edits the notification,
|
|
9
|
-
* glasses-menu
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* that in its storage.
|
|
9
|
+
* glasses-menu, display-position, brightness and microphone keys the phone's
|
|
10
|
+
* settings screens do, through the store, so persistence, server sync and the
|
|
11
|
+
* Bluetooth sync behave as if a phone screen wrote them. A dashboard's own
|
|
12
|
+
* look is not here; it keeps that in its storage.
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import type {ControllerStatus, PairedController} from "@glassly/bluetooth-sdk"
|
|
@@ -28,6 +28,11 @@ export const SETTINGS_BRIDGE_KEYS: Readonly<Record<string, SettingsBridgeAccess>
|
|
|
28
28
|
// Where the glasses draw; each model's steps are its display.positionRange.
|
|
29
29
|
dashboard_depth: "write",
|
|
30
30
|
dashboard_height: "write",
|
|
31
|
+
// Device settings the dashboard's glasses Settings page edits.
|
|
32
|
+
brightness: "write",
|
|
33
|
+
auto_brightness: "write",
|
|
34
|
+
// Per paired model: the store resolves the indexed key.
|
|
35
|
+
preferred_mic: "write",
|
|
31
36
|
twelve_hour_time: "write",
|
|
32
37
|
menu_apps: "write",
|
|
33
38
|
notifications_enabled: "write",
|
|
@@ -35,3 +35,23 @@ function isMentraLiveDevice(model: string | undefined): boolean {
|
|
|
35
35
|
export function getBluetoothSettingKeysForDevice(deviceModel: string | undefined, fullKeys: string[]): string[] {
|
|
36
36
|
return isMentraLiveDevice(deviceModel) ? MENTRA_LIVE_SETTING_KEYS : fullKeys
|
|
37
37
|
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Glasses Menu entries the firmware's own menu cannot open: Settings is the
|
|
41
|
+
* dashboard's glasses page, which only the dashboard's Apps menu shows.
|
|
42
|
+
*/
|
|
43
|
+
const NATIVE_MENU_EXCLUDED_PACKAGES = new Set(["com.glassly.settings"])
|
|
44
|
+
const nativeMenuAppsCache = new WeakMap<object, unknown[]>()
|
|
45
|
+
|
|
46
|
+
/** `menu_apps` as the glasses get it; the same array in gives the same array out, so the change-push stays quiet. */
|
|
47
|
+
export function nativeMenuApps(value: unknown): unknown {
|
|
48
|
+
if (!Array.isArray(value)) return value
|
|
49
|
+
let filtered = nativeMenuAppsCache.get(value)
|
|
50
|
+
if (!filtered) {
|
|
51
|
+
filtered = value.filter(
|
|
52
|
+
(item) => !NATIVE_MENU_EXCLUDED_PACKAGES.has((item as {packageName?: string} | null)?.packageName ?? ""),
|
|
53
|
+
)
|
|
54
|
+
nativeMenuAppsCache.set(value, filtered)
|
|
55
|
+
}
|
|
56
|
+
return filtered
|
|
57
|
+
}
|
package/src/stores/settings.ts
CHANGED
|
@@ -4,7 +4,7 @@ import {create} from "zustand"
|
|
|
4
4
|
import {subscribeWithSelector} from "zustand/middleware"
|
|
5
5
|
|
|
6
6
|
import {storage} from "../utils/storage"
|
|
7
|
-
import {getBluetoothSettingKeysForDevice} from "./bluetoothSettingKeys"
|
|
7
|
+
import {getBluetoothSettingKeysForDevice, nativeMenuApps} from "./bluetoothSettingKeys"
|
|
8
8
|
import {useGlassesStore} from "./glasses"
|
|
9
9
|
|
|
10
10
|
export {MENTRA_LIVE_SETTING_KEYS, getBluetoothSettingKeysForDevice} from "./bluetoothSettingKeys"
|
|
@@ -1586,6 +1586,29 @@ export const useSettingsStore = create<SettingsState>()(
|
|
|
1586
1586
|
// desired value was applied so a transient failure retries on boot.
|
|
1587
1587
|
if (migrationSucceeded) storage.save(CAMERA_FOV_MIGRATION_KEY, true)
|
|
1588
1588
|
}
|
|
1589
|
+
|
|
1590
|
+
// Settings joined the Glasses Menu (the dashboard's glasses Settings
|
|
1591
|
+
// page): add it once, last, to a menu the wearer already saved. An
|
|
1592
|
+
// unsaved menu gets it from the default; a full one (10) is left alone.
|
|
1593
|
+
const MENU_SETTINGS_MIGRATION_KEY = "migration:menu_apps_settings_v1"
|
|
1594
|
+
const menuSettingsMigrationDone = storage.load<boolean>(MENU_SETTINGS_MIGRATION_KEY)
|
|
1595
|
+
if (menuSettingsMigrationDone.is_error() || !menuSettingsMigrationDone.value) {
|
|
1596
|
+
const menu = get().getSetting(SETTINGS.menu_apps.key) as Array<{packageName?: string}> | null
|
|
1597
|
+
let menuMigrated = true
|
|
1598
|
+
if (
|
|
1599
|
+
Array.isArray(menu) &&
|
|
1600
|
+
menu.length < 10 &&
|
|
1601
|
+
!menu.some((item) => item?.packageName === "com.glassly.settings")
|
|
1602
|
+
) {
|
|
1603
|
+
const next = [...menu, {packageName: "com.glassly.settings", name: "Settings"}]
|
|
1604
|
+
const result = await get().setSetting(SETTINGS.menu_apps.key, next, true)
|
|
1605
|
+
if (result.is_error()) {
|
|
1606
|
+
console.log("SETTINGS: menu_apps Settings migration failed:", result.error)
|
|
1607
|
+
menuMigrated = false
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
if (menuMigrated) storage.save(MENU_SETTINGS_MIGRATION_KEY, true)
|
|
1611
|
+
}
|
|
1589
1612
|
})
|
|
1590
1613
|
loadAllSettingsInFlight = inFlight
|
|
1591
1614
|
void Promise.resolve(inFlight).then((result) => {
|
|
@@ -1607,7 +1630,7 @@ export const useSettingsStore = create<SettingsState>()(
|
|
|
1607
1630
|
if (key === SETTINGS.core_token.key && (typeof value !== "string" || value.trim().length === 0)) {
|
|
1608
1631
|
continue
|
|
1609
1632
|
}
|
|
1610
|
-
bluetoothSettings[key] = value
|
|
1633
|
+
bluetoothSettings[key] = key === SETTINGS.menu_apps.key ? nativeMenuApps(value) : value
|
|
1611
1634
|
}
|
|
1612
1635
|
return bluetoothSettings
|
|
1613
1636
|
},
|
|
@@ -21,6 +21,7 @@ import type {
|
|
|
21
21
|
ScenePoint,
|
|
22
22
|
SceneTextStyle,
|
|
23
23
|
SceneTransition,
|
|
24
|
+
SceneTransitionEdge,
|
|
24
25
|
} from "./types"
|
|
25
26
|
import {MAX_SCENE_DEPTH, POINT_SHAPE_ARITY, POINT_SHAPE_TYPES, elementContentHash} from "./types"
|
|
26
27
|
|
|
@@ -66,11 +67,24 @@ function pointsBox(points: ScenePoint[]): SceneBox {
|
|
|
66
67
|
return {x, y, w: Math.max(...xs) - x + 1, h: Math.max(...ys) - y + 1}
|
|
67
68
|
}
|
|
68
69
|
|
|
70
|
+
function validEdge(e: unknown): SceneTransitionEdge | undefined {
|
|
71
|
+
if (!e || typeof e !== "object") return undefined
|
|
72
|
+
const dx = Math.round(Number((e as SceneTransitionEdge).dx ?? 0))
|
|
73
|
+
const dy = Math.round(Number((e as SceneTransitionEdge).dy ?? 0))
|
|
74
|
+
if (!isFinite(dx) || !isFinite(dy) || Math.abs(dx) > 1024 || Math.abs(dy) > 1024) return undefined
|
|
75
|
+
return {dx, dy}
|
|
76
|
+
}
|
|
77
|
+
|
|
69
78
|
function validTransition(t: unknown): SceneTransition | undefined {
|
|
70
79
|
if (!t || typeof t !== "object") return undefined
|
|
71
80
|
const {durationMs, easing} = t as SceneTransition
|
|
72
81
|
if (!isFinite(durationMs) || durationMs <= 0) return undefined
|
|
73
|
-
|
|
82
|
+
const out: SceneTransition = easing ? {durationMs, easing} : {durationMs}
|
|
83
|
+
const enter = validEdge((t as SceneTransition).enter)
|
|
84
|
+
const exit = validEdge((t as SceneTransition).exit)
|
|
85
|
+
if (enter) out.enter = enter
|
|
86
|
+
if (exit) out.exit = exit
|
|
87
|
+
return out
|
|
74
88
|
}
|
|
75
89
|
|
|
76
90
|
function boxShrunk(orig: SceneBox, clamped: SceneBox): boolean {
|
|
@@ -175,6 +189,8 @@ export function processScene(
|
|
|
175
189
|
|
|
176
190
|
for (const {el, index, box, points} of valid) {
|
|
177
191
|
const transition = validTransition((el as {transition?: unknown}).transition)
|
|
192
|
+
// Leaving elements only exist to tween away; a device that jumps never shows them.
|
|
193
|
+
if (transition?.exit && !caps.animation) continue
|
|
178
194
|
const transform: {rotation?: number; pivot?: ScenePoint} = {}
|
|
179
195
|
if (el.rotation !== undefined || el.pivot !== undefined) {
|
|
180
196
|
const angle = el.rotation ?? 0
|