diff --git a/web/containers/CardSidebar/index.tsx b/web/containers/CardSidebar/index.tsx index 8222c4918..4954cbd00 100644 --- a/web/containers/CardSidebar/index.tsx +++ b/web/containers/CardSidebar/index.tsx @@ -11,27 +11,22 @@ import { twMerge } from 'tailwind-merge' import { useClickOutside } from '@/hooks/useClickOutside' +import { usePath } from '@/hooks/usePath' + import { activeThreadAtom } from '@/helpers/atoms/Thread.atom' interface Props { children: ReactNode title: string - onRevealInFinderClick?: (type: string) => void - onViewJsonClick?: (type: string) => void asChild?: boolean } -export default function CardSidebar({ - children, - title, - onRevealInFinderClick, - onViewJsonClick, - asChild, -}: Props) { +export default function CardSidebar({ children, title, asChild }: Props) { const [show, setShow] = useState(true) const [more, setMore] = useState(false) const [menu, setMenu] = useState(null) const [toggle, setToggle] = useState(null) const activeThread = useAtomValue(activeThreadAtom) + const { onReviewInFinder, onViewJson } = usePath() useClickOutside(() => setMore(false), null, [menu, toggle]) @@ -90,7 +85,7 @@ export default function CardSidebar({ title === 'Model' ? 'items-start' : 'items-center' )} onClick={() => { - onRevealInFinderClick && onRevealInFinderClick(title) + onReviewInFinder && onReviewInFinder(title) setMore(false) }} > @@ -121,7 +116,7 @@ export default function CardSidebar({
{ - onViewJsonClick && onViewJsonClick(title) + onViewJson && onViewJson(title) setMore(false) }} > diff --git a/web/containers/Layout/TopBar/index.tsx b/web/containers/Layout/TopBar/index.tsx index 208ca4bdb..992aaf1c0 100644 --- a/web/containers/Layout/TopBar/index.tsx +++ b/web/containers/Layout/TopBar/index.tsx @@ -1,6 +1,5 @@ import { useState } from 'react' -import { getUserSpace, joinPath, openFileExplorer } from '@janhq/core' import { useAtom, useAtomValue } from 'jotai' import { PenSquareIcon, @@ -24,9 +23,11 @@ import { useCreateNewThread } from '@/hooks/useCreateNewThread' import useGetAssistants, { getAssistants } from '@/hooks/useGetAssistants' import { useMainViewState } from '@/hooks/useMainViewState' +import { usePath } from '@/hooks/usePath' + import { showRightSideBarAtom } from '@/screens/Chat/Sidebar' -import { activeThreadAtom, threadStatesAtom } from '@/helpers/atoms/Thread.atom' +import { activeThreadAtom } from '@/helpers/atoms/Thread.atom' const TopBar = () => { const activeThread = useAtomValue(activeThreadAtom) @@ -36,7 +37,7 @@ const TopBar = () => { const [showRightSideBar, setShowRightSideBar] = useAtom(showRightSideBarAtom) const [showLeftSideBar, setShowLeftSideBar] = useAtom(showLeftSideBarAtom) const showing = useAtomValue(showRightSideBarAtom) - const threadStates = useAtomValue(threadStatesAtom) + const { onReviewInFinder, onViewJson } = usePath() const [more, setMore] = useState(false) const [menu, setMenu] = useState(null) const [toggle, setToggle] = useState(null) @@ -66,42 +67,16 @@ const TopBar = () => { } } - 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 && ( + {mainViewState !== MainViewState.Thread && + mainViewState !== MainViewState.LocalServer ? ( +
+ + {titleScreen(mainViewState)} + +
+ ) : (
@@ -148,7 +123,10 @@ const TopBar = () => { {showing && (
- Threads Settings + {mainViewState === MainViewState.Thread && + 'Threads Settings'} + {mainViewState === MainViewState.LocalServer && + 'Model Settings'}
{
- {more && ( + {mainViewState === MainViewState.Thread && more && (
{
{ - onReviewInFinderClick() + onReviewInFinder('Thread') setMore(false) }} > @@ -181,7 +159,7 @@ const TopBar = () => {
{ - onViewJsonClick() + onViewJson('Thread') setMore(false) }} > @@ -201,6 +179,34 @@ const TopBar = () => {
)} + + {mainViewState === MainViewState.LocalServer && more && ( +
+
{ + onReviewInFinder('Model') + setMore(false) + }} + > + +
+ + Show in Finder + + + Opens model.json + +
+
+
+ )}
)}
{
)} - - {mainViewState !== MainViewState.Thread && ( -
- - {titleScreen(mainViewState)} - -
- )}
) diff --git a/web/hooks/usePath.ts b/web/hooks/usePath.ts new file mode 100644 index 000000000..31a99708f --- /dev/null +++ b/web/hooks/usePath.ts @@ -0,0 +1,83 @@ +import { getUserSpace, openFileExplorer, joinPath } from '@janhq/core' +import { useAtomValue } from 'jotai' + +import { selectedModelAtom } from '@/containers/DropdownListSidebar' + +import { activeThreadAtom, threadStatesAtom } from '@/helpers/atoms/Thread.atom' + +export const usePath = () => { + const activeThread = useAtomValue(activeThreadAtom) + const threadStates = useAtomValue(threadStatesAtom) + const selectedModel = useAtomValue(selectedModelAtom) + + const onReviewInFinder = async (type: string) => { + 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 + const assistantId = activeThread.assistants[0]?.assistant_id + switch (type) { + case 'Engine': + case 'Thread': + filePath = await joinPath(['threads', activeThread.id]) + break + case 'Model': + if (!selectedModel) return + filePath = await joinPath(['models', selectedModel.id]) + break + case 'Assistant': + if (!assistantId) return + filePath = await joinPath(['assistants', assistantId]) + break + default: + break + } + + if (!filePath) return + const fullPath = await joinPath([userSpace, filePath]) + openFileExplorer(fullPath) + } + + const onViewJson = async (type: string) => { + 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 + const assistantId = activeThread.assistants[0]?.assistant_id + switch (type) { + case 'Engine': + case 'Thread': + filePath = await joinPath(['threads', activeThread.id, 'thread.json']) + break + case 'Model': + if (!selectedModel) return + filePath = await joinPath(['models', selectedModel.id, 'model.json']) + break + case 'Assistant': + if (!assistantId) return + filePath = await joinPath(['assistants', assistantId, 'assistant.json']) + break + default: + break + } + + if (!filePath) return + const fullPath = await joinPath([userSpace, filePath]) + openFileExplorer(fullPath) + } + + return { + onReviewInFinder, + onViewJson, + } +} diff --git a/web/screens/Chat/Sidebar/index.tsx b/web/screens/Chat/Sidebar/index.tsx index 1826b1700..64e58d4d3 100644 --- a/web/screens/Chat/Sidebar/index.tsx +++ b/web/screens/Chat/Sidebar/index.tsx @@ -1,8 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import React from 'react' -import { getUserSpace, openFileExplorer, joinPath } from '@janhq/core' - import { Input, Textarea } from '@janhq/uikit' import { atom, useAtomValue } from 'jotai' @@ -12,9 +10,7 @@ import { twMerge } from 'tailwind-merge' import LogoMark from '@/containers/Brand/Logo/Mark' import CardSidebar from '@/containers/CardSidebar' -import DropdownListSidebar, { - selectedModelAtom, -} from '@/containers/DropdownListSidebar' +import DropdownListSidebar from '@/containers/DropdownListSidebar' import { useCreateNewThread } from '@/hooks/useCreateNewThread' @@ -29,7 +25,6 @@ import settingComponentBuilder from '../ModelSetting/settingComponentBuilder' import { activeThreadAtom, getActiveThreadModelParamsAtom, - threadStatesAtom, } from '@/helpers/atoms/Thread.atom' export const showRightSideBarAtom = atom(true) @@ -38,82 +33,14 @@ const Sidebar: React.FC = () => { const showing = useAtomValue(showRightSideBarAtom) const activeThread = useAtomValue(activeThreadAtom) const activeModelParams = useAtomValue(getActiveThreadModelParamsAtom) - const selectedModel = useAtomValue(selectedModelAtom) - const { updateThreadMetadata } = useCreateNewThread() - const threadStates = useAtomValue(threadStatesAtom) + const { updateThreadMetadata } = useCreateNewThread() const modelEngineParams = toSettingParams(activeModelParams) const modelRuntimeParams = toRuntimeParams(activeModelParams) const componentDataEngineSetting = getConfigurationsData(modelEngineParams) const componentDataRuntimeSetting = getConfigurationsData(modelRuntimeParams) - const onReviewInFinderClick = async (type: string) => { - 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 - const assistantId = activeThread.assistants[0]?.assistant_id - switch (type) { - case 'Engine': - case 'Thread': - filePath = await joinPath(['threads', activeThread.id]) - break - case 'Model': - if (!selectedModel) return - filePath = await joinPath(['models', selectedModel.id]) - break - case 'Assistant': - if (!assistantId) return - filePath = await joinPath(['assistants', assistantId]) - break - default: - break - } - - if (!filePath) return - const fullPath = await joinPath([userSpace, filePath]) - openFileExplorer(fullPath) - } - - const onViewJsonClick = async (type: string) => { - 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 - const assistantId = activeThread.assistants[0]?.assistant_id - switch (type) { - case 'Engine': - case 'Thread': - filePath = await joinPath(['threads', activeThread.id, 'thread.json']) - break - case 'Model': - if (!selectedModel) return - filePath = await joinPath(['models', selectedModel.id, 'model.json']) - break - case 'Assistant': - if (!assistantId) return - filePath = await joinPath(['assistants', assistantId, 'assistant.json']) - break - default: - break - } - - if (!filePath) return - const fullPath = await joinPath([userSpace, filePath]) - openFileExplorer(fullPath) - } - return (
{
- +
@@ -216,11 +139,7 @@ const Sidebar: React.FC = () => {
*/}
- +
@@ -250,12 +169,7 @@ const Sidebar: React.FC = () => { {componentDataEngineSetting.length !== 0 && (
- +