sanity-plugin-mux-input 2.4.1 → 2.6.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sanity-plugin-mux-input",
3
- "version": "2.4.1",
3
+ "version": "2.6.0",
4
4
  "description": "An input component that integrates Sanity Studio with Mux video encoding/hosting service.",
5
5
  "keywords": [
6
6
  "sanity",
@@ -41,8 +41,7 @@
41
41
  ],
42
42
  "scripts": {
43
43
  "build": "plugin-kit verify-package --silent && pkg-utils build --strict --check --clean",
44
- "clean": "rimraf lib",
45
- "dev": "plugin-kit link-watch --strict",
44
+ "dev": "sanity dev",
46
45
  "format": "prettier --write --cache --ignore-unknown .",
47
46
  "link-watch": "plugin-kit link-watch",
48
47
  "lint": "eslint .",
@@ -71,39 +70,36 @@
71
70
  "use-error-boundary": "^2.0.6"
72
71
  },
73
72
  "devDependencies": {
74
- "@sanity/client": "^6.24.1",
75
- "@sanity/pkg-utils": "^6.12.1",
73
+ "@sanity/client": "^6.28.1",
74
+ "@sanity/pkg-utils": "^6.13.4",
76
75
  "@sanity/plugin-kit": "4.0.19",
77
76
  "@sanity/semantic-release-preset": "^5.0.0",
78
- "@sanity/vision": "^3.68.1",
79
- "@types/lodash": "^4.17.13",
80
- "@types/react": "^18.3.17",
77
+ "@sanity/vision": "^3.77.2",
78
+ "@types/lodash": "^4.17.15",
79
+ "@types/react": "^18.3.18",
81
80
  "@types/react-is": "^18.3.1",
82
- "@types/styled-components": "^5.1.34",
83
81
  "@typescript-eslint/eslint-plugin": "^7.18.0",
84
82
  "@typescript-eslint/parser": "^7.18.0",
85
83
  "eslint": "^8.57.1",
86
84
  "eslint-config-prettier": "^9.1.0",
87
85
  "eslint-config-react-app": "^7.0.1",
88
- "eslint-config-sanity": "^7.1.3",
86
+ "eslint-config-sanity": "^7.1.4",
89
87
  "eslint-plugin-import": "^2.31.0",
90
- "eslint-plugin-prettier": "^5.2.1",
88
+ "eslint-plugin-prettier": "^5.2.3",
91
89
  "eslint-plugin-react-hooks": "^5.1.0",
92
90
  "eslint-plugin-simple-import-sort": "^12.1.1",
93
91
  "husky": "^9.0.11",
94
92
  "lint-staged": "^15.2.2",
95
93
  "npm-run-all2": "^5.0.2",
96
- "prettier": "^3.4.2",
97
- "prettier-plugin-packagejson": "^2.5.6",
94
+ "prettier": "^3.5.2",
95
+ "prettier-plugin-packagejson": "^2.5.9",
98
96
  "react": "^18.3.1",
99
97
  "react-dom": "^18.3.1",
100
98
  "react-is": "^18.3.1",
101
- "rimraf": "^5.0.7",
102
- "sanity": "^3.68.1",
103
- "semantic-release": "^24.2.0",
104
- "styled-components": "^6.1.13",
105
- "typescript": "^5.7.2",
106
- "yalc": "1.0.0-pre.53"
99
+ "sanity": "^3.77.2",
100
+ "semantic-release": "^24.2.3",
101
+ "styled-components": "^6.1.15",
102
+ "typescript": "5.7.3"
107
103
  },
