@hyperframes/studio 0.8.18 → 0.8.20
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/dist/assets/{hyperframes-player-DzRNJZAz.js → hyperframes-player-BEKxuimO.js} +1 -1
- package/dist/assets/{index-B4qse6wy.js → index-BL1zYTW0.js} +1 -1
- package/dist/assets/{index-F-PUkOVc.js → index-CBSKXKAr.js} +164 -164
- package/dist/assets/{index-SGl0bb71.js → index-Cehosfnu.js} +1 -1
- package/dist/index.html +1 -1
- package/dist/index.js +41 -20
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/App.tsx +1 -1
- package/src/components/renders/RenderQueuePanel.tsx +3 -10
- package/src/components/renders/renderQueueTestHarness.tsx +27 -1
- package/src/components/renders/useRenderQueue.ts +20 -4
- package/src/components/renders/useRenderQueueComposition.test.tsx +55 -0
- package/src/components/renders/useRenderQueueTelemetry.test.tsx +6 -12
- package/src/hooks/useEditorSave.test.tsx +81 -3
- package/src/hooks/useEditorSave.ts +31 -6
- package/src/hooks/useGsapInteractionFailureTelemetry.test.tsx +48 -16
- package/src/hooks/useGsapInteractionFailureTelemetry.ts +5 -2
- package/src/utils/studioFileVersion.test.ts +37 -1
- package/src/utils/studioFileVersion.ts +12 -2
- package/src/utils/studioSaveDiagnostics.test.ts +29 -0
- package/src/utils/studioSaveDiagnostics.ts +4 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as P}from"./index-
|
|
1
|
+
import{g as P}from"./index-CBSKXKAr.js";function j(c,d){for(var s=0;s<d.length;s++){const a=d[s];if(typeof a!="string"&&!Array.isArray(a)){for(const i in a)if(i!=="default"&&!(i in c)){const l=Object.getOwnPropertyDescriptor(a,i);l&&Object.defineProperty(c,i,l.get?l:{enumerable:!0,get:()=>a[i]})}}}return Object.freeze(Object.defineProperty(c,Symbol.toStringTag,{value:"Module"}))}var v={},w;function k(){if(w)return v;w=1,Object.defineProperty(v,"__esModule",{value:!0}),v.default=d;var c=window.OfflineAudioContext||window.webkitOfflineAudioContext;function d(e){var r=a(e);return r.start(0),[i,y,O(e.sampleRate),s].reduce(function(t,o){return o(t)},r.buffer.getChannelData(0))}function s(e){return e.sort(function(r,t){return t.count-r.count}).splice(0,5)[0].tempo}function a(e){var r=e.length,t=e.numberOfChannels,o=e.sampleRate,n=new c(t,r,o),u=n.createBufferSource();u.buffer=e;var f=n.createBiquadFilter();return f.type="lowpass",u.connect(f),f.connect(n.destination),u}function i(e){for(var r=[],t=.9,o=.3,n=15;r.length<n&&t>=o;)r=l(e,t),t-=.05;if(r.length<n)throw new Error("Could not find enough samples for a reliable detection.");return r}function l(e,r){for(var t=[],o=0,n=e.length;o<n;o+=1)e[o]>r&&(t.push(o),o+=1e4);return t}function y(e){var r=[];return e.forEach(function(t,o){for(var n=function(x){var g=e[o+x]-t,_=r.some(function(h){if(h.interval===g)return h.count+=1});_||r.push({interval:g,count:1})},u=0;u<10;u+=1)n(u)}),r}function O(e){return function(r){var t=[];return r.forEach(function(o){if(o.interval!==0){for(var n=60/(o.interval/e);n<90;)n*=2;for(;n>180;)n/=2;n=Math.round(n);var u=t.some(function(f){if(f.tempo===n)return f.count+=o.count});u||t.push({tempo:n,count:o.count})}}),t}}return v}var p,b;function q(){return b||(b=1,p=k().default),p}var m=q();const A=P(m),D=j({__proto__:null,default:A},[m]);export{D as i};
|
package/dist/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
|
6
6
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
7
7
|
<title>HyperFrames Studio</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-CBSKXKAr.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/assets/index-yGhfxxoL.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
package/dist/index.js
CHANGED
|
@@ -16306,6 +16306,9 @@ function buildStudioSaveFailureProperties(input) {
|
|
|
16306
16306
|
function trackStudioSaveFailure(input) {
|
|
16307
16307
|
trackStudioEvent("save_failure", buildStudioSaveFailureProperties(input));
|
|
16308
16308
|
}
|
|
16309
|
+
function trackStudioEditBlocked(input) {
|
|
16310
|
+
trackStudioEvent("edit_blocked", buildStudioSaveFailureProperties(input));
|
|
16311
|
+
}
|
|
16309
16312
|
async function createStudioSaveHttpError(response, fallbackMessage, options = {}) {
|
|
16310
16313
|
let body = "";
|
|
16311
16314
|
try {
|
|
@@ -16693,7 +16696,16 @@ async function studioExpectedFileVersion(versions, path, expectedContent) {
|
|
|
16693
16696
|
return versions.get(path);
|
|
16694
16697
|
}
|
|
16695
16698
|
function createStudioWriteToken() {
|
|
16696
|
-
|
|
16699
|
+
const webCrypto = globalThis.crypto;
|
|
16700
|
+
if (typeof webCrypto?.randomUUID === "function") return webCrypto.randomUUID();
|
|
16701
|
+
if (typeof webCrypto?.getRandomValues !== "function") {
|
|
16702
|
+
throw new Error("Web Crypto getRandomValues is required for Studio write identity");
|
|
16703
|
+
}
|
|
16704
|
+
const bytes = webCrypto.getRandomValues(new Uint8Array(16));
|
|
16705
|
+
bytes[6] = bytes[6] & 15 | 64;
|
|
16706
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
16707
|
+
const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
16708
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
16697
16709
|
}
|
|
16698
16710
|
function studioWriteHeaders() {
|
|
16699
16711
|
const token = createStudioWriteToken();
|
|
@@ -60693,7 +60705,7 @@ function writeHiddenIds(projectId, ids) {
|
|
|
60693
60705
|
} catch {
|
|
60694
60706
|
}
|
|
60695
60707
|
}
|
|
60696
|
-
function useRenderQueue(projectId) {
|
|
60708
|
+
function useRenderQueue(projectId, activeCompPathRef) {
|
|
60697
60709
|
const [jobs, setJobs] = useState94([]);
|
|
60698
60710
|
const [loadError, setLoadError] = useState94(null);
|
|
60699
60711
|
const [actionError, setActionError] = useState94(null);
|
|
@@ -60769,7 +60781,7 @@ function useRenderQueue(projectId) {
|
|
|
60769
60781
|
const quality = opts.quality ?? "standard";
|
|
60770
60782
|
const format = opts.format ?? "mp4";
|
|
60771
60783
|
const resolution = opts.resolution;
|
|
60772
|
-
const composition = opts.composition;
|
|
60784
|
+
const composition = opts.composition ?? activeCompPathRef.current ?? void 0;
|
|
60773
60785
|
trackStudioRenderStart({
|
|
60774
60786
|
fps,
|
|
60775
60787
|
quality,
|
|
@@ -60884,7 +60896,7 @@ function useRenderQueue(projectId) {
|
|
|
60884
60896
|
};
|
|
60885
60897
|
return jobId;
|
|
60886
60898
|
},
|
|
60887
|
-
[projectId, closeActiveEventSource, addSessionJob, ffmpeg, ffmpegMissing]
|
|
60899
|
+
[projectId, activeCompPathRef, closeActiveEventSource, addSessionJob, ffmpeg, ffmpegMissing]
|
|
60888
60900
|
);
|
|
60889
60901
|
const cancelRender = useCallback80(
|
|
60890
60902
|
async (jobId) => {
|
|
@@ -62928,6 +62940,7 @@ function useFileTree({ projectId, projectIdRef }) {
|
|
|
62928
62940
|
|
|
62929
62941
|
// src/hooks/useEditorSave.ts
|
|
62930
62942
|
import { useCallback as useCallback87, useRef as useRef112 } from "react";
|
|
62943
|
+
var FAILURE_BURST_MS = 5e3;
|
|
62931
62944
|
function useEditorSave({
|
|
62932
62945
|
editingPathRef,
|
|
62933
62946
|
projectIdRef,
|
|
@@ -62940,18 +62953,32 @@ function useEditorSave({
|
|
|
62940
62953
|
}) {
|
|
62941
62954
|
const saveRafRef = useRef112(null);
|
|
62942
62955
|
const refreshRafRef = useRef112(null);
|
|
62943
|
-
const lastFailureToastAtRef = useRef112(
|
|
62956
|
+
const lastFailureToastAtRef = useRef112(null);
|
|
62957
|
+
const lastFailureReportRef = useRef112(null);
|
|
62944
62958
|
const pendingCandidateRef = useRef112(null);
|
|
62945
62959
|
const inFlightRef = useRef112(null);
|
|
62946
62960
|
const inFlightCandidateRef = useRef112(null);
|
|
62947
62961
|
const reportFailure = useCallback87(
|
|
62948
62962
|
(path, error) => {
|
|
62949
|
-
|
|
62963
|
+
const now2 = Date.now();
|
|
62964
|
+
const properties = buildStudioSaveFailureProperties({
|
|
62950
62965
|
source: "code_editor",
|
|
62951
|
-
|
|
62966
|
+
error,
|
|
62967
|
+
filePath: path
|
|
62952
62968
|
});
|
|
62953
|
-
const
|
|
62954
|
-
|
|
62969
|
+
const errorName = error instanceof Error ? error.name : typeof error;
|
|
62970
|
+
const fingerprint = JSON.stringify([
|
|
62971
|
+
path,
|
|
62972
|
+
errorName,
|
|
62973
|
+
properties.error_message,
|
|
62974
|
+
properties.status_code
|
|
62975
|
+
]);
|
|
62976
|
+
const previous = lastFailureReportRef.current;
|
|
62977
|
+
if (previous === null || previous.fingerprint !== fingerprint || now2 - previous.emittedAt >= FAILURE_BURST_MS) {
|
|
62978
|
+
trackStudioSaveFailure({ source: "code_editor", error, filePath: path });
|
|
62979
|
+
lastFailureReportRef.current = { fingerprint, emittedAt: now2 };
|
|
62980
|
+
}
|
|
62981
|
+
if (lastFailureToastAtRef.current === null || now2 - lastFailureToastAtRef.current >= FAILURE_BURST_MS) {
|
|
62955
62982
|
lastFailureToastAtRef.current = now2;
|
|
62956
62983
|
showToast(
|
|
62957
62984
|
`Couldn't save ${path} \u2014 your latest edits are NOT persisted. Check the preview server; editing again retries the save.`,
|
|
@@ -62974,6 +63001,7 @@ function useEditorSave({
|
|
|
62974
63001
|
recordEdit
|
|
62975
63002
|
}).then(() => {
|
|
62976
63003
|
if (pendingCandidateRef.current === candidate) pendingCandidateRef.current = null;
|
|
63004
|
+
lastFailureReportRef.current = null;
|
|
62977
63005
|
if (refreshRafRef.current != null) cancelAnimationFrame(refreshRafRef.current);
|
|
62978
63006
|
refreshRafRef.current = requestAnimationFrame(() => setRefreshKey((k) => k + 1));
|
|
62979
63007
|
return { status: "clean" };
|
|
@@ -70189,7 +70217,8 @@ import { useCallback as useCallback117 } from "react";
|
|
|
70189
70217
|
function useGsapInteractionFailureTelemetry(activeCompPath, showToast) {
|
|
70190
70218
|
return useCallback117(
|
|
70191
70219
|
(error, selection, mutationType, label) => {
|
|
70192
|
-
trackStudioSaveFailure
|
|
70220
|
+
const report = isGsapEditBlockedError(error) ? trackStudioEditBlocked : trackStudioSaveFailure;
|
|
70221
|
+
report({
|
|
70193
70222
|
source: "gsap_commit",
|
|
70194
70223
|
error,
|
|
70195
70224
|
filePath: selection?.sourceFile ?? activeCompPath ?? "index.html",
|
|
@@ -81852,13 +81881,7 @@ var RenderQueue = memo49(function RenderQueue2({
|
|
|
81852
81881
|
// src/components/renders/RenderQueuePanel.tsx
|
|
81853
81882
|
import { jsx as jsx194 } from "react/jsx-runtime";
|
|
81854
81883
|
var RenderQueuePanel = memo50(function RenderQueuePanel2() {
|
|
81855
|
-
const {
|
|
81856
|
-
projectId,
|
|
81857
|
-
activeCompPath,
|
|
81858
|
-
compositionDimensions,
|
|
81859
|
-
waitForPendingDomEditSaves,
|
|
81860
|
-
renderQueue
|
|
81861
|
-
} = useStudioShellContext();
|
|
81884
|
+
const { projectId, compositionDimensions, waitForPendingDomEditSaves, renderQueue } = useStudioShellContext();
|
|
81862
81885
|
return /* @__PURE__ */ jsx194(
|
|
81863
81886
|
RenderQueue,
|
|
81864
81887
|
{
|
|
@@ -81876,13 +81899,11 @@ var RenderQueuePanel = memo50(function RenderQueuePanel2() {
|
|
|
81876
81899
|
onRecheckFfmpeg: renderQueue.recheckFfmpeg,
|
|
81877
81900
|
onStartRender: async (format, quality, resolution, fps) => {
|
|
81878
81901
|
await waitForPendingDomEditSaves();
|
|
81879
|
-
const composition = activeCompPath && activeCompPath !== "index.html" ? activeCompPath : void 0;
|
|
81880
81902
|
await renderQueue.startRender({
|
|
81881
81903
|
fps,
|
|
81882
81904
|
quality,
|
|
81883
81905
|
format,
|
|
81884
81906
|
resolution,
|
|
81885
|
-
composition,
|
|
81886
81907
|
// Render what the user is previewing: active variable overrides
|
|
81887
81908
|
// from the Variables panel ride along (undefined = defaults).
|
|
81888
81909
|
variables: usePreviewVariablesStore.getState().values ?? void 0
|
|
@@ -87215,7 +87236,7 @@ function StudioApp() {
|
|
|
87215
87236
|
const activeCompPathRef = useRef170(activeCompPath);
|
|
87216
87237
|
activeCompPathRef.current = activeCompPath;
|
|
87217
87238
|
const leftSidebarRef = useRef170(null);
|
|
87218
|
-
const renderQueue = useRenderQueue(projectId);
|
|
87239
|
+
const renderQueue = useRenderQueue(projectId, activeCompPathRef);
|
|
87219
87240
|
const captionEditMode = useCaptionStore((s) => s.isEditMode);
|
|
87220
87241
|
const captionHasSelection = useCaptionStore((s) => s.selectedSegmentIds.size > 0);
|
|
87221
87242
|
const captionSync = useCaptionSync(projectId);
|