sanity-plugin-mux-input 2.1.0 → 2.2.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.
Files changed (67) hide show
  1. package/lib/index.cjs +4037 -4
  2. package/lib/index.cjs.map +1 -1
  3. package/lib/index.d.ts +14 -1
  4. package/lib/index.js +4026 -2
  5. package/lib/index.js.map +1 -1
  6. package/package.json +27 -28
  7. package/src/actions/assets.ts +30 -2
  8. package/src/clients/upChunkObservable.ts +1 -1
  9. package/src/components/ConfigureApi.tsx +9 -1
  10. package/src/components/FormField.tsx +8 -10
  11. package/src/components/IconInfo.tsx +23 -0
  12. package/src/components/Input.styled.tsx +0 -8
  13. package/src/components/Input.tsx +4 -3
  14. package/src/components/InputBrowser.tsx +1 -8
  15. package/src/components/Player.styled.tsx +5 -144
  16. package/src/components/Player.tsx +23 -109
  17. package/src/components/PlayerActionsMenu.tsx +0 -4
  18. package/src/components/SelectAsset.tsx +18 -58
  19. package/src/components/SelectSortOptions.tsx +45 -0
  20. package/src/components/SpinnerBox.tsx +17 -0
  21. package/src/components/StudioTool.tsx +20 -0
  22. package/src/components/VideoDetails/DeleteDialog.tsx +156 -0
  23. package/src/components/VideoDetails/VideoDetails.tsx +298 -0
  24. package/src/components/VideoDetails/VideoReferences.tsx +70 -0
  25. package/src/components/VideoDetails/useVideoDetails.ts +85 -0
  26. package/src/components/VideoInBrowser.tsx +183 -0
  27. package/src/components/VideoMetadata.tsx +43 -0
  28. package/src/components/VideoPlayer.tsx +69 -0
  29. package/src/components/VideoThumbnail.tsx +106 -0
  30. package/src/components/VideosBrowser.tsx +83 -0
  31. package/src/components/__legacy__Uploader.tsx +2 -9
  32. package/src/components/documentPreview/DocumentPreview.tsx +107 -0
  33. package/src/components/documentPreview/DraftStatus.tsx +34 -0
  34. package/src/components/documentPreview/MissingSchemaType.tsx +33 -0
  35. package/src/components/documentPreview/PaneItemPreview.tsx +71 -0
  36. package/src/components/documentPreview/PublishedStatus.tsx +35 -0
  37. package/src/components/documentPreview/TimeAgo.tsx +13 -0
  38. package/src/components/documentPreview/paneItemTypes.ts +7 -0
  39. package/src/components/icons/Resolution.tsx +12 -0
  40. package/src/components/icons/StopWatch.tsx +20 -0
  41. package/src/components/icons/ToolIcon.tsx +21 -0
  42. package/src/hooks/useAssets.ts +61 -0
  43. package/src/hooks/useCancelUpload.ts +2 -2
  44. package/src/hooks/useClient.ts +3 -1
  45. package/src/hooks/useDocReferences.ts +21 -0
  46. package/src/hooks/useInView.ts +45 -0
  47. package/src/index.ts +2 -0
  48. package/src/plugin.tsx +1 -1
  49. package/src/util/constants.ts +7 -0
  50. package/src/util/createSearchFilter.ts +78 -0
  51. package/src/util/formatSeconds.ts +22 -0
  52. package/src/util/getAnimatedPosterSrc.ts +1 -1
  53. package/src/util/getPlaybackId.ts +1 -1
  54. package/src/util/getPlaybackPolicy.ts +1 -1
  55. package/src/util/getVideoMetadata.ts +18 -0
  56. package/src/util/types.ts +16 -1
  57. package/lib/_chunks/Player-d8f163ed.cjs +0 -474
  58. package/lib/_chunks/Player-d8f163ed.cjs.map +0 -1
  59. package/lib/_chunks/Player-fb9712c0.js +0 -465
  60. package/lib/_chunks/Player-fb9712c0.js.map +0 -1
  61. package/lib/_chunks/index-0656ede8.js +0 -3229
  62. package/lib/_chunks/index-0656ede8.js.map +0 -1
  63. package/lib/_chunks/index-9cd542f1.cjs +0 -3271
  64. package/lib/_chunks/index-9cd542f1.cjs.map +0 -1
  65. package/src/components/EditThumbnailDialog.tsx +0 -74
  66. package/src/components/VideoSource.styled.tsx +0 -235
  67. package/src/components/VideoSource.tsx +0 -318
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sanity-plugin-mux-input",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "An input component that integrates Sanity Studio with Mux video encoding/hosting service.",
5
5
  "keywords": [
6
6
  "sanity",
@@ -61,62 +61,61 @@
61
61
  "watch": "pkg-utils watch --strict"
62
62
  },
