feat: support pin topic to the top

Signed-off-by: jtsang4 <info@jtsang.me>
This commit is contained in:
jtsang4 2025-05-20 07:36:50 +08:00 committed by 亢奋猫
parent f5d8f83eb7
commit 1b125270b5
9 changed files with 36 additions and 2 deletions

View File

@ -12,6 +12,7 @@ import {
setTheme,
SettingsState,
setTopicPosition,
setPinTopicsToTop,
setTray as _setTray,
setTrayOnClose,
setWindowStyle
@ -68,6 +69,9 @@ export function useSettings() {
setTopicPosition(topicPosition: 'left' | 'right') {
dispatch(setTopicPosition(topicPosition))
},
setPinTopicsToTop(pinTopicsToTop: boolean) {
dispatch(setPinTopicsToTop(pinTopicsToTop))
},
updateSidebarIcons(icons: { visible: SidebarIcon[]; disabled: SidebarIcon[] }) {
dispatch(setSidebarIcons(icons))
},

View File

@ -1635,6 +1635,7 @@
"topic.position.left": "Left",
"topic.position.right": "Right",
"topic.show.time": "Show topic time",
"topic.pin_to_top": "Pin Topics to Top",
"tray.onclose": "Minimize to Tray on Close",
"tray.show": "Show Tray Icon",
"tray.title": "Tray",

View File

@ -1626,6 +1626,7 @@
"topic.position.left": "左",
"topic.position.right": "右",
"topic.show.time": "トピックの時間を表示",
"topic.pin_to_top": "固定トピックを上部に表示",
"tray.onclose": "閉じるときにトレイに最小化",
"tray.show": "トレイアイコンを表示",
"tray.title": "トレイ",

View File

@ -1626,6 +1626,7 @@
"topic.position.left": "Слева",
"topic.position.right": "Справа",
"topic.show.time": "Показывать время топика",
"topic.pin_to_top": "Закрепленные топики сверху",
"tray.onclose": "Свернуть в трей при закрытии",
"tray.show": "Показать значок в трее",
"tray.title": "Трей",

View File

@ -1635,6 +1635,7 @@
"topic.position.left": "左侧",
"topic.position.right": "右侧",
"topic.show.time": "显示话题时间",
"topic.pin_to_top": "固定话题置顶",
"tray.onclose": "关闭时最小化到托盘",
"tray.show": "显示托盘图标",
"tray.title": "托盘",

View File

@ -1629,6 +1629,7 @@
"topic.position.left": "左側",
"topic.position.right": "右側",
"topic.show.time": "顯示話題時間",
"topic.pin_to_top": "固定話題置頂",
"tray.onclose": "關閉時最小化到系统匣",
"tray.show": "顯示系统匣圖示",
"tray.title": "系统匣",

View File

@ -54,7 +54,7 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic
const { assistants } = useAssistants()
const { assistant, removeTopic, moveTopic, updateTopic, updateTopics } = useAssistant(_assistant.id)
const { t } = useTranslation()
const { showTopicTime, topicPosition } = useSettings()
const { showTopicTime, topicPosition, pinTopicsToTop } = useSettings()
const borderRadius = showTopicTime ? 12 : 'var(--list-item-border-radius)'
@ -380,10 +380,22 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic
targetTopic
])
// Sort topics based on pinned status if pinTopicsToTop is enabled
const sortedTopics = useMemo(() => {
if (pinTopicsToTop) {
return [...assistant.topics].sort((a, b) => {
if (a.pinned && !b.pinned) return -1
if (!a.pinned && b.pinned) return 1
return 0
})
}
return assistant.topics
}, [assistant.topics, pinTopicsToTop])
return (
<Dropdown menu={{ items: getTopicMenuItems }} trigger={['contextMenu']}>
<Container right={topicPosition === 'right'} className="topics-tab">
<DragableList list={assistant.topics} onUpdate={updateTopics}>
<DragableList list={sortedTopics} onUpdate={updateTopics}>
{(topic) => {
const isActive = topic.id === activeTopic?.id
const topicName = topic.name.replace('`', '')

View File

@ -9,6 +9,7 @@ import {
setAssistantIconType,
setClickAssistantToShowTopic,
setCustomCss,
setPinTopicsToTop,
setShowTopicTime,
setSidebarIcons
} from '@renderer/store/settings'
@ -32,6 +33,7 @@ const DisplaySettings: FC = () => {
setTopicPosition,
clickAssistantToShowTopic,
showTopicTime,
pinTopicsToTop,
customCss,
sidebarIcons,
assistantIconType
@ -189,6 +191,11 @@ const DisplaySettings: FC = () => {
<SettingRowTitle>{t('settings.topic.show.time')}</SettingRowTitle>
<Switch checked={showTopicTime} onChange={(checked) => dispatch(setShowTopicTime(checked))} />
</SettingRow>
<SettingDivider />
<SettingRow>
<SettingRowTitle>{t('settings.topic.pin_to_top')}</SettingRowTitle>
<Switch checked={pinTopicsToTop} onChange={(checked) => dispatch(setPinTopicsToTop(checked))} />
</SettingRow>
</SettingGroup>
<SettingGroup theme={theme}>
<SettingTitle>{t('settings.display.assistant.title')}</SettingTitle>

View File

@ -52,6 +52,7 @@ export interface SettingsState {
fontSize: number
topicPosition: 'left' | 'right'
showTopicTime: boolean
pinTopicsToTop: boolean
assistantIconType: AssistantIconType
pasteLongTextAsFile: boolean
pasteLongTextThreshold: number
@ -192,6 +193,7 @@ export const initialState: SettingsState = {
fontSize: 14,
topicPosition: 'left',
showTopicTime: false,
pinTopicsToTop: false,
assistantIconType: 'emoji',
pasteLongTextAsFile: false,
pasteLongTextThreshold: 1500,
@ -375,6 +377,9 @@ const settingsSlice = createSlice({
setShowTopicTime: (state, action: PayloadAction<boolean>) => {
state.showTopicTime = action.payload
},
setPinTopicsToTop: (state, action: PayloadAction<boolean>) => {
state.pinTopicsToTop = action.payload
},
setAssistantIconType: (state, action: PayloadAction<AssistantIconType>) => {
state.assistantIconType = action.payload
},
@ -655,6 +660,7 @@ export const {
setWindowStyle,
setTopicPosition,
setShowTopicTime,
setPinTopicsToTop,
setAssistantIconType,
setPasteLongTextAsFile,
setAutoCheckUpdate,