feat: Add sidebar chat history and functionality

This commit is contained in:
n4ze3m 2025-01-11 20:58:45 +05:30
parent fbf82c39fd
commit 867204604b
21 changed files with 146 additions and 47 deletions

View File

@ -124,5 +124,6 @@
}, },
"pin": "تثبيت", "pin": "تثبيت",
"unpin": "إلغاء التثبيت", "unpin": "إلغاء التثبيت",
"generationInfo": "معلومات التوليد" "generationInfo": "معلومات التوليد",
"sidebarChat": "دردشة الشريط الجانبي"
} }

View File

@ -117,5 +117,6 @@
}, },
"pin": "Fastgør", "pin": "Fastgør",
"unpin": "Frigør", "unpin": "Frigør",
"generationInfo": "Genererings Info" "generationInfo": "Genererings Info",
"sidebarChat": "Sidepanel Chat"
} }

View File

@ -117,5 +117,6 @@
}, },
"pin": "Anheften", "pin": "Anheften",
"unpin": "Losheften", "unpin": "Losheften",
"generationInfo": "Generierungsinformationen" "generationInfo": "Generierungsinformationen",
"sidebarChat": "Seitenleisten-Chat"
} }

View File

@ -151,5 +151,6 @@
}, },
"pin": "Pin", "pin": "Pin",
"unpin": "Unpin", "unpin": "Unpin",
"generationInfo": "Generation Info" "generationInfo": "Generation Info",
"sidebarChat": "Sidebar Chat"
} }

View File

@ -116,5 +116,6 @@
}, },
"pin": "Fijar", "pin": "Fijar",
"unpin": "Desfijar", "unpin": "Desfijar",
"generationInfo": "Información de Generación" "generationInfo": "Información de Generación",
"sidebarChat": "Chat lateral"
} }

View File

@ -110,5 +110,6 @@
}, },
"pin": "پین کردن", "pin": "پین کردن",
"unpin": "حذف پین", "unpin": "حذف پین",
"generationInfo": "اطلاعات تولید" "generationInfo": "اطلاعات تولید",
"sidebarChat": "چت کناری"
} }

View File

@ -116,5 +116,6 @@
}, },
"pin": "Épingler", "pin": "Épingler",
"unpin": "Désépingler", "unpin": "Désépingler",
"generationInfo": "Informations de génération" "generationInfo": "Informations de génération",
"sidebarChat": "Chat latéral"
} }

View File

@ -116,5 +116,6 @@
}, },
"pin": "Fissa", "pin": "Fissa",
"unpin": "Rimuovi", "unpin": "Rimuovi",
"generationInfo": "Informazioni sulla Generazione" "generationInfo": "Informazioni sulla Generazione",
"sidebarChat": "Chat Laterale"
} }

View File

@ -116,5 +116,6 @@
}, },
"pin": "固定", "pin": "固定",
"unpin": "固定解除", "unpin": "固定解除",
"generationInfo": "生成情報" "generationInfo": "生成情報",
"sidebarChat": "サイドバーチャット"
} }

View File

@ -73,7 +73,8 @@
"numPredict": { "numPredict": {
"label": "최대 토큰 수 (num_predict)", "label": "최대 토큰 수 (num_predict)",
"placeholder": "최대 토큰 수를 입력하세요 (예: 2048, 4096)" "placeholder": "최대 토큰 수를 입력하세요 (예: 2048, 4096)"
}, "seed": { },
"seed": {
"label": "시드", "label": "시드",
"placeholder": "시드 값을 입력하세요 (예: 1234)", "placeholder": "시드 값을 입력하세요 (예: 1234)",
"help": "모델 출력의 재현성" "help": "모델 출력의 재현성"
@ -115,5 +116,6 @@
}, },
"pin": "고정", "pin": "고정",
"unpin": "고정 해제", "unpin": "고정 해제",
"generationInfo": "생성 정보" "generationInfo": "생성 정보",
"sidebarChat": "사이드바 채팅"
} }

View File

@ -115,6 +115,7 @@
}, },
"pin": "പിൻ ചെയ്യുക", "pin": "പിൻ ചെയ്യുക",
"unpin": "അൺപിൻ ചെയ്യുക", "unpin": "അൺപിൻ ചെയ്യുക",
"generationInfo": "ജനറേഷൻ വിവരങ്ങൾ" "generationInfo": "ജനറേഷൻ വിവരങ്ങൾ",
"sidebarChat": "സൈഡ്ബാർ ചാറ്റ്"
} }

