sanity-plugin-mux-input 3.0.5 → 4.0.0
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/dist/index.js +28 -28
- package/dist/index.js.map +1 -1
- package/package.json +5 -15
- package/dist/index.cjs +0 -5746
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -288
- package/dist/index.d.cts.map +0 -1
- package/sanity.json +0 -8
- package/src/_exports/index.ts +0 -73
- package/src/actions/assets.ts +0 -152
- package/src/actions/secrets.ts +0 -110
- package/src/actions/upload.ts +0 -308
- package/src/clients/upChunkObservable.ts +0 -54
- package/src/components/AddCaptionDialog.tsx +0 -440
- package/src/components/CaptionsDialog.tsx +0 -23
- package/src/components/ConfigureApi.styled.tsx +0 -19
- package/src/components/ConfigureApi.tsx +0 -296
- package/src/components/DraggableWatermark.tsx +0 -885
- package/src/components/EditCaptionDialog.tsx +0 -511
- package/src/components/EditThumbnailDialog.tsx +0 -121
- package/src/components/ErrorBoundaryCard.tsx +0 -97
- package/src/components/FileInputButton.tsx +0 -54
- package/src/components/FileInputMenuItem.styled.tsx +0 -36
- package/src/components/FileInputMenuItem.tsx +0 -85
- package/src/components/FormField.tsx +0 -38
- package/src/components/IconInfo.tsx +0 -22
- package/src/components/ImportVideosFromMux.tsx +0 -339
- package/src/components/Input.styled.tsx +0 -22
- package/src/components/Input.tsx +0 -78
- package/src/components/InputBrowser.tsx +0 -41
- package/src/components/MuxLogo.tsx +0 -42
- package/src/components/Onboard.tsx +0 -65
- package/src/components/PageSelector.tsx +0 -54
- package/src/components/Player.styled.tsx +0 -11
- package/src/components/Player.tsx +0 -117
- package/src/components/PlayerActionsMenu.tsx +0 -191
- package/src/components/ResyncMetadata.tsx +0 -278
- package/src/components/SelectAsset.tsx +0 -39
- package/src/components/SelectSortOptions.tsx +0 -45
- package/src/components/SpinnerBox.tsx +0 -16
- package/src/components/StudioTool.tsx +0 -24
- package/src/components/TextTracksEditor.tsx +0 -117
- package/src/components/TextTracksManager.tsx +0 -738
- package/src/components/UploadConfiguration.tsx +0 -696
- package/src/components/UploadPlaceholder.tsx +0 -88
- package/src/components/UploadProgress.tsx +0 -80
- package/src/components/Uploader.styled.tsx +0 -65
- package/src/components/Uploader.tsx +0 -499
- package/src/components/VideoDetails/DeleteDialog.tsx +0 -148
- package/src/components/VideoDetails/VideoDetails.tsx +0 -358
- package/src/components/VideoDetails/VideoReferences.tsx +0 -63
- package/src/components/VideoDetails/useVideoDetails.ts +0 -103
- package/src/components/VideoInBrowser.tsx +0 -245
- package/src/components/VideoMetadata.tsx +0 -45
- package/src/components/VideoPlayer.tsx +0 -241
- package/src/components/VideoThumbnail.tsx +0 -139
- package/src/components/VideosBrowser.tsx +0 -100
- package/src/components/documentPreview/DocumentPreview.tsx +0 -84
- package/src/components/documentPreview/DraftStatus.tsx +0 -34
- package/src/components/documentPreview/MissingSchemaType.tsx +0 -32
- package/src/components/documentPreview/PaneItemPreview.tsx +0 -67
- package/src/components/documentPreview/PublishedStatus.tsx +0 -35
- package/src/components/documentPreview/TimeAgo.tsx +0 -12
- package/src/components/icons/Audio.tsx +0 -13
- package/src/components/icons/Resolution.tsx +0 -12
- package/src/components/icons/StopWatch.tsx +0 -20
- package/src/components/icons/ToolIcon.tsx +0 -19
- package/src/components/uploadConfiguration/PlaybackPolicy.tsx +0 -133
- package/src/components/uploadConfiguration/PlaybackPolicyOption.tsx +0 -76
- package/src/components/uploadConfiguration/PlaybackPolicyWarning.tsx +0 -29
- package/src/components/uploadConfiguration/ResolutionTierSelector.tsx +0 -72
- package/src/components/uploadConfiguration/StaticRenditionSelector.tsx +0 -180
- package/src/components/withFocusRing/helpers.ts +0 -24
- package/src/components/withFocusRing/index.ts +0 -1
- package/src/components/withFocusRing/withFocusRing.ts +0 -30
- package/src/context/DialogStateContext.tsx +0 -33
- package/src/context/DrmPlaybackWarningContext.tsx +0 -97
- package/src/hooks/useAccessControl.ts +0 -13
- package/src/hooks/useAssetDocumentValues.ts +0 -11
- package/src/hooks/useAssets.ts +0 -73
- package/src/hooks/useCancelUpload.ts +0 -22
- package/src/hooks/useClient.ts +0 -8
- package/src/hooks/useDialogState.ts +0 -11
- package/src/hooks/useDocReferences.ts +0 -21
- package/src/hooks/useFetchFileSize.ts +0 -55
- package/src/hooks/useImportMuxAssets.ts +0 -132
- package/src/hooks/useInView.ts +0 -41
- package/src/hooks/useMediaMetadata.ts +0 -104
- package/src/hooks/useMuxAssets.ts +0 -179
- package/src/hooks/useMuxPolling.ts +0 -52
- package/src/hooks/useResyncAsset.ts +0 -110
- package/src/hooks/useResyncMuxMetadata.ts +0 -169
- package/src/hooks/useSaveSecrets.ts +0 -78
- package/src/hooks/useSecretsDocumentValues.ts +0 -38
- package/src/hooks/useSecretsFormState.ts +0 -47
- package/src/plugin.tsx +0 -31
- package/src/sanity-ui.d.ts +0 -5
- package/src/schema.ts +0 -196
- package/src/util/addKeysToMuxData.ts +0 -30
- package/src/util/asserters.ts +0 -23
- package/src/util/assetTitlePlaceholder.ts +0 -31
- package/src/util/constants.ts +0 -15
- package/src/util/convertWatermarkToMux.ts +0 -160
- package/src/util/createSearchFilter.ts +0 -76
- package/src/util/createUrlParamsObject.ts +0 -29
- package/src/util/extractFiles.ts +0 -67
- package/src/util/formatBytes.ts +0 -31
- package/src/util/formatDriveShareLink.ts +0 -64
- package/src/util/formatSeconds.ts +0 -48
- package/src/util/generateJwt.ts +0 -57
- package/src/util/getAnimatedPosterSrc.ts +0 -26
- package/src/util/getPlaybackPolicy.ts +0 -69
- package/src/util/getPosterSrc.ts +0 -28
- package/src/util/getVideoMetadata.ts +0 -23
- package/src/util/getVideoSrc.ts +0 -23
- package/src/util/parsers.ts +0 -5
- package/src/util/pluginVersion.ts +0 -5
- package/src/util/readSecrets.ts +0 -38
- package/src/util/roundPxString.ts +0 -16
- package/src/util/textTracks.ts +0 -222
- package/src/util/tryWithSuspend.ts +0 -22
- package/src/util/types.ts +0 -566
- package/v2-incompatible.js +0 -11
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import {useMemo, useState} from 'react'
|
|
2
|
-
import {
|
|
3
|
-
createHookFromObservableFactory,
|
|
4
|
-
type DocumentStore,
|
|
5
|
-
useClient,
|
|
6
|
-
useDocumentStore,
|
|
7
|
-
} from 'sanity'
|
|
8
|
-
|
|
9
|
-
import {addKeysToMuxData} from '../util/addKeysToMuxData'
|
|
10
|
-
import {isEmptyOrPlaceholderTitle} from '../util/assetTitlePlaceholder'
|
|
11
|
-
import type {VideoAssetDocument} from '../util/types'
|
|
12
|
-
import {SANITY_API_VERSION} from './useClient'
|
|
13
|
-
import useMuxAssets from './useMuxAssets'
|
|
14
|
-
import {useSecretsDocumentValues} from './useSecretsDocumentValues'
|
|
15
|
-
|
|
16
|
-
type ResyncState = 'closed' | 'idle' | 'syncing' | 'done' | 'error'
|
|
17
|
-
|
|
18
|
-
export default function useResyncMuxMetadata() {
|
|
19
|
-
const documentStore = useDocumentStore()
|
|
20
|
-
const client = useClient({
|
|
21
|
-
apiVersion: SANITY_API_VERSION,
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
const [sanityAssets, sanityAssetsLoading] = useSanityAssets(documentStore)
|
|
25
|
-
|
|
26
|
-
const secretDocumentValues = useSecretsDocumentValues()
|
|
27
|
-
const hasSecrets = !!secretDocumentValues.value.secrets?.secretKey
|
|
28
|
-
|
|
29
|
-
const [resyncError, setResyncError] = useState<unknown>()
|
|
30
|
-
const [resyncState, setResyncState] = useState<ResyncState>('closed')
|
|
31
|
-
const dialogOpen = resyncState !== 'closed'
|
|
32
|
-
|
|
33
|
-
const muxAssets = useMuxAssets({
|
|
34
|
-
client,
|
|
35
|
-
enabled: hasSecrets && dialogOpen,
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
const matchedAssets = useMemo(() => {
|
|
39
|
-
return sanityAssets && muxAssets.data
|
|
40
|
-
? sanityAssets.map((sanityDoc) => {
|
|
41
|
-
const muxAsset = muxAssets.data?.find(
|
|
42
|
-
(m) => m.id === sanityDoc.assetId || m.id === sanityDoc.data?.id,
|
|
43
|
-
)
|
|
44
|
-
return {
|
|
45
|
-
sanityDoc,
|
|
46
|
-
muxAsset,
|
|
47
|
-
muxTitle: muxAsset?.meta?.title,
|
|
48
|
-
currentTitle: sanityDoc.filename,
|
|
49
|
-
}
|
|
50
|
-
})
|
|
51
|
-
: undefined
|
|
52
|
-
}, [sanityAssets, muxAssets.data])
|
|
53
|
-
|
|
54
|
-
const closeDialog = () => {
|
|
55
|
-
if (resyncState !== 'syncing') setResyncState('closed')
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const openDialog = () => {
|
|
59
|
-
if (resyncState === 'closed') setResyncState('idle')
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
async function syncAllVideos() {
|
|
63
|
-
if (!matchedAssets) return
|
|
64
|
-
|
|
65
|
-
setResyncState('syncing')
|
|
66
|
-
|
|
67
|
-
try {
|
|
68
|
-
const tx = client.transaction()
|
|
69
|
-
|
|
70
|
-
matchedAssets.forEach((matched) => {
|
|
71
|
-
// Update all videos with the Mux title, even if it's undefined/empty
|
|
72
|
-
const newTitle = matched.muxTitle || ''
|
|
73
|
-
tx.patch(matched.sanityDoc._id, {set: {filename: newTitle}})
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
await tx.commit({returnDocuments: false})
|
|
77
|
-
setResyncState('done')
|
|
78
|
-
} catch (error) {
|
|
79
|
-
setResyncState('error')
|
|
80
|
-
setResyncError(error)
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
async function syncOnlyEmpty() {
|
|
85
|
-
if (!matchedAssets) return
|
|
86
|
-
|
|
87
|
-
setResyncState('syncing')
|
|
88
|
-
|
|
89
|
-
try {
|
|
90
|
-
const tx = client.transaction()
|
|
91
|
-
|
|
92
|
-
matchedAssets.forEach((matched) => {
|
|
93
|
-
// Only update if the current title is empty or has the placeholder format
|
|
94
|
-
// AND there's a new title available from Mux
|
|
95
|
-
if (
|
|
96
|
-
matched.muxAsset &&
|
|
97
|
-
matched.muxTitle &&
|
|
98
|
-
isEmptyOrPlaceholderTitle(matched.currentTitle, matched.muxAsset.id)
|
|
99
|
-
) {
|
|
100
|
-
tx.patch(matched.sanityDoc._id, {set: {filename: matched.muxTitle}})
|
|
101
|
-
}
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
await tx.commit({returnDocuments: false})
|
|
105
|
-
setResyncState('done')
|
|
106
|
-
} catch (error) {
|
|
107
|
-
setResyncState('error')
|
|
108
|
-
setResyncError(error)
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
async function syncFullData() {
|
|
113
|
-
if (!matchedAssets) return
|
|
114
|
-
|
|
115
|
-
setResyncState('syncing')
|
|
116
|
-
|
|
117
|
-
try {
|
|
118
|
-
const tx = client.transaction()
|
|
119
|
-
|
|
120
|
-
matchedAssets.forEach((matched) => {
|
|
121
|
-
if (!matched.muxAsset) return
|
|
122
|
-
|
|
123
|
-
const dataWithKeys = addKeysToMuxData(matched.muxAsset)
|
|
124
|
-
|
|
125
|
-
// Update all fields: filename, status, and full data from Mux
|
|
126
|
-
tx.patch(matched.sanityDoc._id, {
|
|
127
|
-
set: {
|
|
128
|
-
filename: matched.muxTitle || matched.currentTitle || '',
|
|
129
|
-
status: matched.muxAsset.status,
|
|
130
|
-
data: dataWithKeys,
|
|
131
|
-
},
|
|
132
|
-
})
|
|
133
|
-
})
|
|
134
|
-
|
|
135
|
-
await tx.commit({returnDocuments: false})
|
|
136
|
-
setResyncState('done')
|
|
137
|
-
} catch (error) {
|
|
138
|
-
setResyncState('error')
|
|
139
|
-
setResyncError(error)
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return {
|
|
144
|
-
sanityAssetsLoading,
|
|
145
|
-
closeDialog,
|
|
146
|
-
dialogOpen,
|
|
147
|
-
resyncState,
|
|
148
|
-
resyncError,
|
|
149
|
-
hasSecrets,
|
|
150
|
-
syncAllVideos,
|
|
151
|
-
syncOnlyEmpty,
|
|
152
|
-
syncFullData,
|
|
153
|
-
matchedAssets,
|
|
154
|
-
muxAssets,
|
|
155
|
-
openDialog,
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const useSanityAssets = createHookFromObservableFactory<VideoAssetDocument[], DocumentStore>(
|
|
160
|
-
(documentStore) => {
|
|
161
|
-
return documentStore.listenQuery(
|
|
162
|
-
/* groq */ `*[_type == "mux.videoAsset"]`,
|
|
163
|
-
{},
|
|
164
|
-
{
|
|
165
|
-
apiVersion: SANITY_API_VERSION,
|
|
166
|
-
},
|
|
167
|
-
)
|
|
168
|
-
},
|
|
169
|
-
)
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import {useCallback} from 'react'
|
|
2
|
-
import type {SanityClient} from 'sanity'
|
|
3
|
-
|
|
4
|
-
import {createSigningKeys, haveValidSigningKeys, saveSecrets, testSecrets} from '../actions/secrets'
|
|
5
|
-
import type {Secrets} from '../util/types'
|
|
6
|
-
|
|
7
|
-
export const useSaveSecrets = (client: SanityClient, secrets: Secrets) => {
|
|
8
|
-
return useCallback(
|
|
9
|
-
async ({
|
|
10
|
-
token,
|
|
11
|
-
secretKey,
|
|
12
|
-
enableSignedUrls,
|
|
13
|
-
drmConfigId,
|
|
14
|
-
}: Pick<
|
|
15
|
-
Secrets,
|
|
16
|
-
'token' | 'secretKey' | 'enableSignedUrls' | 'drmConfigId'
|
|
17
|
-
>): Promise<Secrets> => {
|
|
18
|
-
let {signingKeyId, signingKeyPrivate} = secrets
|
|
19
|
-
|
|
20
|
-
try {
|
|
21
|
-
await saveSecrets(
|
|
22
|
-
client,
|
|
23
|
-
token!,
|
|
24
|
-
secretKey!,
|
|
25
|
-
enableSignedUrls,
|
|
26
|
-
signingKeyId!,
|
|
27
|
-
signingKeyPrivate!,
|
|
28
|
-
drmConfigId!,
|
|
29
|
-
)
|
|
30
|
-
const valid = await testSecrets(client)
|
|
31
|
-
if (!valid?.status && token && secretKey) {
|
|
32
|
-
throw new Error('Invalid secrets')
|
|
33
|
-
}
|
|
34
|
-
} catch (err) {
|
|
35
|
-
console.error('Error while trying to save secrets:', err)
|
|
36
|
-
throw err
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (enableSignedUrls) {
|
|
40
|
-
const hasValidSigningKeys = await haveValidSigningKeys(
|
|
41
|
-
client,
|
|
42
|
-
signingKeyId!,
|
|
43
|
-
signingKeyPrivate!,
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
if (!hasValidSigningKeys) {
|
|
47
|
-
try {
|
|
48
|
-
const {data} = await createSigningKeys(client)
|
|
49
|
-
signingKeyId = data.id
|
|
50
|
-
signingKeyPrivate = data.private_key
|
|
51
|
-
await saveSecrets(
|
|
52
|
-
client,
|
|
53
|
-
token!,
|
|
54
|
-
secretKey!,
|
|
55
|
-
enableSignedUrls,
|
|
56
|
-
signingKeyId,
|
|
57
|
-
signingKeyPrivate,
|
|
58
|
-
drmConfigId ?? '',
|
|
59
|
-
)
|
|
60
|
-
} catch (err: any) {
|
|
61
|
-
// eslint-disable-next-line no-console
|
|
62
|
-
console.log('Error while creating and saving signing key:', err?.message)
|
|
63
|
-
throw err
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return {
|
|
68
|
-
token,
|
|
69
|
-
secretKey,
|
|
70
|
-
enableSignedUrls,
|
|
71
|
-
signingKeyId,
|
|
72
|
-
signingKeyPrivate,
|
|
73
|
-
drmConfigId,
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
|
-
[client, secrets],
|
|
77
|
-
)
|
|
78
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import {useMemo} from 'react'
|
|
2
|
-
import {useDocumentValues} from 'sanity'
|
|
3
|
-
|
|
4
|
-
import {muxSecretsDocumentId} from '../util/constants'
|
|
5
|
-
import type {Secrets} from '../util/types'
|
|
6
|
-
|
|
7
|
-
const path = [
|
|
8
|
-
'token',
|
|
9
|
-
'secretKey',
|
|
10
|
-
'enableSignedUrls',
|
|
11
|
-
'signingKeyId',
|
|
12
|
-
'signingKeyPrivate',
|
|
13
|
-
'drmConfigId',
|
|
14
|
-
]
|
|
15
|
-
export const useSecretsDocumentValues = () => {
|
|
16
|
-
const {error, isLoading, value} = useDocumentValues<Partial<Secrets> | null | undefined>(
|
|
17
|
-
muxSecretsDocumentId,
|
|
18
|
-
path,
|
|
19
|
-
)
|
|
20
|
-
const cache = useMemo(() => {
|
|
21
|
-
const exists = Boolean(value)
|
|
22
|
-
const secrets: Secrets = {
|
|
23
|
-
token: value?.token || null,
|
|
24
|
-
secretKey: value?.secretKey || null,
|
|
25
|
-
enableSignedUrls: value?.enableSignedUrls || false,
|
|
26
|
-
signingKeyId: value?.signingKeyId || null,
|
|
27
|
-
signingKeyPrivate: value?.signingKeyPrivate || null,
|
|
28
|
-
drmConfigId: value?.drmConfigId || null,
|
|
29
|
-
}
|
|
30
|
-
return {
|
|
31
|
-
isInitialSetup: !exists,
|
|
32
|
-
needsSetup: !secrets?.token || !secrets?.secretKey,
|
|
33
|
-
secrets,
|
|
34
|
-
}
|
|
35
|
-
}, [value])
|
|
36
|
-
|
|
37
|
-
return {error, isLoading, value: cache}
|
|
38
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import {useReducer} from 'react'
|
|
2
|
-
|
|
3
|
-
import type {Secrets} from '../util/types'
|
|
4
|
-
|
|
5
|
-
export interface State extends Pick<
|
|
6
|
-
Secrets,
|
|
7
|
-
'token' | 'secretKey' | 'enableSignedUrls' | 'drmConfigId'
|
|
8
|
-
> {
|
|
9
|
-
submitting: boolean
|
|
10
|
-
error: string | null
|
|
11
|
-
}
|
|
12
|
-
export type Action =
|
|
13
|
-
| {type: 'submit'}
|
|
14
|
-
| {type: 'error'; payload: string}
|
|
15
|
-
| {type: 'reset'; payload: Secrets}
|
|
16
|
-
| {type: 'change'; payload: {name: 'token'; value: string}}
|
|
17
|
-
| {type: 'change'; payload: {name: 'secretKey'; value: string}}
|
|
18
|
-
| {type: 'change'; payload: {name: 'enableSignedUrls'; value: boolean}}
|
|
19
|
-
| {type: 'change'; payload: {name: 'drmConfigId'; value: string}}
|
|
20
|
-
function init({token, secretKey, enableSignedUrls, drmConfigId}: Secrets): State {
|
|
21
|
-
return {
|
|
22
|
-
submitting: false,
|
|
23
|
-
error: null,
|
|
24
|
-
// Form inputs don't set the state back to null when clearing a field, but uses empty strings
|
|
25
|
-
// This ensures the `dirty` check works correctly
|
|
26
|
-
token: token ?? '',
|
|
27
|
-
secretKey: secretKey ?? '',
|
|
28
|
-
enableSignedUrls: enableSignedUrls ?? false,
|
|
29
|
-
drmConfigId: drmConfigId ?? '',
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
function reducer(state: State, action: Action) {
|
|
33
|
-
switch (action?.type) {
|
|
34
|
-
case 'submit':
|
|
35
|
-
return {...state, submitting: true, error: null}
|
|
36
|
-
case 'error':
|
|
37
|
-
return {...state, submitting: false, error: action.payload}
|
|
38
|
-
case 'reset':
|
|
39
|
-
return init(action.payload)
|
|
40
|
-
case 'change':
|
|
41
|
-
return {...state, [action.payload.name]: action.payload.value}
|
|
42
|
-
default:
|
|
43
|
-
throw new Error(`Unknown action type: ${(action as unknown as Action)?.type}`)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export const useSecretsFormState = (secrets: Secrets) => useReducer(reducer, secrets, init)
|
package/src/plugin.tsx
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import Input from './components/Input'
|
|
2
|
-
import VideoThumbnail from './components/VideoThumbnail'
|
|
3
|
-
import type {MuxInputProps, PluginConfig, VideoAssetDocument} from './util/types'
|
|
4
|
-
|
|
5
|
-
export function muxVideoCustomRendering(config: PluginConfig) {
|
|
6
|
-
return {
|
|
7
|
-
components: {
|
|
8
|
-
input: (props: MuxInputProps) => (
|
|
9
|
-
<Input config={{...config, ...props.schemaType.options}} {...props} />
|
|
10
|
-
),
|
|
11
|
-
},
|
|
12
|
-
preview: {
|
|
13
|
-
select: {
|
|
14
|
-
filename: 'asset.filename',
|
|
15
|
-
playbackId: 'asset.playbackId',
|
|
16
|
-
status: 'asset.status',
|
|
17
|
-
assetId: 'asset.assetId',
|
|
18
|
-
thumbTime: 'asset.thumbTime',
|
|
19
|
-
data: 'asset.data',
|
|
20
|
-
},
|
|
21
|
-
prepare: (asset: Partial<VideoAssetDocument>) => {
|
|
22
|
-
const {filename, playbackId, status} = asset
|
|
23
|
-
return {
|
|
24
|
-
title: filename || playbackId || '',
|
|
25
|
-
subtitle: status ? `status: ${status}` : null,
|
|
26
|
-
media: asset.playbackId ? <VideoThumbnail asset={asset} width={64} /> : null,
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
},
|
|
30
|
-
}
|
|
31
|
-
}
|
package/src/sanity-ui.d.ts
DELETED
package/src/schema.ts
DELETED
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
export const muxVideoSchema = {
|
|
2
|
-
name: 'mux.video',
|
|
3
|
-
type: 'object',
|
|
4
|
-
title: 'Video asset reference',
|
|
5
|
-
fields: [
|
|
6
|
-
{
|
|
7
|
-
title: 'Video',
|
|
8
|
-
name: 'asset',
|
|
9
|
-
type: 'reference',
|
|
10
|
-
weak: true,
|
|
11
|
-
to: [{type: 'mux.videoAsset'}],
|
|
12
|
-
},
|
|
13
|
-
],
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const muxTrack = {
|
|
17
|
-
name: 'mux.track',
|
|
18
|
-
type: 'object',
|
|
19
|
-
fields: [
|
|
20
|
-
{type: 'string', name: 'id'},
|
|
21
|
-
{type: 'string', name: 'type'},
|
|
22
|
-
{type: 'number', name: 'max_width'},
|
|
23
|
-
{type: 'number', name: 'max_frame_rate'},
|
|
24
|
-
{type: 'number', name: 'duration'},
|
|
25
|
-
{type: 'number', name: 'max_height'},
|
|
26
|
-
{type: 'string', name: 'language_code'},
|
|
27
|
-
{type: 'string', name: 'name'},
|
|
28
|
-
{type: 'string', name: 'status'},
|
|
29
|
-
{type: 'string', name: 'text_source'},
|
|
30
|
-
{type: 'string', name: 'text_type'},
|
|
31
|
-
],
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const muxPlaybackId = {
|
|
35
|
-
name: 'mux.playbackId',
|
|
36
|
-
type: 'object',
|
|
37
|
-
fields: [
|
|
38
|
-
{type: 'string', name: 'id'},
|
|
39
|
-
{type: 'string', name: 'policy'},
|
|
40
|
-
],
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const muxStaticRenditionFile = {
|
|
44
|
-
name: 'mux.staticRenditionFile',
|
|
45
|
-
type: 'object',
|
|
46
|
-
fields: [
|
|
47
|
-
{type: 'string', name: 'name'},
|
|
48
|
-
{type: 'string', name: 'ext'},
|
|
49
|
-
{type: 'number', name: 'height'},
|
|
50
|
-
{type: 'number', name: 'width'},
|
|
51
|
-
{type: 'number', name: 'bitrate'},
|
|
52
|
-
{type: 'string', name: 'filesize'},
|
|
53
|
-
{type: 'string', name: 'type'},
|
|
54
|
-
{type: 'string', name: 'status'},
|
|
55
|
-
{type: 'string', name: 'resolution_tier'},
|
|
56
|
-
{type: 'string', name: 'resolution'},
|
|
57
|
-
{type: 'string', name: 'id'},
|
|
58
|
-
{type: 'string', name: 'passthrough'},
|
|
59
|
-
],
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const muxStaticRenditions = {
|
|
63
|
-
name: 'mux.staticRenditions',
|
|
64
|
-
type: 'object',
|
|
65
|
-
fields: [
|
|
66
|
-
{type: 'string', name: 'status'},
|
|
67
|
-
{
|
|
68
|
-
name: 'files',
|
|
69
|
-
type: 'array',
|
|
70
|
-
of: [{type: 'mux.staticRenditionFile'}],
|
|
71
|
-
},
|
|
72
|
-
],
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const muxAssetData = {
|
|
76
|
-
name: 'mux.assetData',
|
|
77
|
-
title: 'Mux asset data',
|
|
78
|
-
type: 'object',
|
|
79
|
-
fields: [
|
|
80
|
-
{
|
|
81
|
-
type: 'string',
|
|
82
|
-
name: 'resolution_tier',
|
|
83
|
-
},
|
|
84
|
-
{
|
|
85
|
-
type: 'string',
|
|
86
|
-
name: 'upload_id',
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
type: 'string',
|
|
90
|
-
name: 'created_at',
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
type: 'string',
|
|
94
|
-
name: 'id',
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
type: 'string',
|
|
98
|
-
name: 'status',
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
type: 'string',
|
|
102
|
-
name: 'max_stored_resolution',
|
|
103
|
-
},
|
|
104
|
-
{
|
|
105
|
-
type: 'string',
|
|
106
|
-
name: 'passthrough',
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
type: 'string',
|
|
110
|
-
name: 'encoding_tier',
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
type: 'string',
|
|
114
|
-
name: 'video_quality',
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
type: 'string',
|
|
118
|
-
name: 'master_access',
|
|
119
|
-
},
|
|
120
|
-
{
|
|
121
|
-
type: 'string',
|
|
122
|
-
name: 'aspect_ratio',
|
|
123
|
-
},
|
|
124
|
-
{
|
|
125
|
-
type: 'number',
|
|
126
|
-
name: 'duration',
|
|
127
|
-
},
|
|
128
|
-
{
|
|
129
|
-
type: 'number',
|
|
130
|
-
name: 'max_stored_frame_rate',
|
|
131
|
-
},
|
|
132
|
-
{
|
|
133
|
-
type: 'string',
|
|
134
|
-
name: 'mp4_support',
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
type: 'string',
|
|
138
|
-
name: 'max_resolution_tier',
|
|
139
|
-
},
|
|
140
|
-
{
|
|
141
|
-
name: 'tracks',
|
|
142
|
-
type: 'array',
|
|
143
|
-
of: [{type: 'mux.track'}],
|
|
144
|
-
},
|
|
145
|
-
{
|
|
146
|
-
name: 'playback_ids',
|
|
147
|
-
type: 'array',
|
|
148
|
-
of: [{type: 'mux.playbackId'}],
|
|
149
|
-
},
|
|
150
|
-
{
|
|
151
|
-
name: 'static_renditions',
|
|
152
|
-
type: 'mux.staticRenditions',
|
|
153
|
-
},
|
|
154
|
-
],
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const muxVideoAsset = {
|
|
158
|
-
name: 'mux.videoAsset',
|
|
159
|
-
type: 'document',
|
|
160
|
-
title: 'Video asset',
|
|
161
|
-
fields: [
|
|
162
|
-
{
|
|
163
|
-
type: 'string',
|
|
164
|
-
name: 'status',
|
|
165
|
-
},
|
|
166
|
-
{
|
|
167
|
-
type: 'string',
|
|
168
|
-
name: 'assetId',
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
type: 'string',
|
|
172
|
-
name: 'playbackId',
|
|
173
|
-
},
|
|
174
|
-
{
|
|
175
|
-
type: 'string',
|
|
176
|
-
name: 'filename',
|
|
177
|
-
},
|
|
178
|
-
{
|
|
179
|
-
type: 'number',
|
|
180
|
-
name: 'thumbTime',
|
|
181
|
-
},
|
|
182
|
-
{
|
|
183
|
-
type: 'mux.assetData',
|
|
184
|
-
name: 'data',
|
|
185
|
-
},
|
|
186
|
-
],
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
export const schemaTypes = [
|
|
190
|
-
muxTrack,
|
|
191
|
-
muxPlaybackId,
|
|
192
|
-
muxStaticRenditionFile,
|
|
193
|
-
muxStaticRenditions,
|
|
194
|
-
muxAssetData,
|
|
195
|
-
muxVideoAsset,
|
|
196
|
-
]
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import {uuid} from '@sanity/uuid'
|
|
2
|
-
|
|
3
|
-
import type {MuxAsset} from './types'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Adds _key to array items in MuxAsset data for Sanity compatibility.
|
|
7
|
-
* Sanity requires _key on array items for proper editing support.
|
|
8
|
-
*/
|
|
9
|
-
export function addKeysToMuxData(data: MuxAsset): MuxAsset {
|
|
10
|
-
return {
|
|
11
|
-
...data,
|
|
12
|
-
tracks: data.tracks?.map((track) => ({
|
|
13
|
-
...track,
|
|
14
|
-
_key: uuid(),
|
|
15
|
-
})),
|
|
16
|
-
playback_ids: data.playback_ids?.map((playbackId) => ({
|
|
17
|
-
...playbackId,
|
|
18
|
-
_key: uuid(),
|
|
19
|
-
})),
|
|
20
|
-
static_renditions: data.static_renditions
|
|
21
|
-
? {
|
|
22
|
-
...data.static_renditions,
|
|
23
|
-
files: data.static_renditions.files?.map((file) => ({
|
|
24
|
-
...file,
|
|
25
|
-
_key: uuid(),
|
|
26
|
-
})),
|
|
27
|
-
}
|
|
28
|
-
: undefined,
|
|
29
|
-
}
|
|
30
|
-
}
|
package/src/util/asserters.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import {ServerError} from '@sanity/client'
|
|
2
|
-
|
|
3
|
-
export function isValidUrl(url: string): boolean {
|
|
4
|
-
try {
|
|
5
|
-
const parsed = new URL(url)
|
|
6
|
-
return parsed && !!parsed.protocol.match(/http:|https:/)
|
|
7
|
-
} catch {
|
|
8
|
-
return false
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* We consider a server error one with status code 5XX.
|
|
14
|
-
* Used mainly to handle unknown Proxy issues.
|
|
15
|
-
*/
|
|
16
|
-
export function isServerError(error: Error): error is ServerError {
|
|
17
|
-
return (
|
|
18
|
-
'statusCode' in error &&
|
|
19
|
-
typeof error.statusCode === 'number' &&
|
|
20
|
-
500 <= error.statusCode &&
|
|
21
|
-
error.statusCode <= 600
|
|
22
|
-
)
|
|
23
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import {truncateString} from 'sanity'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Generates a placeholder title for a Mux asset when no title is available.
|
|
5
|
-
* This format is used when importing assets that don't have a title in Mux.
|
|
6
|
-
*
|
|
7
|
-
* @param assetId - The Mux asset ID
|
|
8
|
-
* @returns A placeholder title in the format "Asset #[truncated-id]"
|
|
9
|
-
*/
|
|
10
|
-
export function generateAssetPlaceholder(assetId: string): string {
|
|
11
|
-
return `Asset #${truncateString(assetId, 15)}`
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Checks if a filename is empty or has the placeholder format.
|
|
16
|
-
* This is used to determine if a video title should be updated during metadata sync.
|
|
17
|
-
*
|
|
18
|
-
* @param filename - The current filename/title of the video
|
|
19
|
-
* @param assetId - The Mux asset ID to check against
|
|
20
|
-
* @returns true if the filename is empty or matches the placeholder format
|
|
21
|
-
*/
|
|
22
|
-
export function isEmptyOrPlaceholderTitle(filename: string | undefined, assetId: string): boolean {
|
|
23
|
-
// Check if filename is empty/undefined
|
|
24
|
-
if (!filename || filename.trim() === '') {
|
|
25
|
-
return true
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Check if filename matches the placeholder format for this asset
|
|
29
|
-
const placeholder = generateAssetPlaceholder(assetId)
|
|
30
|
-
return filename === placeholder
|
|
31
|
-
}
|
package/src/util/constants.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export const name = 'mux-input' as const
|
|
2
|
-
|
|
3
|
-
// Caching namespace, as suspend-react might be in use by other components on the page we must ensure we don't collide
|
|
4
|
-
export const cacheNs = 'sanity-plugin-mux-input' as const
|
|
5
|
-
|
|
6
|
-
export const muxSecretsDocumentId = 'secrets.mux' as const
|
|
7
|
-
|
|
8
|
-
export const DIALOGS_Z_INDEX = 60_000
|
|
9
|
-
|
|
10
|
-
export const THUMBNAIL_ASPECT_RATIO = 16 / 9
|
|
11
|
-
|
|
12
|
-
/** To prevent excessive height, thumbnails and input should not go beyond to this aspect ratio. */
|
|
13
|
-
export const MIN_ASPECT_RATIO = 5 / 4
|
|
14
|
-
|
|
15
|
-
export const AUDIO_ASPECT_RATIO = 5 / 1
|