@remotion/studio
Version:
APIs for interacting with the Remotion Studio
170 lines (169 loc) • 6.88 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.useSequencePropsSubscription = void 0;
const react_1 = require("react");
const remotion_1 = require("remotion");
const client_id_1 = require("../../helpers/client-id");
const timeline_layout_1 = require("../../helpers/timeline-layout");
const call_api_1 = require("../call-api");
const useSequencePropsSubscription = (sequence, originalLocation, visualModeEnabled) => {
var _a;
var _b, _c, _d, _e;
const { setCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeOverridesContext);
const overrideId = (_b = (_a = sequence.controls) === null || _a === void 0 ? void 0 : _a.overrideId) !== null && _b !== void 0 ? _b : null;
const setPropStatusesForSequence = (0, react_1.useCallback)((statuses) => {
if (!overrideId) {
return;
}
setCodeValues(overrideId, statuses);
}, [overrideId, setCodeValues]);
const { previewServerState: state, subscribeToEvent } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
const clientId = state.type === 'connected' ? state.clientId : undefined;
const schemaFields = (0, react_1.useMemo)(() => (0, timeline_layout_1.getSchemaFields)(sequence.controls), [sequence.controls]);
const schemaKeysString = (0, react_1.useMemo)(() => (schemaFields ? schemaFields.map((f) => f.key).join(',') : null), [schemaFields]);
const validatedLocation = (0, react_1.useMemo)(() => {
var _a;
if (!originalLocation ||
!originalLocation.source ||
!originalLocation.line) {
return null;
}
return {
source: originalLocation.source,
line: originalLocation.line,
column: (_a = originalLocation.column) !== null && _a !== void 0 ? _a : 0,
};
}, [originalLocation]);
const locationSource = (_c = validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source) !== null && _c !== void 0 ? _c : null;
const locationLine = (_d = validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.line) !== null && _d !== void 0 ? _d : null;
const locationColumn = (_e = validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.column) !== null && _e !== void 0 ? _e : null;
const currentLocationSource = (0, react_1.useRef)(locationSource);
currentLocationSource.current = locationSource;
const currentLocationLine = (0, react_1.useRef)(locationLine);
currentLocationLine.current = locationLine;
const currentLocationColumn = (0, react_1.useRef)(locationColumn);
currentLocationColumn.current = locationColumn;
const nodePathRef = (0, react_1.useRef)(null);
const [nodePath, setNodePath] = (0, react_1.useState)(null);
const isMountedRef = (0, react_1.useRef)(true);
const setNodePathBoth = (0, react_1.useCallback)((next) => {
nodePathRef.current = next;
setNodePath(next);
}, []);
(0, react_1.useEffect)(() => {
isMountedRef.current = true;
return () => {
isMountedRef.current = false;
};
}, []);
(0, react_1.useEffect)(() => {
if (!visualModeEnabled) {
setPropStatusesForSequence(null);
setNodePathBoth(null);
return;
}
if (!clientId ||
!locationSource ||
!locationLine ||
locationColumn === null ||
!schemaKeysString) {
setPropStatusesForSequence(null);
setNodePathBoth(null);
return;
}
const keys = schemaKeysString.split(',');
(0, call_api_1.callApi)('/api/subscribe-to-sequence-props', {
fileName: locationSource,
line: locationLine,
column: locationColumn,
keys,
clientId,
})
.then((result) => {
if (currentLocationSource.current !== locationSource ||
currentLocationLine.current !== locationLine ||
currentLocationColumn.current !== locationColumn) {
return;
}
if (result.canUpdate) {
setNodePathBoth(result.nodePath);
setPropStatusesForSequence(result.props);
}
else {
setNodePathBoth(null);
setPropStatusesForSequence(null);
}
})
.catch((err) => {
setNodePathBoth(null);
remotion_1.Internals.Log.error(err);
setPropStatusesForSequence(null);
});
return () => {
const currentNodePath = nodePathRef.current;
// Only clear props on true unmount, not on re-subscribe due to
// line number changes — avoids flicker while re-subscribing.
if (!isMountedRef.current) {
setPropStatusesForSequence(null);
}
setNodePathBoth(null);
if (currentNodePath) {
(0, call_api_1.callApi)('/api/unsubscribe-from-sequence-props', {
fileName: locationSource,
nodePath: currentNodePath,
clientId,
}).catch(() => {
// Ignore unsubscribe errors
});
}
};
}, [
visualModeEnabled,
clientId,
locationSource,
locationLine,
locationColumn,
schemaKeysString,
setPropStatusesForSequence,
setNodePathBoth,
]);
(0, react_1.useEffect)(() => {
if (!visualModeEnabled) {
return;
}
if (!locationSource || !locationLine || locationColumn === null) {
return;
}
const listener = (event) => {
if (event.type !== 'sequence-props-updated') {
return;
}
if (event.fileName !== currentLocationSource.current ||
!nodePathRef.current ||
JSON.stringify(event.nodePath) !== JSON.stringify(nodePathRef.current)) {
return;
}
if (event.result.canUpdate) {
setPropStatusesForSequence(event.result.props);
}
else {
setPropStatusesForSequence(null);
setNodePathBoth(null);
}
};
const unsub = subscribeToEvent('sequence-props-updated', listener);
return () => {
unsub();
};
}, [
visualModeEnabled,
locationSource,
locationLine,
locationColumn,
subscribeToEvent,
setPropStatusesForSequence,
setNodePathBoth,
]);
return nodePath;
};
exports.useSequencePropsSubscription = useSequencePropsSubscription;