import Popover from "@/app/components/Popover"; import React, { useMemo, useRef } from "react"; import useRelativePosition, { Orientation, } from "@/app/hooks/useRelativePosition"; import Locale from "@/app/locales"; import { useChatStore } from "@/app/store/chat"; import { useAllModels } from "@/app/utils/hooks"; import { ModelType, useAppConfig } from "@/app/store/config"; import { showToast } from "@/app/components/ui-lib"; import BottomArrow from "@/app/icons/downArrowLgIcon.svg"; import BottomArrowMobile from "@/app/icons/bottomArrow.svg"; import Modal, { TriggerProps } from "@/app/components/Modal"; import Selected from "@/app/icons/selectedIcon.svg"; const ModelSelect = () => { const config = useAppConfig(); const { isMobileScreen } = config; const chatStore = useChatStore(); const currentModel = chatStore.currentSession().mask.modelConfig.model; const allModels = useAllModels(); const models = useMemo(() => { const filteredModels = allModels.filter((m) => m.available); const defaultModel = filteredModels.find((m) => m.isDefault); if (defaultModel) { const arr = [ defaultModel, ...filteredModels.filter((m) => m !== defaultModel), ]; return arr; } else { return filteredModels; } }, [allModels]); const rootRef = useRef(null); const { position, getRelativePosition } = useRelativePosition({ delay: 0, }); const contentRef = useMemo<{ current: HTMLDivElement | null }>(() => { return { current: null, }; }, []); const selectedItemRef = useRef(null); const autoScrollToSelectedModal = () => { window.setTimeout(() => { const distanceToParent = selectedItemRef.current?.offsetTop || 0; const childHeight = selectedItemRef.current?.offsetHeight || 0; const parentHeight = contentRef.current?.offsetHeight || 0; const distanceToParentCenter = distanceToParent + childHeight / 2 - parentHeight / 2; if (distanceToParentCenter > 0 && contentRef.current) { contentRef.current.scrollTop = distanceToParentCenter; } }); }; const content: TriggerProps["content"] = ({ close }) => (
{models?.map((o) => (
{ close(); chatStore.updateCurrentSession((session) => { session.mask.modelConfig.model = o.name as ModelType; session.mask.syncGlobalConfig = false; }); showToast(o.name); }} ref={currentModel === o.name ? selectedItemRef : undefined} >
{o.name}
))}
); if (isMobileScreen) { return ( (
{content(e)}
)} type="bottom-drawer" onOpen={(e) => { if (e) { autoScrollToSelectedModal(); getRelativePosition(rootRef.current!, ""); } }} title={Locale.Chat.SelectModel} headerBordered noFooter modelClassName="h-model-bottom-drawer" >
{currentModel}
); } return ( {} })} trigger="click" noArrow placement={ position?.poi.relativePosition[1] !== Orientation.bottom ? "lb" : "lt" } popoverClassName="border border-select-popover rounded-lg shadow-select-popover-shadow w-actions-popover bg-select-popover-panel max-h-chat-actions-select-model-popover w-[280px]" onShow={(e) => { if (e) { autoScrollToSelectedModal(); getRelativePosition(rootRef.current!, ""); } }} getPopoverPanelRef={(ref) => (contentRef.current = ref.current)} >
{currentModel}
); }; export default ModelSelect;