diff options
Diffstat (limited to 'src/state/queries/video/video-upload.web.ts')
-rw-r--r-- | src/state/queries/video/video-upload.web.ts | 137 |
1 files changed, 73 insertions, 64 deletions
diff --git a/src/state/queries/video/video-upload.web.ts b/src/state/queries/video/video-upload.web.ts index c93e20603..bbae64199 100644 --- a/src/state/queries/video/video-upload.web.ts +++ b/src/state/queries/video/video-upload.web.ts @@ -1,86 +1,95 @@ import {AppBskyVideoDefs} from '@atproto/api' +import {BskyAgent} from '@atproto/api' +import {I18n} from '@lingui/core' import {msg} from '@lingui/macro' -import {useLingui} from '@lingui/react' -import {useMutation} from '@tanstack/react-query' import {nanoid} from 'nanoid/non-secure' -import {cancelable} from '#/lib/async/cancelable' +import {AbortError} from '#/lib/async/cancelable' import {ServerError} from '#/lib/media/video/errors' import {CompressedVideo} from '#/lib/media/video/types' import {createVideoEndpointUrl, mimeToExt} from '#/state/queries/video/util' -import {useSession} from '#/state/session' -import {useServiceAuthToken, useVideoUploadLimits} from './video-upload.shared' +import {getServiceAuthToken, getVideoUploadLimits} from './video-upload.shared' -export const useUploadVideoMutation = ({ - onSuccess, - onError, +export async function uploadVideo({ + video, + agent, + did, setProgress, signal, + _, }: { - onSuccess: (response: AppBskyVideoDefs.JobStatus) => void - onError: (e: any) => void + video: CompressedVideo + agent: BskyAgent + did: string setProgress: (progress: number) => void signal: AbortSignal -}) => { - const {currentAccount} = useSession() - const getToken = useServiceAuthToken({ + _: I18n['_'] +}) { + if (signal.aborted) { + throw new AbortError() + } + await getVideoUploadLimits(agent, _) + + const uri = createVideoEndpointUrl('/xrpc/app.bsky.video.uploadVideo', { + did, + name: `${nanoid(12)}.${mimeToExt(video.mimeType)}`, + }) + + let bytes = video.bytes + if (!bytes) { + if (signal.aborted) { + throw new AbortError() + } + bytes = await fetch(video.uri).then(res => res.arrayBuffer()) + } + + if (signal.aborted) { + throw new AbortError() + } + const token = await getServiceAuthToken({ + agent, lxm: 'com.atproto.repo.uploadBlob', exp: Date.now() / 1000 + 60 * 30, // 30 minutes }) - const checkLimits = useVideoUploadLimits() - const {_} = useLingui() - - return useMutation({ - mutationKey: ['video', 'upload'], - mutationFn: cancelable(async (video: CompressedVideo) => { - await checkLimits() - const uri = createVideoEndpointUrl('/xrpc/app.bsky.video.uploadVideo', { - did: currentAccount!.did, - name: `${nanoid(12)}.${mimeToExt(video.mimeType)}`, + if (signal.aborted) { + throw new AbortError() + } + const xhr = new XMLHttpRequest() + const res = await new Promise<AppBskyVideoDefs.JobStatus>( + (resolve, reject) => { + xhr.upload.addEventListener('progress', e => { + const progress = e.loaded / e.total + setProgress(progress) }) - - let bytes = video.bytes - if (!bytes) { - bytes = await fetch(video.uri).then(res => res.arrayBuffer()) + xhr.onloadend = () => { + if (signal.aborted) { + reject(new AbortError()) + } else if (xhr.readyState === 4) { + const uploadRes = JSON.parse( + xhr.responseText, + ) as AppBskyVideoDefs.JobStatus + resolve(uploadRes) + } else { + reject(new ServerError(_(msg`Failed to upload video`))) + } } - - const token = await getToken() - - const xhr = new XMLHttpRequest() - const res = await new Promise<AppBskyVideoDefs.JobStatus>( - (resolve, reject) => { - xhr.upload.addEventListener('progress', e => { - const progress = e.loaded / e.total - setProgress(progress) - }) - xhr.onloadend = () => { - if (xhr.readyState === 4) { - const uploadRes = JSON.parse( - xhr.responseText, - ) as AppBskyVideoDefs.JobStatus - resolve(uploadRes) - } else { - reject(new ServerError(_(msg`Failed to upload video`))) - } - } - xhr.onerror = () => { - reject(new ServerError(_(msg`Failed to upload video`))) - } - xhr.open('POST', uri) - xhr.setRequestHeader('Content-Type', video.mimeType) - xhr.setRequestHeader('Authorization', `Bearer ${token}`) - xhr.send(bytes) - }, - ) - - if (!res.jobId) { - throw new ServerError(res.error || _(msg`Failed to upload video`)) + xhr.onerror = () => { + reject(new ServerError(_(msg`Failed to upload video`))) } + xhr.open('POST', uri) + xhr.setRequestHeader('Content-Type', video.mimeType) + xhr.setRequestHeader('Authorization', `Bearer ${token}`) + xhr.send(bytes) + }, + ) - return res - }, signal), - onError, - onSuccess, - }) + if (!res.jobId) { + throw new ServerError(res.error || _(msg`Failed to upload video`)) + } + + if (signal.aborted) { + throw new AbortError() + } + return res } |