convert useLoadDraft() hook to regular async function

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Samuel Newman
2026-01-27 19:57:32 +02:00
parent 6d46a70b7a
commit e15c6c3c64
2 changed files with 42 additions and 53 deletions
+2 -3
View File
@@ -131,7 +131,7 @@ import {useAnalytics} from '#/analytics'
import {IS_ANDROID, IS_IOS, IS_NATIVE, IS_WEB} from '#/env' import {IS_ANDROID, IS_IOS, IS_NATIVE, IS_WEB} from '#/env'
import {BottomSheetPortalProvider} from '../../../../modules/bottom-sheet' import {BottomSheetPortalProvider} from '../../../../modules/bottom-sheet'
import {draftToComposerPosts} from './drafts/state/api' import {draftToComposerPosts} from './drafts/state/api'
import {useLoadDraft, useSaveDraftMutation} from './drafts/state/queries' import {loadDraft, useSaveDraftMutation} from './drafts/state/queries'
import {type DraftSummary} from './drafts/state/schema' import {type DraftSummary} from './drafts/state/schema'
import {PostLanguageSelect} from './select-language/PostLanguageSelect' import {PostLanguageSelect} from './select-language/PostLanguageSelect'
import { import {
@@ -193,7 +193,6 @@ export const ComposePost = ({
const discardPromptControl = Prompt.usePromptControl() const discardPromptControl = Prompt.usePromptControl()
const {mutateAsync: saveDraft, isPending: _isSavingDraft} = const {mutateAsync: saveDraft, isPending: _isSavingDraft} =
useSaveDraftMutation() useSaveDraftMutation()
const loadDraft = useLoadDraft()
const {closeAllDialogs} = useDialogStateControlContext() const {closeAllDialogs} = useDialogStateControlContext()
const {closeAllModals} = useModalControls() const {closeAllModals} = useModalControls()
const {data: preferences} = usePreferencesQuery() const {data: preferences} = usePreferencesQuery()
@@ -343,7 +342,7 @@ export const ComposePost = ({
loadedMedia, loadedMedia,
}) })
}, },
[loadDraft, composerDispatch], [composerDispatch],
) )
const [publishOnUpload, setPublishOnUpload] = useState(false) const [publishOnUpload, setPublishOnUpload] = useState(false)
+40 -50
View File
@@ -1,4 +1,3 @@
import {useCallback} from 'react'
import {AppBskyDraftCreateDraft, type AppBskyDraftDefs} from '@atproto/api' import {AppBskyDraftCreateDraft, type AppBskyDraftDefs} from '@atproto/api'
import { import {
useInfiniteQuery, useInfiniteQuery,
@@ -40,53 +39,46 @@ export function useDraftsQuery() {
} }
/** /**
* Hook to load a draft's local media for editing. * Load a draft's local media for editing.
* Takes the full Draft object (from DraftSummary) to avoid re-fetching. * Takes the full Draft object (from DraftSummary) to avoid re-fetching.
*/ */
export function useLoadDraft() { export async function loadDraft(draft: AppBskyDraftDefs.Draft): Promise<{
return useCallback( loadedMedia: Map<string, string>
async ( }> {
draft: AppBskyDraftDefs.Draft, // Load local media files
): Promise<{ const loadedMedia = new Map<string, string>()
loadedMedia: Map<string, string> for (const post of draft.posts) {
}> => { // Load images
// Load local media files if (post.embedImages) {
const loadedMedia = new Map<string, string>() for (const img of post.embedImages) {
for (const post of draft.posts) { try {
// Load images const url = await storage.loadMediaFromLocal(img.localRef.path)
if (post.embedImages) { loadedMedia.set(img.localRef.path, url)
for (const img of post.embedImages) { } catch (e) {
try { logger.warn('Failed to load draft image', {
const url = await storage.loadMediaFromLocal(img.localRef.path) path: img.localRef.path,
loadedMedia.set(img.localRef.path, url) error: e,
} catch (e) { })
logger.warn('Failed to load draft image', {
path: img.localRef.path,
error: e,
})
}
}
}
// Load videos
if (post.embedVideos) {
for (const vid of post.embedVideos) {
try {
const url = await storage.loadMediaFromLocal(vid.localRef.path)
loadedMedia.set(vid.localRef.path, url)
} catch (e) {
logger.warn('Failed to load draft video', {
path: vid.localRef.path,
error: e,
})
}
}
} }
} }
}
// Load videos
if (post.embedVideos) {
for (const vid of post.embedVideos) {
try {
const url = await storage.loadMediaFromLocal(vid.localRef.path)
loadedMedia.set(vid.localRef.path, url)
} catch (e) {
logger.warn('Failed to load draft video', {
path: vid.localRef.path,
error: e,
})
}
}
}
}
return {loadedMedia} return {loadedMedia}
},
[],
)
} }
/** /**
@@ -158,12 +150,15 @@ export function useDeleteDraftMutation() {
return useMutation({ return useMutation({
mutationFn: async ({ mutationFn: async ({
draftId, draftId,
draft,
}: { }: {
draftId: string draftId: string
draft: AppBskyDraftDefs.Draft draft: AppBskyDraftDefs.Draft
}) => { }) => {
// Delete local media files // Delete from server first - if this fails, we keep local media for retry
await agent.app.bsky.draft.deleteDraft({id: draftId})
},
onSuccess: async (_, {draft}) => {
// Only delete local media after server deletion succeeds
for (const post of draft.posts) { for (const post of draft.posts) {
if (post.embedImages) { if (post.embedImages) {
for (const img of post.embedImages) { for (const img of post.embedImages) {
@@ -176,11 +171,6 @@ export function useDeleteDraftMutation() {
} }
} }
} }
// Delete from server
await agent.app.bsky.draft.deleteDraft({id: draftId})
},
onSuccess: () => {
queryClient.invalidateQueries({queryKey: DRAFTS_QUERY_KEY}) queryClient.invalidateQueries({queryKey: DRAFTS_QUERY_KEY})
}, },
}) })