import { useState } from 'react' import { getUserSpace, joinPath, openFileExplorer } from '@janhq/core' import { useAtomValue, useSetAtom } from 'jotai' import { PanelLeftIcon, PenSquareIcon, PanelRightIcon, MoreVerticalIcon, FolderOpenIcon, Code2Icon, } from 'lucide-react' import { twMerge } from 'tailwind-merge' import CommandListDownloadedModel from '@/containers/Layout/TopBar/CommandListDownloadedModel' import CommandSearch from '@/containers/Layout/TopBar/CommandSearch' import { MainViewState } from '@/constants/screens' import { useClickOutside } from '@/hooks/useClickOutside' import { useCreateNewThread } from '@/hooks/useCreateNewThread' import useGetAssistants, { getAssistants } from '@/hooks/useGetAssistants' import { useMainViewState } from '@/hooks/useMainViewState' import { showRightSideBarAtom } from '@/screens/Chat/Sidebar' import { activeThreadAtom, threadStatesAtom } from '@/helpers/atoms/Thread.atom' const TopBar = () => { const activeThread = useAtomValue(activeThreadAtom) const { mainViewState } = useMainViewState() const { requestCreateNewThread } = useCreateNewThread() const { assistants } = useGetAssistants() const setShowRightSideBar = useSetAtom(showRightSideBarAtom) const showing = useAtomValue(showRightSideBarAtom) const threadStates = useAtomValue(threadStatesAtom) const [more, setMore] = useState(false) const [menu, setMenu] = useState(null) const [toggle, setToggle] = useState(null) useClickOutside(() => setMore(false), null, [menu, toggle]) const titleScreen = (viewStateName: MainViewState) => { switch (viewStateName) { case MainViewState.Thread: return activeThread ? activeThread?.title : 'New Thread' default: return MainViewState[viewStateName]?.replace(/([A-Z])/g, ' $1').trim() } } const onCreateConversationClick = async () => { if (assistants.length === 0) { await getAssistants().then((res) => { if (res) { if (res.length === 0) { alert('No assistant available') return } requestCreateNewThread(res[0]) } }) } else { requestCreateNewThread(assistants[0]) } } const onReviewInFinderClick = async () => { if (!activeThread) return const activeThreadState = threadStates[activeThread.id] if (!activeThreadState.isFinishInit) { alert('Thread is not started yet') return } const userSpace = await getUserSpace() let filePath = undefined filePath = await joinPath(['threads', activeThread.id]) if (!filePath) return const fullPath = await joinPath([userSpace, filePath]) openFileExplorer(fullPath) } const onViewJsonClick = async () => { if (!activeThread) return const activeThreadState = threadStates[activeThread.id] if (!activeThreadState.isFinishInit) { alert('Thread is not started yet') return } const userSpace = await getUserSpace() let filePath = undefined filePath = await joinPath(['threads', activeThread.id, 'thread.json']) if (!filePath) return const fullPath = await joinPath([userSpace, filePath]) openFileExplorer(fullPath) } return (
{mainViewState === MainViewState.Thread && (
{titleScreen(mainViewState)}
{activeThread && (
{showing && (
Threads Settings
setMore(!more)} >
{more && (
{ onReviewInFinderClick() setMore(false) }} > Show in Finder
{ onViewJsonClick() setMore(false) }} >
Edit Threads Settings Opens thread.json. Changes affect this thread only.
)}
)}
setShowRightSideBar((show) => !show)} >
)}
)} {mainViewState !== MainViewState.Thread && (
{titleScreen(mainViewState)}
)}
) } export default TopBar