infinite query, rename file to queries
This commit is contained in:
@@ -130,12 +130,8 @@ import {Text} from '#/components/Typography'
|
|||||||
import {useAnalytics} from '#/analytics'
|
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 {
|
import {draftToComposerPosts} from './drafts/state/api'
|
||||||
draftToComposerPosts,
|
import {useLoadDraft, useSaveDraftMutation} from './drafts/state/queries'
|
||||||
threadgateToUISettings,
|
|
||||||
useLoadDraft,
|
|
||||||
useSaveDraft,
|
|
||||||
} from './drafts/state/hooks'
|
|
||||||
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 {
|
||||||
@@ -195,7 +191,8 @@ export const ComposePost = ({
|
|||||||
const setLangPrefs = useLanguagePrefsApi()
|
const setLangPrefs = useLanguagePrefsApi()
|
||||||
const textInput = useRef<TextInputRef>(null)
|
const textInput = useRef<TextInputRef>(null)
|
||||||
const discardPromptControl = Prompt.usePromptControl()
|
const discardPromptControl = Prompt.usePromptControl()
|
||||||
const {mutateAsync: saveDraft, isPending: _isSavingDraft} = useSaveDraft()
|
const {mutateAsync: saveDraft, isPending: _isSavingDraft} =
|
||||||
|
useSaveDraftMutation()
|
||||||
const loadDraft = useLoadDraft()
|
const loadDraft = useLoadDraft()
|
||||||
const {closeAllDialogs} = useDialogStateControlContext()
|
const {closeAllDialogs} = useDialogStateControlContext()
|
||||||
const {closeAllModals} = useModalControls()
|
const {closeAllModals} = useModalControls()
|
||||||
@@ -338,14 +335,14 @@ export const ComposePost = ({
|
|||||||
|
|
||||||
// Convert server draft to composer posts
|
// Convert server draft to composer posts
|
||||||
const posts = draftToComposerPosts(draft, loadedMedia)
|
const posts = draftToComposerPosts(draft, loadedMedia)
|
||||||
const threadgate = threadgateToUISettings(draft.threadgateAllow)
|
|
||||||
|
|
||||||
// Dispatch restore action (this also sets draftId in state)
|
// Dispatch restore action (this also sets draftId in state)
|
||||||
composerDispatch({
|
composerDispatch({
|
||||||
type: 'restore_from_draft',
|
type: 'restore_from_draft',
|
||||||
draftId: draftSummary.id,
|
draftId: draftSummary.id,
|
||||||
posts,
|
posts,
|
||||||
threadgate,
|
threadgateAllow: draft.threadgateAllow,
|
||||||
|
postgateEmbeddingRules: draft.postgateEmbeddingRules,
|
||||||
loadedMedia,
|
loadedMedia,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -402,8 +399,11 @@ export const ComposePost = ({
|
|||||||
|
|
||||||
// Clear the composer (discard current content)
|
// Clear the composer (discard current content)
|
||||||
const handleClearComposer = React.useCallback(() => {
|
const handleClearComposer = React.useCallback(() => {
|
||||||
composerDispatch({type: 'clear'})
|
composerDispatch({
|
||||||
}, [composerDispatch])
|
type: 'clear',
|
||||||
|
initInteractionSettings: preferences?.postInteractionSettings,
|
||||||
|
})
|
||||||
|
}, [composerDispatch, preferences?.postInteractionSettings])
|
||||||
|
|
||||||
const insets = useSafeAreaInsets()
|
const insets = useSafeAreaInsets()
|
||||||
const viewStyles = useMemo(
|
const viewStyles = useMemo(
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {Button, ButtonText} from '#/components/Button'
|
|||||||
import * as Dialog from '#/components/Dialog'
|
import * as Dialog from '#/components/Dialog'
|
||||||
import * as Prompt from '#/components/Prompt'
|
import * as Prompt from '#/components/Prompt'
|
||||||
import {DraftsListDialog} from './DraftsListDialog'
|
import {DraftsListDialog} from './DraftsListDialog'
|
||||||
import {useSaveDraft} from './state/hooks'
|
import {useSaveDraftMutation} from './state/queries'
|
||||||
import {type DraftSummary} from './state/schema'
|
import {type DraftSummary} from './state/schema'
|
||||||
|
|
||||||
export function DraftsButton({
|
export function DraftsButton({
|
||||||
@@ -27,7 +27,7 @@ export function DraftsButton({
|
|||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const draftsDialogControl = Dialog.useDialogControl()
|
const draftsDialogControl = Dialog.useDialogControl()
|
||||||
const savePromptControl = Prompt.usePromptControl()
|
const savePromptControl = Prompt.usePromptControl()
|
||||||
const {isPending: isSaving} = useSaveDraft()
|
const {isPending: isSaving} = useSaveDraftMutation()
|
||||||
|
|
||||||
const handlePress = () => {
|
const handlePress = () => {
|
||||||
if (isEmpty || !isDirty) {
|
if (isEmpty || !isDirty) {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import * as Dialog from '#/components/Dialog'
|
|||||||
import {PageX_Stroke2_Corner0_Rounded_Large as PageXIcon} from '#/components/icons/PageX'
|
import {PageX_Stroke2_Corner0_Rounded_Large as PageXIcon} from '#/components/icons/PageX'
|
||||||
import {Loader} from '#/components/Loader'
|
import {Loader} from '#/components/Loader'
|
||||||
import {DraftItem} from './DraftItem'
|
import {DraftItem} from './DraftItem'
|
||||||
import {useDeleteDraft, useDrafts} from './state/hooks'
|
import {useDeleteDraftMutation, useDraftsQuery} from './state/queries'
|
||||||
import {type DraftSummary} from './state/schema'
|
import {type DraftSummary} from './state/schema'
|
||||||
|
|
||||||
export function DraftsListDialog({
|
export function DraftsListDialog({
|
||||||
@@ -23,8 +23,13 @@ export function DraftsListDialog({
|
|||||||
}) {
|
}) {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {data: drafts, isLoading} = useDrafts()
|
const {data, isLoading} = useDraftsQuery()
|
||||||
const {mutate: deleteDraft} = useDeleteDraft()
|
const {mutate: deleteDraft} = useDeleteDraftMutation()
|
||||||
|
|
||||||
|
const drafts = useMemo(
|
||||||
|
() => data?.pages.flatMap(page => page.drafts) ?? [],
|
||||||
|
[data],
|
||||||
|
)
|
||||||
|
|
||||||
const handleSelectDraft = useCallback(
|
const handleSelectDraft = useCallback(
|
||||||
(summary: DraftSummary) => {
|
(summary: DraftSummary) => {
|
||||||
@@ -105,7 +110,7 @@ export function DraftsListDialog({
|
|||||||
<Dialog.Outer control={control}>
|
<Dialog.Outer control={control}>
|
||||||
{isNative && header}
|
{isNative && header}
|
||||||
<Dialog.InnerFlatList
|
<Dialog.InnerFlatList
|
||||||
data={drafts ?? []}
|
data={drafts}
|
||||||
renderItem={renderItem}
|
renderItem={renderItem}
|
||||||
keyExtractor={item => item.id}
|
keyExtractor={item => item.id}
|
||||||
ListHeaderComponent={web(header)}
|
ListHeaderComponent={web(header)}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Type converters for Draft API - convert between ComposerState and server Draft types.
|
* Type converters for Draft API - convert between ComposerState and server Draft types.
|
||||||
*/
|
*/
|
||||||
import {type AppBskyDraftDefs} from '@atproto/api'
|
import {type AppBskyDraftDefs, RichText} from '@atproto/api'
|
||||||
import {nanoid} from 'nanoid/non-secure'
|
import {nanoid} from 'nanoid/non-secure'
|
||||||
|
|
||||||
import {type ComposerImage} from '#/state/gallery'
|
import {type ComposerImage} from '#/state/gallery'
|
||||||
@@ -341,11 +341,9 @@ export function draftToComposerPosts(
|
|||||||
draft: AppBskyDraftDefs.Draft,
|
draft: AppBskyDraftDefs.Draft,
|
||||||
loadedMedia: Map<string, string>,
|
loadedMedia: Map<string, string>,
|
||||||
): PostDraft[] {
|
): PostDraft[] {
|
||||||
// Import these dynamically to avoid circular dependencies
|
|
||||||
const {RichText} = require('@atproto/api')
|
|
||||||
|
|
||||||
return draft.posts.map((post, index) => {
|
return draft.posts.map((post, index) => {
|
||||||
const richtext = new RichText({text: post.text || ''})
|
const richtext = new RichText({text: post.text || ''})
|
||||||
|
richtext.detectFacetsWithoutResolution()
|
||||||
|
|
||||||
const embed: EmbedDraft = {
|
const embed: EmbedDraft = {
|
||||||
quote: undefined,
|
quote: undefined,
|
||||||
@@ -434,7 +432,7 @@ export function draftToComposerPosts(
|
|||||||
// Parse labels
|
// Parse labels
|
||||||
const labels: string[] = []
|
const labels: string[] = []
|
||||||
if (post.labels && 'values' in post.labels) {
|
if (post.labels && 'values' in post.labels) {
|
||||||
for (const val of (post.labels as {values: {val: string}[]}).values) {
|
for (const val of post.labels.values) {
|
||||||
labels.push(val.val)
|
labels.push(val.val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-20
@@ -1,18 +1,16 @@
|
|||||||
import {useCallback} from 'react'
|
import {useCallback} from 'react'
|
||||||
import {AppBskyDraftCreateDraft, type AppBskyDraftDefs} from '@atproto/api'
|
import {AppBskyDraftCreateDraft, type AppBskyDraftDefs} from '@atproto/api'
|
||||||
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
|
import {
|
||||||
|
useInfiniteQuery,
|
||||||
|
useMutation,
|
||||||
|
useQueryClient,
|
||||||
|
} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {isNetworkError} from '#/lib/strings/errors'
|
import {isNetworkError} from '#/lib/strings/errors'
|
||||||
import {useAgent} from '#/state/session'
|
import {useAgent} from '#/state/session'
|
||||||
import {type ComposerState} from '#/view/com/composer/state/composer'
|
import {type ComposerState} from '#/view/com/composer/state/composer'
|
||||||
import {
|
import {composerStateToDraft, draftViewToSummary} from './api'
|
||||||
composerStateToDraft,
|
|
||||||
draftToComposerPosts,
|
|
||||||
draftViewToSummary,
|
|
||||||
threadgateToUISettings,
|
|
||||||
} from './api'
|
|
||||||
import {logger} from './logger'
|
import {logger} from './logger'
|
||||||
import {type DraftSummary} from './schema'
|
|
||||||
import * as storage from './storage'
|
import * as storage from './storage'
|
||||||
|
|
||||||
const DRAFTS_QUERY_KEY = ['drafts']
|
const DRAFTS_QUERY_KEY = ['drafts']
|
||||||
@@ -20,19 +18,24 @@ const DRAFTS_QUERY_KEY = ['drafts']
|
|||||||
/**
|
/**
|
||||||
* Hook to list all drafts for the current account
|
* Hook to list all drafts for the current account
|
||||||
*/
|
*/
|
||||||
export function useDrafts() {
|
export function useDraftsQuery() {
|
||||||
const agent = useAgent()
|
const agent = useAgent()
|
||||||
|
|
||||||
return useQuery<DraftSummary[]>({
|
return useInfiniteQuery({
|
||||||
queryKey: DRAFTS_QUERY_KEY,
|
queryKey: DRAFTS_QUERY_KEY,
|
||||||
queryFn: async () => {
|
queryFn: async ({pageParam}) => {
|
||||||
// Ensure media cache is populated before checking which media exists
|
// Ensure media cache is populated before checking which media exists
|
||||||
await storage.ensureMediaCachePopulated()
|
await storage.ensureMediaCachePopulated()
|
||||||
const res = await agent.app.bsky.draft.getDrafts({})
|
const res = await agent.app.bsky.draft.getDrafts({cursor: pageParam})
|
||||||
return res.data.drafts.map(view =>
|
return {
|
||||||
draftViewToSummary(view, path => storage.mediaExists(path)),
|
cursor: res.data.cursor,
|
||||||
)
|
drafts: res.data.drafts.map(view =>
|
||||||
|
draftViewToSummary(view, path => storage.mediaExists(path)),
|
||||||
|
),
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
initialPageParam: undefined as string | undefined,
|
||||||
|
getNextPageParam: page => page.cursor,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +102,7 @@ export function useLoadDraft() {
|
|||||||
/**
|
/**
|
||||||
* Hook to save a draft
|
* Hook to save a draft
|
||||||
*/
|
*/
|
||||||
export function useSaveDraft() {
|
export function useSaveDraftMutation() {
|
||||||
const agent = useAgent()
|
const agent = useAgent()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
|
|
||||||
@@ -157,7 +160,7 @@ export function useSaveDraft() {
|
|||||||
/**
|
/**
|
||||||
* Hook to delete a draft
|
* Hook to delete a draft
|
||||||
*/
|
*/
|
||||||
export function useDeleteDraft() {
|
export function useDeleteDraftMutation() {
|
||||||
const agent = useAgent()
|
const agent = useAgent()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
|
|
||||||
@@ -191,6 +194,3 @@ export function useDeleteDraft() {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-export utilities for use in composer
|
|
||||||
export {draftToComposerPosts, threadgateToUISettings}
|
|
||||||
Reference in New Issue
Block a user