90 lines
3.1 KiB
TypeScript
90 lines
3.1 KiB
TypeScript
import { useCallback, useRef } from 'react'
|
|
import type { Asset } from '../../types/project-model'
|
|
import { addGenericAssetToProject, addVisualAssetToProject } from '../../lib/asset-copy'
|
|
import { pathToFileUrl } from '../../lib/file-url'
|
|
import { useEditorActions } from './editor-store'
|
|
|
|
interface UseEditorMediaImportParams {
|
|
currentProjectId: string | null
|
|
}
|
|
|
|
export function useEditorMediaImport(params: UseEditorMediaImportParams) {
|
|
const { currentProjectId } = params
|
|
const { addAssetToEditor } = useEditorActions()
|
|
const fileInputRef = useRef<HTMLInputElement>(null)
|
|
|
|
const getMediaDuration = useCallback((url: string, isAudio = false): Promise<number> => {
|
|
return new Promise((resolve) => {
|
|
const media = document.createElement(isAudio ? 'audio' : 'video')
|
|
media.src = url
|
|
media.onloadedmetadata = () => resolve(media.duration)
|
|
media.onerror = () => resolve(5)
|
|
})
|
|
}, [])
|
|
|
|
const handleImportFile = useCallback(async (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
const files = e.target.files
|
|
if (!files || !currentProjectId) return
|
|
|
|
for (const file of Array.from(files)) {
|
|
const isVideo = file.type.startsWith('video/')
|
|
const isAudio = file.type.startsWith('audio/')
|
|
const isImage = file.type.startsWith('image/')
|
|
if (!isVideo && !isAudio && !isImage) continue
|
|
|
|
const electronFilePath = window.electronAPI?.getPathForFile(file)
|
|
let persistentPath = electronFilePath || file.name
|
|
let bigThumbnailPath: string | undefined
|
|
let smallThumbnailPath: string | undefined
|
|
let width: number | undefined
|
|
let height: number | undefined
|
|
|
|
let duration = 5
|
|
if (isVideo || isAudio) {
|
|
const mediaUrl = electronFilePath ? pathToFileUrl(electronFilePath) : URL.createObjectURL(file)
|
|
duration = await getMediaDuration(mediaUrl, isAudio)
|
|
}
|
|
|
|
if (electronFilePath) {
|
|
if (isVideo || isImage) {
|
|
const copied = await addVisualAssetToProject(electronFilePath, currentProjectId, isVideo ? 'video' : 'image')
|
|
if (!copied) continue
|
|
persistentPath = copied.path
|
|
bigThumbnailPath = copied.bigThumbnailPath
|
|
smallThumbnailPath = copied.smallThumbnailPath
|
|
width = copied.width
|
|
height = copied.height
|
|
} else if (isAudio) {
|
|
const copied = await addGenericAssetToProject(electronFilePath, currentProjectId)
|
|
if (copied?.path) persistentPath = copied.path
|
|
}
|
|
}
|
|
|
|
const asset: Asset = {
|
|
id: `asset-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`,
|
|
type: isVideo ? 'video' : isAudio ? 'audio' : 'image',
|
|
path: persistentPath,
|
|
bigThumbnailPath,
|
|
smallThumbnailPath,
|
|
width,
|
|
height,
|
|
prompt: `Imported: ${file.name}`,
|
|
resolution: 'imported',
|
|
duration,
|
|
createdAt: Date.now(),
|
|
}
|
|
addAssetToEditor(asset)
|
|
}
|
|
|
|
e.target.value = ''
|
|
if (fileInputRef.current && fileInputRef.current !== e.target) {
|
|
fileInputRef.current.value = ''
|
|
}
|
|
}, [addAssetToEditor, currentProjectId, getMediaDuration])
|
|
|
|
return {
|
|
fileInputRef,
|
|
handleImportFile,
|
|
}
|
|
}
|