Download frontend/src/lib/timeline-node-size.ts from turtle89431/Moxie-Multimedia: direct link, hf CLI and curl.
- Browser
- Download file 6.83 kB
-
https://huggingface.co/turtle89431/Moxie-Multimedia/resolve/main/frontend/src/lib/timeline-node-size.ts
- Command line
-
hf download hf://turtle89431/Moxie-Multimedia/frontend/src/lib/timeline-node-size.ts
-
curl -L -o timeline-node-size.ts https://huggingface.co/turtle89431/Moxie-Multimedia/resolve/main/frontend/src/lib/timeline-node-size.ts
6.83 kB
| const TIMELINE_NODE_NAME = new Set(['easy timelineEditor', 'easy multiTrackEditor']) | |
| const TIMELINE_HEIGHT_PROPERTY = 'easyMediaTimelineHeight' | |
| const TIMELINE_WIDGET_RESIZE_GUARD = '__easyMediaTimelineWidgetResizeGuard' | |
| const TIMELINE_HEIGHT_RESTORE_VERSION = '__easyMediaTimelineHeightRestoreVersion' | |
| const TIMELINE_WIDGET_DEFAULT_SIZES: Record<string, [number, number]> = { | |
| 'easy timelineEditor': [520, 430], | |
| 'easy multiTrackEditor': [800, 700], | |
| } | |
| const WIDGET_RESIZE_GUARD_MS = 500 | |
| type NodeSize = [number, number] | |
| type ResizeGuard = { height: number; width?: number; expiresAt: number } | |
| function readSize(size: unknown): NodeSize | null { | |
| if (Array.isArray(size) && size.length >= 2) { | |
| const width = Number(size[0]) | |
| const height = Number(size[1]) | |
| return Number.isFinite(width) && Number.isFinite(height) ? [width, height] : null | |
| } | |
| if (ArrayBuffer.isView(size) && 'length' in size && Number(size.length) >= 2) { | |
| const arrayLikeSize = size as unknown as ArrayLike<number> | |
| const width = Number(arrayLikeSize[0]) | |
| const height = Number(arrayLikeSize[1]) | |
| return Number.isFinite(width) && Number.isFinite(height) ? [width, height] : null | |
| } | |
| if (!size || typeof size !== 'object') return null | |
| const sizeObject = size as Record<string, unknown> | |
| const width = Number(sizeObject.width ?? sizeObject[0]) | |
| const height = Number(sizeObject.height ?? sizeObject[1]) | |
| return Number.isFinite(width) && Number.isFinite(height) ? [width, height] : null | |
| } | |
| function readStoredHeight(node: any, serialisedNode?: any): number | null { | |
| const propertyHeight = Number( | |
| node?.properties?.[TIMELINE_HEIGHT_PROPERTY] | |
| ?? serialisedNode?.properties?.[TIMELINE_HEIGHT_PROPERTY], | |
| ) | |
| if (Number.isFinite(propertyHeight) && propertyHeight > 0) return propertyHeight | |
| return readSize(serialisedNode?.size)?.[1] ?? null | |
| } | |
| function preserveHeight(node: any, height: unknown) { | |
| const numericHeight = Number(height) | |
| if (!Number.isFinite(numericHeight) || numericHeight <= 0) return | |
| node.properties ??= {} | |
| node.properties[TIMELINE_HEIGHT_PROPERTY] = numericHeight | |
| } | |
| function applyHeight(node: any, height: number, fallbackWidth?: number) { | |
| const currentSize = readSize(node.size) | |
| if (!currentSize || Math.abs(currentSize[1] - height) < 1) return | |
| const width = currentSize[0] || fallbackWidth || 480 | |
| if (typeof node.setSize === 'function') { | |
| node.setSize([width, height]) | |
| } else { | |
| node.size = [width, height] | |
| } | |
| node.setDirtyCanvas?.(true, true) | |
| } | |
| function invalidatePendingHeightRestores(node: any) { | |
| const currentVersion = Number(node?.[TIMELINE_HEIGHT_RESTORE_VERSION]) | |
| node[TIMELINE_HEIGHT_RESTORE_VERSION] = Number.isFinite(currentVersion) ? currentVersion + 1 : 1 | |
| } | |
| export function adjustMultiTrackEditorNodeHeight(node: any, heightDelta: number) { | |
| const currentSize = readSize(node?.size) | |
| if (!currentSize || !Number.isFinite(heightDelta) || heightDelta === 0) return | |
| const nextHeight = Math.max(1, currentSize[1] + heightDelta) | |
| invalidatePendingHeightRestores(node) | |
| delete node[TIMELINE_WIDGET_RESIZE_GUARD] | |
| preserveHeight(node, nextHeight) | |
| applyHeight(node, nextHeight, currentSize[0]) | |
| } | |
| function restoreHeight(node: any, height: number | null, fallbackWidth?: number) { | |
| if (!Number.isFinite(height) || height === null || height <= 0) return | |
| const restoreVersion = Number(node?.[TIMELINE_HEIGHT_RESTORE_VERSION]) || 0 | |
| globalThis.setTimeout(() => { | |
| if ((Number(node?.[TIMELINE_HEIGHT_RESTORE_VERSION]) || 0) !== restoreVersion) return | |
| applyHeight(node, height, fallbackWidth) | |
| }, 100) | |
| } | |
| function readWidgetResizeGuard(node: any): ResizeGuard | null { | |
| const guard = node?.[TIMELINE_WIDGET_RESIZE_GUARD] as ResizeGuard | undefined | |
| if (!guard || !Number.isFinite(guard.height) || guard.height <= 0) return null | |
| if (Date.now() > guard.expiresAt) { | |
| delete node[TIMELINE_WIDGET_RESIZE_GUARD] | |
| return null | |
| } | |
| return guard | |
| } | |
| function beginWidgetResizeGuard(node: any) { | |
| const currentSize = readSize(node?.size) | |
| const height = readStoredHeight(node) ?? currentSize?.[1] ?? null | |
| if (!Number.isFinite(height) || height === null || height <= 0) return | |
| node.properties ??= {} | |
| node.properties[TIMELINE_HEIGHT_PROPERTY] = height | |
| node[TIMELINE_WIDGET_RESIZE_GUARD] = { | |
| height, | |
| width: currentSize?.[0], | |
| expiresAt: Date.now() + WIDGET_RESIZE_GUARD_MS, | |
| } satisfies ResizeGuard | |
| } | |
| export function preserveTimelineEditorNodeSize(nodeType: any, nodeData: { name?: string }) { | |
| if (!TIMELINE_NODE_NAME.has(nodeData.name || '')) return | |
| const originalOnNodeCreated = nodeType.prototype.onNodeCreated | |
| const originalOnConfigure = nodeType.prototype.onConfigure | |
| const originalOnResize = nodeType.prototype.onResize | |
| const originalOnSerialize = nodeType.prototype.onSerialize | |
| const originalOnWidgetChanged = nodeType.prototype.onWidgetChanged | |
| nodeType.prototype.onNodeCreated = function () { | |
| originalOnNodeCreated?.call(this) | |
| const nodeName = nodeData.name || '' | |
| const defaultSize = TIMELINE_WIDGET_DEFAULT_SIZES[nodeName] | |
| if (!defaultSize) return | |
| this.size[0] = defaultSize[0] | |
| this.size[1] = defaultSize[1] | |
| this.setDirtyCanvas?.(true, true) | |
| } | |
| nodeType.prototype.onConfigure = function (serialisedNode: any) { | |
| originalOnConfigure?.call(this, serialisedNode) | |
| const savedHeight = readStoredHeight(this, serialisedNode) | |
| invalidatePendingHeightRestores(this) | |
| if (savedHeight !== null) preserveHeight(this, savedHeight) | |
| restoreHeight(this, savedHeight, readSize(serialisedNode?.size)?.[0]) | |
| } | |
| nodeType.prototype.onResize = function (size: unknown) { | |
| originalOnResize?.call(this, size) | |
| const nextSize = readSize(size) | |
| if (!nextSize) return | |
| const resizeGuard = readWidgetResizeGuard(this) | |
| if (resizeGuard) { | |
| preserveHeight(this, resizeGuard.height) | |
| restoreHeight(this, resizeGuard.height, resizeGuard.width ?? nextSize[0]) | |
| return | |
| } | |
| preserveHeight(this, nextSize[1]) | |
| } | |
| nodeType.prototype.onWidgetChanged = function ( | |
| name: string, | |
| value: unknown, | |
| oldValue: unknown, | |
| widget: unknown, | |
| ) { | |
| beginWidgetResizeGuard(this) | |
| originalOnWidgetChanged?.call(this, name, value, oldValue, widget) | |
| const resizeGuard = readWidgetResizeGuard(this) | |
| if (resizeGuard) restoreHeight(this, resizeGuard.height, resizeGuard.width) | |
| } | |
| nodeType.prototype.onSerialize = function (serialisedNode: any) { | |
| originalOnSerialize?.call(this, serialisedNode) | |
| const currentSize = readSize(this.size) | |
| if (currentSize) preserveHeight(this, currentSize[1]) | |
| serialisedNode.properties ??= {} | |
| serialisedNode.properties[TIMELINE_HEIGHT_PROPERTY] = this.properties?.[TIMELINE_HEIGHT_PROPERTY] | |
| } | |
| } | |
| export const preserveTimelineEditorNodeHeight = preserveTimelineEditorNodeSize | |