({
projectId,
activeCompPath,
showToast,
writeProjectFile,
recordEdit,
domEditSaveTimestampRef,
reloadPreview,
isRecordingRef,
}: UseRazorSplitOptions)
| 165 | } |
| 166 | |
| 167 | export function useRazorSplit({ |
| 168 | projectId, |
| 169 | activeCompPath, |
| 170 | showToast, |
| 171 | writeProjectFile, |
| 172 | recordEdit, |
| 173 | domEditSaveTimestampRef, |
| 174 | reloadPreview, |
| 175 | isRecordingRef, |
| 176 | }: UseRazorSplitOptions) { |
| 177 | const projectIdRef = useRef(projectId); |
| 178 | projectIdRef.current = projectId; |
| 179 | |
| 180 | const handleRazorSplit = useCallback( |
| 181 | // fallow-ignore-next-line complexity |
| 182 | async (element: TimelineElement, splitTime: number) => { |
| 183 | if (isRecordingRef?.current) { |
| 184 | showToast("Cannot edit timeline while recording", "error"); |
| 185 | return; |
| 186 | } |
| 187 | |
| 188 | const pid = projectIdRef.current; |
| 189 | if (!pid || !canSplitElementAt(element, splitTime)) return; |
| 190 | |
| 191 | try { |
| 192 | const { targetPath, originalContent, patchedContent, changed, skippedSelectors } = |
| 193 | await executeSplit(pid, element, splitTime, activeCompPath, writeProjectFile); |
| 194 | |
| 195 | if (!changed) { |
| 196 | showToast("Failed to split clip — playhead may be outside the clip", "error"); |
| 197 | return; |
| 198 | } |
| 199 | |
| 200 | domEditSaveTimestampRef.current = Date.now(); |
| 201 | await saveProjectFilesWithHistory({ |
| 202 | projectId: pid, |
| 203 | label: "Split timeline clip", |
| 204 | kind: "timeline", |
| 205 | files: { [targetPath]: patchedContent }, |
| 206 | readFile: async () => originalContent, |
| 207 | writeFile: writeProjectFile, |
| 208 | recordEdit, |
| 209 | }); |
| 210 | |
| 211 | reloadPreview(); |
| 212 | trackStudioRazorSplit({ mode: "single", count: 1 }); |
| 213 | showToast(`Split ${getTimelineElementLabel(element)} at ${splitTime.toFixed(2)}s`, "info"); |
| 214 | if (skippedSelectors?.length) { |
| 215 | showToast( |
| 216 | `Some animations use non-ID selectors (${skippedSelectors.join(", ")}) and were not retargeted`, |
| 217 | "info", |
| 218 | ); |
| 219 | } |
| 220 | } catch (error) { |
| 221 | const message = error instanceof Error ? error.message : "Failed to split timeline clip"; |
| 222 | showToast(message, "error"); |
| 223 | } |
| 224 | }, |
no test coverage detected