index.tsx 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. import type { FC } from 'react'
  2. import {
  3. useEffect,
  4. useState,
  5. } from 'react'
  6. import { useAsyncEffect } from 'ahooks'
  7. import {
  8. ChatWithHistoryContext,
  9. useChatWithHistoryContext,
  10. } from './context'
  11. import { useChatWithHistory } from './hooks'
  12. import Sidebar from './sidebar'
  13. import HeaderInMobile from './header-in-mobile'
  14. import ConfigPanel from './config-panel'
  15. import ChatWrapper from './chat-wrapper'
  16. import type { InstalledApp } from '@/models/explore'
  17. import Loading from '@/app/components/base/loading'
  18. import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
  19. import { checkOrSetAccessToken } from '@/app/components/share/utils'
  20. import AppUnavailable from '@/app/components/base/app-unavailable'
  21. type ChatWithHistoryProps = {
  22. className?: string
  23. }
  24. const ChatWithHistory: FC<ChatWithHistoryProps> = ({
  25. className,
  26. }) => {
  27. const {
  28. appInfoError,
  29. appData,
  30. appInfoLoading,
  31. appPrevChatList,
  32. showConfigPanelBeforeChat,
  33. appChatListDataLoading,
  34. chatShouldReloadKey,
  35. isMobile,
  36. } = useChatWithHistoryContext()
  37. const chatReady = (!showConfigPanelBeforeChat || !!appPrevChatList.length)
  38. const customConfig = appData?.custom_config
  39. const site = appData?.site
  40. useEffect(() => {
  41. if (site) {
  42. if (customConfig)
  43. document.title = `${site.title}`
  44. else
  45. document.title = `${site.title} - Powered by Dify`
  46. }
  47. }, [site, customConfig])
  48. if (appInfoLoading) {
  49. return (
  50. <Loading type='app' />
  51. )
  52. }
  53. if (appInfoError) {
  54. return (
  55. <AppUnavailable />
  56. )
  57. }
  58. return (
  59. <div className={`h-full flex bg-white ${className} ${isMobile && 'flex-col'}`}>
  60. {
  61. !isMobile && (
  62. <Sidebar />
  63. )
  64. }
  65. {
  66. isMobile && (
  67. <HeaderInMobile />
  68. )
  69. }
  70. <div className={`grow overflow-hidden ${showConfigPanelBeforeChat && !appPrevChatList.length && 'flex items-center justify-center'}`}>
  71. {
  72. showConfigPanelBeforeChat && !appChatListDataLoading && !appPrevChatList.length && (
  73. <div className={`flex w-full items-center justify-center h-full ${isMobile && 'px-4'}`}>
  74. <ConfigPanel />
  75. </div>
  76. )
  77. }
  78. {
  79. appChatListDataLoading && chatReady && (
  80. <Loading type='app' />
  81. )
  82. }
  83. {
  84. chatReady && !appChatListDataLoading && (
  85. <ChatWrapper key={chatShouldReloadKey} />
  86. )
  87. }
  88. </div>
  89. </div>
  90. )
  91. }
  92. export type ChatWithHistoryWrapProps = {
  93. installedAppInfo?: InstalledApp
  94. className?: string
  95. }
  96. const ChatWithHistoryWrap: FC<ChatWithHistoryWrapProps> = ({
  97. installedAppInfo,
  98. className,
  99. }) => {
  100. const media = useBreakpoints()
  101. const isMobile = media === MediaType.mobile
  102. const {
  103. appInfoError,
  104. appInfoLoading,
  105. appData,
  106. appParams,
  107. appMeta,
  108. appChatListDataLoading,
  109. currentConversationId,
  110. currentConversationItem,
  111. appPrevChatList,
  112. pinnedConversationList,
  113. conversationList,
  114. showConfigPanelBeforeChat,
  115. newConversationInputs,
  116. handleNewConversationInputsChange,
  117. inputsForms,
  118. handleNewConversation,
  119. handleStartChat,
  120. handleChangeConversation,
  121. handlePinConversation,
  122. handleUnpinConversation,
  123. handleDeleteConversation,
  124. conversationRenaming,
  125. handleRenameConversation,
  126. handleNewConversationCompleted,
  127. chatShouldReloadKey,
  128. isInstalledApp,
  129. appId,
  130. handleFeedback,
  131. currentChatInstanceRef,
  132. } = useChatWithHistory(installedAppInfo)
  133. return (
  134. <ChatWithHistoryContext.Provider value={{
  135. appInfoError,
  136. appInfoLoading,
  137. appData,
  138. appParams,
  139. appMeta,
  140. appChatListDataLoading,
  141. currentConversationId,
  142. currentConversationItem,
  143. appPrevChatList,
  144. pinnedConversationList,
  145. conversationList,
  146. showConfigPanelBeforeChat,
  147. newConversationInputs,
  148. handleNewConversationInputsChange,
  149. inputsForms,
  150. handleNewConversation,
  151. handleStartChat,
  152. handleChangeConversation,
  153. handlePinConversation,
  154. handleUnpinConversation,
  155. handleDeleteConversation,
  156. conversationRenaming,
  157. handleRenameConversation,
  158. handleNewConversationCompleted,
  159. chatShouldReloadKey,
  160. isMobile,
  161. isInstalledApp,
  162. appId,
  163. handleFeedback,
  164. currentChatInstanceRef,
  165. }}>
  166. <ChatWithHistory className={className} />
  167. </ChatWithHistoryContext.Provider>
  168. )
  169. }
  170. const ChatWithHistoryWrapWithCheckToken: FC<ChatWithHistoryWrapProps> = ({
  171. installedAppInfo,
  172. className,
  173. }) => {
  174. const [inited, setInited] = useState(false)
  175. const [appUnavailable, setAppUnavailable] = useState<boolean>(false)
  176. const [isUnknwonReason, setIsUnknwonReason] = useState<boolean>(false)
  177. useAsyncEffect(async () => {
  178. if (!inited) {
  179. if (!installedAppInfo) {
  180. try {
  181. await checkOrSetAccessToken()
  182. }
  183. catch (e: any) {
  184. if (e.status === 404) {
  185. setAppUnavailable(true)
  186. }
  187. else {
  188. setIsUnknwonReason(true)
  189. setAppUnavailable(true)
  190. }
  191. }
  192. }
  193. setInited(true)
  194. }
  195. }, [])
  196. if (appUnavailable)
  197. return <AppUnavailable isUnknwonReason={isUnknwonReason} />
  198. if (!inited)
  199. return null
  200. return (
  201. <ChatWithHistoryWrap
  202. installedAppInfo={installedAppInfo}
  203. className={className}
  204. />
  205. )
  206. }
  207. export default ChatWithHistoryWrapWithCheckToken