fix: update default values and improve component structure

- Changed default value for `getTrayOnClose` to true in `ConfigManager`.
- Removed fullscreen toggle logic from `WindowService`.
- Adjusted styles in `OpenAIAlert` for better spacing.
- Reorganized imports in `Navbar` and updated component paths in `AssistantsTab` and `SettingsTab`.
- Added new components `AssistantItem` and `OpenAISettingsGroup` for better modularity.
- Enhanced `SettingGroup` styles for improved UI consistency.
- Updated `QuickPhraseSettings` to utilize theme context.
- Minor fixes and refactoring across various services and components.
This commit is contained in:
kangfenmao 2025-05-20 00:20:02 +08:00
parent a3a3045b1a
commit 35d3c8e451
17 changed files with 101 additions and 91 deletions

View File

@ -62,7 +62,7 @@ export class ConfigManager {
} }
getTrayOnClose(): boolean { getTrayOnClose(): boolean {
return !!this.get(ConfigKeys.TrayOnClose, false) return !!this.get(ConfigKeys.TrayOnClose, true)
} }
setTrayOnClose(value: boolean) { setTrayOnClose(value: boolean) {

View File

@ -331,11 +331,6 @@ export class WindowService {
event.preventDefault() event.preventDefault()
if (mainWindow.isFullScreen()) {
mainWindow.setFullScreen(false)
return
}
mainWindow.hide() mainWindow.hide()
//for mac users, should hide dock icon if close to tray //for mac users, should hide dock icon if close to tray

View File

@ -17,7 +17,7 @@ const OpenAIAlert = () => {
return ( return (
<Alert <Alert
style={{ width: '100%', marginTop: 5 }} style={{ width: '100%', marginTop: 5, marginBottom: 5 }}
message={t('settings.provider.openai.alert')} message={t('settings.provider.openai.alert')}
closable closable
afterClose={() => { afterClose={() => {

View File

@ -1,6 +1,6 @@
import { isLinux, isMac, isWindows } from '@renderer/config/constant' import { isLinux, isMac, isWindows } from '@renderer/config/constant'
import useNavBackgroundColor from '@renderer/hooks/useNavBackgroundColor'
import { useFullscreen } from '@renderer/hooks/useFullscreen' import { useFullscreen } from '@renderer/hooks/useFullscreen'
import useNavBackgroundColor from '@renderer/hooks/useNavBackgroundColor'
import type { FC, PropsWithChildren } from 'react' import type { FC, PropsWithChildren } from 'react'
import type { HTMLAttributes } from 'react' import type { HTMLAttributes } from 'react'
import styled from 'styled-components' import styled from 'styled-components'

View File

@ -869,7 +869,8 @@
"number_images_tip": "Количество увеличенных результатов для генерации", "number_images_tip": "Количество увеличенных результатов для генерации",
"seed_tip": "Контролирует случайный характер увеличения изображений для воспроизводимых результатов", "seed_tip": "Контролирует случайный характер увеличения изображений для воспроизводимых результатов",
"magic_prompt_option_tip": "Улучшает увеличение изображений с помощью интеллектуального оптимизирования промптов" "magic_prompt_option_tip": "Улучшает увеличение изображений с помощью интеллектуального оптимизирования промптов"
} },
"rendering_speed": "Скорость рендеринга"
}, },
"prompts": { "prompts": {
"explanation": "Объясните мне этот концепт", "explanation": "Объясните мне этот концепт",
@ -927,7 +928,6 @@
"restore": { "restore": {
"confirm": "Вы уверены, что хотите восстановить данные?", "confirm": "Вы уверены, что хотите восстановить данные?",
"confirm.button": "Выбрать файл резервной копии", "confirm.button": "Выбрать файл резервной копии",
"content": "Операция восстановления перезапишет все текущие данные приложения данными из резервной копии. Это может занять некоторое время.", "content": "Операция восстановления перезапишет все текущие данные приложения данными из резервной копии. Это может занять некоторое время.",
"progress": { "progress": {
"completed": "Восстановление завершено", "completed": "Восстановление завершено",

View File

@ -244,7 +244,7 @@
"settings.context_count": "上下文数", "settings.context_count": "上下文数",
"settings.context_count.tip": "要保留在上下文中的消息数量,数值越大,上下文越长,消耗的 token 越多。普通聊天建议 5-10", "settings.context_count.tip": "要保留在上下文中的消息数量,数值越大,上下文越长,消耗的 token 越多。普通聊天建议 5-10",
"settings.max": "不限", "settings.max": "不限",
"settings.max_tokens": "最大 Token 数", "settings.max_tokens": "最大 TOKEN 数",
"settings.max_tokens.confirm": "最大 Token 数", "settings.max_tokens.confirm": "最大 Token 数",
"settings.max_tokens.confirm_content": "设置单次交互所用的最大 Token 数, 会影响返回结果的长度。要根据模型上下文限制来设置,否则会报错", "settings.max_tokens.confirm_content": "设置单次交互所用的最大 Token 数, 会影响返回结果的长度。要根据模型上下文限制来设置,否则会报错",
"settings.max_tokens.tip": "单次交互所用的最大 Token 数, 会影响返回结果的长度。要根据模型上下文限制来设置,否则会报错", "settings.max_tokens.tip": "单次交互所用的最大 Token 数, 会影响返回结果的长度。要根据模型上下文限制来设置,否则会报错",
@ -1678,7 +1678,7 @@
"reset": "重置" "reset": "重置"
}, },
"openai": { "openai": {
"title": "OpenAI设置", "title": "OpenAI 设置",
"summary_text_mode.title": "摘要模式", "summary_text_mode.title": "摘要模式",
"summary_text_mode.tip": "模型执行的推理摘要", "summary_text_mode.tip": "模型执行的推理摘要",
"summary_text_mode.auto": "自动", "summary_text_mode.auto": "自动",

View File

@ -156,14 +156,16 @@ const App: FC<Props> = ({ app, onClick, size = 60, isLast }) => {
: []) : [])
] ]
if (!isVisible && !isLast) return null if (!isVisible && !isLast) {
return null
}
return ( return (
<> <>
<Dropdown menu={{ items: menuItems }} trigger={['contextMenu']}> <Dropdown menu={{ items: menuItems }} trigger={['contextMenu']}>
<Container onClick={handleClick}> <Container onClick={handleClick}>
{isLast ? ( {isLast ? (
<AddButton> <AddButton size={size}>
<PlusOutlined /> <PlusOutlined />
</AddButton> </AddButton>
) : ( ) : (
@ -252,9 +254,9 @@ const AppTitle = styled.div`
white-space: nowrap; white-space: nowrap;
` `
const AddButton = styled.div` const AddButton = styled.div<{ size?: number }>`
width: 60px; width: ${({ size }) => size || 60}px;
height: 60px; height: ${({ size }) => size || 60}px;
border-radius: 12px; border-radius: 12px;
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -256,6 +256,7 @@ const Messages: React.FC<MessagesProps> = ({ assistant, topic, setActiveTopic, o
useEffect(() => { useEffect(() => {
requestAnimationFrame(() => onComponentUpdate?.()) requestAnimationFrame(() => onComponentUpdate?.())
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []) }, [])
const groupedMessages = useMemo(() => Object.entries(getGroupedMessages(displayMessages)), [displayMessages]) const groupedMessages = useMemo(() => Object.entries(getGroupedMessages(displayMessages)), [displayMessages])

View File

@ -8,7 +8,7 @@ import { FC, useCallback, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import styled from 'styled-components' import styled from 'styled-components'
import AssistantItem from './AssistantItem' import AssistantItem from './components/AssistantItem'
interface AssistantsTabProps { interface AssistantsTabProps {
activeAssistant: Assistant activeAssistant: Assistant

View File

@ -63,7 +63,7 @@ import { FC, useCallback, useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import styled from 'styled-components' import styled from 'styled-components'
import OpenAISettingsTab from './OpenAISettingsTab' import OpenAISettingsGroup from './components/OpenAISettingsGroup'
interface Props { interface Props {
assistant: Assistant assistant: Assistant
@ -218,8 +218,7 @@ const SettingsTab: FC<Props> = (props) => {
/> />
</HStack> </HStack>
}> }>
<SettingGroup style={{ marginTop: 10 }}> <SettingGroup style={{ marginTop: 5 }}>
<SettingDivider />
<Row align="middle"> <Row align="middle">
<Label>{t('chat.settings.temperature')}</Label> <Label>{t('chat.settings.temperature')}</Label>
<Tooltip title={t('chat.settings.temperature.tip')}> <Tooltip title={t('chat.settings.temperature.tip')}>
@ -227,7 +226,7 @@ const SettingsTab: FC<Props> = (props) => {
</Tooltip> </Tooltip>
</Row> </Row>
<Row align="middle" gutter={10}> <Row align="middle" gutter={10}>
<Col span={24}> <div style={{ width: '100%' }}>
<Slider <Slider
min={0} min={0}
max={2} max={2}
@ -236,7 +235,7 @@ const SettingsTab: FC<Props> = (props) => {
value={typeof temperature === 'number' ? temperature : 0} value={typeof temperature === 'number' ? temperature : 0}
step={0.1} step={0.1}
/> />
</Col> </div>
</Row> </Row>
<Row align="middle"> <Row align="middle">
<Label>{t('chat.settings.context_count')}</Label> <Label>{t('chat.settings.context_count')}</Label>
@ -245,7 +244,7 @@ const SettingsTab: FC<Props> = (props) => {
</Tooltip> </Tooltip>
</Row> </Row>
<Row align="middle" gutter={10}> <Row align="middle" gutter={10}>
<Col span={24}> <div style={{ width: '100%' }}>
<Slider <Slider
min={0} min={0}
max={maxContextCount} max={maxContextCount}
@ -254,7 +253,7 @@ const SettingsTab: FC<Props> = (props) => {
value={typeof contextCount === 'number' ? contextCount : 0} value={typeof contextCount === 'number' ? contextCount : 0}
step={1} step={1}
/> />
</Col> </div>
</Row> </Row>
<SettingDivider /> <SettingDivider />
<SettingRow> <SettingRow>
@ -296,7 +295,7 @@ const SettingsTab: FC<Props> = (props) => {
/> />
</SettingRow> </SettingRow>
{enableMaxTokens && ( {enableMaxTokens && (
<Row align="middle" gutter={10}> <Row align="middle" gutter={10} style={{ marginTop: 10 }}>
<Col span={24}> <Col span={24}>
<InputNumber <InputNumber
disabled={!enableMaxTokens} disabled={!enableMaxTokens}
@ -314,16 +313,17 @@ const SettingsTab: FC<Props> = (props) => {
)} )}
<SettingDivider /> <SettingDivider />
</SettingGroup> </SettingGroup>
{isOpenAI && (
<OpenAISettingsTab
isOpenAIReasoning={isOpenAIReasoning}
isSupportedFlexServiceTier={isOpenAIFlexServiceTier}
/>
)}
</CollapsibleSettingGroup> </CollapsibleSettingGroup>
{isOpenAI && (
<OpenAISettingsGroup
isOpenAIReasoning={isOpenAIReasoning}
isSupportedFlexServiceTier={isOpenAIFlexServiceTier}
SettingGroup={SettingGroup}
SettingRowTitleSmall={SettingRowTitleSmall}
/>
)}
<CollapsibleSettingGroup title={t('settings.messages.title')} defaultExpanded={true}> <CollapsibleSettingGroup title={t('settings.messages.title')} defaultExpanded={true}>
<SettingGroup> <SettingGroup>
<SettingDivider />
<SettingRow> <SettingRow>
<SettingRowTitleSmall>{t('settings.messages.prompt')}</SettingRowTitleSmall> <SettingRowTitleSmall>{t('settings.messages.prompt')}</SettingRowTitleSmall>
<Switch size="small" checked={showPrompt} onChange={(checked) => dispatch(setShowPrompt(checked))} /> <Switch size="small" checked={showPrompt} onChange={(checked) => dispatch(setShowPrompt(checked))} />
@ -440,7 +440,6 @@ const SettingsTab: FC<Props> = (props) => {
</CollapsibleSettingGroup> </CollapsibleSettingGroup>
<CollapsibleSettingGroup title={t('chat.settings.code.title')} defaultExpanded={true}> <CollapsibleSettingGroup title={t('chat.settings.code.title')} defaultExpanded={true}>
<SettingGroup> <SettingGroup>
<SettingDivider />
<SettingRow> <SettingRow>
<SettingRowTitleSmall>{t('message.message.code_style')}</SettingRowTitleSmall> <SettingRowTitleSmall>{t('message.message.code_style')}</SettingRowTitleSmall>
<StyledSelect <StyledSelect
@ -568,7 +567,6 @@ const SettingsTab: FC<Props> = (props) => {
</CollapsibleSettingGroup> </CollapsibleSettingGroup>
<CollapsibleSettingGroup title={t('settings.messages.input.title')} defaultExpanded={true}> <CollapsibleSettingGroup title={t('settings.messages.input.title')} defaultExpanded={true}>
<SettingGroup> <SettingGroup>
<SettingDivider />
<SettingRow> <SettingRow>
<SettingRowTitleSmall>{t('settings.messages.input.show_estimated_tokens')}</SettingRowTitleSmall> <SettingRowTitleSmall>{t('settings.messages.input.show_estimated_tokens')}</SettingRowTitleSmall>
<Switch <Switch
@ -710,11 +708,11 @@ const Label = styled.p`
margin-right: 5px; margin-right: 5px;
` `
export const SettingRowTitleSmall = styled(SettingRowTitle)` const SettingRowTitleSmall = styled(SettingRowTitle)`
font-size: 13px; font-size: 13px;
` `
export const SettingGroup = styled.div<{ theme?: ThemeMode }>` const SettingGroup = styled.div<{ theme?: ThemeMode }>`
padding: 0 5px; padding: 0 5px;
width: 100%; width: 100%;
margin-top: 0; margin-top: 0;

View File

@ -1,4 +1,5 @@
import { SettingDivider, SettingRow, SettingSubtitle } from '@renderer/pages/settings' import { SettingDivider, SettingRow } from '@renderer/pages/settings'
import { CollapsibleSettingGroup } from '@renderer/pages/settings/SettingGroup'
import { RootState, useAppDispatch } from '@renderer/store' import { RootState, useAppDispatch } from '@renderer/store'
import { setOpenAIServiceTier, setOpenAISummaryText } from '@renderer/store/settings' import { setOpenAIServiceTier, setOpenAISummaryText } from '@renderer/store/settings'
import { OpenAIServiceTier, OpenAISummaryText } from '@renderer/types' import { OpenAIServiceTier, OpenAISummaryText } from '@renderer/types'
@ -9,11 +10,11 @@ import { useTranslation } from 'react-i18next'
import { useSelector } from 'react-redux' import { useSelector } from 'react-redux'
import styled from 'styled-components' import styled from 'styled-components'
import { SettingGroup, SettingRowTitleSmall } from './SettingsTab'
interface Props { interface Props {
isOpenAIReasoning: boolean isOpenAIReasoning: boolean
isSupportedFlexServiceTier: boolean isSupportedFlexServiceTier: boolean
SettingGroup: FC<{ children: React.ReactNode }>
SettingRowTitleSmall: FC<{ children: React.ReactNode }>
} }
const FALL_BACK_SERVICE_TIER: Record<OpenAIServiceTier, OpenAIServiceTier> = { const FALL_BACK_SERVICE_TIER: Record<OpenAIServiceTier, OpenAIServiceTier> = {
@ -22,7 +23,12 @@ const FALL_BACK_SERVICE_TIER: Record<OpenAIServiceTier, OpenAIServiceTier> = {
flex: 'default' flex: 'default'
} }
const OpenAISettingsTab: FC<Props> = (props) => { const OpenAISettingsGroup: FC<Props> = ({
isOpenAIReasoning,
isSupportedFlexServiceTier,
SettingGroup,
SettingRowTitleSmall
}) => {
const { t } = useTranslation() const { t } = useTranslation()
const summaryText = useSelector((state: RootState) => state.settings.openAI.summaryText) const summaryText = useSelector((state: RootState) => state.settings.openAI.summaryText)
const serviceTierMode = useSelector((state: RootState) => state.settings.openAI.serviceTier) const serviceTierMode = useSelector((state: RootState) => state.settings.openAI.serviceTier)
@ -74,11 +80,11 @@ const OpenAISettingsTab: FC<Props> = (props) => {
] ]
return baseOptions.filter((option) => { return baseOptions.filter((option) => {
if (option.value === 'flex') { if (option.value === 'flex') {
return props.isSupportedFlexServiceTier return isSupportedFlexServiceTier
} }
return true return true
}) })
}, [props.isSupportedFlexServiceTier, t]) }, [isSupportedFlexServiceTier, t])
useEffect(() => { useEffect(() => {
if (serviceTierMode && !serviceTierOptions.some((option) => option.value === serviceTierMode)) { if (serviceTierMode && !serviceTierOptions.some((option) => option.value === serviceTierMode)) {
@ -87,49 +93,49 @@ const OpenAISettingsTab: FC<Props> = (props) => {
}, [serviceTierMode, serviceTierOptions, setServiceTierMode]) }, [serviceTierMode, serviceTierOptions, setServiceTierMode])
return ( return (
<SettingGroup> <CollapsibleSettingGroup title={t('settings.openai.title')} defaultExpanded={true}>
<SettingSubtitle style={{ marginTop: 0 }}>{t('settings.openai.title')}</SettingSubtitle> <SettingGroup>
<SettingDivider /> <SettingRow>
<SettingRow> <SettingRowTitleSmall>
<SettingRowTitleSmall> {t('settings.openai.service_tier.title')}{' '}
{t('settings.openai.service_tier.title')}{' '} <Tooltip title={t('settings.openai.service_tier.tip')}>
<Tooltip title={t('settings.openai.service_tier.tip')}> <CircleHelp size={14} style={{ marginLeft: 4 }} color="var(--color-text-2)" />
<CircleHelp size={14} style={{ marginLeft: 4 }} color="var(--color-text-2)" /> </Tooltip>
</Tooltip> </SettingRowTitleSmall>
</SettingRowTitleSmall> <StyledSelect
<StyledSelect value={serviceTierMode}
value={serviceTierMode} style={{ width: 135 }}
style={{ width: 135 }} onChange={(value) => {
onChange={(value) => { setServiceTierMode(value as OpenAIServiceTier)
setServiceTierMode(value as OpenAIServiceTier) }}
}} size="small"
size="small" options={serviceTierOptions}
options={serviceTierOptions} />
/> </SettingRow>
</SettingRow> {isOpenAIReasoning && (
{props.isOpenAIReasoning && ( <>
<> <SettingDivider />
<SettingDivider /> <SettingRow>
<SettingRow> <SettingRowTitleSmall>
<SettingRowTitleSmall> {t('settings.openai.summary_text_mode.title')}{' '}
{t('settings.openai.summary_text_mode.title')}{' '} <Tooltip title={t('settings.openai.summary_text_mode.tip')}>
<Tooltip title={t('settings.openai.summary_text_mode.tip')}> <CircleHelp size={14} style={{ marginLeft: 4 }} color="var(--color-text-2)" />
<CircleHelp size={14} style={{ marginLeft: 4 }} color="var(--color-text-2)" /> </Tooltip>
</Tooltip> </SettingRowTitleSmall>
</SettingRowTitleSmall> <StyledSelect
<StyledSelect value={summaryText}
value={summaryText} style={{ width: 135 }}
style={{ width: 135 }} onChange={(value) => {
onChange={(value) => { setSummaryText(value as OpenAISummaryText)
setSummaryText(value as OpenAISummaryText) }}
}} size="small"
size="small" options={summaryTextOptions}
options={summaryTextOptions} />
/> </SettingRow>
</SettingRow> </>
</> )}
)} </SettingGroup>
</SettingGroup> </CollapsibleSettingGroup>
) )
} }
@ -141,4 +147,4 @@ const StyledSelect = styled(Select)`
} }
` `
export default OpenAISettingsTab export default OpenAISettingsGroup

View File

@ -1,5 +1,6 @@
import { DeleteOutlined, EditOutlined, ExclamationCircleOutlined, PlusOutlined } from '@ant-design/icons' import { DeleteOutlined, EditOutlined, ExclamationCircleOutlined, PlusOutlined } from '@ant-design/icons'
import DragableList from '@renderer/components/DragableList' import DragableList from '@renderer/components/DragableList'
import { useTheme } from '@renderer/context/ThemeProvider'
import FileItem from '@renderer/pages/files/FileItem' import FileItem from '@renderer/pages/files/FileItem'
import QuickPhraseService from '@renderer/services/QuickPhraseService' import QuickPhraseService from '@renderer/services/QuickPhraseService'
import { QuickPhrase } from '@renderer/types' import { QuickPhrase } from '@renderer/types'
@ -19,6 +20,7 @@ const QuickPhraseSettings: FC = () => {
const [editingPhrase, setEditingPhrase] = useState<QuickPhrase | null>(null) const [editingPhrase, setEditingPhrase] = useState<QuickPhrase | null>(null)
const [formData, setFormData] = useState({ title: '', content: '' }) const [formData, setFormData] = useState({ title: '', content: '' })
const [dragging, setDragging] = useState(false) const [dragging, setDragging] = useState(false)
const { theme } = useTheme()
const loadPhrases = async () => { const loadPhrases = async () => {
const data = await QuickPhraseService.getAll() const data = await QuickPhraseService.getAll()
@ -68,8 +70,8 @@ const QuickPhraseSettings: FC = () => {
const reversedPhrases = [...phrasesList].reverse() const reversedPhrases = [...phrasesList].reverse()
return ( return (
<SettingContainer> <SettingContainer theme={theme}>
<SettingGroup style={{ marginBottom: 0 }}> <SettingGroup style={{ marginBottom: 0 }} theme={theme}>
<SettingTitle> <SettingTitle>
{t('settings.quickPhrase.title')} {t('settings.quickPhrase.title')}
<Button type="text" icon={<PlusOutlined />} onClick={handleAdd} /> <Button type="text" icon={<PlusOutlined />} onClick={handleAdd} />

View File

@ -46,8 +46,11 @@ const GroupHeader = styled.div`
display: flex; display: flex;
align-items: center; align-items: center;
cursor: pointer; cursor: pointer;
padding: 6px 0; padding: 8px 0;
padding-bottom: 12px;
user-select: none; user-select: none;
margin-bottom: 10px;
border-bottom: 0.5px solid var(--color-border);
` `
const GroupTitle = styled.div` const GroupTitle = styled.div`

View File

@ -1,3 +1,4 @@
/* eslint-disable simple-import-sort/imports */
import Logger from '@renderer/config/logger' import Logger from '@renderer/config/logger'
import db from '@renderer/databases' import db from '@renderer/databases'
import { upgradeToV7 } from '@renderer/databases/upgrades' import { upgradeToV7 } from '@renderer/databases/upgrades'

View File

@ -217,7 +217,7 @@ export async function getMessageTitle(message: Message, length = 30): Promise<st
const tempMessage = resetMessage(message, { const tempMessage = resetMessage(message, {
status: AssistantMessageStatus.SUCCESS, status: AssistantMessageStatus.SUCCESS,
blocks: message.blocks, blocks: message.blocks
}) })
const title = await fetchMessagesSummary({ messages: [tempMessage], assistant: {} as Assistant }) const title = await fetchMessagesSummary({ messages: [tempMessage], assistant: {} as Assistant })

View File

@ -1406,6 +1406,8 @@ const migrateConfig = {
searchMessageShortcut.shortcut = [isMac ? 'Command' : 'Ctrl', 'Shift', 'F'] searchMessageShortcut.shortcut = [isMac ? 'Command' : 'Ctrl', 'Shift', 'F']
} }
} }
// Quick assistant model
state.llm.quickAssistantModel = state.llm.defaultModel || SYSTEM_MODELS.silicon[1]
return state return state
} catch (error) { } catch (error) {
return state return state