63
63
  "dependencies": {
64
- "@mux/mux-video-react": "^0.7.7",
64
+ "@mux/mux-player-react": "^1.11.4",
65
65
  "@mux/upchunk": "^3",
66
66
  "@sanity/icons": "^2",
67
67
  "@sanity/incompatible-plugin": "^1",
68
68
  "@sanity/ui": "^1",
69
69
  "@sanity/uuid": "^3",
70
- "classnames": "^2.3.2",
71
70
  "jsonwebtoken-esm": "^1.0.5",
72
- "media-chrome": "^0.21.0",
73
- "motion": "^10",
71
+ "lodash": "^4",
72
+ "react-rx": "^2.1.3",
74
73
  "rxjs": "^7",
75
74
  "scroll-into-view-if-needed": "^3",
76
- "suspend-react": "^0.0.10",
75
+ "suspend-react": "^0.1.0",
77
76
  "swr": "^2.1.0",
78
- "use-device-pixel-ratio": "^1.1.2",
77
+ "type-fest": "^3.6.1",
79
78
  "use-error-boundary": "^2.0.6"
80
79
  },
81
80
  "devDependencies": {
82
- "@commitlint/cli": "^17.4.4",
83
- "@commitlint/config-conventional": "^17.4.4",
84
- "@sanity/pkg-utils": "^2.2.13",
81
+ "@commitlint/cli": "^17.6.7",
82
+ "@commitlint/config-conventional": "^17.6.7",
83
+ "@sanity/pkg-utils": "^2.3.10",
85
84
  "@sanity/plugin-kit": "^3.1.7",
86
- "@sanity/semantic-release-preset": "^4.0.0",
87
- "@sanity/vision": "^3.6.0",
88
- "@types/react": "^18.0.28",
85
+ "@sanity/semantic-release-preset": "^4.1.2",
86
+ "@sanity/vision": "^3.14.5",
87
+ "@types/react": "^18.2.18",
89
88
  "@types/styled-components": "^5.1.26",
90
- "@typescript-eslint/eslint-plugin": "^5.54.1",
91
- "@typescript-eslint/parser": "^5.54.1",
89
+ "@typescript-eslint/eslint-plugin": "^5.62.0",
90
+ "@typescript-eslint/parser": "^5.62.0",
92
91
  "cz-conventional-changelog": "^3.3.0",
93
- "eslint": "^8.36.0",
94
- "eslint-config-prettier": "^8.7.0",
92
+ "eslint": "^8.46.0",
93
+ "eslint-config-prettier": "^8.10.0",
95
94
  "eslint-config-react-app": "^7.0.1",
96
95
  "eslint-config-sanity": "^6.0.0",
97
- "eslint-plugin-import": "^2.27.5",
96
+ "eslint-plugin-import": "^2.28.0",
98
97
  "eslint-plugin-prettier": "^4.2.1",
99
- "eslint-plugin-react": "^7.32.2",
98
+ "eslint-plugin-react": "^7.33.1",
100
99
  "eslint-plugin-react-hooks": "^4.6.0",
101
100
  "eslint-plugin-simple-import-sort": "^10.0.0",
102
101
  "husky": "^8.0.3",
103
- "lint-staged": "^13.2.0",
104
- "next": "^13.2.4",
105
- "next-sanity": "^4.1.5",
102
+ "lint-staged": "^13.2.3",
103
+ "next": "^13.4.12",
104
+ "next-sanity": "^4.3.3",
106
105
  "npm-run-all": "^4.1.5",
107
- "prettier": "^2.8.4",
108
- "prettier-plugin-packagejson": "^2.4.3",
106
+ "prettier": "^2.8.8",
107
+ "prettier-plugin-packagejson": "^2.4.5",
109
108
  "react": "^18.2.0",
110
109
  "react-dom": "^18.2.0",
111
110
  "react-is": "^18.2.0",
112
111
  "rimraf": "^5.0.0",
113
- "sanity": "^3.6.0",
114
- "styled-components": "^5.3.9",
115
- "type-fest": "^3.6.1",
116
- "typescript": "^5.0.2"
112
+ "sanity": "^3.14.5",
113
+ "styled-components": "^5.3.11",
114
+ "typescript": "^5.1.6"
117
115
  },