View File

@ -117,5 +117,6 @@
}, },
"pin": "Fest", "pin": "Fest",
"unpin": "Løsne", "unpin": "Løsne",
"generationInfo": "Generasjonsinformasjon" "generationInfo": "Generasjonsinformasjon",
"sidebarChat": "Sidepanel-chat"
} }

View File

@ -116,5 +116,6 @@
}, },
"pin": "Fixar", "pin": "Fixar",
"unpin": "Desafixar", "unpin": "Desafixar",
"generationInfo": "Informações de Geração" "generationInfo": "Informações de Geração",
"sidebarChat": "Chat Lateral"
} }

View File

@ -116,5 +116,6 @@
}, },
"pin": "Закрепить", "pin": "Закрепить",
"unpin": "Открепить", "unpin": "Открепить",
"generationInfo": "Информация о генерации" "generationInfo": "Информация о генерации",
"sidebarChat": "Боковой чат"
} }

View File

@ -121,5 +121,6 @@
}, },
"pin": "Fäst", "pin": "Fäst",
"unpin": "Ta bort fäst", "unpin": "Ta bort fäst",
"generationInfo": "Generationsinformation" "generationInfo": "Generationsinformation",
"sidebarChat": "Sidofältschatt"
} }

View File

@ -121,5 +121,6 @@
}, },
"pin": "Прикріпити", "pin": "Прикріпити",
"unpin": "Відкріпити", "unpin": "Відкріпити",
"generationInfo": "Інформація про генерацію" "generationInfo": "Інформація про генерацію",
"sidebarChat": "Бічний чат"
} }

View File

@ -116,5 +116,6 @@
}, },
"pin": "置顶", "pin": "置顶",
"unpin": "取消置顶", "unpin": "取消置顶",
"generationInfo": "生成信息" "generationInfo": "生成信息",
"sidebarChat": "侧边栏聊天"
} }

View File

