Plugin Directory

source: jetpack/trunk/jetpack_vendor/automattic/jetpack-videopress/src/client/admin/components/video-thumbnail/index.tsx @ 2832426

Last change on this file since 2832426 was 2832426, checked in by wpkaren, 20 months ago

Updating trunk to version 11.7-a.3

File size: 5.9 KB
Line 
1/**
2 * External dependencies
3 */
4import { Text, Button, useBreakpointMatch } from '@automattic/jetpack-components';
5import { Dropdown } from '@wordpress/components';
6import { gmdateI18n } from '@wordpress/date';
7import { __, sprintf } from '@wordpress/i18n';
8import { Icon, edit, cloud, image, media, video } from '@wordpress/icons';
9import classnames from 'classnames';
10import { forwardRef } from 'react';
11/**
12 * Internal dependencies
13 */
14import Placeholder from '../placeholder';
15import ProgressBar from '../progress-bar';
16import styles from './style.module.scss';
17/**
18 * Types
19 */
20import { VideoThumbnailDropdownProps, VideoThumbnailProps } from './types';
21import type React from 'react';
22
23export const VideoThumbnailDropdownButtons = ( {
24        onUseDefaultThumbnail,
25        onSelectFromVideo,
26        onUploadImage,
27        onClose,
28        isUpdatingPoster = false,
29} ) => {
30        return (
31                <>
32                        { /* TODO: Implement use default and remove disabled class */ }
33                        <Button
34                                className={ styles.disabled }
35                                weight="regular"
36                                fullWidth
37                                variant="tertiary"
38                                icon={ image }
39                                onClick={ () => {
40                                        onClose();
41                                        onUseDefaultThumbnail?.();
42                                } }
43                        >
44                                { __( 'Use default thumbnail', 'jetpack-videopress-pkg' ) }
45                        </Button>
46                        <Button
47                                weight="regular"
48                                fullWidth
49                                variant="tertiary"
50                                icon={ media }
51                                onClick={ () => {
52                                        onClose();
53                                        onSelectFromVideo?.();
54                                } }
55                        >
56                                { __( 'Select from video', 'jetpack-videopress-pkg' ) }
57                        </Button>
58                        <Button
59                                weight="regular"
60                                fullWidth
61                                variant="tertiary"
62                                icon={ cloud }
63                                disabled={ isUpdatingPoster }
64                                onClick={ () => {
65                                        onClose();
66                                        onUploadImage?.();
67                                } }
68                        >
69                                { __( 'Upload image', 'jetpack-videopress-pkg' ) }
70                        </Button>
71                </>
72        );
73};
74
75export const VideoThumbnailDropdown = ( {
76        onUseDefaultThumbnail,
77        onSelectFromVideo,
78        onUploadImage,
79}: VideoThumbnailDropdownProps ) => {
80        return (
81                <div className={ styles[ 'video-thumbnail-edit' ] }>
82                        <Dropdown
83                                position="bottom left"
84                                renderToggle={ ( { isOpen, onToggle } ) => (
85                                        <Button
86                                                variant="secondary"
87                                                className={ styles[ 'thumbnail__edit-button' ] }
88                                                icon={ edit }
89                                                onClick={ onToggle }
90                                                aria-expanded={ isOpen }
91                                        />
92                                ) }
93                                renderContent={ ( { onClose } ) => (
94                                        <VideoThumbnailDropdownButtons
95                                                onClose={ onClose }
96                                                onUseDefaultThumbnail={ onUseDefaultThumbnail }
97                                                onSelectFromVideo={ onSelectFromVideo }
98                                                onUploadImage={ onUploadImage }
99                                        />
100                                ) }
101                        />
102                </div>
103        );
104};
105
106const UploadingThumbnail = ( {
107        uploadProgress = 0,
108        isRow = false,
109}: {
110        uploadProgress: number;
111        isRow?: boolean;
112} ) => {
113        const completingTextFull = __( 'Completing upload', 'jetpack-videopress-pkg' );
114        const completingTextCompact = __( 'Completing', 'jetpack-videopress-pkg' );
115        const completingText = isRow ? completingTextCompact : completingTextFull;
116
117        const uploadPercentage = `${ Math.floor( uploadProgress * 100 ) }%`;
118        const uploadingText = sprintf(
119                /* translators: placeholder is the upload percentage */
120                __( 'Uploading %s', 'jetpack-videopress-pkg' ),
121                uploadPercentage
122        );
123        const infoText = uploadProgress === 1 ? completingText : uploadingText;
124
125        return (
126                <div
127                        className={ classnames( styles[ 'custom-thumbnail' ], { [ styles[ 'is-row' ] ]: isRow } ) }
128                >
129                        <ProgressBar
130                                className={ styles[ 'progress-bar' ] }
131                                size="small"
132                                progress={ uploadProgress }
133                        />
134                        <Text variant={ isRow ? 'body-extra-small' : 'body' } className={ styles[ 'upload-text' ] }>
135                                { infoText }
136                        </Text>
137                </div>
138        );
139};
140
141const ProcessingThumbnail = ( { isRow = false }: { isRow?: boolean } ) => (
142        <div className={ styles[ 'custom-thumbnail' ] }>
143                <Text variant={ isRow ? 'body-extra-small' : 'body' } className={ styles.pulse }>
144                        { __( 'Processing', 'jetpack-videopress-pkg' ) }
145                </Text>
146        </div>
147);
148
149/**
150 * React component to display video thumbnail.
151 *
152 * @param {VideoThumbnailProps} props - Component props.
153 * @returns {React.ReactNode} - VideoThumbnail react component.
154 */
155const VideoThumbnail = forwardRef< HTMLDivElement, VideoThumbnailProps >(
156        (
157                {
158                        className,
159                        thumbnail: defaultThumbnail,
160                        duration,
161                        editable,
162                        blankIconSize = 96,
163                        loading = false,
164                        uploading = false,
165                        processing = false,
166                        onUseDefaultThumbnail,
167                        onSelectFromVideo,
168                        onUploadImage,
169                        uploadProgress,
170                        isRow = false,
171                },
172                ref
173        ) => {
174                const [ isSmall ] = useBreakpointMatch( 'sm' );
175
176                // Mapping thumbnail (Ordered by priority)
177                let thumbnail = defaultThumbnail;
178                thumbnail = loading ? <Placeholder /> : thumbnail;
179                thumbnail = uploading ? (
180                        <UploadingThumbnail isRow={ isRow } uploadProgress={ uploadProgress } />
181                ) : (
182                        thumbnail
183                );
184                thumbnail = processing ? <ProcessingThumbnail isRow={ isRow } /> : thumbnail;
185
186                thumbnail =
187                        typeof thumbnail === 'string' && thumbnail !== '' ? (
188                                <img src={ thumbnail } alt={ __( 'Video thumbnail', 'jetpack-videopress-pkg' ) } />
189                        ) : (
190                                thumbnail
191                        );
192
193                /** If the thumbnail is not set, use the placeholder with an icon */
194                thumbnail = thumbnail ? (
195                        thumbnail
196                ) : (
197                        <div className={ styles[ 'thumbnail-blank' ] }>
198                                <Icon icon={ video } size={ blankIconSize } />
199                        </div>
200                );
201
202                return (
203                        <div
204                                className={ classnames( className, styles.thumbnail, {
205                                        [ styles[ 'is-small' ] ]: isSmall,
206                                } ) }
207                                ref={ ref }
208                        >
209                                { Boolean( thumbnail ) && editable && (
210                                        <VideoThumbnailDropdown
211                                                onUseDefaultThumbnail={ onUseDefaultThumbnail }
212                                                onSelectFromVideo={ onSelectFromVideo }
213                                                onUploadImage={ onUploadImage }
214                                        />
215                                ) }
216                                { Number.isFinite( duration ) && (
217                                        <div className={ styles[ 'video-thumbnail-duration' ] }>
218                                                <Text variant="body-small" component="div">
219                                                        { duration >= 3600 * 1000
220                                                                ? gmdateI18n( 'H:i:s', new Date( duration ) )
221                                                                : gmdateI18n( 'i:s', new Date( duration ) ) }
222                                                </Text>
223                                        </div>
224                                ) }
225
226                                <div className={ styles[ 'thumbnail-placeholder' ] }>{ thumbnail }</div>
227                        </div>
228                );
229        }
230);
231
232export default VideoThumbnail;
Note: See TracBrowser for help on using the repository browser.