diff --git a/web/app/(commonLayout)/layout.tsx b/web/app/(commonLayout)/layout.tsx
index d07e2a99d9..64186a1b10 100644
--- a/web/app/(commonLayout)/layout.tsx
+++ b/web/app/(commonLayout)/layout.tsx
@@ -1,6 +1,6 @@
import React from 'react'
import type { ReactNode } from 'react'
-import SwrInitor from '@/app/components/swr-initor'
+import SwrInitializer from '@/app/components/swr-initializer'
import { AppContextProvider } from '@/context/app-context'
import GA, { GaType } from '@/app/components/base/ga'
import HeaderWrapper from '@/app/components/header/header-wrapper'
@@ -13,7 +13,7 @@ const Layout = ({ children }: { children: ReactNode }) => {
return (
<>
-
+
@@ -26,7 +26,7 @@ const Layout = ({ children }: { children: ReactNode }) => {
-
+
>
)
}
diff --git a/web/app/account/account-page/index.tsx b/web/app/account/account-page/index.tsx
index 55fa2983dd..47b8f045d2 100644
--- a/web/app/account/account-page/index.tsx
+++ b/web/app/account/account-page/index.tsx
@@ -1,5 +1,6 @@
'use client'
import { useState } from 'react'
+import useSWR from 'swr'
import { useTranslation } from 'react-i18next'
import {
RiGraduationCapFill,
@@ -22,6 +23,8 @@ import PremiumBadge from '@/app/components/base/premium-badge'
import { useGlobalPublicStore } from '@/context/global-public-context'
import EmailChangeModal from './email-change-modal'
import { validPassword } from '@/config'
+import { fetchAppList } from '@/service/apps'
+import type { App } from '@/types/app'
const titleClassName = `
system-sm-semibold text-text-secondary
@@ -33,7 +36,9 @@ const descriptionClassName = `
export default function AccountPage() {
const { t } = useTranslation()
const { systemFeatures } = useGlobalPublicStore()
- const { mutateUserProfile, userProfile, apps } = useAppContext()
+ const { data: appList } = useSWR({ url: '/apps', params: { page: 1, limit: 100, name: '' } }, fetchAppList)
+ const apps = appList?.data || []
+ const { mutateUserProfile, userProfile } = useAppContext()
const { isEducationAccount } = useProviderContext()
const { notify } = useContext(ToastContext)
const [editNameModalVisible, setEditNameModalVisible] = useState(false)
@@ -202,7 +207,7 @@ export default function AccountPage() {
{!!apps.length && (
({ ...app, key: app.id, name: app.name }))}
+ items={apps.map((app: App) => ({ ...app, key: app.id, name: app.name }))}
renderItem={renderAppItem}
wrapperClassName='mt-2'
/>
diff --git a/web/app/account/layout.tsx b/web/app/account/layout.tsx
index e74716fb3b..b3225b5341 100644
--- a/web/app/account/layout.tsx
+++ b/web/app/account/layout.tsx
@@ -1,7 +1,7 @@
import React from 'react'
import type { ReactNode } from 'react'
import Header from './header'
-import SwrInitor from '@/app/components/swr-initor'
+import SwrInitor from '@/app/components/swr-initializer'
import { AppContextProvider } from '@/context/app-context'
import GA, { GaType } from '@/app/components/base/ga'
import HeaderWrapper from '@/app/components/header/header-wrapper'
diff --git a/web/app/components/app-sidebar/app-info.tsx b/web/app/components/app-sidebar/app-info.tsx
index e85eaa2f53..c35047bbc5 100644
--- a/web/app/components/app-sidebar/app-info.tsx
+++ b/web/app/components/app-sidebar/app-info.tsx
@@ -1,6 +1,6 @@
import { useTranslation } from 'react-i18next'
import { useRouter } from 'next/navigation'
-import { useContext, useContextSelector } from 'use-context-selector'
+import { useContext } from 'use-context-selector'
import React, { useCallback, useState } from 'react'
import {
RiDeleteBinLine,
@@ -15,7 +15,7 @@ import AppIcon from '../base/app-icon'
import cn from '@/utils/classnames'
import { useStore as useAppStore } from '@/app/components/app/store'
import { ToastContext } from '@/app/components/base/toast'
-import AppsContext, { useAppContext } from '@/context/app-context'
+import { useAppContext } from '@/context/app-context'
import { useProviderContext } from '@/context/provider-context'
import { copyApp, deleteApp, exportAppConfig, updateAppInfo } from '@/service/apps'
import type { DuplicateAppModalProps } from '@/app/components/app/duplicate-modal'
@@ -73,11 +73,6 @@ const AppInfo = ({ expand, onlyShowDetail = false, openState = false, onDetailEx
const [showImportDSLModal, setShowImportDSLModal] = useState(false)
const [secretEnvList, setSecretEnvList] = useState([])
- const mutateApps = useContextSelector(
- AppsContext,
- state => state.mutateApps,
- )
-
const onEdit: CreateAppModalProps['onConfirm'] = useCallback(async ({
name,
icon_type,
@@ -106,12 +101,11 @@ const AppInfo = ({ expand, onlyShowDetail = false, openState = false, onDetailEx
message: t('app.editDone'),
})
setAppDetail(app)
- mutateApps()
}
catch {
notify({ type: 'error', message: t('app.editFailed') })
}
- }, [appDetail, mutateApps, notify, setAppDetail, t])
+ }, [appDetail, notify, setAppDetail, t])
const onCopy: DuplicateAppModalProps['onConfirm'] = async ({ name, icon_type, icon, icon_background }) => {
if (!appDetail)
@@ -131,7 +125,6 @@ const AppInfo = ({ expand, onlyShowDetail = false, openState = false, onDetailEx
message: t('app.newApp.appCreated'),
})
localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1')
- mutateApps()
onPlanInfoChanged()
getRedirection(true, newApp, replace)
}
@@ -186,7 +179,6 @@ const AppInfo = ({ expand, onlyShowDetail = false, openState = false, onDetailEx
try {
await deleteApp(appDetail.id)
notify({ type: 'success', message: t('app.appDeleted') })
- mutateApps()
onPlanInfoChanged()
setAppDetail()
replace('/apps')
@@ -198,7 +190,7 @@ const AppInfo = ({ expand, onlyShowDetail = false, openState = false, onDetailEx
})
}
setShowConfirmDelete(false)
- }, [appDetail, mutateApps, notify, onPlanInfoChanged, replace, setAppDetail, t])
+ }, [appDetail, notify, onPlanInfoChanged, replace, setAppDetail, t])
const { isCurrentWorkspaceEditor } = useAppContext()
diff --git a/web/app/components/app/create-app-modal/index.tsx b/web/app/components/app/create-app-modal/index.tsx
index f0a0da41a5..bdc839e848 100644
--- a/web/app/components/app/create-app-modal/index.tsx
+++ b/web/app/components/app/create-app-modal/index.tsx
@@ -4,7 +4,7 @@ import { useCallback, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useRouter } from 'next/navigation'
-import { useContext, useContextSelector } from 'use-context-selector'
+import { useContext } from 'use-context-selector'
import { RiArrowRightLine, RiArrowRightSLine, RiCommandLine, RiCornerDownLeftLine, RiExchange2Fill } from '@remixicon/react'
import Link from 'next/link'
import { useDebounceFn, useKeyPress } from 'ahooks'
@@ -15,7 +15,7 @@ import Button from '@/app/components/base/button'
import Divider from '@/app/components/base/divider'
import cn from '@/utils/classnames'
import { basePath } from '@/utils/var'
-import AppsContext, { useAppContext } from '@/context/app-context'
+import { useAppContext } from '@/context/app-context'
import { useProviderContext } from '@/context/provider-context'
import { ToastContext } from '@/app/components/base/toast'
import type { AppMode } from '@/types/app'
@@ -41,7 +41,6 @@ function CreateApp({ onClose, onSuccess, onCreateFromTemplate }: CreateAppProps)
const { t } = useTranslation()
const { push } = useRouter()
const { notify } = useContext(ToastContext)
- const mutateApps = useContextSelector(AppsContext, state => state.mutateApps)
const [appMode, setAppMode] = useState('advanced-chat')
const [appIcon, setAppIcon] = useState({ type: 'emoji', icon: '🤖', background: '#FFEAD5' })
@@ -80,7 +79,6 @@ function CreateApp({ onClose, onSuccess, onCreateFromTemplate }: CreateAppProps)
notify({ type: 'success', message: t('app.newApp.appCreated') })
onSuccess()
onClose()
- mutateApps()
localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1')
getRedirection(isCurrentWorkspaceEditor, app, push)
}
@@ -88,7 +86,7 @@ function CreateApp({ onClose, onSuccess, onCreateFromTemplate }: CreateAppProps)
notify({ type: 'error', message: t('app.newApp.appCreateFailed') })
}
isCreatingRef.current = false
- }, [name, notify, t, appMode, appIcon, description, onSuccess, onClose, mutateApps, push, isCurrentWorkspaceEditor])
+ }, [name, notify, t, appMode, appIcon, description, onSuccess, onClose, push, isCurrentWorkspaceEditor])
const { run: handleCreateApp } = useDebounceFn(onCreate, { wait: 300 })
useKeyPress(['meta.enter', 'ctrl.enter'], () => {
diff --git a/web/app/components/apps/app-card.tsx b/web/app/components/apps/app-card.tsx
index bfb7813bf4..603b5922c5 100644
--- a/web/app/components/apps/app-card.tsx
+++ b/web/app/components/apps/app-card.tsx
@@ -1,7 +1,7 @@
'use client'
import React, { useCallback, useEffect, useMemo, useState } from 'react'
-import { useContext, useContextSelector } from 'use-context-selector'
+import { useContext } from 'use-context-selector'
import { useRouter } from 'next/navigation'
import { useTranslation } from 'react-i18next'
import { RiBuildingLine, RiGlobalLine, RiLockLine, RiMoreFill, RiVerifiedBadgeLine } from '@remixicon/react'
@@ -11,7 +11,7 @@ import Toast, { ToastContext } from '@/app/components/base/toast'
import { copyApp, deleteApp, exportAppConfig, updateAppInfo } from '@/service/apps'
import type { DuplicateAppModalProps } from '@/app/components/app/duplicate-modal'
import AppIcon from '@/app/components/base/app-icon'
-import AppsContext, { useAppContext } from '@/context/app-context'
+import { useAppContext } from '@/context/app-context'
import type { HtmlContentProps } from '@/app/components/base/popover'
import CustomPopover from '@/app/components/base/popover'
import Divider from '@/app/components/base/divider'
@@ -65,11 +65,6 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
const { onPlanInfoChanged } = useProviderContext()
const { push } = useRouter()
- const mutateApps = useContextSelector(
- AppsContext,
- state => state.mutateApps,
- )
-
const [showEditModal, setShowEditModal] = useState(false)
const [showDuplicateModal, setShowDuplicateModal] = useState(false)
const [showSwitchModal, setShowSwitchModal] = useState(false)
@@ -83,7 +78,6 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
notify({ type: 'success', message: t('app.appDeleted') })
if (onRefresh)
onRefresh()
- mutateApps()
onPlanInfoChanged()
}
catch (e: any) {
@@ -93,7 +87,7 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
})
}
setShowConfirmDelete(false)
- }, [app.id, mutateApps, notify, onPlanInfoChanged, onRefresh, t])
+ }, [app.id, notify, onPlanInfoChanged, onRefresh, t])
const onEdit: CreateAppModalProps['onConfirm'] = useCallback(async ({
name,
@@ -122,12 +116,11 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
})
if (onRefresh)
onRefresh()
- mutateApps()
}
catch {
notify({ type: 'error', message: t('app.editFailed') })
}
- }, [app.id, mutateApps, notify, onRefresh, t])
+ }, [app.id, notify, onRefresh, t])
const onCopy: DuplicateAppModalProps['onConfirm'] = async ({ name, icon_type, icon, icon_background }) => {
try {
@@ -147,7 +140,6 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1')
if (onRefresh)
onRefresh()
- mutateApps()
onPlanInfoChanged()
getRedirection(isCurrentWorkspaceEditor, newApp, push)
}
@@ -195,16 +187,14 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
const onSwitch = () => {
if (onRefresh)
onRefresh()
- mutateApps()
setShowSwitchModal(false)
}
const onUpdateAccessControl = useCallback(() => {
if (onRefresh)
onRefresh()
- mutateApps()
setShowAccessControl(false)
- }, [onRefresh, mutateApps, setShowAccessControl])
+ }, [onRefresh, setShowAccessControl])
const Operations = (props: HtmlContentProps) => {
const { data: userCanAccessApp, isLoading: isGettingUserCanAccessApp } = useGetUserCanAccessApp({ appId: app?.id, enabled: (!!props?.open && systemFeatures.webapp_auth.enabled) })
@@ -325,7 +315,6 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
dateFormat: `${t('datasetDocuments.segment.dateTimeFormat')}`,
})
return `${t('datasetDocuments.segment.editedAt')} ${timeText}`
- // eslint-disable-next-line react-hooks/exhaustive-deps
}, [app.updated_at, app.created_at])
return (
diff --git a/web/app/components/browser-initor.tsx b/web/app/components/browser-initializer.tsx
similarity index 88%
rename from web/app/components/browser-initor.tsx
rename to web/app/components/browser-initializer.tsx
index f2f4b02dc0..fcae22c448 100644
--- a/web/app/components/browser-initor.tsx
+++ b/web/app/components/browser-initializer.tsx
@@ -43,10 +43,10 @@ Object.defineProperty(globalThis, 'sessionStorage', {
value: sessionStorage,
})
-const BrowserInitor = ({
+const BrowserInitializer = ({
children,
-}: { children: React.ReactNode }) => {
+}: { children: React.ReactElement }) => {
return children
}
-export default BrowserInitor
+export default BrowserInitializer
diff --git a/web/app/components/sentry-initor.tsx b/web/app/components/sentry-initializer.tsx
similarity index 85%
rename from web/app/components/sentry-initor.tsx
rename to web/app/components/sentry-initializer.tsx
index 457a1cf7c7..10c056f21b 100644
--- a/web/app/components/sentry-initor.tsx
+++ b/web/app/components/sentry-initializer.tsx
@@ -5,9 +5,9 @@ import * as Sentry from '@sentry/react'
const isDevelopment = process.env.NODE_ENV === 'development'
-const SentryInit = ({
+const SentryInitializer = ({
children,
-}: { children: React.ReactNode }) => {
+}: { children: React.ReactElement }) => {
useEffect(() => {
const SENTRY_DSN = document?.body?.getAttribute('data-public-sentry-dsn')
if (!isDevelopment && SENTRY_DSN) {
@@ -26,4 +26,4 @@ const SentryInit = ({
return children
}
-export default SentryInit
+export default SentryInitializer
diff --git a/web/app/components/swr-initor.tsx b/web/app/components/swr-initializer.tsx
similarity index 95%
rename from web/app/components/swr-initor.tsx
rename to web/app/components/swr-initializer.tsx
index 8f9c5b4e05..3592a0e017 100644
--- a/web/app/components/swr-initor.tsx
+++ b/web/app/components/swr-initializer.tsx
@@ -10,12 +10,12 @@ import {
EDUCATION_VERIFY_URL_SEARCHPARAMS_ACTION,
} from '@/app/education-apply/constants'
-type SwrInitorProps = {
+type SwrInitializerProps = {
children: ReactNode
}
-const SwrInitor = ({
+const SwrInitializer = ({
children,
-}: SwrInitorProps) => {
+}: SwrInitializerProps) => {
const router = useRouter()
const searchParams = useSearchParams()
const consoleToken = decodeURIComponent(searchParams.get('access_token') || '')
@@ -86,4 +86,4 @@ const SwrInitor = ({
: null
}
-export default SwrInitor
+export default SwrInitializer
diff --git a/web/app/layout.tsx b/web/app/layout.tsx
index 525445db30..f086499ca4 100644
--- a/web/app/layout.tsx
+++ b/web/app/layout.tsx
@@ -1,10 +1,10 @@
import RoutePrefixHandle from './routePrefixHandle'
import type { Viewport } from 'next'
import I18nServer from './components/i18n-server'
-import BrowserInitor from './components/browser-initor'
-import SentryInitor from './components/sentry-initor'
+import BrowserInitializer from './components/browser-initializer'
+import SentryInitializer from './components/sentry-initializer'
import { getLocaleOnServer } from '@/i18n/server'
-import { TanstackQueryIniter } from '@/context/query-client'
+import { TanstackQueryInitializer } from '@/context/query-client'
import { ThemeProvider } from 'next-themes'
import './styles/globals.css'
import './styles/markdown.scss'
@@ -62,9 +62,9 @@ const LocaleLayout = async ({
className="color-scheme h-full select-auto"
{...datasetMap}
>
-
-
-
+
+
+
-
-
-
+
+
+