118
116
  "peerDependencies": {
119
117
  "react": "^18",
118
+ "react-is": "^18",
120
119
  "sanity": "^3",
121
120
  "styled-components": "^5.2"
122
121
  },
@@ -1,8 +1,8 @@
1
1
  import type {SanityClient} from 'sanity'
2
2
 
3
- import type {MuxAsset} from '../util/types'
3
+ import type {MuxAsset, VideoAssetDocument} from '../util/types'
4
4
 
5
- export function deleteAsset(client: SanityClient, assetId: string) {
5
+ export function deleteAssetOnMux(client: SanityClient, assetId: string) {
6
6
  const {dataset} = client.config()
7
7
  return client.request<void>({
8
8
  url: `/addons/mux/assets/${dataset}/${assetId}`,
@@ -11,6 +11,34 @@ export function deleteAsset(client: SanityClient, assetId: string) {
11
11
  })
12
12
  }
13
13
 
14
+ export async function deleteAsset({
15
+ client,
16
+ asset,
17
+ deleteOnMux,
18
+ }: {
19
+ client: SanityClient
20
+ asset: VideoAssetDocument
21
+ deleteOnMux: boolean
22
+ }) {
23
+ if (!asset?._id) return true
24
+
25
+ try {
26
+ await client.delete(asset._id)
27
+ } catch (error) {
28
+ return 'failed-sanity'
29
+ }
30
+
31
+ if (deleteOnMux && asset?.assetId) {
32
+ try {
33
+ await deleteAssetOnMux(client, asset.assetId)
34
+ } catch (error) {
35
+ return 'failed-mux'
36
+ }
37
+ }
38
+
39
+ return true
40
+ }
41
+
14
42
  export function getAsset(client: SanityClient, assetId: string) {
15
43
  const {dataset} = client.config()
16
44
  return client.request<{data: MuxAsset}>({
@@ -1,4 +1,4 @@
1
- import * as UpChunk from '@mux/upchunk'
1
+ import {UpChunk} from '@mux/upchunk'
2
2
  import {Observable} from 'rxjs'
3
3
 
4
4
  export function createUpChunkObservable(uuid: string, uploadUrl: string, source: File) {
@@ -108,7 +108,15 @@ function ConfigureApi({secrets, setDialogState}: Props) {
108
108
  }, [firstField])
109
109
 
110
110
  return (
111
- <Dialog id={id} onClose={handleClose} header={<Header />} width={0}>
111
+ <Dialog
112
+ id={id}
113
+ onClose={handleClose}
114
+ header={<Header />}
115
+ width={1}
116
+ style={{
117
+ maxWidth: '550px',
118
+ }}
119
+ >
112
120
  <Box padding={4} style={{position: 'relative'}}>
113
121
  <form onSubmit={handleSubmit} noValidate>
114
122
  <Stack space={4}>
@@ -18,17 +18,15 @@ function FormField(props: Props) {
18
18
  <Flex align="flex-end">
19
19
  <Box flex={1} paddingY={2}>
20
20
  <Stack space={2}>
21
- <Flex>
22
- <Text as="label" htmlFor={inputId} weight="semibold" size={1}>
23
- {title || <em>Untitled</em>}
24
- </Text>
21
+ <Text as="label" htmlFor={inputId} weight="semibold" size={1}>
22
+ {title || <em>Untitled</em>}
23
+ </Text>
25
24
 
26
- {description && (
27
- <Text muted size={1}>
28
- {description}
29
- </Text>
30
- )}
31
- </Flex>
25
+ {description && (
26
+ <Text muted size={1}>
27
+ {description}
28
+ </Text>
29
+ )}
32
30
  </Stack>
33
31
  </Box>
34
32
  </Flex>
@@ -0,0 +1,23 @@
1
+ import {Flex, Text} from '@sanity/ui'
2
+ import React from 'react'
3
+
4
+ const IconInfo: React.FC<{
5
+ text: string
6
+ icon: React.FC
7
+ size?: number
8
+ muted?: boolean
9
+ }> = (props) => {
10
+ const Icon = props.icon
11
+ return (
12
+ <Flex gap={2} align="center" padding={1}>
13
+ <Text size={(props.size || 1) + 1} muted>
14
+ <Icon />
15
+ </Text>
16
+ <Text size={props.size || 1} muted={props.muted}>
17
+ {props.text}
18
+ </Text>
19
+ </Flex>
20
+ )
21
+ }
22
+
23
+ export default IconInfo
@@ -1,13 +1,5 @@
1
1
  import {Box, Card, Flex, Spinner, Text} from '@sanity/ui'
2
2
  import React from 'react'
3
- import styled from 'styled-components'
4
-
5
- // This container base container ensures everything uses the same aspect ratio, avoids layout shifts and stuff jumping around
6
- export const AspectRatioCard = styled(Card)`
7
- aspect-ratio: 16 / 9;
8
- position: relative;
9
- width: 100%;
10
- `
11
3
 
12
4
  export const InputFallback = () => {
13
5
  return (
@@ -1,3 +1,4 @@
1
+ import {Card} from '@sanity/ui'
1
2
  import React, {memo, Suspense} from 'react'
2
3
 
3
4
  import {useAssetDocumentValues} from '../hooks/useAssetDocumentValues'
@@ -9,7 +10,7 @@ import type {Config, MuxInputProps} from '../util/types'
9
10
  import Uploader from './__legacy__Uploader'
10
11
  import ConfigureApi from './ConfigureApi'
11
12
  import ErrorBoundaryCard from './ErrorBoundaryCard'
12
- import {AspectRatioCard, InputFallback} from './Input.styled'
13
+ import {InputFallback} from './Input.styled'
13
14
  import Onboard from './Onboard'
14
15
 
15
16
  export interface InputProps extends MuxInputProps {
@@ -35,7 +36,7 @@ const Input = (props: InputProps) => {
35
36
  const isLoading = secretDocumentValues.isLoading || assetDocumentValues.isLoading
36
37
 
37
38
  return (
38
- <AspectRatioCard>
39
+ <Card>
39
40
  <ErrorBoundaryCard schemaType={props.schemaType}>
40
41
  <Suspense fallback={<InputFallback />}>
41
42
  {isLoading ? (
@@ -68,7 +69,7 @@ const Input = (props: InputProps) => {
68
69
  )}
69
70
  </Suspense>
70
71
  </ErrorBoundaryCard>
71
- </AspectRatioCard>
72
+ </Card>
72
73
  )
73
74
  }
74
75
 
@@ -11,14 +11,7 @@ export default function InputBrowser({setDialogState, asset, onChange}: Props) {
11
11
  const id = `InputBrowser${useId()}`
12
12
  const handleClose = useCallback(() => setDialogState(false), [setDialogState])
13
13
  return (
14
- <Dialog
15
- scheme="dark"
16
- __unstable_autoFocus
17
- header="Select video"
18
- id={id}
19
- onClose={handleClose}
20
- width={2}
21
- >
14
+ <Dialog __unstable_autoFocus header="Select video" id={id} onClose={handleClose} width={2}>
22
15
  <SelectAsset asset={asset} onChange={onChange} setDialogState={setDialogState} />
23
16
  </Dialog>
24
17
  )
@@ -1,131 +1,10 @@
1
- import {Card} from '@sanity/ui'
2
- import {MediaControlBar, MediaPosterImage} from 'media-chrome/dist/react'
3
- import React, {useEffect, useMemo, useRef, useState} from 'react'
1
+ import {useState} from 'react'
4
2
  import styled from 'styled-components'
5
3
 
6
4
  import {useClient} from '../hooks/useClient'
7
- import {getPosterSrc} from '../util/getPosterSrc'
8
5
  import {getStoryboardSrc} from '../util/getStoryboardSrc'
9
6
  import type {VideoAssetDocument} from '../util/types'
10
7
 
11
- export const VideoContainer = styled(Card)`
12
- position: relative;
13
- min-height: 150px;
14
- aspect-ratio: 16 / 9;
15
- overflow: hidden;
16
- border-radius: 1px;
17
- media-airplay-button[media-airplay-unavailable] {
18
- display: none;
19
- }
20
- media-volume-range[media-volume-unavailable] {
21
- display: none;
22
- }
23
- media-pip-button[media-pip-unavailable] {
24
- display: none;
25
- }
26
- media-controller {
27
- --media-control-background: transparent;
28
- --media-control-hover-background: transparent;
29
- --media-range-track-background-color: rgba(255, 255, 255, 0.5);
30
- --media-range-track-border-radius: 3px;
31
- width: 100%;
32
- height: 100%;
33
- background-color: transparent;
34
- }
35
- media-control-bar {
36
- --media-button-icon-width: 18px;
37
- --media-preview-time-margin: 0px;
38
- }
39
- media-control-bar:not([slot]) :is([role='button'], [role='switch'], button) {
40
- height: 44px;
41
- }
42
- .size-extra-small media-control-bar [role='button'],
43
- .size-extra-small media-control-bar [role='switch'] {
44
- height: auto;
45
- padding: 4.4% 3.2%;
46
- }
47
- .mxp-spacer {
48
- flex-grow: 1;
49
- height: 100%;
50
- background-color: var(--media-control-background, rgba(20, 20, 30, 0.7));
51
- }
52
- media-controller::part(vertical-layer) {
53
- transition: background-color 1s;
54
- }
55
- media-controller:is([media-paused], :not([user-inactive]))::part(vertical-layer) {
56
- background-color: rgba(0, 0, 0, 0.6);
57
- transition: background-color 0.25s;
58
- }
59
- .mxp-center-controls {
60
- --media-background-color: transparent;
61
- --media-button-icon-width: 100%;
62
- --media-button-icon-height: auto;
63
- pointer-events: none;
64
- width: 100%;
65
- display: flex;
66
- flex-flow: row;
67
- align-items: center;
68
- justify-content: center;
69
- }
70
- .mxp-center-controls media-play-button {
71
- --media-control-background: transparent;
72
- --media-control-hover-background: transparent;
73
- padding: 0;
74
- width: max(27px, min(9%, 90px));
75
- }
76
- .mxp-center-controls media-seek-backward-button,
77
- .mxp-center-controls media-seek-forward-button {
78
- --media-control-background: transparent;
79
- --media-control-hover-background: transparent;
80
- padding: 0;
81
- margin: 0 10%;
82
- width: min(7%, 70px);
83
- }
84
- media-loading-indicator {
85
- --media-loading-icon-width: 100%;
86
- --media-button-icon-height: auto;
87
- pointer-events: none;
88
- position: absolute;
89
- width: min(15%, 150px);
90
- display: flex;
91
- flex-flow: row;
92
- align-items: center;
93
- justify-content: center;
94
- }
95
- /* Intentionally don't target the div for transition but the children
96
- of the div. Prevents messing with media-chrome's autohide feature. */
97
- media-loading-indicator + div * {
98
- transition: opacity 0.15s;
99
- opacity: 1;
100
- }
101
- media-loading-indicator[media-loading]:not([media-paused]) ~ div > * {
102
- opacity: 0;
103
- transition-delay: 400ms;
104
- }
105
- media-volume-range {
106
- width: min(100%, 100px);
107
- }
108
- media-time-display {
109
- white-space: nowrap;
110
- }
111
- :is(media-time-display, media-text-display, media-playback-rate-button) {
112
- color: inherit;
113
- }
114
- media-controller:fullscreen media-control-bar[slot='top-chrome'] {
115
- /* Hide menus and buttons that trigger modals when in full-screen */
116
- display: none;
117
- }
118
- video {
119
- background: transparent;
120
- }
121
- media-controller:not(:fullscreen) video {
122
- aspect-ratio: 16 / 9;
123
- }
124
- media-controller:not(:-webkit-full-screen) video {
125
- aspect-ratio: 16 / 9;
126
- }
127
- `
128
-
129
8
  export const StyledCenterControls = styled.div`
130
9
  && {
131
10
  --media-background-color: transparent;
@@ -146,7 +25,10 @@ export const StyledCenterControls = styled.div`
146
25
  }
147
26
  `
148
27
 
149
- export const TopControls = styled(MediaControlBar)`
28
+ export const TopControls = styled.div`
29
+ position: absolute;
30
+ top: 0;
31
+ right: 0;
150
32
  justify-content: flex-end;
151
33
  button {
152
34
  height: auto;
@@ -156,27 +38,6 @@ export const TopControls = styled(MediaControlBar)`
156
38
  export interface PosterImageProps {
157
39
  asset: VideoAssetDocument
158
40
  }
159
- export function PosterImage({asset}: PosterImageProps) {
160
- const client = useClient()
161
- const ref = useRef<HTMLElement>(null)
162
- const src = useMemo(
163
- () => getPosterSrc({client, asset, width: 1920, height: 1080}),
164
- [client, asset]
165
- )
166
-
167
- useEffect(() => {
168
- if (ref.current) {
169
- const style = document.createElement('style')
170
- style.innerHTML = 'img { object-fit: contain; }'
171
- if (ref.current?.shadowRoot) {
172
- ref.current.shadowRoot.appendChild(style)
173
- }
174
- }
175
- }, [])
176
-
177
- return <MediaPosterImage ref={ref} slot="poster" src={src} />
178
- }
179
-
180
41
  export interface ThumbnailsMetadataTrackProps {
181
42
  asset: VideoAssetDocument
182
43
  }
@@ -1,43 +1,18 @@
1
- import MuxVideo from '@mux/mux-video-react'
2
1
  import {Card, Text} from '@sanity/ui'
3
- import {
4
- MediaControlBar,
5
- MediaController,
6
- MediaDurationDisplay,
7
- MediaFullscreenButton,
8
- MediaLoadingIndicator,
9
- MediaMuteButton,
10
- MediaPlayButton,
11
- MediaTimeDisplay,
12
- MediaTimeRange,
13
- } from 'media-chrome/dist/react'
14
- import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'
2
+ import React, {useEffect, useMemo, useRef} from 'react'
15
3
 
16
4
  import {useCancelUpload} from '../hooks/useCancelUpload'
17
- import {useClient} from '../hooks/useClient'
18
- import type {DialogState, SetDialogState} from '../hooks/useDialogState'
19
- import {getVideoSrc} from '../util/getVideoSrc'
20
5
  import type {MuxInputProps, VideoAssetDocument} from '../util/types'
21
- import pluginPkg from './../../package.json'
22
- import EditThumbnailDialog from './EditThumbnailDialog'
23
- import {
24
- PosterImage,
25
- StyledCenterControls,
26
- ThumbnailsMetadataTrack,
27
- TopControls,
28
- VideoContainer,
29
- } from './Player.styled'
6
+ import {TopControls} from './Player.styled'
30
7
  import {UploadProgress} from './UploadProgress'
8
+ import VideoPlayer from './VideoPlayer'
31
9
 
32
10
  interface Props extends Pick<MuxInputProps, 'onChange' | 'readOnly'> {
33
11
  buttons?: React.ReactNode
34
12
  asset: VideoAssetDocument
35
- dialogState: DialogState
36
- setDialogState: SetDialogState
37
13
  }
38
14
 
39
- const MuxVideoOld = ({asset, buttons, readOnly, onChange, dialogState, setDialogState}: Props) => {
40
- const client = useClient()
15
+ const Player = ({asset, buttons, readOnly, onChange}: Props) => {
41
16
  const isLoading = useMemo<boolean | string>(() => {
42
17
  if (asset?.status === 'preparing') {
43
18
  return 'Preparing the video'
@@ -66,16 +41,8 @@ const MuxVideoOld = ({asset, buttons, readOnly, onChange, dialogState, setDialog
66
41
  }
67
42
  return false
68
43
  }, [asset?.data?.static_renditions?.status])
69
- const videoSrc = useMemo(() => asset.playbackId && getVideoSrc({client, asset}), [asset, client])
70
- const [error, setError] = useState<MediaError | Error | null>(null)
71
- const handleError = useCallback<React.ReactEventHandler<HTMLVideoElement>>(
72
- (event) => setError(event.currentTarget.error),
73
- []
74
- )
75
44
  const playRef = useRef<HTMLDivElement>(null)
76
45
  const muteRef = useRef<HTMLDivElement>(null)
77
- const video = useRef<HTMLVideoElement>(null)
78
- const getCurrentTime = useCallback(() => video.current?.currentTime ?? 0, [video])
79
46
  const handleCancelUpload = useCancelUpload(asset, onChange)
80
47
 
81
48
  useEffect(() => {
@@ -99,20 +66,6 @@ const MuxVideoOld = ({asset, buttons, readOnly, onChange, dialogState, setDialog
99
66
  }
100
67
  }, [asset.data?.errors?.messages, asset?.status, handleCancelUpload])
101
68
 
102
- const signedToken = useMemo(() => {
103
- try {
104
- const url = new URL(videoSrc!)
105
- return url.searchParams.get('token')
106
- } catch {
107
- return false
108
- }
109
- }, [videoSrc])
110
-
111
- if (error) {
112
- // @TODO better error handling
113
- throw error
114
- }
115
-
116
69
  if (!asset || !asset.status) {
117
70
  return null
118
71
  }
@@ -129,65 +82,26 @@ const MuxVideoOld = ({asset, buttons, readOnly, onChange, dialogState, setDialog
129
82
  }
130
83
 
131
84
  return (
132
- <>
133
- <VideoContainer shadow={1} tone="transparent" scheme="dark">
134
- <MediaController>
135
- <MuxVideo
136
- playsInline
137
- ref={video}
138
- playbackId={`${asset.playbackId}${signedToken ? `?token=${signedToken}` : ''}`}
139
- onError={handleError}
140
- slot="media"
141
- preload="metadata"
142
- crossOrigin="anonymous"
143
- metadata={{
144
- player_name: 'Sanity Admin Dashboard',
145
- player_version: pluginPkg.version,
146
- page_type: 'Preview Player',
147
- }}
148
- >
149
- <ThumbnailsMetadataTrack asset={asset} />
150
- </MuxVideo>
151
- <PosterImage asset={asset} />
152
- <MediaLoadingIndicator slot="centered-chrome" noAutoHide />
153
- <StyledCenterControls slot="centered-chrome">
154
- <MediaPlayButton />
155
- </StyledCenterControls>
156
- {buttons && <TopControls slot="top-chrome">{buttons}</TopControls>}
157
- <MediaControlBar>
158
- <MediaMuteButton />
159
- <MediaTimeDisplay />
160
- <MediaTimeRange />
161
- <MediaDurationDisplay />
162
- <MediaFullscreenButton />
163
- </MediaControlBar>
164
- </MediaController>
165
- {isPreparingStaticRenditions && (
166
- <Card
167
- padding={2}
168
- radius={1}
169
- style={{
170
- background: 'var(--card-fg-color)',
171
- position: 'absolute',
172
- top: '0.5em',
173
- left: '0.5em',
174
- }}
175
- >
176
- <Text size={1} style={{color: 'var(--card-bg-color)'}}>
177
- MUX is preparing static renditions, please stand by
178
- </Text>
179
- </Card>
180
- )}
181
- </VideoContainer>
182
- {dialogState === 'edit-thumbnail' && (
183
- <EditThumbnailDialog
184
- asset={asset}
185
- getCurrentTime={getCurrentTime}
186
- setDialogState={setDialogState}
187
- />
85
+ <VideoPlayer asset={asset}>
86
+ {buttons && <TopControls slot="top-chrome">{buttons}</TopControls>}
87
+ {isPreparingStaticRenditions && (
88
+ <Card
89
+ padding={2}
90
+ radius={1}
91
+ style={{
92
+ background: 'var(--card-fg-color)',
93
+ position: 'absolute',
94
+ top: '0.5em',
95
+ left: '0.5em',
96
+ }}
97
+ >
98
+ <Text size={1} style={{color: 'var(--card-bg-color)'}}>
99
+ MUX is preparing static renditions, please stand by
100
+ </Text>
101
+ </Card>
188
102
  )}
189
- </>
103
+ </VideoPlayer>
190
104
  )
191
105
  }
192
106
 
193
- export default MuxVideoOld
107
+ export default Player
@@ -1,5 +1,4 @@
1
1
  import {
2
- EditIcon,
3
2
  EllipsisVerticalIcon,
4
3
  LockIcon,
5
4
  PlugIcon,
@@ -88,9 +87,6 @@ function PlayerActionsMenu(props: Props) {
88
87
  </LockCard>
89
88
  </Tooltip>
90
89
  )}
91
- {!readOnly && (
92
- <Button icon={EditIcon} mode="ghost" onClick={() => setDialogState('edit-thumbnail')} />
93
- )}
94
90
  <Popover
95
91
  content={
96
92
  <Menu ref={setMenuRef}>