Skip to content

Commit

Permalink
feature: customizable sidebar module #644 (#680)
Browse files Browse the repository at this point in the history
* feat:对话的时候支持侧边栏拖拽调整宽度

* feat:对话的时候支持侧边栏拖拽调整宽度

* feat: 隐藏app sidebar 用户体验度提升,不支持隐藏对话

* fix:对话勾选知识库 国际化错误

* refactor: split the SidebarIconsManager module out of DisplaySettings

* style: update SidebarIconsManager style

* ci: fix typecheck

* Revert "feat:对话的时候支持侧边栏拖拽调整宽度"

This reverts commit 5807212.

* refactor: merge migrate versions

* refactor: simplify sidebarIcons data structure

* chore: move react-beautiful-dnd to dev dependencies

* chore: use @hello-pangea/dnd replace react-beautiful-dnd

* docs: update translation and formatting of input messages

---------

Co-authored-by: hxp0618 <[email protected]>
Co-authored-by: huang <[email protected]>
  • Loading branch information
3 people authored Jan 7, 2025
1 parent edac200 commit c9813bb
Show file tree
Hide file tree
Showing 22 changed files with 2,327 additions and 1,879 deletions.
2 changes: 1 addition & 1 deletion electron.vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export default defineConfig({
}
},
optimizeDeps: {
exclude: ['chunk-QH6N6I7P.js', 'chunk-PB73W2YU.js']
exclude: ['chunk-QH6N6I7P.js', 'chunk-PB73W2YU.js', 'chunk-AFE5XGNG.js']
}
}
})
2 changes: 2 additions & 0 deletions src/main/services/KnowledgeService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,14 @@ class KnowledgeService {
if (item.type === 'url') {
const content = item.content as string
if (content.startsWith('http')) {
// @ts-ignore loader type
return await ragApplication.addLoader(new WebLoader({ urlOrContent: content }), forceReload)
}
}

if (item.type === 'sitemap') {
const content = item.content as string
// @ts-ignore loader type
return await ragApplication.addLoader(new SitemapLoader({ url: content }), forceReload)
}

Expand Down
100 changes: 37 additions & 63 deletions src/renderer/src/components/app/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ const Sidebar: FC = () => {
const { minappShow } = useRuntime()
const { t } = useTranslation()
const navigate = useNavigate()
const { windowStyle, showTranslateIcon, showPaintingIcon, showMinappIcon, showKnowledgeIcon, showFilesIcon } =
useSettings()
const { windowStyle, sidebarIcons } = useSettings()
const { theme, toggleTheme } = useTheme()

const isRoute = (path: string): string => (pathname === path ? 'active' : '')
Expand All @@ -38,6 +37,41 @@ const Sidebar: FC = () => {
navigate(path)
}

const renderMainMenus = () => {
return sidebarIcons.visible.map((icon) => {
const iconMap = {
assistants: <i className="iconfont icon-chat" />,
agents: <i className="iconfont icon-business-smart-assistant" />,
paintings: <PictureOutlined style={{ fontSize: 16 }} />,
translate: <TranslationOutlined />,
minapp: <i className="iconfont icon-appstore" />,
knowledge: <FileSearchOutlined />,
files: <FolderOutlined />
}

const pathMap = {
assistants: '/',
agents: '/agents',
paintings: '/paintings',
translate: '/translate',
minapp: '/apps',
knowledge: '/knowledge',
files: '/files'
}

const path = pathMap[icon]
const isActive = path === '/' ? isRoute(path) : isRoutes(path)

return (
<Tooltip key={icon} title={t(`${icon}.title`)} mouseEnterDelay={0.8} placement="right">
<StyledLink onClick={() => to(path)}>
<Icon className={isActive}>{iconMap[icon]}</Icon>
</StyledLink>
</Tooltip>
)
})
}

return (
<Container
id="app-sidebar"
Expand All @@ -47,67 +81,7 @@ const Sidebar: FC = () => {
}}>
<AvatarImg src={avatar || UserAvatar} draggable={false} className="nodrag" onClick={onEditUser} />
<MainMenus>
<Menus onClick={MinApp.onClose}>
<Tooltip title={t('assistants.title')} mouseEnterDelay={0.8} placement="right">
<StyledLink onClick={() => to('/')}>
<Icon className={isRoute('/')}>
<i className="iconfont icon-chat" />
</Icon>
</StyledLink>
</Tooltip>
<Tooltip title={t('agents.title')} mouseEnterDelay={0.8} placement="right">
<StyledLink onClick={() => to('/agents')}>
<Icon className={isRoutes('/agents')}>
<i className="iconfont icon-business-smart-assistant" />
</Icon>
</StyledLink>
</Tooltip>
{showPaintingIcon && (
<Tooltip title={t('paintings.title')} mouseEnterDelay={0.8} placement="right">
<StyledLink onClick={() => to('/paintings')}>
<Icon className={isRoute('/paintings')}>
<PictureOutlined style={{ fontSize: 16 }} />
</Icon>
</StyledLink>
</Tooltip>
)}
{showTranslateIcon && (
<Tooltip title={t('translate.title')} mouseEnterDelay={0.8} placement="right">
<StyledLink onClick={() => to('/translate')}>
<Icon className={isRoute('/translate')}>
<TranslationOutlined />
</Icon>
</StyledLink>
</Tooltip>
)}
{showMinappIcon && (
<Tooltip title={t('minapp.title')} mouseEnterDelay={0.8} placement="right">
<StyledLink onClick={() => to('/apps')}>
<Icon className={isRoute('/apps')}>
<i className="iconfont icon-appstore" />
</Icon>
</StyledLink>
</Tooltip>
)}
{showKnowledgeIcon && (
<Tooltip title={t('knowledge_base.title')} mouseEnterDelay={0.5} placement="right">
<StyledLink onClick={() => to('/knowledge')}>
<Icon className={isRoute('/knowledge')}>
<FileSearchOutlined />
</Icon>
</StyledLink>
</Tooltip>
)}
{showFilesIcon && (
<Tooltip title={t('files.title')} mouseEnterDelay={0.8} placement="right">
<StyledLink onClick={() => to('/files')}>
<Icon className={isRoute('/files')}>
<FolderOutlined />
</Icon>
</StyledLink>
</Tooltip>
)}
</Menus>
<Menus onClick={MinApp.onClose}>{renderMainMenus()}</Menus>
</MainMenus>
<Menus onClick={MinApp.onClose}>
<Tooltip title={t('settings.theme.title')} mouseEnterDelay={0.8} placement="right">
Expand Down
8 changes: 6 additions & 2 deletions src/renderer/src/i18n/locales/en-us.json
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,10 @@
"display.sidebar.knowledge.icon": "Show Knowledge icon",
"display.sidebar.files.icon": "Show Files icon",
"display.sidebar.title": "Sidebar Settings",
"display.sidebar.visible": "Show my sidebar icons",
"display.sidebar.disabled": "Hide my sidebar icons",
"display.sidebar.chat.hiddenMessage": "Assistants are basic functions, not supported for hiding",
"display.sidebar.empty": "Drag the hidden feature from the left side here",
"display.topic.title": "Topic Settings",
"display.custom.css": "Custom CSS",
"display.custom.css.placeholder": "/* Put custom CSS here */",
Expand All @@ -411,7 +415,7 @@
"messages.input.show_estimated_tokens": "Show estimated tokens",
"messages.metrics": "{{time_first_token_millsec}}ms to first token | {{token_speed}} tok/sec",
"messages.input.title": "Input Settings",
"messages.markdown_rendering_input_message": "Markdown render input msg",
"messages.markdown_rendering_input_message": "Markdown render input message",
"messages.math_engine": "Math render engine",
"messages.model.title": "Model Settings",
"messages.title": "Message Settings",
Expand Down Expand Up @@ -547,7 +551,7 @@
"show_window": "Show Window",
"quit": "Quit"
},
"knowledge_base": {
"knowledge": {
"title": "Knowledge Base",
"search": "Search knowledge base",
"empty": "No knowledge base found",
Expand Down
6 changes: 5 additions & 1 deletion src/renderer/src/i18n/locales/ja-jp.json
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,10 @@
"display.sidebar.knowledge.icon": "ナレッジのアイコンを表示",
"display.sidebar.files.icon": "ファイルのアイコンを表示",
"display.sidebar.title": "サイドバー設定",
"display.sidebar.visible": "サイドバーのアイコンを表示する",
"display.sidebar.disabled": "サイドバーのアイコンを非表示にする",
"display.sidebar.chat.hiddenMessage": "アシスタントは基本的な機能であり、非表示はサポートされていません",
"display.sidebar.empty": "非表示にする機能を左側からここにドラッグ",
"display.topic.title": "トピック設定",
"display.custom.css": "カスタムCSS",
"display.custom.css.placeholder": "/* ここにカスタムCSSを入力 */",
Expand Down Expand Up @@ -533,7 +537,7 @@
"show_window": "ウィンドウを表示",
"quit": "終了"
},
"knowledge_base": {
"knowledge": {
"title": "ナレッジベース",
"search": "ナレッジベースを検索",
"empty": "ナレッジベースが見つかりません",
Expand Down
6 changes: 5 additions & 1 deletion src/renderer/src/i18n/locales/ru-ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,10 @@
"display.sidebar.knowledge.icon": "Показывать иконку знаний",
"display.sidebar.files.icon": "Показывать иконку файлов",
"display.sidebar.title": "Настройки боковой панели",
"display.sidebar.visible": "Показать мои значки на боковой панели",
"display.sidebar.disabled": "Скрыть значок на боковой панели",
"display.sidebar.chat.hiddenMessage": "Помощник является базовой функцией и не поддерживает скрытие",
"display.sidebar.empty": "Перетащите скрываемую функцию с левой стороны сюда",
"display.topic.title": "Настройки топиков",
"display.custom.css": "Пользовательский CSS",
"display.custom.css.placeholder": "/* Здесь введите пользовательский CSS */",
Expand Down Expand Up @@ -547,7 +551,7 @@
"show_window": "Показать окно",
"quit": "Выйти"
},
"knowledge_base": {
"knowledge": {
"title": "База знаний",
"search": "Поиск в базе знаний",
"empty": "База знаний не найдена",
Expand Down
6 changes: 5 additions & 1 deletion src/renderer/src/i18n/locales/zh-cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,10 @@
"display.sidebar.knowledge.icon": "显示知识图标",
"display.sidebar.files.icon": "显示文件图标",
"display.sidebar.title": "侧边栏设置",
"display.sidebar.visible": "显示我的侧边栏图标",
"display.sidebar.disabled": "隐藏我的侧边栏图标",
"display.sidebar.chat.hiddenMessage": "助手是基础功能,不支持隐藏",
"display.sidebar.empty": "把要隐藏的功能从左侧拖拽到这里",
"display.topic.title": "话题设置",
"display.custom.css": "自定义 CSS",
"display.custom.css.placeholder": "/* 这里写自定义CSS */",
Expand Down Expand Up @@ -536,7 +540,7 @@
"show_window": "显示窗口",
"quit": "退出"
},
"knowledge_base": {
"knowledge": {
"title": "知识库",
"search": "搜索知识库",
"empty": "暂无知识库",
Expand Down
6 changes: 5 additions & 1 deletion src/renderer/src/i18n/locales/zh-tw.json
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,10 @@
"display.sidebar.files.icon": "顯示文件圖示",
"display.sidebar.title": "側邊欄設定",
"display.topic.title": "話題設定",
"display.sidebar.chat.hiddenMessage": "助手是基礎功能,不支援隱藏",
"display.sidebar.empty": "把要隱藏的功能從左側拖拽到這裡",
"display.sidebar.visible": "顯示我的側邊欄圖標",
"display.sidebar.disabled": "隱藏我的側邊欄圖標",
"display.custom.css": "自定義 CSS",
"display.custom.css.placeholder": "/* 這裡寫自定義 CSS */",
"input.auto_translate_with_space": "快速敲擊3次空格翻譯",
Expand Down Expand Up @@ -535,7 +539,7 @@
"show_window": "顯示視窗",
"quit": "退出"
},
"knowledge_base": {
"knowledge": {
"title": "知識庫",
"search": "搜尋知識庫",
"empty": "暫無知識庫",
Expand Down
4 changes: 3 additions & 1 deletion src/renderer/src/pages/home/Inputbar/Inputbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic }) => {
clickAssistantToShowTopic,
language,
autoTranslateWithSpace,
showKnowledgeIcon
sidebarIcons
} = useSettings()
const [expended, setExpend] = useState(false)
const [estimateTokenCount, setEstimateTokenCount] = useState(0)
Expand All @@ -85,6 +85,8 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic }) => {
const isVision = useMemo(() => isVisionModel(model), [model])
const supportExts = useMemo(() => [...textExts, ...documentExts, ...(isVision ? imageExts : [])], [isVision])

const showKnowledgeIcon = sidebarIcons.visible.includes('knowledge')

const estimateTextTokens = useCallback(debounce(estimateTxtTokens, 1000), [])
const inputTokenCount = useMemo(
() => (showInputEstimatedTokens ? estimateTextTokens(text) || 0 : 0),
Expand Down
3 changes: 2 additions & 1 deletion src/renderer/src/pages/home/Messages/MessageHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const getAvatarSource = (isLocalAi: boolean, modelId: string | undefined) => {
const MessageHeader: FC<Props> = memo(({ assistant, model, message }) => {
const avatar = useAvatar()
const { theme } = useTheme()
const { userName, showMinappIcon } = useSettings()
const { userName, sidebarIcons } = useSettings()
const { t } = useTranslation()
const { isBubbleStyle } = useMessageStyle()

Expand All @@ -40,6 +40,7 @@ const MessageHeader: FC<Props> = memo(({ assistant, model, message }) => {
}, [message.modelId, message.role, model?.id, model?.name, t, userName])

const isAssistantMessage = message.role === 'assistant'
const showMinappIcon = sidebarIcons.visible.includes('minapp')

const avatarName = useMemo(() => firstLetter(assistant?.name).toUpperCase(), [assistant?.name])
const username = useMemo(() => removeLeadingEmoji(getUserName()), [getUserName])
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/src/pages/home/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ interface Props {
const HeaderNavbar: FC<Props> = ({ activeAssistant }) => {
const { assistant } = useAssistant(activeAssistant.id)
const { showAssistants, toggleShowAssistants } = useShowAssistants()
const { topicPosition, showMinappIcon } = useSettings()
const { topicPosition, sidebarIcons } = useSettings()
const { showTopics, toggleShowTopics } = useShowTopics()

useShortcut('toggle_show_assistants', () => {
Expand Down Expand Up @@ -79,7 +79,7 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant }) => {
<NavbarIcon onClick={() => SearchPopup.show()}>
<SearchOutlined />
</NavbarIcon>
{showMinappIcon && (
{sidebarIcons.visible.includes('minapp') && (
<AppStorePopover>
<NavbarIcon style={{ marginLeft: isMac ? 5 : 10 }}>
<i className="iconfont icon-appstore" />
Expand Down
Loading

0 comments on commit c9813bb

Please sign in to comment.