108
104
  "peerDependencies": {
109
105
  "react": "^18",
@@ -32,15 +32,25 @@ export function saveSecrets(
32
32
  return client.createOrReplace(doc)
33
33
  }
34
34
 
35
- export function createSigningKeys(client: SanityClient) {
36
- const {dataset} = client.config()
37
- return client.request<{
38
- data: {private_key: string; id: string; created_at: string}
39
- }>({
40
- url: `/addons/mux/signing-keys/${dataset}`,
41
- withCredentials: true,
42
- method: 'POST',
43
- })
35
+ export async function createSigningKeys(client: SanityClient) {
36
+ try {
37
+ const {dataset} = client.config()
38
+ const res = await client.request<{
39
+ data: {private_key: string; id: string; created_at: string}
40
+ }>({
41
+ url: `/addons/mux/signing-keys/${dataset}`,
42
+ withCredentials: true,
43
+ method: 'POST',
44
+ })
45
+ return res
46
+ } catch (error: any) {
47
+ console.error('Error creating signing keys', error)
48
+ const message =
49
+ error.response?.statusCode === 401
50
+ ? 'Unauthorized - Failed to create the Signing Key. Please ensure that the token has "System" permissions'
51
+ : error.message
52
+ throw new Error(message)
53
+ }
44
54
  }
45
55
 
46
56
  export function testSecrets(client: SanityClient) {
@@ -139,6 +139,8 @@ function ConfigureApi({secrets, setDialogState}: Props) {
139
139
  The access token needs permissions: <strong>Mux Video </strong>
140
140
  (Full Access) and <strong>Mux Data</strong> (Read)
141
141
  <br />
142
+ To use Signed URLs, the token must also have System permissions.
143
+ <br />
142
144
  The credentials will be stored safely in a hidden document only available to
143
145
  editors.
144
146
  </Text>
@@ -0,0 +1,122 @@
1
+ import {Button, Dialog, Flex, Stack, Text, TextInput} from '@sanity/ui'
2
+ import React, {useId, useMemo, useState} from 'react'
3
+ import {getDevicePixelRatio} from 'use-device-pixel-ratio'
4
+
5
+ import {useDialogStateContext} from '../context/DialogStateContext'
6
+ import {useClient} from '../hooks/useClient'
7
+ import {
8
+ formatSecondsToHHMMSS,
9
+ getSecondsFromTimeFormat,
10
+ isValidTimeFormat,
11
+ } from '../util/formatSeconds'
12
+ import type {VideoAssetDocument} from '../util/types'
13
+ import VideoThumbnail from './VideoThumbnail'
14
+
15
+ export interface Props {
16
+ asset: VideoAssetDocument
17
+ currentTime?: number
18
+ }
19
+
20
+ export default function EditThumbnailDialog({asset, currentTime = 0}: Props) {
21
+ const client = useClient()
22
+
23
+ const {setDialogState} = useDialogStateContext()
24
+ const dialogId = `EditThumbnailDialog${useId()}`
25
+
26
+ const [timeFormatted, setTimeFormatted] = useState<string>(() =>
27
+ formatSecondsToHHMMSS(currentTime)
28
+ )
29
+ const [nextTime, setNextTime] = useState<number>(currentTime)
30
+ const [inputError, setInputError] = useState<string>('')
31
+
32
+ const assetWithNewThumbnail = useMemo(() => ({...asset, thumbTime: nextTime}), [asset, nextTime])
33
+ const [saving, setSaving] = useState(false)
34
+ const [saveThumbnailError, setSaveThumbnailError] = useState<Error | null>(null)
35
+ const handleSave = () => {
36
+ setSaving(true)
37
+ client
38
+ .patch(asset._id!)
39
+ .set({thumbTime: nextTime})
40
+ .commit({returnDocuments: false})
41
+ .then(() => void setDialogState(false))
42
+ .catch(setSaveThumbnailError)
43
+ .finally(() => void setSaving(false))
44
+ }
45
+ const width = 300 * getDevicePixelRatio({maxDpr: 2})
46
+
47
+ if (saveThumbnailError) {
48
+ // eslint-disable-next-line no-warning-comments
49
+ // @TODO handle errors more gracefully
50
+ throw saveThumbnailError
51
+ }
52
+
53
+ const handleInputChange = (event: React.FormEvent<HTMLInputElement>) => {
54
+ const value = event.currentTarget.value
55
+ setTimeFormatted(value)
56
+
57
+ if (isValidTimeFormat(value)) {
58
+ setInputError('')
59
+ const totalSeconds = getSecondsFromTimeFormat(value)
60
+ setNextTime(totalSeconds)
61
+ } else {
62
+ setInputError('Invalid time format')
63
+ }
64
+ }
65
+
66
+ return (
67
+ <Dialog
68
+ id={dialogId}
69
+ header="Edit thumbnail"
70
+ onClose={() => setDialogState(false)}
71
+ footer={
72
+ <Stack padding={3}>
73
+ <Button
74
+ key="thumbnail"
75
+ disabled={inputError !== ''}
76
+ mode="ghost"
77
+ tone="primary"
78
+ loading={saving}
79
+ onClick={handleSave}
80
+ text="Set new thumbnail"
81
+ />
82
+ </Stack>
83
+ }
84
+ >
85
+ <Stack space={3} padding={3}>
86
+ <Stack space={2}>
87
+ <Text size={1} weight="semibold">
88
+ Current:
89
+ </Text>
90
+ <VideoThumbnail asset={asset} width={width} staticImage />
91
+ </Stack>
92
+ <Stack space={2}>
93
+ <Text size={1} weight="semibold">
94
+ New:
95
+ </Text>
96
+ <VideoThumbnail asset={assetWithNewThumbnail} width={width} staticImage />
97
+ </Stack>
98
+
99
+ <Stack space={2}>
100
+ <Flex align={'center'} justify={'center'}>
101
+ <Text size={5} weight="semibold">
102
+ Or
103
+ </Text>
104
+ </Flex>
105
+ </Stack>
106
+
107
+ <Stack space={2}>
108
+ <Text size={1} weight="semibold">
109
+ Selected time for thumbnail (hh:mm:ss):
110
+ </Text>
111
+ <TextInput
112
+ size={1}
113
+ value={timeFormatted}
114
+ placeholder="hh:mm:ss"
115
+ onChange={handleInputChange}
116
+ customValidity={inputError}
117
+ />
118
+ </Stack>
119
+ </Stack>
120
+ </Dialog>
121
+ )
122
+ }