diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/api/index.ts | 32 | ||||
-rw-r--r-- | src/view/com/composer/Composer.tsx | 47 | ||||
-rw-r--r-- | src/view/com/composer/state/video.ts | 48 | ||||
-rw-r--r-- | src/view/com/composer/videos/SubtitleDialog.tsx | 12 |
4 files changed, 89 insertions, 50 deletions
diff --git a/src/lib/api/index.ts b/src/lib/api/index.ts index 8b7925004..c7608ae55 100644 --- a/src/lib/api/index.ts +++ b/src/lib/api/index.ts @@ -1,5 +1,4 @@ import { - AppBskyEmbedDefs, AppBskyEmbedExternal, AppBskyEmbedImages, AppBskyEmbedRecord, @@ -7,7 +6,6 @@ import { AppBskyEmbedVideo, AppBskyFeedPostgate, AtUri, - BlobRef, BskyAgent, ComAtprotoLabelDefs, RichText, @@ -46,14 +44,7 @@ interface PostOpts { uri: string cid: string } - video?: { - blobRef: BlobRef - altText: string - captions: {lang: string; file: File}[] - aspectRatio?: AppBskyEmbedDefs.AspectRatio - } extLink?: ExternalEmbedDraft - images?: ComposerImage[] labels?: string[] threadgate: ThreadgateAllowUISetting[] postgate: AppBskyFeedPostgate.Record @@ -230,13 +221,15 @@ async function resolveMedia( | AppBskyEmbedVideo.Main | undefined > { - if (opts.images?.length) { + const state = opts.composerState + const media = state.embed.media + if (media?.type === 'images') { logger.debug(`Uploading images`, { - count: opts.images.length, + count: media.images.length, }) opts.onStateChange?.(`Uploading images...`) const images: AppBskyEmbedImages.Image[] = await Promise.all( - opts.images.map(async (image, i) => { + media.images.map(async (image, i) => { logger.debug(`Compressing image #${i}`) const {path, width, height, mime} = await compressImage(image) logger.debug(`Uploading image #${i}`) @@ -253,9 +246,10 @@ async function resolveMedia( images, } } - if (opts.video) { + if (media?.type === 'video' && media.video.status === 'done') { + const video = media.video const captions = await Promise.all( - opts.video.captions + video.captions .filter(caption => caption.lang !== '') .map(async caption => { const {data} = await agent.uploadBlob(caption.file, { @@ -266,13 +260,17 @@ async function resolveMedia( ) return { $type: 'app.bsky.embed.video', - video: opts.video.blobRef, - alt: opts.video.altText || undefined, + video: video.pendingPublish.blobRef, + alt: video.altText || undefined, captions: captions.length === 0 ? undefined : captions, - aspectRatio: opts.video.aspectRatio, + aspectRatio: { + width: video.asset.width, + height: video.asset.height, + }, } } if (opts.extLink) { + // TODO: Read this from composer state as well. if (opts.extLink.embed) { return undefined } diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx index b5f2d84d4..227964907 100644 --- a/src/view/com/composer/Composer.tsx +++ b/src/view/com/composer/Composer.tsx @@ -184,9 +184,6 @@ export const ComposePost = ({ initQuote, ) - const [videoAltText, setVideoAltText] = useState('') - const [captions, setCaptions] = useState<{lang: string; file: File}[]>([]) - // TODO: Move more state here. const [composerState, dispatch] = useReducer( composerReducer, @@ -422,10 +419,9 @@ export const ComposePost = ({ try { postUri = ( await apilib.post(agent, { - composerState, // TODO: not used yet. + composerState, // TODO: move more state here. rawText: richtext.text, replyTo: replyTo?.uri, - images, quote, extLink, labels, @@ -433,18 +429,6 @@ export const ComposePost = ({ postgate, onStateChange: setProcessingState, langs: toPostLanguages(langPrefs.postLanguage), - video: - videoState.status === 'done' - ? { - blobRef: videoState.pendingPublish.blobRef, - altText: videoAltText, - captions: captions, - aspectRatio: { - width: videoState.asset.width, - height: videoState.asset.height, - }, - } - : undefined, }) ).uri try { @@ -522,7 +506,6 @@ export const ComposePost = ({ [ _, agent, - captions, composerState, extLink, images, @@ -541,9 +524,7 @@ export const ComposePost = ({ setExtLink, setLangPrefs, threadgateAllowUISettings, - videoAltText, videoState.asset, - videoState.pendingPublish, videoState.status, ], ) @@ -811,10 +792,28 @@ export const ComposePost = ({ /> ) : null)} <SubtitleDialogBtn - defaultAltText={videoAltText} - saveAltText={setVideoAltText} - captions={captions} - setCaptions={setCaptions} + defaultAltText={videoState.altText} + saveAltText={altText => + dispatch({ + type: 'embed_update_video', + videoAction: { + type: 'update_alt_text', + altText, + signal: videoState.abortController.signal, + }, + }) + } + captions={videoState.captions} + setCaptions={updater => { + dispatch({ + type: 'embed_update_video', + videoAction: { + type: 'update_captions', + updater, + signal: videoState.abortController.signal, + }, + }) + }} /> </Animated.View> )} diff --git a/src/view/com/composer/state/video.ts b/src/view/com/composer/state/video.ts index 269505657..e29687200 100644 --- a/src/view/com/composer/state/video.ts +++ b/src/view/com/composer/state/video.ts @@ -4,8 +4,6 @@ import {JobStatus} from '@atproto/api/dist/client/types/app/bsky/video/defs' import {I18n} from '@lingui/core' import {msg} from '@lingui/macro' -import {createVideoAgent} from '#/lib/media/video/util' -import {uploadVideo} from '#/lib/media/video/upload' import {AbortError} from '#/lib/async/cancelable' import {compressVideo} from '#/lib/media/video/compress' import { @@ -14,8 +12,12 @@ import { VideoTooLargeError, } from '#/lib/media/video/errors' import {CompressedVideo} from '#/lib/media/video/types' +import {uploadVideo} from '#/lib/media/video/upload' +import {createVideoAgent} from '#/lib/media/video/util' import {logger} from '#/logger' +type CaptionsTrack = {lang: string; file: File} + export type VideoAction = | { type: 'compressing_to_uploading' @@ -41,6 +43,16 @@ export type VideoAction = signal: AbortSignal } | { + type: 'update_alt_text' + altText: string + signal: AbortSignal + } + | { + type: 'update_captions' + updater: (prev: CaptionsTrack[]) => CaptionsTrack[] + signal: AbortSignal + } + | { type: 'update_job_status' jobStatus: AppBskyVideoDefs.JobStatus signal: AbortSignal @@ -57,6 +69,8 @@ export const NO_VIDEO = Object.freeze({ video: undefined, jobId: undefined, pendingPublish: undefined, + altText: '', + captions: [], }) export type NoVideoState = typeof NO_VIDEO @@ -70,6 +84,8 @@ type ErrorState = { jobId: string | null error: string pendingPublish?: undefined + altText: string + captions: CaptionsTrack[] } type CompressingState = { @@ -80,6 +96,8 @@ type CompressingState = { video?: undefined jobId?: undefined pendingPublish?: undefined + altText: string + captions: CaptionsTrack[] } type UploadingState = { @@ -90,6 +108,8 @@ type UploadingState = { video: CompressedVideo jobId?: undefined pendingPublish?: undefined + altText: string + captions: CaptionsTrack[] } type ProcessingState = { @@ -101,6 +121,8 @@ type ProcessingState = { jobId: string jobStatus: AppBskyVideoDefs.JobStatus | null pendingPublish?: undefined + altText: string + captions: CaptionsTrack[] } type DoneState = { @@ -111,6 +133,8 @@ type DoneState = { video: CompressedVideo jobId?: undefined pendingPublish: {blobRef: BlobRef; mutableProcessed: boolean} + altText: string + captions: CaptionsTrack[] } export type VideoState = @@ -129,6 +153,8 @@ export function createVideoState( progress: 0, abortController, asset, + altText: '', + captions: [], } } @@ -149,6 +175,8 @@ export function videoReducer( asset: state.asset ?? null, video: state.video ?? null, jobId: state.jobId ?? null, + altText: state.altText, + captions: state.captions, } } else if (action.type === 'update_progress') { if (state.status === 'compressing' || state.status === 'uploading') { @@ -164,6 +192,16 @@ export function videoReducer( asset: {...state.asset, width: action.width, height: action.height}, } } + } else if (action.type === 'update_alt_text') { + return { + ...state, + altText: action.altText, + } + } else if (action.type === 'update_captions') { + return { + ...state, + captions: action.updater(state.captions), + } } else if (action.type === 'compressing_to_uploading') { if (state.status === 'compressing') { return { @@ -172,6 +210,8 @@ export function videoReducer( abortController: state.abortController, asset: state.asset, video: action.video, + altText: state.altText, + captions: state.captions, } } return state @@ -185,6 +225,8 @@ export function videoReducer( video: state.video, jobId: action.jobId, jobStatus: null, + altText: state.altText, + captions: state.captions, } } } else if (action.type === 'update_job_status') { @@ -210,6 +252,8 @@ export function videoReducer( blobRef: action.blobRef, mutableProcessed: false, }, + altText: state.altText, + captions: state.captions, } } } diff --git a/src/view/com/composer/videos/SubtitleDialog.tsx b/src/view/com/composer/videos/SubtitleDialog.tsx index c07fdfc56..f66684d4e 100644 --- a/src/view/com/composer/videos/SubtitleDialog.tsx +++ b/src/view/com/composer/videos/SubtitleDialog.tsx @@ -22,13 +22,13 @@ import {SubtitleFilePicker} from './SubtitleFilePicker' const MAX_NUM_CAPTIONS = 1 +type CaptionsTrack = {lang: string; file: File} + interface Props { defaultAltText: string - captions: {lang: string; file: File}[] + captions: CaptionsTrack[] saveAltText: (altText: string) => void - setCaptions: React.Dispatch< - React.SetStateAction<{lang: string; file: File}[]> - > + setCaptions: (updater: (prev: CaptionsTrack[]) => CaptionsTrack[]) => void } export function SubtitleDialogBtn(props: Props) { @@ -198,9 +198,7 @@ function SubtitleFileRow({ language: string file: File otherLanguages: {code2: string; code3: string; name: string}[] - setCaptions: React.Dispatch< - React.SetStateAction<{lang: string; file: File}[]> - > + setCaptions: (updater: (prev: CaptionsTrack[]) => CaptionsTrack[]) => void style: StyleProp<ViewStyle> }) { const {_} = useLingui() |