refacor video upload (#138)
* refacor video upload * remove unused imports
This commit is contained in:
parent
8a2f8d2f98
commit
664adfc2dc
|
@ -180,7 +180,12 @@ export const FullArticle = (props: ArticleProps) => {
|
|||
<For each={media() || []}>
|
||||
{(m: MediaItem) => (
|
||||
<div class={styles.shoutMediaBody}>
|
||||
<VideoPlayer videoUrl={m.url} title={m.title} description={m.body} />
|
||||
<VideoPlayer
|
||||
articleView={true}
|
||||
videoUrl={m.url}
|
||||
title={m.title}
|
||||
description={m.body}
|
||||
/>
|
||||
<Show when={m?.body}>
|
||||
<MD body={m.body} />
|
||||
</Show>
|
||||
|
|
|
@ -2,32 +2,24 @@ import { clsx } from 'clsx'
|
|||
import styles from './VideoUploader.module.scss'
|
||||
import { useLocalize } from '../../../context/localize'
|
||||
import { createDropzone } from '@solid-primitives/upload'
|
||||
import { createEffect, createSignal, Show } from 'solid-js'
|
||||
import { createSignal, For, Show } from 'solid-js'
|
||||
import { useSnackbar } from '../../../context/snackbar'
|
||||
import { validateUrl } from '../../../utils/validateUrl'
|
||||
import { VideoPlayer } from '../../_shared/VideoPlayer'
|
||||
import type { MediaItem } from '../../../pages/types'
|
||||
// import { handleFileUpload } from '../../../utils/handleFileUpload'
|
||||
import { composeMediaItems } from '../../../utils/composeMediaItems'
|
||||
import { VideoPlayer } from '../../_shared/VideoPlayer'
|
||||
|
||||
type Props = {
|
||||
class?: string
|
||||
data: (value: MediaItem[]) => void
|
||||
video: MediaItem[]
|
||||
onVideoAdd: (value: MediaItem[]) => void
|
||||
onVideoDelete: (mediaItemIndex: number) => void
|
||||
}
|
||||
|
||||
export const VideoUploader = (props: Props) => {
|
||||
const { t } = useLocalize()
|
||||
const [dragActive, setDragActive] = createSignal(false)
|
||||
const [dragError, setDragError] = createSignal<string>()
|
||||
const [error, setError] = createSignal<string>()
|
||||
const [incorrectUrl, setIncorrectUrl] = createSignal<boolean>(false)
|
||||
const [data, setData] = createSignal<MediaItem>()
|
||||
|
||||
const updateData = (key, value) => {
|
||||
setData((prev) => ({ ...prev, [key]: value }))
|
||||
}
|
||||
|
||||
createEffect(() => {
|
||||
props.data([data()])
|
||||
})
|
||||
|
||||
const {
|
||||
actions: { showSnackbar }
|
||||
|
@ -39,97 +31,84 @@ export const VideoUploader = (props: Props) => {
|
|||
current: null
|
||||
}
|
||||
|
||||
// const [videoUrl, setVideoUrl] = createSignal<string | undefined>()
|
||||
// const runUpload = async (file) => {
|
||||
// try {
|
||||
// const fileUrl = await handleFileUpload(file)
|
||||
// setVideoUrl(fileUrl)
|
||||
// } catch (error) {
|
||||
// console.error('[runUpload]', error)
|
||||
// }
|
||||
// }
|
||||
|
||||
const { setRef: dropzoneRef, files: droppedFiles } = createDropzone({
|
||||
onDrop: async () => {
|
||||
setDragActive(false)
|
||||
if (droppedFiles().length > 1) {
|
||||
setDragError(t('Many files, choose only one'))
|
||||
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.'
|
||||
)
|
||||
})
|
||||
// await runUpload(droppedFiles()[0])
|
||||
} else {
|
||||
setDragError(t('Video format not supported'))
|
||||
setError(t('Video format not supported'))
|
||||
}
|
||||
}
|
||||
})
|
||||
const handleDrag = (event) => {
|
||||
if (event.type === 'dragenter' || event.type === 'dragover') {
|
||||
setDragActive(true)
|
||||
setDragError()
|
||||
setError()
|
||||
} else if (event.type === 'dragleave') {
|
||||
setDragActive(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleUrlInput = async (value: string) => {
|
||||
setError()
|
||||
if (validateUrl(value)) {
|
||||
updateData('url', value)
|
||||
props.onVideoAdd(composeMediaItems([{ url: value }]))
|
||||
} else {
|
||||
setIncorrectUrl(true)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div class={clsx(styles.VideoUploader, props.class)}>
|
||||
<Show
|
||||
when={data() && data().url}
|
||||
fallback={
|
||||
<>
|
||||
<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={dragError()}>
|
||||
<div class={styles.error}>{dragError()}</div>
|
||||
</Show>
|
||||
<div class={styles.inputHolder}>
|
||||
<input
|
||||
class={clsx(styles.urlInput, { [styles.hasError]: incorrectUrl() })}
|
||||
ref={(el) => (urlInput.current = 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>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<VideoPlayer
|
||||
deleteAction={() => setData()}
|
||||
videoUrl={data().url}
|
||||
title={data().title}
|
||||
description={data().body}
|
||||
/>
|
||||
</Show>
|
||||
</div>
|
||||
<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.current = 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>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { For, Show, createSignal, createEffect, onMount, onCleanup } from 'solid-js'
|
||||
import { Show, createSignal, createEffect, onMount, onCleanup } from 'solid-js'
|
||||
import { Icon } from '../_shared/Icon'
|
||||
import { Modal } from './Modal'
|
||||
import { AuthModal } from './AuthModal'
|
||||
import { useModalStore } from '../../stores/ui'
|
||||
import { router, ROUTES, useRouter } from '../../stores/router'
|
||||
import { router, useRouter } from '../../stores/router'
|
||||
import styles from './Header.module.scss'
|
||||
import { getPagePath } from '@nanostores/router'
|
||||
import { clsx } from 'clsx'
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Accessor, createMemo, createSignal, For, onCleanup, onMount, Show } from 'solid-js'
|
||||
import { Accessor, createMemo, createSignal, onCleanup, onMount, Show } from 'solid-js'
|
||||
import { useLocalize } from '../../context/localize'
|
||||
import { clsx } from 'clsx'
|
||||
import { Title } from '@solidjs/meta'
|
||||
|
@ -17,7 +17,6 @@ import { imageProxy } from '../../utils/imageProxy'
|
|||
import { GrowingTextarea } from '../_shared/GrowingTextarea'
|
||||
import { VideoUploader } from '../Editor/VideoUploader'
|
||||
import { AudioUploader } from '../Editor/AudioUploader'
|
||||
import { VideoPlayer } from '../_shared/VideoPlayer'
|
||||
import { slugify } from '../../utils/slugify'
|
||||
import { SolidSwiper } from '../_shared/SolidSwiper'
|
||||
import { DropArea } from '../_shared/DropArea'
|
||||
|
@ -136,7 +135,7 @@ export const EditView = (props: Props) => {
|
|||
setForm('media', JSON.stringify(data))
|
||||
}
|
||||
|
||||
const handleImageDelete = (index) => {
|
||||
const handleMediaDelete = (index) => {
|
||||
const copy = [...mediaItems()]
|
||||
copy.splice(index, 1)
|
||||
setForm('media', JSON.stringify(copy))
|
||||
|
@ -307,36 +306,18 @@ export const EditView = (props: Props) => {
|
|||
editorMode={true}
|
||||
images={mediaItems()}
|
||||
onImageChange={handleMediaChange}
|
||||
onImageDelete={(index) => handleImageDelete(index)}
|
||||
onImageDelete={(index) => handleMediaDelete(index)}
|
||||
onImagesAdd={(value) => handleAddMedia(value)}
|
||||
onImagesSorted={(value) => handleSortedMedia(value)}
|
||||
/>
|
||||
</Show>
|
||||
|
||||
<Show when={props.shout.layout === 'video'}>
|
||||
<Show
|
||||
when={form.media}
|
||||
fallback={
|
||||
<VideoUploader
|
||||
data={(data) => {
|
||||
handleAddMedia(data)
|
||||
}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<For each={mediaItems()}>
|
||||
{(mediaItem) => (
|
||||
<>
|
||||
<VideoPlayer
|
||||
videoUrl={mediaItem?.url}
|
||||
title={mediaItem?.title}
|
||||
description={mediaItem?.body}
|
||||
deleteAction={() => setForm('media', null)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</For>
|
||||
</Show>
|
||||
<VideoUploader
|
||||
video={mediaItems()}
|
||||
onVideoAdd={(data) => handleAddMedia(data)}
|
||||
onVideoDelete={(index) => handleMediaDelete(index)}
|
||||
/>
|
||||
</Show>
|
||||
|
||||
<Show when={props.shout.layout === 'audio'}>
|
||||
|
|
|
@ -25,7 +25,6 @@ interface Props {
|
|||
export const Slider = (props: Props) => {
|
||||
let el: HTMLDivElement | undefined
|
||||
let thumbsEl: HTMLDivElement | undefined
|
||||
let pagEl: HTMLDivElement | undefined
|
||||
let nextEl: HTMLDivElement | undefined
|
||||
let prevEl: HTMLDivElement | undefined
|
||||
|
||||
|
|
|
@ -3,11 +3,13 @@
|
|||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 1rem 0;
|
||||
margin: 1rem auto;
|
||||
position: relative;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
margin: 1rem -16.6666% 2rem -25%;
|
||||
&.articleView {
|
||||
@include media-breakpoint-up(md) {
|
||||
margin: 1rem -16.6666% 2rem -25%;
|
||||
}
|
||||
}
|
||||
|
||||
.controls {
|
||||
|
|
|
@ -11,7 +11,8 @@ type Props = {
|
|||
title?: string
|
||||
description?: string
|
||||
class?: string
|
||||
deleteAction?: () => void
|
||||
onVideoDelete?: () => void
|
||||
articleView?: boolean
|
||||
}
|
||||
|
||||
export const VideoPlayer = (props: Props) => {
|
||||
|
@ -37,15 +38,15 @@ export const VideoPlayer = (props: Props) => {
|
|||
})
|
||||
|
||||
return (
|
||||
<div class={clsx(styles.VideoPlayer, props.class)}>
|
||||
<Show when={props.deleteAction}>
|
||||
<div class={clsx(styles.VideoPlayer, props.class, { [styles.articleView]: props.articleView })}>
|
||||
<Show when={props.onVideoDelete}>
|
||||
<Popover content={t('Delete')}>
|
||||
{(triggerRef: (el) => void) => (
|
||||
<Button
|
||||
ref={triggerRef}
|
||||
size="S"
|
||||
class={styles.deleteAction}
|
||||
onClick={props.deleteAction}
|
||||
onClick={() => props.onVideoDelete()}
|
||||
value={<Icon class={styles.deleteIcon} name="delete" />}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -45,5 +45,5 @@ export type MediaItem = {
|
|||
|
||||
export type UploadedFile = {
|
||||
url: string
|
||||
originalFilename: string
|
||||
originalFilename?: string
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ export const composeMediaItems = (value: UploadedFile[], optionalParams = {}) =>
|
|||
return {
|
||||
url: fileData.url,
|
||||
source: '',
|
||||
title: removeFileExtension(fileData.originalFilename),
|
||||
title: fileData.originalFilename ? removeFileExtension(fileData.originalFilename) : '',
|
||||
body: '',
|
||||
...optionalParams
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user