mirror of https://github.com/langgenius/dify.git
merge
This commit is contained in:
commit
8b7fe6add7
|
|
@ -6,6 +6,11 @@ import Button from '@/app/components/base/button'
|
|||
import cn from '@/utils/classnames'
|
||||
import type { App } from '@/models/explore'
|
||||
import AppIcon from '@/app/components/base/app-icon'
|
||||
import { useGlobalPublicStore } from '@/context/global-public-context'
|
||||
import { RiInformation2Line } from '@remixicon/react'
|
||||
import { useCallback } from 'react'
|
||||
import AppListContext from '@/context/app-list-context'
|
||||
import { useContextSelector } from 'use-context-selector'
|
||||
|
||||
export type AppCardProps = {
|
||||
app: App
|
||||
|
|
@ -19,6 +24,14 @@ const AppCard = ({
|
|||
}: AppCardProps) => {
|
||||
const { t } = useTranslation()
|
||||
const { app: appBasicInfo } = app
|
||||
const { systemFeatures } = useGlobalPublicStore()
|
||||
const isTrialApp = app.can_trial && systemFeatures.enable_trial_app
|
||||
const setShowTryAppPanel = useContextSelector(AppListContext, ctx => ctx.setShowTryAppPanel)
|
||||
const showTryAPPPanel = useCallback((appId: string) => {
|
||||
return () => {
|
||||
setShowTryAppPanel?.(true, { appId, app })
|
||||
}
|
||||
}, [setShowTryAppPanel, app.category])
|
||||
return (
|
||||
<div className={cn('group relative flex h-[132px] cursor-pointer flex-col overflow-hidden rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-on-panel-item-bg p-4 shadow-xs hover:shadow-lg')}>
|
||||
<div className='flex shrink-0 grow-0 items-center gap-3 pb-2'>
|
||||
|
|
@ -46,11 +59,17 @@ const AppCard = ({
|
|||
</div>
|
||||
</div>
|
||||
<div className={cn('absolute bottom-0 left-0 right-0 hidden bg-gradient-to-t from-components-panel-gradient-2 from-[60.27%] to-transparent p-4 pt-8 group-hover:flex')}>
|
||||
<div className={cn('flex h-8 w-full items-center space-x-2')}>
|
||||
<Button variant='primary' className='grow' onClick={() => onCreate()}>
|
||||
<div className={cn('w-full', isTrialApp && 'grid grid-cols-2 gap-2')}>
|
||||
<Button variant='primary' className='w-full' onClick={() => onCreate()}>
|
||||
<PlusIcon className='mr-1 h-4 w-4' />
|
||||
<span className='text-xs'>{t('app.newApp.useTemplate')}</span>
|
||||
</Button>
|
||||
{isTrialApp && (
|
||||
<Button className='w-full' onClick={showTryAPPPanel(app.app_id)}>
|
||||
<RiInformation2Line className='mr-1 size-4' />
|
||||
<span>{t('explore.appCard.try')}</span>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,16 @@ import { useEducationInit } from '@/app/education-apply/hooks'
|
|||
import List from './list'
|
||||
import useDocumentTitle from '@/hooks/use-document-title'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import AppListContext from '@/context/app-list-context'
|
||||
import { useCallback, useState } from 'react'
|
||||
import type { CurrentTryAppParams } from '@/context/explore-context'
|
||||
import TryApp from '../explore/try-app'
|
||||
import type { CreateAppModalProps } from '../explore/create-app-modal'
|
||||
import CreateAppModal from '../explore/create-app-modal'
|
||||
import { fetchAppDetail } from '@/service/explore'
|
||||
import { DSLImportMode } from '@/models/app'
|
||||
import { useImportDSL } from '@/hooks/use-import-dsl'
|
||||
import DSLConfirmModal from '../app/create-from-dsl-modal/dsl-confirm-modal'
|
||||
|
||||
const Apps = () => {
|
||||
const { t } = useTranslation()
|
||||
|
|
@ -10,10 +20,122 @@ const Apps = () => {
|
|||
useDocumentTitle(t('common.menus.apps'))
|
||||
useEducationInit()
|
||||
|
||||
const [currentTryAppParams, setCurrentTryAppParams] = useState<CurrentTryAppParams | undefined>(undefined)
|
||||
const currApp = currentTryAppParams?.app
|
||||
const [isShowTryAppPanel, setIsShowTryAppPanel] = useState(false)
|
||||
const hideTryAppPanel = useCallback(() => {
|
||||
setIsShowTryAppPanel(false)
|
||||
}, [])
|
||||
const setShowTryAppPanel = (showTryAppPanel: boolean, params?: CurrentTryAppParams) => {
|
||||
if (showTryAppPanel)
|
||||
setCurrentTryAppParams(params)
|
||||
else
|
||||
setCurrentTryAppParams(undefined)
|
||||
setIsShowTryAppPanel(showTryAppPanel)
|
||||
}
|
||||
const [isShowCreateModal, setIsShowCreateModal] = useState(false)
|
||||
|
||||
const handleShowFromTryApp = useCallback(() => {
|
||||
setIsShowCreateModal(true)
|
||||
}, [])
|
||||
|
||||
const [controlRefreshList, setControlRefreshList] = useState(0)
|
||||
const [controlHideCreateFromTemplatePanel, setControlHideCreateFromTemplatePanel] = useState(0)
|
||||
const onSuccess = useCallback(() => {
|
||||
setControlRefreshList(prev => prev + 1)
|
||||
setControlHideCreateFromTemplatePanel(prev => prev + 1)
|
||||
}, [])
|
||||
|
||||
const [showDSLConfirmModal, setShowDSLConfirmModal] = useState(false)
|
||||
|
||||
const {
|
||||
handleImportDSL,
|
||||
handleImportDSLConfirm,
|
||||
versions,
|
||||
isFetching,
|
||||
} = useImportDSL()
|
||||
|
||||
const onConfirmDSL = useCallback(async () => {
|
||||
await handleImportDSLConfirm({
|
||||
onSuccess,
|
||||
})
|
||||
}, [handleImportDSLConfirm, onSuccess])
|
||||
|
||||
const onCreate: CreateAppModalProps['onConfirm'] = async ({
|
||||
name,
|
||||
icon_type,
|
||||
icon,
|
||||
icon_background,
|
||||
description,
|
||||
}) => {
|
||||
hideTryAppPanel()
|
||||
|
||||
const { export_data } = await fetchAppDetail(
|
||||
currApp?.app.id as string,
|
||||
)
|
||||
const payload = {
|
||||
mode: DSLImportMode.YAML_CONTENT,
|
||||
yaml_content: export_data,
|
||||
name,
|
||||
icon_type,
|
||||
icon,
|
||||
icon_background,
|
||||
description,
|
||||
}
|
||||
await handleImportDSL(payload, {
|
||||
onSuccess: () => {
|
||||
setIsShowCreateModal(false)
|
||||
},
|
||||
onPending: () => {
|
||||
setShowDSLConfirmModal(true)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='relative flex h-0 shrink-0 grow flex-col overflow-y-auto bg-background-body'>
|
||||
<List />
|
||||
</div >
|
||||
<AppListContext.Provider value={{
|
||||
currentApp: currentTryAppParams,
|
||||
isShowTryAppPanel,
|
||||
setShowTryAppPanel,
|
||||
controlHideCreateFromTemplatePanel,
|
||||
}}>
|
||||
<div className='relative flex h-0 shrink-0 grow flex-col overflow-y-auto bg-background-body'>
|
||||
<List controlRefreshList={controlRefreshList} />
|
||||
{isShowTryAppPanel && (
|
||||
<TryApp appId={currentTryAppParams?.appId || ''}
|
||||
category={currentTryAppParams?.app?.category}
|
||||
onClose={hideTryAppPanel}
|
||||
onCreate={handleShowFromTryApp}
|
||||
/>
|
||||
)}
|
||||
|
||||
{
|
||||
showDSLConfirmModal && (
|
||||
<DSLConfirmModal
|
||||
versions={versions}
|
||||
onCancel={() => setShowDSLConfirmModal(false)}
|
||||
onConfirm={onConfirmDSL}
|
||||
confirmDisabled={isFetching}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
{isShowCreateModal && (
|
||||
<CreateAppModal
|
||||
appIconType={currApp?.app.icon_type || 'emoji'}
|
||||
appIcon={currApp?.app.icon || ''}
|
||||
appIconBackground={currApp?.app.icon_background || ''}
|
||||
appIconUrl={currApp?.app.icon_url}
|
||||
appName={currApp?.app.name || ''}
|
||||
appDescription={currApp?.app.description || ''}
|
||||
show
|
||||
onConfirm={onCreate}
|
||||
confirmDisabled={isFetching}
|
||||
onHide={() => setIsShowCreateModal(false)}
|
||||
/>
|
||||
)}
|
||||
</div >
|
||||
</AppListContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
'use client'
|
||||
|
||||
import type { FC } from 'react'
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import {
|
||||
useRouter,
|
||||
|
|
@ -67,7 +68,12 @@ const getKey = (
|
|||
return null
|
||||
}
|
||||
|
||||
const List = () => {
|
||||
type Props = {
|
||||
controlRefreshList: number
|
||||
}
|
||||
const List: FC<Props> = ({
|
||||
controlRefreshList,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { systemFeatures } = useGlobalPublicStore()
|
||||
const router = useRouter()
|
||||
|
|
@ -142,6 +148,10 @@ const List = () => {
|
|||
|
||||
return () => window.clearInterval(timer)
|
||||
}, [workflowIds.join(','), mutate, refreshOnlineUsers])
|
||||
useEffect(() => {
|
||||
if (controlRefreshList > 0)
|
||||
mutate()
|
||||
}, [controlRefreshList])
|
||||
|
||||
const anchorRef = useRef<HTMLDivElement>(null)
|
||||
const options = [
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use client'
|
||||
|
||||
import React, { useMemo, useState } from 'react'
|
||||
import React, { useEffect, useMemo, useState } from 'react'
|
||||
import {
|
||||
useRouter,
|
||||
useSearchParams,
|
||||
|
|
@ -11,6 +11,8 @@ import { useProviderContext } from '@/context/provider-context'
|
|||
import { FileArrow01, FilePlus01, FilePlus02 } from '@/app/components/base/icons/src/vender/line/files'
|
||||
import cn from '@/utils/classnames'
|
||||
import dynamic from 'next/dynamic'
|
||||
import AppListContext from '@/context/app-list-context'
|
||||
import { useContextSelector } from 'use-context-selector'
|
||||
|
||||
const CreateAppModal = dynamic(() => import('@/app/components/app/create-app-modal'), {
|
||||
ssr: false,
|
||||
|
|
@ -52,6 +54,12 @@ const CreateAppCard = ({
|
|||
return undefined
|
||||
}, [dslUrl])
|
||||
|
||||
const controlHideCreateFromTemplatePanel = useContextSelector(AppListContext, ctx => ctx.controlHideCreateFromTemplatePanel)
|
||||
useEffect(() => {
|
||||
if (controlHideCreateFromTemplatePanel > 0)
|
||||
setShowNewAppTemplateDialog(false)
|
||||
}, [controlHideCreateFromTemplatePanel])
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ const Answer: FC<AnswerProps> = ({
|
|||
data={workflowProcess}
|
||||
item={item}
|
||||
hideProcessDetail={hideProcessDetail}
|
||||
readonly={hideProcessDetail && appData ? !appData.site.show_workflow_steps : undefined}
|
||||
readonly={hideProcessDetail && appData ? !appData.site?.show_workflow_steps : undefined}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -316,7 +316,7 @@ const Chat: FC<ChatProps> = ({
|
|||
{
|
||||
!noChatInput && (
|
||||
<ChatInputArea
|
||||
botName={appData?.site.title || 'Bot'}
|
||||
botName={appData?.site?.title || 'Bot'}
|
||||
disabled={inputDisabled}
|
||||
showFeatureBar={showFeatureBar}
|
||||
showFileUpload={showFileUpload}
|
||||
|
|
|
|||
|
|
@ -193,6 +193,8 @@ const ChatWrapper = () => {
|
|||
return null
|
||||
if (!collapsed && inputsForms.length > 0 && !allInputsHidden)
|
||||
return null
|
||||
if (!appData?.site)
|
||||
return null
|
||||
if (welcomeMessage.suggestedQuestions && welcomeMessage.suggestedQuestions?.length > 0) {
|
||||
return (
|
||||
<div className={cn('flex items-center justify-center px-4 py-12', isMobile ? 'min-h-[30vh] py-0' : 'h-[50vh]')}>
|
||||
|
|
@ -226,7 +228,7 @@ const ChatWrapper = () => {
|
|||
</div>
|
||||
</div>
|
||||
)
|
||||
}, [appData?.site.icon, appData?.site.icon_background, appData?.site.icon_type, appData?.site.icon_url, chatList, collapsed, currentConversationId, inputsForms.length, respondingState, allInputsHidden])
|
||||
}, [appData?.site, chatList, collapsed, currentConversationId, inputsForms.length, respondingState, allInputsHidden])
|
||||
|
||||
const answerIcon = isDify()
|
||||
? <LogoAvatar className='relative shrink-0' />
|
||||
|
|
|
|||
|
|
@ -72,8 +72,12 @@ export const useEmbeddedChatbot = (appSourceType: AppSourceType, tryAppId?: stri
|
|||
const isInstalledApp = false // just can be webapp and try app
|
||||
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
|
||||
const isTryApp = appSourceType === AppSourceType.tryApp
|
||||
const { data: appInfo, isLoading: appInfoLoading, error: appInfoError } = useSWR('appInfo', isTryApp ? () => fetchTryAppInfo(tryAppId) : fetchAppInfo)
|
||||
const appId = useMemo(() => isTryApp ? tryAppId : appInfo?.app_id, [appInfo])
|
||||
const { data: appInfo, isLoading: appInfoLoading, error: appInfoError } = useSWR('appInfo', () => {
|
||||
return isTryApp ? () => fetchTryAppInfo(tryAppId!) : fetchAppInfo
|
||||
})
|
||||
const appId = useMemo(() => {
|
||||
return isTryApp ? tryAppId : (appInfo as any)?.app_id
|
||||
}, [appInfo])
|
||||
|
||||
const [userId, setUserId] = useState<string>()
|
||||
const [conversationId, setConversationId] = useState<string>()
|
||||
|
|
@ -116,9 +120,16 @@ export const useEmbeddedChatbot = (appSourceType: AppSourceType, tryAppId?: stri
|
|||
const [conversationIdInfo, setConversationIdInfo] = useLocalStorageState<Record<string, Record<string, string>>>(CONVERSATION_ID_INFO, {
|
||||
defaultValue: {},
|
||||
})
|
||||
const removeConversationIdInfo = useCallback((appId: string) => {
|
||||
setConversationIdInfo((prev) => {
|
||||
const newInfo = { ...prev }
|
||||
delete newInfo[appId]
|
||||
return newInfo
|
||||
})
|
||||
}, [setConversationIdInfo])
|
||||
const allowResetChat = !conversationId
|
||||
const currentConversationId = useMemo(() => isTryApp ? '' : conversationIdInfo?.[appId || '']?.[userId || 'DEFAULT'] || conversationId || '',
|
||||
[isTryApp, appId, conversationIdInfo, userId, conversationId])
|
||||
const currentConversationId = useMemo(() => conversationIdInfo?.[appId || '']?.[userId || 'DEFAULT'] || conversationId || '',
|
||||
[appId, conversationIdInfo, userId, conversationId])
|
||||
const handleConversationIdInfoChange = useCallback((changeConversationId: string) => {
|
||||
if (appId) {
|
||||
let prevValue = conversationIdInfo?.[appId || '']
|
||||
|
|
@ -146,7 +157,7 @@ export const useEmbeddedChatbot = (appSourceType: AppSourceType, tryAppId?: stri
|
|||
const { data: appMeta } = useSWR(isTryApp ? null : ['appMeta', appSourceType, appId], () => fetchAppMeta(appSourceType, appId))
|
||||
const { data: appPinnedConversationData } = useSWR(isTryApp ? null : ['appConversationData', appSourceType, appId, true], () => fetchConversations(appSourceType, appId, undefined, true, 100))
|
||||
const { data: appConversationData, isLoading: appConversationDataLoading, mutate: mutateAppConversationData } = useSWR(isTryApp ? null : ['appConversationData', appSourceType, appId, false], () => fetchConversations(appSourceType, appId, undefined, false, 100))
|
||||
const { data: appChatListData, isLoading: appChatListDataLoading } = useSWR(chatShouldReloadKey ? ['appChatList', chatShouldReloadKey, appSourceType, appId] : null, () => fetchChatList(chatShouldReloadKey, appSourceType, appId))
|
||||
const { data: appChatListData, isLoading: appChatListDataLoading } = useSWR((chatShouldReloadKey && !isTryApp) ? ['appChatList', chatShouldReloadKey, appSourceType, appId] : null, () => fetchChatList(chatShouldReloadKey, appSourceType, appId))
|
||||
|
||||
const [clearChatList, setClearChatList] = useState(false)
|
||||
const [isResponding, setIsResponding] = useState(false)
|
||||
|
|
@ -317,7 +328,7 @@ export const useEmbeddedChatbot = (appSourceType: AppSourceType, tryAppId?: stri
|
|||
}, [appChatListData, currentConversationId])
|
||||
const [currentConversationInputs, setCurrentConversationInputs] = useState<Record<string, any>>(currentConversationLatestInputs || {})
|
||||
useEffect(() => {
|
||||
if (currentConversationItem)
|
||||
if (currentConversationItem && !isTryApp)
|
||||
setCurrentConversationInputs(currentConversationLatestInputs || {})
|
||||
}, [currentConversationItem, currentConversationLatestInputs])
|
||||
|
||||
|
|
@ -377,12 +388,17 @@ export const useEmbeddedChatbot = (appSourceType: AppSourceType, tryAppId?: stri
|
|||
setClearChatList(false)
|
||||
}, [handleConversationIdInfoChange, setClearChatList])
|
||||
const handleNewConversation = useCallback(async () => {
|
||||
if (isTryApp) {
|
||||
setClearChatList(true)
|
||||
return
|
||||
}
|
||||
|
||||
currentChatInstanceRef.current.handleStop()
|
||||
setShowNewConversationItemInList(true)
|
||||
handleChangeConversation('')
|
||||
handleNewConversationInputsChange(await getProcessedInputsFromUrlParams())
|
||||
setClearChatList(true)
|
||||
}, [handleChangeConversation, setShowNewConversationItemInList, handleNewConversationInputsChange, setClearChatList])
|
||||
}, [isTryApp, setShowNewConversationItemInList, handleNewConversationInputsChange, setClearChatList])
|
||||
|
||||
const handleNewConversationCompleted = useCallback((newConversationId: string) => {
|
||||
setNewConversationId(newConversationId)
|
||||
|
|
@ -406,6 +422,7 @@ export const useEmbeddedChatbot = (appSourceType: AppSourceType, tryAppId?: stri
|
|||
appId,
|
||||
currentConversationId,
|
||||
currentConversationItem,
|
||||
removeConversationIdInfo,
|
||||
handleConversationIdInfoChange,
|
||||
appData: appInfo,
|
||||
appParams: appParams || {} as ChatConfig,
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ const ViewFormDropdown = ({ iconColor }: Props) => {
|
|||
<RiChatSettingsLine className={cn('h-[18px] w-[18px]', iconColor)} />
|
||||
</ActionButton>
|
||||
</PortalToFollowElemTrigger>
|
||||
<PortalToFollowElemContent className="z-50">
|
||||
<PortalToFollowElemContent className="z-[99]">
|
||||
<div className='w-[400px] rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-lg backdrop-blur-sm'>
|
||||
<div className='flex items-center gap-3 rounded-t-2xl border-b border-divider-subtle px-6 py-4'>
|
||||
<Message3Fill className='h-6 w-6 shrink-0' />
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ const AppCard = ({
|
|||
{isExplore && (canCreate || isTrialApp) && (
|
||||
<div className={cn(
|
||||
'absolute bottom-0 left-0 right-0 hidden bg-gradient-to-t from-components-panel-gradient-2 from-[60.27%] to-transparent p-4 pt-8',
|
||||
(canCreate && isTrialApp) && 'grid-cols-2 gap-2 group-hover:grid ',
|
||||
(canCreate && isTrialApp) && 'grid-cols-2 gap-2 group-hover:grid',
|
||||
)}>
|
||||
{canCreate && (
|
||||
<Button variant='primary' className='h-7' onClick={() => onCreate()}>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import React, { useEffect } from 'react'
|
||||
import ChatWrapper from '@/app/components/base/chat/embedded-chatbot/chat-wrapper'
|
||||
import { useThemeContext } from '../../../base/chat/embedded-chatbot/theme/theme-context'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
|
|
@ -17,6 +17,10 @@ import { useTranslation } from 'react-i18next'
|
|||
import { useBoolean } from 'ahooks'
|
||||
import type { TryAppInfo } from '@/service/try-app'
|
||||
import AppIcon from '@/app/components/base/app-icon'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import { RiResetLeftLine } from '@remixicon/react'
|
||||
import ViewFormDropdown from '@/app/components/base/chat/embedded-chatbot/inputs-form/view-form-dropdown'
|
||||
|
||||
type Props = {
|
||||
appId: string
|
||||
|
|
@ -33,10 +37,21 @@ const TryApp: FC<Props> = ({
|
|||
const media = useBreakpoints()
|
||||
const isMobile = media === MediaType.mobile
|
||||
const themeBuilder = useThemeContext()
|
||||
const chatData = useEmbeddedChatbot(AppSourceType.tryApp, appId)
|
||||
const { removeConversationIdInfo, ...chatData } = useEmbeddedChatbot(AppSourceType.tryApp, appId)
|
||||
const currentConversationId = chatData.currentConversationId
|
||||
const inputsForms = chatData.inputsForms
|
||||
useEffect(() => {
|
||||
if (appId)
|
||||
removeConversationIdInfo(appId)
|
||||
}, [appId])
|
||||
const [isHideTryNotice, {
|
||||
setTrue: hideTryNotice,
|
||||
}] = useBoolean(false)
|
||||
|
||||
const handleNewConversation = () => {
|
||||
removeConversationIdInfo(appId)
|
||||
chatData.handleNewConversation()
|
||||
}
|
||||
return (
|
||||
<EmbeddedChatbotContext.Provider value={{
|
||||
...chatData,
|
||||
|
|
@ -56,6 +71,20 @@ const TryApp: FC<Props> = ({
|
|||
/>
|
||||
<div className='system-md-semibold grow truncate text-text-primary' title={appDetail.name}>{appDetail.name}</div>
|
||||
</div>
|
||||
<div className='flex items-center gap-1'>
|
||||
{currentConversationId && (
|
||||
<Tooltip
|
||||
popupContent={t('share.chat.resetChat')}
|
||||
>
|
||||
<ActionButton size='l' onClick={handleNewConversation}>
|
||||
<RiResetLeftLine className='h-[18px] w-[18px]' />
|
||||
</ActionButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
{currentConversationId && inputsForms.length > 0 && (
|
||||
<ViewFormDropdown />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className='mx-auto mt-4 flex h-[0] w-[769px] grow flex-col'>
|
||||
{!isHideTryNotice && (
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
import { createContext } from 'use-context-selector'
|
||||
import { noop } from 'lodash-es'
|
||||
import type { CurrentTryAppParams } from './explore-context'
|
||||
|
||||
type Props = {
|
||||
currentApp?: CurrentTryAppParams
|
||||
isShowTryAppPanel: boolean
|
||||
setShowTryAppPanel: (showTryAppPanel: boolean, params?: CurrentTryAppParams) => void
|
||||
controlHideCreateFromTemplatePanel: number
|
||||
}
|
||||
|
||||
const AppListContext = createContext<Props>({
|
||||
isShowTryAppPanel: false,
|
||||
setShowTryAppPanel: noop,
|
||||
currentApp: undefined,
|
||||
controlHideCreateFromTemplatePanel: 0,
|
||||
})
|
||||
|
||||
export default AppListContext
|
||||
Loading…
Reference in New Issue