Skip to content

Commit d663c5c

Browse files
committed
feat: display video thumbnail instead of default file icon
1 parent a8d88b8 commit d663c5c

File tree

4 files changed

+81
-17
lines changed

4 files changed

+81
-17
lines changed

Diff for: packages/ui/src/elements/Thumbnail/index.scss

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
overflow: hidden;
88

99
img,
10+
video,
1011
svg {
1112
width: 100%;
1213
height: 100%;
@@ -20,6 +21,7 @@
2021
position: relative;
2122

2223
img,
24+
video,
2325
svg {
2426
position: absolute;
2527
top: 0;

Diff for: packages/ui/src/elements/Thumbnail/index.tsx

+32-12
Original file line numberDiff line numberDiff line change
@@ -30,36 +30,56 @@ const ThumbnailContext = React.createContext({
3030
export const useThumbnailContext = () => React.useContext(ThumbnailContext)
3131

3232
export const Thumbnail: React.FC<ThumbnailProps> = (props) => {
33-
const { className = '', doc: { filename } = {}, fileSrc, imageCacheTag, size } = props
33+
const { className = '', doc: { filename, mimeType } = {}, fileSrc, imageCacheTag, size } = props
3434
const [fileExists, setFileExists] = React.useState(undefined)
35-
3635
const classNames = [baseClass, `${baseClass}--size-${size || 'medium'}`, className].join(' ')
36+
const [type, setType] = React.useState<'audio' | 'document' | 'image' | 'unknown' | 'video'>(
37+
undefined,
38+
)
3739

3840
React.useEffect(() => {
39-
if (!fileSrc) {
41+
if (mimeType) setType(mimeType.split('/')[0])
42+
}, [mimeType])
43+
44+
React.useEffect(() => {
45+
if (!fileSrc || !type) {
4046
setFileExists(false)
4147
return
4248
}
43-
44-
const img = new Image()
45-
img.src = fileSrc
46-
img.onload = () => {
47-
setFileExists(true)
48-
}
49-
img.onerror = () => {
49+
if (type === 'image') {
50+
const img = new Image()
51+
img.src = fileSrc
52+
img.onload = () => setFileExists(true)
53+
img.onerror = () => setFileExists(false)
54+
} else if (type === 'video') {
55+
const video = document.createElement('video')
56+
video.src = fileSrc
57+
video.crossOrigin = 'anonymous'
58+
video.onloadeddata = () => setFileExists(true)
59+
video.onerror = () => setFileExists(false)
60+
} else {
5061
setFileExists(false)
5162
}
52-
}, [fileSrc])
63+
}, [fileSrc, type])
5364

5465
return (
5566
<div className={classNames}>
5667
{fileExists === undefined && <ShimmerEffect height="100%" />}
57-
{fileExists && (
68+
{fileExists && type === 'image' && (
5869
<img
5970
alt={filename as string}
6071
src={`${fileSrc}${imageCacheTag ? `?${imageCacheTag}` : ''}`}
6172
/>
6273
)}
74+
{fileExists && type === 'video' && (
75+
<video
76+
autoPlay={false}
77+
controls={false}
78+
muted={true}
79+
playsInline={true}
80+
src={`${fileSrc}${imageCacheTag ? `?${imageCacheTag}` : ''}`}
81+
/>
82+
)}
6383
{fileExists === false && <File />}
6484
</div>
6585
)

Diff for: test/_community/config.ts

+2-5
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,15 @@ import path from 'path'
33

44
import { buildConfigWithDefaults } from '../buildConfigWithDefaults.js'
55
import { devUser } from '../credentials.js'
6-
// import { MediaCollection } from './collections/Media/index.js'
6+
import { MediaCollection } from './collections/Media/index.js'
77
import { PostsCollection, postsSlug } from './collections/Posts/index.js'
88
import { MenuGlobal } from './globals/Menu/index.js'
99
const filename = fileURLToPath(import.meta.url)
1010
const dirname = path.dirname(filename)
1111

1212
export default buildConfigWithDefaults({
1313
// ...extend config here
14-
collections: [
15-
PostsCollection,
16-
// MediaCollection
17-
],
14+
collections: [PostsCollection, MediaCollection],
1815
cors: ['http://localhost:3000', 'http://localhost:3001'],
1916
globals: [
2017
MenuGlobal,

Diff for: test/_community/payload-types.ts

+45
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export interface Config {
1212
};
1313
collections: {
1414
posts: Post;
15+
media: Media;
1516
users: User;
1617
'payload-preferences': PayloadPreference;
1718
'payload-migrations': PayloadMigration;
@@ -85,6 +86,50 @@ export interface Post {
8586
createdAt: string;
8687
_status?: ('draft' | 'published') | null;
8788
}
89+
/**
90+
* This interface was referenced by `Config`'s JSON-Schema
91+
* via the `definition` "media".
92+
*/
93+
export interface Media {
94+
id: string;
95+
updatedAt: string;
96+
createdAt: string;
97+
url?: string | null;
98+
thumbnailURL?: string | null;
99+
filename?: string | null;
100+
mimeType?: string | null;
101+
filesize?: number | null;
102+
width?: number | null;
103+
height?: number | null;
104+
focalX?: number | null;
105+
focalY?: number | null;
106+
sizes?: {
107+
thumbnail?: {
108+
url?: string | null;
109+
width?: number | null;
110+
height?: number | null;
111+
mimeType?: string | null;
112+
filesize?: number | null;
113+
filename?: string | null;
114+
};
115+
medium?: {
116+
url?: string | null;
117+
width?: number | null;
118+
height?: number | null;
119+
mimeType?: string | null;
120+
filesize?: number | null;
121+
filename?: string | null;
122+
};
123+
large?: {
124+
url?: string | null;
125+
width?: number | null;
126+
height?: number | null;
127+
mimeType?: string | null;
128+
filesize?: number | null;
129+
filename?: string | null;
130+
};
131+
};
132+
}
88133
/**
89134
* This interface was referenced by `Config`'s JSON-Schema
90135
* via the `definition` "users".

0 commit comments

Comments
 (0)