@ -11,6 +11,7 @@ import { EraserIcon } from "lucide-react"
import { PageAssitDatabase } from "@/db" import { PageAssitDatabase } from "@/db"
import { useMessageOption } from "@/hooks/useMessageOption" import { useMessageOption } from "@/hooks/useMessageOption"
import { useQueryClient } from "@tanstack/react-query" import { useQueryClient } from "@tanstack/react-query"
import { useStoreChatModelSettings } from "@/store/model"
export default function OptionLayout({ export default function OptionLayout({
children children
@ -20,8 +21,19 @@ export default function OptionLayout({
const [sidebarOpen, setSidebarOpen] = useState(false) const [sidebarOpen, setSidebarOpen] = useState(false)
const { t } = useTranslation(["option", "common", "settings"]) const { t } = useTranslation(["option", "common", "settings"])
const [openModelSettings, setOpenModelSettings] = useState(false) const [openModelSettings, setOpenModelSettings] = useState(false)
const { clearChat } = useMessageOption() const {
setMessages,
setHistory,
setHistoryId,
historyId,
clearChat,
setSelectedModel,
temporaryChat,
setSelectedSystemPrompt
} = useMessageOption()
const queryClient = useQueryClient() const queryClient = useQueryClient()
const { setSystemPrompt } = useStoreChatModelSettings()
return ( return (
<> <>
@ -70,7 +82,19 @@ export default function OptionLayout({
closeIcon={null} closeIcon={null}
onClose={() => setSidebarOpen(false)} onClose={() => setSidebarOpen(false)}
open={sidebarOpen}> open={sidebarOpen}>
<Sidebar onClose={() => setSidebarOpen(false)} /> <Sidebar
onClose={() => setSidebarOpen(false)}
setMessages={setMessages}
setHistory={setHistory}
setHistoryId={setHistoryId}
setSelectedModel={setSelectedModel}
setSelectedSystemPrompt={setSelectedSystemPrompt}
clearChat={clearChat}
historyId={historyId}
setSystemPrompt={setSystemPrompt}
temporaryChat={temporaryChat}
history={history}
/>
</Drawer> </Drawer>
<CurrentChatModelSettings <CurrentChatModelSettings

View File

@ -8,14 +8,14 @@ import {
pinHistory, pinHistory,
getPromptById getPromptById
} from "@/db" } from "@/db"
import { Empty, Skeleton, Dropdown, Menu } from "antd" import { Empty, Skeleton, Dropdown, Menu, Tooltip } from "antd"
import { useMessageOption } from "~/hooks/useMessageOption"
import { import {
PencilIcon, PencilIcon,
Trash2, Trash2,
MoreVertical, MoreVertical,
PinIcon, PinIcon,
PinOffIcon PinOffIcon,
BotIcon
} from "lucide-react" } from "lucide-react"
import { useNavigate } from "react-router-dom" import { useNavigate } from "react-router-dom"
import { useTranslation } from "react-i18next" import { useTranslation } from "react-i18next"
@ -24,26 +24,33 @@ import {
getLastUsedChatSystemPrompt, getLastUsedChatSystemPrompt,
lastUsedChatModelEnabled lastUsedChatModelEnabled
} from "@/services/model-settings" } from "@/services/model-settings"
import { useStoreChatModelSettings } from "@/store/model"
type Props = { type Props = {
onClose: () => void onClose: () => void
setMessages: (messages: any) => void
setHistory: (history: any) => void
setHistoryId: (historyId: string) => void
setSelectedModel: (model: string) => void
setSelectedSystemPrompt: (prompt: string) => void
setSystemPrompt: (prompt: string) => void
clearChat: () => void
temporaryChat: boolean
historyId: string
history: any
} }
export const Sidebar = ({ onClose }: Props) => { export const Sidebar = ({
const { onClose,
setMessages, setMessages,
setHistory, setHistory,
setHistoryId, setHistoryId,
historyId, setSelectedModel,
clearChat, setSelectedSystemPrompt,
setSelectedModel, clearChat,
temporaryChat, historyId,
setSelectedSystemPrompt setSystemPrompt,
} = useMessageOption() temporaryChat
}: Props) => {
const { setSystemPrompt } = useStoreChatModelSettings()
const { t } = useTranslation(["option", "common"]) const { t } = useTranslation(["option", "common"])
const client = useQueryClient() const client = useQueryClient()
const navigate = useNavigate() const navigate = useNavigate()
@ -162,7 +169,12 @@ export const Sidebar = ({ onClose }: Props) => {
{group.items.map((chat, index) => ( {group.items.map((chat, index) => (
<div <div
key={index} key={index}
className="flex py-2 px-2 items-start gap-3 relative rounded-md truncate hover:pr-4 group transition-opacity duration-300 ease-in-out bg-gray-100 dark:bg-[#232222] dark:text-gray-100 text-gray-800 border hover:bg-gray-200 dark:hover:bg-[#2d2d2d] dark:border-gray-800"> className="flex py-2 px-2 items-center gap-3 relative rounded-md truncate hover:pr-4 group transition-opacity duration-300 ease-in-out bg-gray-100 dark:bg-[#232222] dark:text-gray-100 text-gray-800 border hover:bg-gray-200 dark:hover:bg-[#2d2d2d] dark:border-gray-800">
{chat?.message_source === "copilot" && (
<Tooltip title={t("common:sidebarChat")} placement="top">
<BotIcon className="size-3 text-green-500" />
</Tooltip>
)}
<button <button
className="flex-1 overflow-hidden break-all text-start truncate w-full" className="flex-1 overflow-hidden break-all text-start truncate w-full"
onClick={async () => { onClick={async () => {

View File

@ -1,13 +1,20 @@
import logoImage from "~/assets/icon.png" import logoImage from "~/assets/icon.png"
import { useMessage } from "~/hooks/useMessage" import { useMessage } from "~/hooks/useMessage"
import { Link } from "react-router-dom" import { Link } from "react-router-dom"
import { Tooltip } from "antd" import { Tooltip, Drawer } from "antd"
import { BoxesIcon, BrainCog, CogIcon, EraserIcon } from "lucide-react" import {
BoxesIcon,
BrainCog,
CogIcon,
EraserIcon,
HistoryIcon
} from "lucide-react"
import { useTranslation } from "react-i18next" import { useTranslation } from "react-i18next"
import { CurrentChatModelSettings } from "@/components/Common/Settings/CurrentChatModelSettings" import { CurrentChatModelSettings } from "@/components/Common/Settings/CurrentChatModelSettings"
import React from "react" import React from "react"
import { useStorage } from "@plasmohq/storage/hook" import { useStorage } from "@plasmohq/storage/hook"
import { PromptSelect } from "@/components/Common/PromptSelect" import { PromptSelect } from "@/components/Common/PromptSelect"
import { Sidebar } from "@/components/Option/Sidebar"
export const SidepanelHeader = () => { export const SidepanelHeader = () => {
const [hideCurrentChatModelSettings] = useStorage( const [hideCurrentChatModelSettings] = useStorage(
"hideCurrentChatModelSettings", "hideCurrentChatModelSettings",
@ -21,10 +28,16 @@ export const SidepanelHeader = () => {
streaming, streaming,
selectedSystemPrompt, selectedSystemPrompt,
setSelectedSystemPrompt, setSelectedSystemPrompt,
setSelectedQuickPrompt setSelectedQuickPrompt,
setMessages,
setHistory,
setHistoryId,
setSelectedModel,
historyId
} = useMessage() } = useMessage()
const { t } = useTranslation(["sidepanel", "common"]) const { t } = useTranslation(["sidepanel", "common"])
const [openModelSettings, setOpenModelSettings] = React.useState(false) const [openModelSettings, setOpenModelSettings] = React.useState(false)
const [sidebarOpen, setSidebarOpen] = React.useState(false)
return ( return (
<div className="flex px-3 justify-between bg-white dark:bg-[#171717] border-b border-gray-300 dark:border-gray-700 py-4 items-center"> <div className="flex px-3 justify-between bg-white dark:bg-[#171717] border-b border-gray-300 dark:border-gray-700 py-4 items-center">
@ -53,13 +66,21 @@ export const SidepanelHeader = () => {
<EraserIcon className="h-5 w-5 text-gray-500 dark:text-gray-400" /> <EraserIcon className="h-5 w-5 text-gray-500 dark:text-gray-400" />
</button> </button>
)} )}
<Tooltip title={t("tooltip.history")}>
<button
onClick={() => {
setSidebarOpen(true)
}}
className="flex items-center space-x-1 focus:outline-none focus-visible:ring-2 focus-visible:ring-pink-700">
<HistoryIcon className="h-5 w-5 text-gray-500 dark:text-gray-400" />
</button>
</Tooltip>
<PromptSelect <PromptSelect
selectedSystemPrompt={selectedSystemPrompt} selectedSystemPrompt={selectedSystemPrompt}
setSelectedSystemPrompt={setSelectedSystemPrompt} setSelectedSystemPrompt={setSelectedSystemPrompt}
setSelectedQuickPrompt={setSelectedQuickPrompt} setSelectedQuickPrompt={setSelectedQuickPrompt}
className="text-gray-500 dark:text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors" className="text-gray-500 dark:text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors"
/> />
{!hideCurrentChatModelSettings && ( {!hideCurrentChatModelSettings && (
<Tooltip title={t("common:currentChatModelSettings")}> <Tooltip title={t("common:currentChatModelSettings")}>
<button <button
@ -77,6 +98,31 @@ export const SidepanelHeader = () => {
open={openModelSettings} open={openModelSettings}
setOpen={setOpenModelSettings} setOpen={setOpenModelSettings}
/> />
<Drawer
title={
<div className="flex items-center justify-between">
{t("tooltip.history")}
</div>
}
placement="left"
closeIcon={null}
onClose={() => setSidebarOpen(false)}
open={sidebarOpen}>
<Sidebar
onClose={() => setSidebarOpen(false)}
setMessages={setMessages}
setHistory={setHistory}
setHistoryId={setHistoryId}
setSelectedModel={setSelectedModel}
setSelectedSystemPrompt={setSelectedSystemPrompt}
clearChat={clearChat}
historyId={historyId}
setSystemPrompt={(e) => {}}
temporaryChat={false}
history={history}
/>
</Drawer>
</div> </div>
) )
} }

View File

@ -34,7 +34,6 @@ import { pageAssistModel } from "@/models"
import { getPrompt } from "@/services/application" import { getPrompt } from "@/services/application"
import { humanMessageFormatter } from "@/utils/human-message" import { humanMessageFormatter } from "@/utils/human-message"
import { pageAssistEmbeddingModel } from "@/models/embedding" import { pageAssistEmbeddingModel } from "@/models/embedding"
import { PageAssistVectorStore } from "@/libs/PageAssistVectorStore"
import { PAMemoryVectorStore } from "@/libs/PAMemoryVectorStore" import { PAMemoryVectorStore } from "@/libs/PAMemoryVectorStore"
import { getScreenshotFromCurrentTab } from "@/libs/get-screenshot" import { getScreenshotFromCurrentTab } from "@/libs/get-screenshot"