refactor(web): migrate share chat swr to react query

This commit is contained in:
yyh 2025-12-27 12:39:57 +08:00
parent c393d7a2dc
commit fd7f8fd1f0
No known key found for this signature in database
3 changed files with 202 additions and 42 deletions

View File

@ -20,7 +20,6 @@ import {
useState,
} from 'react'
import { useTranslation } from 'react-i18next'
import useSWR from 'swr'
import { getProcessedFilesFromResponse } from '@/app/components/base/file-uploader/utils'
import { useToastContext } from '@/app/components/base/toast'
import { InputVarType } from '@/app/components/workflow/types'
@ -29,14 +28,17 @@ import { useAppFavicon } from '@/hooks/use-app-favicon'
import { changeLanguage } from '@/i18n-config/i18next-config'
import {
delConversation,
fetchChatList,
fetchConversations,
generationConversationName,
pinConversation,
renameConversation,
unpinConversation,
updateFeedback,
} from '@/service/share'
import {
useInvalidateShareConversations,
useShareChatList,
useShareConversationName,
useShareConversations,
} from '@/service/use-share'
import { TransferMethod } from '@/types/app'
import { addFileInfos, sortAgentSorts } from '../../../tools/utils'
import { CONVERSATION_ID_INFO } from '../constants'
@ -174,21 +176,42 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
return currentConversationId
}, [currentConversationId, newConversationId])
const { data: appPinnedConversationData, mutate: mutateAppPinnedConversationData } = useSWR(
appId ? ['appConversationData', isInstalledApp, appId, true] : null,
() => fetchConversations(isInstalledApp, appId, undefined, true, 100),
{ revalidateOnFocus: false, revalidateOnReconnect: false },
)
const { data: appConversationData, isLoading: appConversationDataLoading, mutate: mutateAppConversationData } = useSWR(
appId ? ['appConversationData', isInstalledApp, appId, false] : null,
() => fetchConversations(isInstalledApp, appId, undefined, false, 100),
{ revalidateOnFocus: false, revalidateOnReconnect: false },
)
const { data: appChatListData, isLoading: appChatListDataLoading } = useSWR(
chatShouldReloadKey ? ['appChatList', chatShouldReloadKey, isInstalledApp, appId] : null,
() => fetchChatList(chatShouldReloadKey, isInstalledApp, appId),
{ revalidateOnFocus: false, revalidateOnReconnect: false },
)
const { data: appPinnedConversationData } = useShareConversations({
isInstalledApp,
appId,
pinned: true,
limit: 100,
}, {
enabled: !!appId,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
})
const {
data: appConversationData,
isLoading: appConversationDataLoading,
} = useShareConversations({
isInstalledApp,
appId,
pinned: false,
limit: 100,
}, {
enabled: !!appId,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
})
const {
data: appChatListData,
isLoading: appChatListDataLoading,
} = useShareChatList({
conversationId: chatShouldReloadKey,
isInstalledApp,
appId,
}, {
enabled: !!chatShouldReloadKey,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
})
const invalidateShareConversations = useInvalidateShareConversations()
const [clearChatList, setClearChatList] = useState(false)
const [isResponding, setIsResponding] = useState(false)
@ -309,7 +332,13 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
handleNewConversationInputsChange(conversationInputs)
}, [handleNewConversationInputsChange, inputsForms])
const { data: newConversation } = useSWR(newConversationId ? [isInstalledApp, appId, newConversationId] : null, () => generationConversationName(isInstalledApp, appId, newConversationId), { revalidateOnFocus: false })
const { data: newConversation } = useShareConversationName({
conversationId: newConversationId,
isInstalledApp,
appId,
}, {
refetchOnWindowFocus: false,
})
const [originConversationList, setOriginConversationList] = useState<ConversationItem[]>([])
useEffect(() => {
if (appConversationData?.data && !appConversationDataLoading)
@ -429,9 +458,8 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
setClearChatList(true)
}, [handleChangeConversation, setShowNewConversationItemInList, handleNewConversationInputsChange, setClearChatList, inputsForms])
const handleUpdateConversationList = useCallback(() => {
mutateAppConversationData()
mutateAppPinnedConversationData()
}, [mutateAppConversationData, mutateAppPinnedConversationData])
invalidateShareConversations()
}, [invalidateShareConversations])
const handlePinConversation = useCallback(async (conversationId: string) => {
await pinConversation(isInstalledApp, appId, conversationId)
@ -518,8 +546,8 @@ export const useChatWithHistory = (installedAppInfo?: InstalledApp) => {
setNewConversationId(newConversationId)
handleConversationIdInfoChange(newConversationId)
setShowNewConversationItemInList(false)
mutateAppConversationData()
}, [mutateAppConversationData, handleConversationIdInfoChange])
invalidateShareConversations()
}, [handleConversationIdInfoChange, invalidateShareConversations])
const handleFeedback = useCallback(async (messageId: string, feedback: Feedback) => {
await updateFeedback({ url: `/messages/${messageId}/feedbacks`, body: { rating: feedback.rating, content: feedback.content } }, isInstalledApp, appId)

View File

@ -19,18 +19,18 @@ import {
useState,
} from 'react'
import { useTranslation } from 'react-i18next'
import useSWR from 'swr'
import { useToastContext } from '@/app/components/base/toast'
import { addFileInfos, sortAgentSorts } from '@/app/components/tools/utils'
import { InputVarType } from '@/app/components/workflow/types'
import { useWebAppStore } from '@/context/web-app-context'
import { changeLanguage } from '@/i18n-config/i18next-config'
import { updateFeedback } from '@/service/share'
import {
fetchChatList,
fetchConversations,
generationConversationName,
updateFeedback,
} from '@/service/share'
useInvalidateShareConversations,
useShareChatList,
useShareConversationName,
useShareConversations,
} from '@/service/use-share'
import { TransferMethod } from '@/types/app'
import { getProcessedFilesFromResponse } from '../../file-uploader/utils'
import { CONVERSATION_ID_INFO } from '../constants'
@ -137,9 +137,30 @@ export const useEmbeddedChatbot = () => {
return currentConversationId
}, [currentConversationId, newConversationId])
const { data: appPinnedConversationData } = useSWR(['appConversationData', isInstalledApp, appId, true], () => fetchConversations(isInstalledApp, appId, undefined, true, 100))
const { data: appConversationData, isLoading: appConversationDataLoading, mutate: mutateAppConversationData } = useSWR(['appConversationData', isInstalledApp, appId, false], () => fetchConversations(isInstalledApp, appId, undefined, false, 100))
const { data: appChatListData, isLoading: appChatListDataLoading } = useSWR(chatShouldReloadKey ? ['appChatList', chatShouldReloadKey, isInstalledApp, appId] : null, () => fetchChatList(chatShouldReloadKey, isInstalledApp, appId))
const { data: appPinnedConversationData } = useShareConversations({
isInstalledApp,
appId,
pinned: true,
limit: 100,
})
const {
data: appConversationData,
isLoading: appConversationDataLoading,
} = useShareConversations({
isInstalledApp,
appId,
pinned: false,
limit: 100,
})
const {
data: appChatListData,
isLoading: appChatListDataLoading,
} = useShareChatList({
conversationId: chatShouldReloadKey,
isInstalledApp,
appId,
})
const invalidateShareConversations = useInvalidateShareConversations()
const [clearChatList, setClearChatList] = useState(false)
const [isResponding, setIsResponding] = useState(false)
@ -259,7 +280,13 @@ export const useEmbeddedChatbot = () => {
handleNewConversationInputsChange(conversationInputs)
}, [handleNewConversationInputsChange, inputsForms])
const { data: newConversation } = useSWR(newConversationId ? [isInstalledApp, appId, newConversationId] : null, () => generationConversationName(isInstalledApp, appId, newConversationId), { revalidateOnFocus: false })
const { data: newConversation } = useShareConversationName({
conversationId: newConversationId,
isInstalledApp,
appId,
}, {
refetchOnWindowFocus: false,
})
const [originConversationList, setOriginConversationList] = useState<ConversationItem[]>([])
useEffect(() => {
if (appConversationData?.data && !appConversationDataLoading)
@ -379,8 +406,8 @@ export const useEmbeddedChatbot = () => {
setNewConversationId(newConversationId)
handleConversationIdInfoChange(newConversationId)
setShowNewConversationItemInList(false)
mutateAppConversationData()
}, [mutateAppConversationData, handleConversationIdInfoChange])
invalidateShareConversations()
}, [handleConversationIdInfoChange, invalidateShareConversations])
const handleFeedback = useCallback(async (messageId: string, feedback: Feedback) => {
await updateFeedback({ url: `/messages/${messageId}/feedbacks`, body: { rating: feedback.rating, content: feedback.content } }, isInstalledApp, appId)

View File

@ -1,11 +1,58 @@
import type { AppConversationData, ConversationItem } from '@/models/share'
import { useQuery } from '@tanstack/react-query'
import { fetchAppInfo, fetchAppMeta, fetchAppParams, getAppAccessModeByAppCode } from './share'
import {
fetchAppInfo,
fetchAppMeta,
fetchAppParams,
fetchChatList,
fetchConversations,
generationConversationName,
getAppAccessModeByAppCode,
} from './share'
import { useInvalid } from './use-base'
const NAME_SPACE = 'webapp'
type ShareConversationsParams = {
isInstalledApp: boolean
appId?: string
lastId?: string
pinned?: boolean
limit?: number
}
type ShareChatListParams = {
conversationId: string
isInstalledApp: boolean
appId?: string
}
type ShareConversationNameParams = {
conversationId: string
isInstalledApp: boolean
appId?: string
}
type ShareQueryOptions = {
enabled?: boolean
refetchOnWindowFocus?: boolean
refetchOnReconnect?: boolean
}
export const shareQueryKeys = {
appAccessMode: (code: string | null) => [NAME_SPACE, 'appAccessMode', code] as const,
appInfo: [NAME_SPACE, 'appInfo'] as const,
appParams: [NAME_SPACE, 'appParams'] as const,
appMeta: [NAME_SPACE, 'appMeta'] as const,
conversations: [NAME_SPACE, 'conversations'] as const,
conversationList: (params: ShareConversationsParams) => [NAME_SPACE, 'conversations', params] as const,
chatList: (params: ShareChatListParams) => [NAME_SPACE, 'chatList', params] as const,
conversationName: (params: ShareConversationNameParams) => [NAME_SPACE, 'conversationName', params] as const,
}
export const useGetWebAppAccessModeByCode = (code: string | null) => {
return useQuery({
queryKey: [NAME_SPACE, 'appAccessMode', code],
queryKey: shareQueryKeys.appAccessMode(code),
queryFn: () => getAppAccessModeByAppCode(code!),
enabled: !!code,
staleTime: 0, // backend change the access mode may cause the logic error. Because /permission API is no cached.
@ -15,7 +62,7 @@ export const useGetWebAppAccessModeByCode = (code: string | null) => {
export const useGetWebAppInfo = () => {
return useQuery({
queryKey: [NAME_SPACE, 'appInfo'],
queryKey: shareQueryKeys.appInfo,
queryFn: () => {
return fetchAppInfo()
},
@ -24,7 +71,7 @@ export const useGetWebAppInfo = () => {
export const useGetWebAppParams = () => {
return useQuery({
queryKey: [NAME_SPACE, 'appParams'],
queryKey: shareQueryKeys.appParams,
queryFn: () => {
return fetchAppParams(false)
},
@ -33,9 +80,67 @@ export const useGetWebAppParams = () => {
export const useGetWebAppMeta = () => {
return useQuery({
queryKey: [NAME_SPACE, 'appMeta'],
queryKey: shareQueryKeys.appMeta,
queryFn: () => {
return fetchAppMeta(false)
},
})
}
export const useShareConversations = (params: ShareConversationsParams, options: ShareQueryOptions = {}) => {
const {
enabled = true,
refetchOnReconnect,
refetchOnWindowFocus,
} = options
const isEnabled = enabled && (!params.isInstalledApp || !!params.appId)
return useQuery<AppConversationData>({
queryKey: shareQueryKeys.conversationList(params),
queryFn: () => fetchConversations(
params.isInstalledApp,
params.appId,
params.lastId,
params.pinned,
params.limit,
),
enabled: isEnabled,
refetchOnReconnect,
refetchOnWindowFocus,
})
}
export const useShareChatList = (params: ShareChatListParams, options: ShareQueryOptions = {}) => {
const {
enabled = true,
refetchOnReconnect,
refetchOnWindowFocus,
} = options
const isEnabled = enabled && (!params.isInstalledApp || !!params.appId) && !!params.conversationId
return useQuery({
queryKey: shareQueryKeys.chatList(params),
queryFn: () => fetchChatList(params.conversationId, params.isInstalledApp, params.appId),
enabled: isEnabled,
refetchOnReconnect,
refetchOnWindowFocus,
})
}
export const useShareConversationName = (params: ShareConversationNameParams, options: ShareQueryOptions = {}) => {
const {
enabled = true,
refetchOnReconnect,
refetchOnWindowFocus,
} = options
const isEnabled = enabled && (!params.isInstalledApp || !!params.appId) && !!params.conversationId
return useQuery<ConversationItem>({
queryKey: shareQueryKeys.conversationName(params),
queryFn: () => generationConversationName(params.isInstalledApp, params.appId, params.conversationId),
enabled: isEnabled,
refetchOnReconnect,
refetchOnWindowFocus,
})
}
export const useInvalidateShareConversations = () => {
return useInvalid(shareQueryKeys.conversations)
}