sanity-plugin-mux-input 3.0.4 → 3.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -2
- package/dist/index.cjs +2876 -4400
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +134 -193
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +134 -193
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2877 -4401
- package/dist/index.js.map +1 -1
- package/package.json +36 -36
- package/src/_exports/index.ts +1 -1
- package/src/actions/assets.ts +5 -5
- package/src/actions/secrets.ts +5 -6
- package/src/actions/upload.ts +32 -34
- package/src/components/AddCaptionDialog.tsx +3 -3
- package/src/components/ConfigureApi.tsx +7 -7
- package/src/components/DraggableWatermark.tsx +15 -7
- package/src/components/EditCaptionDialog.tsx +6 -5
- package/src/components/EditThumbnailDialog.tsx +4 -5
- package/src/components/ErrorBoundaryCard.tsx +1 -0
- package/src/components/FileInputButton.tsx +1 -1
- package/src/components/FileInputMenuItem.tsx +10 -10
- package/src/components/ImportVideosFromMux.tsx +0 -3
- package/src/components/MuxLogo.tsx +1 -1
- package/src/components/Onboard.tsx +1 -1
- package/src/components/PageSelector.tsx +1 -1
- package/src/components/Player.styled.tsx +0 -44
- package/src/components/Player.tsx +1 -1
- package/src/components/PlayerActionsMenu.tsx +3 -2
- package/src/components/ResyncMetadata.tsx +4 -6
- package/src/components/SelectAsset.tsx +2 -2
- package/src/components/SelectSortOptions.tsx +3 -3
- package/src/components/TextTracksEditor.tsx +2 -2
- package/src/components/TextTracksManager.tsx +5 -4
- package/src/components/UploadConfiguration.tsx +17 -15
- package/src/components/UploadPlaceholder.tsx +1 -1
- package/src/components/UploadProgress.tsx +4 -4
- package/src/components/Uploader.styled.tsx +1 -2
- package/src/components/Uploader.tsx +15 -14
- package/src/components/VideoDetails/DeleteDialog.tsx +2 -1
- package/src/components/VideoDetails/VideoDetails.tsx +3 -3
- package/src/components/VideoDetails/useVideoDetails.ts +2 -2
- package/src/components/VideoInBrowser.tsx +1 -1
- package/src/components/VideoMetadata.tsx +1 -1
- package/src/components/VideoPlayer.tsx +12 -6
- package/src/components/VideoThumbnail.tsx +4 -3
- package/src/components/VideosBrowser.tsx +1 -1
- package/src/components/documentPreview/DocumentPreview.tsx +4 -3
- package/src/components/documentPreview/PaneItemPreview.tsx +5 -12
- package/src/components/uploadConfiguration/PlaybackPolicy.tsx +3 -3
- package/src/components/uploadConfiguration/PlaybackPolicyOption.tsx +2 -2
- package/src/components/uploadConfiguration/PlaybackPolicyWarning.tsx +1 -1
- package/src/components/uploadConfiguration/ResolutionTierSelector.tsx +2 -2
- package/src/components/uploadConfiguration/StaticRenditionSelector.tsx +4 -4
- package/src/components/withFocusRing/withFocusRing.ts +1 -1
- package/src/context/DialogStateContext.tsx +3 -6
- package/src/context/DrmPlaybackWarningContext.tsx +14 -10
- package/src/hooks/useAccessControl.ts +1 -1
- package/src/hooks/useAssetDocumentValues.ts +2 -2
- package/src/hooks/useAssets.ts +11 -6
- package/src/hooks/useCancelUpload.ts +2 -2
- package/src/hooks/useDocReferences.ts +2 -2
- package/src/hooks/useFetchFileSize.ts +4 -3
- package/src/hooks/useImportMuxAssets.ts +3 -3
- package/src/hooks/useInView.ts +3 -4
- package/src/hooks/useMediaMetadata.ts +5 -4
- package/src/hooks/useMuxAssets.ts +15 -15
- package/src/hooks/useMuxPolling.ts +6 -3
- package/src/hooks/useResyncAsset.ts +1 -1
- package/src/hooks/useResyncMuxMetadata.ts +4 -11
- package/src/hooks/useSaveSecrets.ts +4 -4
- package/src/hooks/useSecretsDocumentValues.ts +1 -1
- package/src/util/asserters.ts +0 -13
- package/src/util/convertWatermarkToMux.ts +4 -4
- package/src/util/createUrlParamsObject.ts +3 -3
- package/src/util/extractFiles.ts +3 -3
- package/src/util/formatBytes.ts +0 -1
- package/src/util/formatSeconds.ts +0 -1
- package/src/util/generateJwt.ts +3 -3
- package/src/util/getAnimatedPosterSrc.ts +1 -1
- package/src/util/getPlaybackPolicy.ts +6 -6
- package/src/util/getPosterSrc.ts +1 -1
- package/src/util/pluginVersion.ts +5 -1
- package/src/util/readSecrets.ts +1 -1
- package/src/util/textTracks.ts +5 -5
- package/src/util/tryWithSuspend.ts +1 -1
- package/src/util/types.ts +2 -32
- package/src/components/InputError.tsx +0 -17
- package/src/components/documentPreview/paneItemTypes.ts +0 -7
- package/src/util/areSecretsSignable.ts +0 -5
- package/src/util/getStoryboardSrc.ts +0 -27
- package/src/util/isSigned.ts +0 -20
|
@@ -24,7 +24,7 @@ export default function EditThumbnailDialog({asset, currentTime = 0}: Props) {
|
|
|
24
24
|
const dialogId = `EditThumbnailDialog${useId()}`
|
|
25
25
|
|
|
26
26
|
const [timeFormatted, setTimeFormatted] = useState<string>(() =>
|
|
27
|
-
formatSecondsToHHMMSS(currentTime)
|
|
27
|
+
formatSecondsToHHMMSS(currentTime),
|
|
28
28
|
)
|
|
29
29
|
const [nextTime, setNextTime] = useState<number>(currentTime)
|
|
30
30
|
const [inputError, setInputError] = useState<string>('')
|
|
@@ -35,17 +35,16 @@ export default function EditThumbnailDialog({asset, currentTime = 0}: Props) {
|
|
|
35
35
|
const handleSave = () => {
|
|
36
36
|
setSaving(true)
|
|
37
37
|
client
|
|
38
|
-
.patch(asset._id
|
|
38
|
+
.patch(asset._id)
|
|
39
39
|
.set({thumbTime: nextTime})
|
|
40
40
|
.commit({returnDocuments: false})
|
|
41
|
-
.then(() =>
|
|
41
|
+
.then(() => setDialogState(false))
|
|
42
42
|
.catch(setSaveThumbnailError)
|
|
43
|
-
.finally(() =>
|
|
43
|
+
.finally(() => setSaving(false))
|
|
44
44
|
}
|
|
45
45
|
const width = 300 * getDevicePixelRatio({maxDpr: 2})
|
|
46
46
|
|
|
47
47
|
if (saveThumbnailError) {
|
|
48
|
-
// eslint-disable-next-line no-warning-comments
|
|
49
48
|
// @TODO handle errors more gracefully
|
|
50
49
|
throw saveThumbnailError
|
|
51
50
|
}
|
|
@@ -16,6 +16,7 @@ function ErrorBoundaryCard(props: Props) {
|
|
|
16
16
|
const {push: pushToast} = useToast()
|
|
17
17
|
const errorRef = useRef(null)
|
|
18
18
|
const {ErrorBoundary, didCatch, error, reset} = useErrorBoundary({
|
|
19
|
+
// oxlint-disable-next-line no-unstable-nested-components
|
|
19
20
|
onDidCatch: (err, errorInfo) => {
|
|
20
21
|
console.group(err.toString())
|
|
21
22
|
console.groupCollapsed('console.error')
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {Box, ButtonProps, Flex, Text} from '@sanity/ui'
|
|
2
|
-
import
|
|
1
|
+
import {Box, type ButtonProps, Flex, Text} from '@sanity/ui'
|
|
2
|
+
import {isValidElement, useId, forwardRef, useCallback} from 'react'
|
|
3
3
|
import {isValidElementType} from 'react-is'
|
|
4
4
|
|
|
5
5
|
import {FileButton} from './FileInputMenuItem.styled'
|
|
@@ -12,13 +12,13 @@ export interface FileInputMenuItemProps extends ButtonProps {
|
|
|
12
12
|
disabled?: boolean
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
export const FileInputMenuItem =
|
|
15
|
+
export const FileInputMenuItem = forwardRef(function FileInputMenuItem(
|
|
16
16
|
props: FileInputMenuItemProps &
|
|
17
17
|
Omit<React.HTMLProps<HTMLButtonElement>, 'as' | 'ref' | 'type' | 'value' | 'onSelect'>,
|
|
18
|
-
forwardedRef: React.ForwardedRef<HTMLInputElement
|
|
18
|
+
forwardedRef: React.ForwardedRef<HTMLInputElement>,
|
|
19
19
|
) {
|
|
20
20
|
const {
|
|
21
|
-
icon,
|
|
21
|
+
icon: Icon,
|
|
22
22
|
id: idProp,
|
|
23
23
|
accept,
|
|
24
24
|
capture,
|
|
@@ -34,23 +34,23 @@ export const FileInputMenuItem = React.forwardRef(function FileInputMenuItem(
|
|
|
34
34
|
const idHook = useId()
|
|
35
35
|
const id = idProp || idHook
|
|
36
36
|
|
|
37
|
-
const handleChange =
|
|
37
|
+
const handleChange = useCallback(
|
|
38
38
|
(event: React.ChangeEvent<HTMLInputElement>) => {
|
|
39
39
|
if (onSelect && event.target.files) {
|
|
40
40
|
onSelect(Array.from(event.target.files))
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
|
-
[onSelect]
|
|
43
|
+
[onSelect],
|
|
44
44
|
)
|
|
45
45
|
|
|
46
46
|
const content = (
|
|
47
47
|
<Flex align="center" justify="flex-start">
|
|
48
48
|
{/* Icon */}
|
|
49
|
-
{
|
|
49
|
+
{Icon && (
|
|
50
50
|
<Box marginRight={text ? space : undefined}>
|
|
51
51
|
<Text size={fontSize}>
|
|
52
|
-
{isValidElement(
|
|
53
|
-
{isValidElementType(
|
|
52
|
+
{isValidElement(Icon) && Icon}
|
|
53
|
+
{isValidElementType(Icon) && <Icon />}
|
|
54
54
|
</Text>
|
|
55
55
|
</Box>
|
|
56
56
|
)}
|
|
@@ -98,7 +98,6 @@ function MissingAsset({
|
|
|
98
98
|
)
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
// eslint-disable-next-line complexity
|
|
102
101
|
function ImportVideosDialog(props: ReturnType<typeof useImportMuxAssets>) {
|
|
103
102
|
const {importState} = props
|
|
104
103
|
|
|
@@ -333,10 +332,8 @@ export default function ImportVideosFromMux() {
|
|
|
333
332
|
}
|
|
334
333
|
|
|
335
334
|
if (importAssets.dialogOpen) {
|
|
336
|
-
// eslint-disable-next-line consistent-return
|
|
337
335
|
return <ImportVideosDialog {...importAssets} />
|
|
338
336
|
}
|
|
339
337
|
|
|
340
|
-
// eslint-disable-next-line consistent-return
|
|
341
338
|
return <Button mode="bleed" text="Import from Mux" onClick={importAssets.openDialog} />
|
|
342
339
|
}
|
|
@@ -4,7 +4,7 @@ import {useCallback} from 'react'
|
|
|
4
4
|
|
|
5
5
|
import {useAccessControl} from '../hooks/useAccessControl'
|
|
6
6
|
import type {SetDialogState} from '../hooks/useDialogState'
|
|
7
|
-
import {PluginConfig} from '../util/types'
|
|
7
|
+
import {type PluginConfig} from '../util/types'
|
|
8
8
|
import MuxLogo from './MuxLogo'
|
|
9
9
|
|
|
10
10
|
interface OnboardProps {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {ChevronLeftIcon, ChevronRightIcon} from '@sanity/icons'
|
|
2
2
|
import {Button, Label} from '@sanity/ui'
|
|
3
|
-
import {Dispatch, SetStateAction, useEffect} from 'react'
|
|
3
|
+
import {type Dispatch, type SetStateAction, useEffect} from 'react'
|
|
4
4
|
|
|
5
5
|
const PageSelector = (props: {
|
|
6
6
|
page: number
|
|
@@ -1,30 +1,5 @@
|
|
|
1
|
-
import {Suspense, useState} from 'react'
|
|
2
1
|
import {styled} from 'styled-components'
|
|
3
2
|
|
|
4
|
-
import {useClient} from '../hooks/useClient'
|
|
5
|
-
import {getStoryboardSrc} from '../util/getStoryboardSrc'
|
|
6
|
-
import type {VideoAssetDocument} from '../util/types'
|
|
7
|
-
|
|
8
|
-
export const StyledCenterControls = styled.div`
|
|
9
|
-
&& {
|
|
10
|
-
--media-background-color: transparent;
|
|
11
|
-
--media-button-icon-width: 100%;
|
|
12
|
-
--media-button-icon-height: auto;
|
|
13
|
-
pointer-events: none;
|
|
14
|
-
width: 100%;
|
|
15
|
-
display: flex;
|
|
16
|
-
flex-flow: row;
|
|
17
|
-
align-items: center;
|
|
18
|
-
justify-content: center;
|
|
19
|
-
media-play-button {
|
|
20
|
-
--media-control-background: transparent;
|
|
21
|
-
--media-control-hover-background: transparent;
|
|
22
|
-
padding: 0;
|
|
23
|
-
width: max(27px, min(9%, 90px));
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
`
|
|
27
|
-
|
|
28
3
|
export const TopControls = styled.div`
|
|
29
4
|
position: absolute;
|
|
30
5
|
top: 0;
|
|
@@ -34,22 +9,3 @@ export const TopControls = styled.div`
|
|
|
34
9
|
height: auto;
|
|
35
10
|
}
|
|
36
11
|
`
|
|
37
|
-
|
|
38
|
-
export interface PosterImageProps {
|
|
39
|
-
asset: VideoAssetDocument
|
|
40
|
-
}
|
|
41
|
-
export interface ThumbnailsMetadataTrackProps {
|
|
42
|
-
asset: VideoAssetDocument
|
|
43
|
-
}
|
|
44
|
-
export function ThumbnailsMetadataTrack({asset}: ThumbnailsMetadataTrackProps) {
|
|
45
|
-
const client = useClient()
|
|
46
|
-
// Why useState instead of useMemo? Because we really really only want to run it exactly once and useMemo doesn't make that guarantee
|
|
47
|
-
const [src] = useState<string>(() => getStoryboardSrc({asset, client}))
|
|
48
|
-
|
|
49
|
-
return (
|
|
50
|
-
/* We use Suspense here because `getStoryboardSrc` uses suspend() under the hood */
|
|
51
|
-
<Suspense fallback={null}>
|
|
52
|
-
<track label="thumbnails" default kind="metadata" src={src} />
|
|
53
|
-
</Suspense>
|
|
54
|
-
)
|
|
55
|
-
}
|
|
@@ -33,6 +33,7 @@ const Player = ({asset, buttons, readOnly, onChange, config}: Props) => {
|
|
|
33
33
|
|
|
34
34
|
return true
|
|
35
35
|
}, [asset])
|
|
36
|
+
// oxlint-disable-next-line react/react-compiler
|
|
36
37
|
const isPreparingStaticRenditions = useMemo<boolean>(() => {
|
|
37
38
|
// Legacy: If static_renditions has a status field, it was created with mp4_support (deprecated)
|
|
38
39
|
// We don't process this old format, just return false
|
|
@@ -70,7 +71,6 @@ const Player = ({asset, buttons, readOnly, onChange, config}: Props) => {
|
|
|
70
71
|
useEffect(() => {
|
|
71
72
|
if (asset?.status === 'errored') {
|
|
72
73
|
handleCancelUpload()
|
|
73
|
-
// eslint-disable-next-line no-warning-comments
|
|
74
74
|
// @TODO use better error handling
|
|
75
75
|
throw new Error(asset.data?.errors?.messages?.join(' '))
|
|
76
76
|
}
|
|
@@ -61,7 +61,7 @@ function PlayerActionsMenu(
|
|
|
61
61
|
setDialogState: SetDialogState
|
|
62
62
|
config: PluginConfig
|
|
63
63
|
accept: string
|
|
64
|
-
}
|
|
64
|
+
},
|
|
65
65
|
) {
|
|
66
66
|
const {asset, readOnly, dialogState, setDialogState, onChange, onSelect, accept} = props
|
|
67
67
|
const [open, setOpen] = useState(false)
|
|
@@ -79,13 +79,14 @@ function PlayerActionsMenu(
|
|
|
79
79
|
|
|
80
80
|
useEffect(() => {
|
|
81
81
|
if (open && dialogState) {
|
|
82
|
+
// oxlint-disable-next-line react/react-compiler
|
|
82
83
|
setOpen(false)
|
|
83
84
|
}
|
|
84
85
|
}, [dialogState, open])
|
|
85
86
|
|
|
86
87
|
useClickOutsideEvent(
|
|
87
88
|
() => setOpen(false),
|
|
88
|
-
() => [menuElement]
|
|
89
|
+
() => [menuElement],
|
|
89
90
|
)
|
|
90
91
|
|
|
91
92
|
return (
|
|
@@ -69,7 +69,7 @@ function ResyncMetadataDialog(props: ReturnType<typeof useResyncMuxMetadata>) {
|
|
|
69
69
|
const videosToUpdate = props.matchedAssets?.filter((m) => m.muxAsset).length || 0
|
|
70
70
|
const videosWithEmptyOrPlaceholder =
|
|
71
71
|
props.matchedAssets?.filter(
|
|
72
|
-
(m) => m.muxAsset && m.muxTitle && isEmptyOrPlaceholderTitle(m.currentTitle, m.muxAsset.id)
|
|
72
|
+
(m) => m.muxAsset && m.muxTitle && isEmptyOrPlaceholderTitle(m.currentTitle, m.muxAsset.id),
|
|
73
73
|
).length || 0
|
|
74
74
|
|
|
75
75
|
const hasEmptyTitles = videosWithEmptyOrPlaceholder > 0
|
|
@@ -84,13 +84,13 @@ function ResyncMetadataDialog(props: ReturnType<typeof useResyncMuxMetadata>) {
|
|
|
84
84
|
const handleSync = () => {
|
|
85
85
|
switch (selectedOption) {
|
|
86
86
|
case 'fillEmpty':
|
|
87
|
-
props.syncOnlyEmpty()
|
|
87
|
+
void props.syncOnlyEmpty()
|
|
88
88
|
break
|
|
89
89
|
case 'syncTitles':
|
|
90
|
-
props.syncAllVideos()
|
|
90
|
+
void props.syncAllVideos()
|
|
91
91
|
break
|
|
92
92
|
case 'fullResync':
|
|
93
|
-
props.syncFullData()
|
|
93
|
+
void props.syncFullData()
|
|
94
94
|
break
|
|
95
95
|
default:
|
|
96
96
|
break
|
|
@@ -271,10 +271,8 @@ export default function ResyncMetadata() {
|
|
|
271
271
|
}
|
|
272
272
|
|
|
273
273
|
if (resyncMetadata.dialogOpen) {
|
|
274
|
-
// eslint-disable-next-line consistent-return
|
|
275
274
|
return <ResyncMetadataDialog {...resyncMetadata} />
|
|
276
275
|
}
|
|
277
276
|
|
|
278
|
-
// eslint-disable-next-line consistent-return
|
|
279
277
|
return <Button mode="bleed" text="Sync with Mux" onClick={resyncMetadata.openDialog} />
|
|
280
278
|
}
|
|
@@ -27,12 +27,12 @@ export default function SelectAssets({
|
|
|
27
27
|
PatchEvent.from([
|
|
28
28
|
setIfMissing({asset: {}, _type: 'mux.video'}),
|
|
29
29
|
set({_type: 'reference', _weak: true, _ref: chosenAsset._id}, ['asset']),
|
|
30
|
-
])
|
|
30
|
+
]),
|
|
31
31
|
)
|
|
32
32
|
}
|
|
33
33
|
setDialogState(false)
|
|
34
34
|
},
|
|
35
|
-
[onChange, setDialogState, selectedAsset]
|
|
35
|
+
[onChange, setDialogState, selectedAsset],
|
|
36
36
|
)
|
|
37
37
|
|
|
38
38
|
return <VideosBrowser onSelect={handleSelect} config={config} />
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {SortIcon} from '@sanity/icons'
|
|
2
|
-
import {Button, Menu, MenuButton, MenuItem, PopoverProps} from '@sanity/ui'
|
|
2
|
+
import {Button, Menu, MenuButton, MenuItem, type PopoverProps} from '@sanity/ui'
|
|
3
3
|
import {useId} from 'react'
|
|
4
4
|
|
|
5
|
-
import {ASSET_SORT_OPTIONS, SortOption} from '../hooks/useAssets'
|
|
5
|
+
import {ASSET_SORT_OPTIONS, type SortOption} from '../hooks/useAssets'
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
const CONTEXT_MENU_POPOVER_PROPS: PopoverProps = {
|
|
8
8
|
constrainSize: true,
|
|
9
9
|
placement: 'bottom',
|
|
10
10
|
portal: true,
|
|
@@ -2,10 +2,10 @@ import {TranslateIcon} from '@sanity/icons'
|
|
|
2
2
|
import {Autocomplete, Box, Card, Checkbox, Flex, Stack, Text} from '@sanity/ui'
|
|
3
3
|
import {uuid} from '@sanity/uuid'
|
|
4
4
|
import LanguagesList from 'iso-639-1'
|
|
5
|
-
import {Dispatch} from 'react'
|
|
5
|
+
import {type Dispatch} from 'react'
|
|
6
6
|
import {FormField} from 'sanity'
|
|
7
7
|
|
|
8
|
-
import {type PluginConfig, SUPPORTED_MUX_LANGUAGES, UploadTextTrack} from '../util/types'
|
|
8
|
+
import {type PluginConfig, SUPPORTED_MUX_LANGUAGES, type UploadTextTrack} from '../util/types'
|
|
9
9
|
|
|
10
10
|
const ALL_LANGUAGE_CODES = LanguagesList.getAllCodes().map((code) => ({
|
|
11
11
|
value: code,
|
|
@@ -225,7 +225,7 @@ export default function TextTracksManager({
|
|
|
225
225
|
const activeTracks = realTracks.filter(
|
|
226
226
|
(track) =>
|
|
227
227
|
track.id &&
|
|
228
|
-
(track.status === 'ready' || track.status === 'preparing' || track.status === 'errored')
|
|
228
|
+
(track.status === 'ready' || track.status === 'preparing' || track.status === 'errored'),
|
|
229
229
|
)
|
|
230
230
|
|
|
231
231
|
const allTracks = useMemo(() => {
|
|
@@ -260,7 +260,7 @@ export default function TextTracksManager({
|
|
|
260
260
|
|
|
261
261
|
const isTrackAlreadyInRealTracks = (
|
|
262
262
|
addedTrack: MuxTextTrack,
|
|
263
|
-
realTracksList: MuxTextTrack[]
|
|
263
|
+
realTracksList: MuxTextTrack[],
|
|
264
264
|
) => {
|
|
265
265
|
if (!addedTrack.id) return false
|
|
266
266
|
if (addedTrack.id.startsWith('generating-')) {
|
|
@@ -306,6 +306,7 @@ export default function TextTracksManager({
|
|
|
306
306
|
}
|
|
307
307
|
})
|
|
308
308
|
|
|
309
|
+
// oxlint-disable-next-line react/react-compiler
|
|
309
310
|
setAutogeneratedTrackIds((prev) => {
|
|
310
311
|
let hasNew = false
|
|
311
312
|
const updated = new Set(prev)
|
|
@@ -335,7 +336,7 @@ export default function TextTracksManager({
|
|
|
335
336
|
|
|
336
337
|
const isMockTrackReplaced = (
|
|
337
338
|
mockTrack: MuxTextTrack,
|
|
338
|
-
fetchedTracksList: MuxTextTrack[]
|
|
339
|
+
fetchedTracksList: MuxTextTrack[],
|
|
339
340
|
) => {
|
|
340
341
|
if (!mockTrack.id || !mockTrack.id.startsWith('generating-')) {
|
|
341
342
|
return false
|
|
@@ -423,7 +424,7 @@ export default function TextTracksManager({
|
|
|
423
424
|
const visibleTracks = allTracks
|
|
424
425
|
.filter(
|
|
425
426
|
(track) =>
|
|
426
|
-
track.status === 'ready' || track.status === 'preparing' || track.status === 'errored'
|
|
427
|
+
track.status === 'ready' || track.status === 'preparing' || track.status === 'errored',
|
|
427
428
|
)
|
|
428
429
|
.sort((a, b) => {
|
|
429
430
|
const orderA = trackActivityOrder.get(a.id) || 0
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
type SupportedMuxLanguage,
|
|
23
23
|
type UploadConfig,
|
|
24
24
|
type UploadTextTrack,
|
|
25
|
-
WatermarkConfig,
|
|
25
|
+
type WatermarkConfig,
|
|
26
26
|
} from '../util/types'
|
|
27
27
|
import DraggableWatermark, {WatermarkControls} from './DraggableWatermark'
|
|
28
28
|
import TextTracksEditor, {type TrackAction} from './TextTracksEditor'
|
|
@@ -56,7 +56,7 @@ const VIDEO_QUALITY_LEVELS = [
|
|
|
56
56
|
* If both are present, only 'highest' (and 'audio-only' if present) will be kept.
|
|
57
57
|
*/
|
|
58
58
|
function sanitizeStaticRenditions(
|
|
59
|
-
renditions: StaticRenditionResolution[]
|
|
59
|
+
renditions: StaticRenditionResolution[],
|
|
60
60
|
): StaticRenditionResolution[] {
|
|
61
61
|
const hasHighest = renditions.includes('highest')
|
|
62
62
|
const hasSpecificResolutions = renditions.some((r) => r !== 'highest' && r !== 'audio-only')
|
|
@@ -91,6 +91,7 @@ export default function UploadConfiguration({
|
|
|
91
91
|
const [watermarkValidationError, setWatermarkValidationError] = useState<string | null>(null)
|
|
92
92
|
const watermarkPreviewContainerRef = useRef<HTMLDivElement>(null)
|
|
93
93
|
const watermarkPreviewVideoRef = useRef<HTMLVideoElement>(null)
|
|
94
|
+
// oxlint-disable-next-line react/react-compiler
|
|
94
95
|
const autoTextTracks = useRef<NonNullable<UploadConfig['text_tracks']>>(
|
|
95
96
|
pluginConfig.video_quality === 'plus' && pluginConfig.defaultAutogeneratedSubtitleLang
|
|
96
97
|
? [
|
|
@@ -101,10 +102,11 @@ export default function UploadConfiguration({
|
|
|
101
102
|
name: LanguagesList.getNativeName(pluginConfig.defaultAutogeneratedSubtitleLang),
|
|
102
103
|
} satisfies AutogeneratedTextTrack,
|
|
103
104
|
]
|
|
104
|
-
: []
|
|
105
|
+
: [],
|
|
105
106
|
).current
|
|
106
107
|
|
|
107
108
|
const [config, dispatch] = useReducer(
|
|
109
|
+
// oxlint-disable-next-line react/react-compiler
|
|
108
110
|
(prev: UploadConfig, action: UploadConfigurationStateAction) => {
|
|
109
111
|
switch (action.action) {
|
|
110
112
|
case 'video_quality':
|
|
@@ -143,7 +145,6 @@ export default function UploadConfiguration({
|
|
|
143
145
|
case 'track': {
|
|
144
146
|
const text_tracks = [...prev.text_tracks]
|
|
145
147
|
const target_track_i = text_tracks.findIndex(({_id}) => _id === action.id)
|
|
146
|
-
// eslint-disable-next-line default-case
|
|
147
148
|
switch (action.subAction) {
|
|
148
149
|
case 'add':
|
|
149
150
|
// Exit early if track already exists
|
|
@@ -180,7 +181,7 @@ export default function UploadConfiguration({
|
|
|
180
181
|
drm_policy: pluginConfig.defaultDrm && !!secrets.drmConfigId,
|
|
181
182
|
normalize_audio: pluginConfig.normalize_audio,
|
|
182
183
|
text_tracks: autoTextTracks,
|
|
183
|
-
} as UploadConfig
|
|
184
|
+
} as UploadConfig,
|
|
184
185
|
)
|
|
185
186
|
|
|
186
187
|
// Video validations
|
|
@@ -190,7 +191,7 @@ export default function UploadConfiguration({
|
|
|
190
191
|
|
|
191
192
|
const {fileSize, isLoadingFileSize, canSkipFileSizeValidation} = useFetchFileSize(
|
|
192
193
|
stagedUpload,
|
|
193
|
-
MAX_FILE_SIZE
|
|
194
|
+
MAX_FILE_SIZE,
|
|
194
195
|
)
|
|
195
196
|
const {videoAssetMetadata, setVideoAssetMetadata, isLoadingMetadata} =
|
|
196
197
|
useMediaMetadata(stagedUpload)
|
|
@@ -205,7 +206,7 @@ export default function UploadConfiguration({
|
|
|
205
206
|
const validateDuration = (duration: number) => {
|
|
206
207
|
if (MAX_DURATION_SECONDS && duration > MAX_DURATION_SECONDS) {
|
|
207
208
|
setValidationError(
|
|
208
|
-
`Video duration (${formatSeconds(duration)}) exceeds maximum allowed duration of ${formatSeconds(MAX_DURATION_SECONDS)}
|
|
209
|
+
`Video duration (${formatSeconds(duration)}) exceeds maximum allowed duration of ${formatSeconds(MAX_DURATION_SECONDS)}`,
|
|
209
210
|
)
|
|
210
211
|
return false
|
|
211
212
|
}
|
|
@@ -218,7 +219,7 @@ export default function UploadConfiguration({
|
|
|
218
219
|
}
|
|
219
220
|
|
|
220
221
|
setValidationError(
|
|
221
|
-
`File size (${formatBytes(size)}) exceeds maximum allowed size of ${formatBytes(MAX_FILE_SIZE)}
|
|
222
|
+
`File size (${formatBytes(size)}) exceeds maximum allowed size of ${formatBytes(MAX_FILE_SIZE)}`,
|
|
222
223
|
)
|
|
223
224
|
return false
|
|
224
225
|
}
|
|
@@ -242,6 +243,7 @@ export default function UploadConfiguration({
|
|
|
242
243
|
valid = valid && validateDrmAvailability(videoAssetMetadata.isAudioOnly)
|
|
243
244
|
}
|
|
244
245
|
if (valid) {
|
|
246
|
+
// oxlint-disable-next-line react/react-compiler
|
|
245
247
|
setValidationError(null)
|
|
246
248
|
}
|
|
247
249
|
}, [
|
|
@@ -276,7 +278,7 @@ export default function UploadConfiguration({
|
|
|
276
278
|
const basicConfig = config.video_quality !== 'plus' && config.video_quality !== 'premium'
|
|
277
279
|
const playbackPolicySelected = config.public_policy || config.signed_policy || config.drm_policy
|
|
278
280
|
const maxSupportedResolution = RESOLUTION_TIERS.findIndex(
|
|
279
|
-
(rt) => rt.value === pluginConfig.max_resolution_tier
|
|
281
|
+
(rt) => rt.value === pluginConfig.max_resolution_tier,
|
|
280
282
|
)
|
|
281
283
|
return (
|
|
282
284
|
<Dialog
|
|
@@ -314,11 +316,11 @@ export default function UploadConfiguration({
|
|
|
314
316
|
<DocumentVideoIcon fontSize="2em" />
|
|
315
317
|
<Stack space={2}>
|
|
316
318
|
<Text textOverflow="ellipsis" as="h2" size={3}>
|
|
317
|
-
{stagedUpload.type === 'file' ? stagedUpload.files[0]
|
|
319
|
+
{stagedUpload.type === 'file' ? stagedUpload.files[0]!.name : stagedUpload.url}
|
|
318
320
|
</Text>
|
|
319
321
|
<Text as="p" size={1} muted>
|
|
320
322
|
{stagedUpload.type === 'file'
|
|
321
|
-
? `Direct File Upload (${formatBytes(stagedUpload.files[0]
|
|
323
|
+
? `Direct File Upload (${formatBytes(stagedUpload.files[0]!.size)})`
|
|
322
324
|
: (() => {
|
|
323
325
|
if (videoAssetMetadata?.size) {
|
|
324
326
|
return `File From URL (${formatBytes(videoAssetMetadata.size)})`
|
|
@@ -456,7 +458,7 @@ export default function UploadConfiguration({
|
|
|
456
458
|
|
|
457
459
|
function setAdvancedPlaybackPolicy(
|
|
458
460
|
config: UploadConfig,
|
|
459
|
-
secrets: Secrets
|
|
461
|
+
secrets: Secrets,
|
|
460
462
|
): MuxNewAssetSettings['advanced_playback_policies'] {
|
|
461
463
|
const advanced_playback_policies: MuxNewAssetSettings['advanced_playback_policies'] = []
|
|
462
464
|
if (config.public_policy) {
|
|
@@ -481,7 +483,7 @@ function setAdvancedPlaybackPolicy(
|
|
|
481
483
|
function formatUploadConfig(
|
|
482
484
|
config: UploadConfig,
|
|
483
485
|
secrets: Secrets,
|
|
484
|
-
options?: {videoAspectRatio?: number | null}
|
|
486
|
+
options?: {videoAspectRatio?: number | null},
|
|
485
487
|
): {
|
|
486
488
|
settings: MuxNewAssetSettings
|
|
487
489
|
watermark?: WatermarkConfig
|
|
@@ -512,7 +514,7 @@ function formatUploadConfig(
|
|
|
512
514
|
}
|
|
513
515
|
return acc
|
|
514
516
|
},
|
|
515
|
-
[] as NonNullable<MuxNewAssetSettings['input']
|
|
517
|
+
[] as NonNullable<MuxNewAssetSettings['input']>,
|
|
516
518
|
),
|
|
517
519
|
]
|
|
518
520
|
|
|
@@ -633,7 +635,7 @@ const WatermarkPreview = memo(function WatermarkPreview({
|
|
|
633
635
|
useEffect(() => {
|
|
634
636
|
if (videoRef.current && stagedUpload.type === 'file') {
|
|
635
637
|
const file = stagedUpload.files[0]
|
|
636
|
-
const url = URL.createObjectURL(file)
|
|
638
|
+
const url = URL.createObjectURL(file!)
|
|
637
639
|
videoRef.current.src = url
|
|
638
640
|
|
|
639
641
|
return () => {
|
|
@@ -4,7 +4,7 @@ import {useCallback} from 'react'
|
|
|
4
4
|
|
|
5
5
|
import {useAccessControl} from '../hooks/useAccessControl'
|
|
6
6
|
import type {SetDialogState} from '../hooks/useDialogState'
|
|
7
|
-
import {PluginConfig} from '../util/types'
|
|
7
|
+
import {type PluginConfig} from '../util/types'
|
|
8
8
|
import {FileInputButton, type FileInputButtonProps} from './FileInputButton'
|
|
9
9
|
|
|
10
10
|
function formatAcceptString(accept: string): string {
|
|
@@ -4,22 +4,22 @@ import {Button, Card, Code, Flex, Inline, Stack, Text} from '@sanity/ui'
|
|
|
4
4
|
import {LinearProgress} from 'sanity'
|
|
5
5
|
import {styled} from 'styled-components'
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
const CardWrapper = styled(Card)`
|
|
8
8
|
min-height: 82px;
|
|
9
9
|
box-sizing: border-box;
|
|
10
10
|
`
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
const FlexWrapper = styled(Flex)`
|
|
13
13
|
text-overflow: ellipsis;
|
|
14
14
|
overflow: hidden;
|
|
15
15
|
`
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
const LeftSection = styled(Stack)`
|
|
18
18
|
position: relative;
|
|
19
19
|
width: 60%;
|
|
20
20
|
`
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
const CodeWrapper = styled(Code)`
|
|
23
23
|
position: relative;
|
|
24
24
|
width: 100%;
|
|
25
25
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable no-nested-ternary */
|
|
2
1
|
import {Card, type CardTone} from '@sanity/ui'
|
|
3
2
|
import React, {forwardRef, useCallback, useRef} from 'react'
|
|
4
3
|
import {styled} from 'styled-components'
|
|
@@ -51,7 +50,7 @@ export const UploadCard = forwardRef<HTMLDivElement, UploadCardProps>(
|
|
|
51
50
|
{children}
|
|
52
51
|
</UploadCardWithFocusRing>
|
|
53
52
|
)
|
|
54
|
-
}
|
|
53
|
+
},
|
|
55
54
|
)
|
|
56
55
|
|
|
57
56
|
const HiddenInput = styled.input.attrs({type: 'text'})`
|