109 lines
3.4 KiB
TypeScript
109 lines
3.4 KiB
TypeScript
import { createDropzone } from '@solid-primitives/upload'
|
|
import { clsx } from 'clsx'
|
|
import { For, Show, createSignal } from 'solid-js'
|
|
|
|
import { useSnackbar } from '~/context/ui'
|
|
import { useLocalize } from '../../../context/localize'
|
|
import { composeMediaItems } from '../../../utils/composeMediaItems'
|
|
import { validateUrl } from '../../../utils/validateUrl'
|
|
import { VideoPlayer } from '../../_shared/VideoPlayer'
|
|
|
|
import { MediaItem } from '~/types/mediaitem'
|
|
import styles from './VideoUploader.module.scss'
|
|
|
|
type Props = {
|
|
video: MediaItem[]
|
|
onVideoAdd: (value: MediaItem[]) => void
|
|
onVideoDelete: (mediaItemIndex: number) => void
|
|
}
|
|
|
|
export const VideoUploader = (props: Props) => {
|
|
const { t } = useLocalize()
|
|
const [dragActive, setDragActive] = createSignal(false)
|
|
const [error, setError] = createSignal<string>()
|
|
const [incorrectUrl, setIncorrectUrl] = createSignal<boolean>(false)
|
|
const { showSnackbar } = useSnackbar()
|
|
let urlInput: HTMLInputElement | undefined
|
|
|
|
const { setRef: dropzoneRef, files: droppedFiles } = createDropzone({
|
|
onDrop: async () => {
|
|
setDragActive(false)
|
|
if (droppedFiles().length > 1) {
|
|
setError(t('Many files, choose only one'))
|
|
} else if (droppedFiles()[0].file.type.startsWith('video/')) {
|
|
await showSnackbar({
|
|
body: t(
|
|
'This functionality is currently not available, we would like to work on this issue. Use the download link.'
|
|
)
|
|
})
|
|
} else {
|
|
setError(t('Video format not supported'))
|
|
}
|
|
}
|
|
})
|
|
const handleDrag = (event: DragEvent) => {
|
|
if (event.type === 'dragenter' || event.type === 'dragover') {
|
|
setDragActive(true)
|
|
setError()
|
|
} else if (event.type === 'dragleave') {
|
|
setDragActive(false)
|
|
}
|
|
}
|
|
|
|
const handleUrlInput = (value: string) => {
|
|
setError()
|
|
if (validateUrl(value)) {
|
|
props.onVideoAdd(composeMediaItems([{ url: value }]))
|
|
} else {
|
|
setIncorrectUrl(true)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Show
|
|
when={props.video.length === 0}
|
|
fallback={
|
|
<For each={props.video}>
|
|
{(mi, index) => (
|
|
<VideoPlayer onVideoDelete={() => props.onVideoDelete(index())} videoUrl={mi?.url} />
|
|
)}
|
|
</For>
|
|
}
|
|
>
|
|
<div class={styles.VideoUploader}>
|
|
<div
|
|
onDragEnter={handleDrag}
|
|
onDragLeave={handleDrag}
|
|
onDragOver={handleDrag}
|
|
onClick={() =>
|
|
showSnackbar({
|
|
body: t(
|
|
'This functionality is currently not available, we would like to work on this issue. Use the download link.'
|
|
)
|
|
})
|
|
}
|
|
ref={dropzoneRef}
|
|
class={clsx(styles.dropArea, { [styles.active]: dragActive() })}
|
|
>
|
|
<div class={styles.text}>{t('Upload video')}</div>
|
|
</div>
|
|
<Show when={error()}>
|
|
<div class={styles.error}>{error()}</div>
|
|
</Show>
|
|
<div class={styles.inputHolder}>
|
|
<input
|
|
class={clsx(styles.urlInput, { [styles.hasError]: incorrectUrl() })}
|
|
ref={(el) => (urlInput = el)}
|
|
type="text"
|
|
placeholder={t('Insert video link')}
|
|
onChange={(event) => handleUrlInput(event.currentTarget.value)}
|
|
/>
|
|
</div>
|
|
<Show when={incorrectUrl()}>
|
|
<div class={styles.error}>{t('It does not look like url')}</div>
|
|
</Show>
|
|
</div>
|
|
</Show>
|
|
)
|
|
}
|