Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f9f1a723da | |||
| c2dde99947 | |||
| 63cde7c8ab | |||
| 913238c991 |
@@ -1,3 +1,5 @@
|
|||||||
|
import * as z from 'zod'
|
||||||
|
|
||||||
import type { PreferenceSchemas } from './preferenceSchemas'
|
import type { PreferenceSchemas } from './preferenceSchemas'
|
||||||
|
|
||||||
export type PreferenceDefaultScopeType = PreferenceSchemas['default']
|
export type PreferenceDefaultScopeType = PreferenceSchemas['default']
|
||||||
@@ -38,6 +40,38 @@ export type SelectionActionItem = {
|
|||||||
searchEngine?: string
|
searchEngine?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SelectionBuiltinActionItemIdSchema = z.enum([
|
||||||
|
'translate',
|
||||||
|
'explain',
|
||||||
|
'summary',
|
||||||
|
'search',
|
||||||
|
'copy',
|
||||||
|
'refine',
|
||||||
|
'quote'
|
||||||
|
])
|
||||||
|
|
||||||
|
export type SelectionBuiltinActionItemId = z.infer<typeof SelectionBuiltinActionItemIdSchema>
|
||||||
|
|
||||||
|
export function isBuiltinActionItemId(id: string): id is SelectionBuiltinActionItemId {
|
||||||
|
return SelectionBuiltinActionItemIdSchema.safeParse(id).success
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SelectionBuiltinActionItem extends SelectionActionItem {
|
||||||
|
id: SelectionBuiltinActionItemId
|
||||||
|
isBuiltIn: true
|
||||||
|
assistantId?: never
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isSelectionBuiltinActionItem(
|
||||||
|
item: SelectionActionItem | null | undefined
|
||||||
|
): item is SelectionBuiltinActionItem {
|
||||||
|
if (!item) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return isBuiltinActionItemId(item.id)
|
||||||
|
}
|
||||||
|
|
||||||
export enum ThemeMode {
|
export enum ThemeMode {
|
||||||
light = 'light',
|
light = 'light',
|
||||||
dark = 'dark',
|
dark = 'dark',
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
import type { PayloadAction } from '@reduxjs/toolkit'
|
import type { PayloadAction } from '@reduxjs/toolkit'
|
||||||
import { createSlice } from '@reduxjs/toolkit'
|
import { createSlice } from '@reduxjs/toolkit'
|
||||||
import type { SelectionActionItem } from '@shared/data/preference/preferenceTypes'
|
import type { SelectionActionItem, SelectionBuiltinActionItem } from '@shared/data/preference/preferenceTypes'
|
||||||
import { SelectionFilterMode, SelectionTriggerMode } from '@shared/data/preference/preferenceTypes'
|
import { SelectionFilterMode, SelectionTriggerMode } from '@shared/data/preference/preferenceTypes'
|
||||||
|
|
||||||
export interface SelectionState {
|
export interface SelectionState {
|
||||||
@@ -20,7 +20,7 @@ export interface SelectionState {
|
|||||||
actionItems: SelectionActionItem[]
|
actionItems: SelectionActionItem[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaultActionItems: SelectionActionItem[] = [
|
export const defaultActionItems = [
|
||||||
{ id: 'translate', name: 'selection.action.builtin.translate', enabled: true, isBuiltIn: true, icon: 'languages' },
|
{ id: 'translate', name: 'selection.action.builtin.translate', enabled: true, isBuiltIn: true, icon: 'languages' },
|
||||||
{ id: 'explain', name: 'selection.action.builtin.explain', enabled: true, isBuiltIn: true, icon: 'file-question' },
|
{ id: 'explain', name: 'selection.action.builtin.explain', enabled: true, isBuiltIn: true, icon: 'file-question' },
|
||||||
{ id: 'summary', name: 'selection.action.builtin.summary', enabled: true, isBuiltIn: true, icon: 'scan-text' },
|
{ id: 'summary', name: 'selection.action.builtin.summary', enabled: true, isBuiltIn: true, icon: 'scan-text' },
|
||||||
@@ -35,7 +35,7 @@ export const defaultActionItems: SelectionActionItem[] = [
|
|||||||
{ id: 'copy', name: 'selection.action.builtin.copy', enabled: true, isBuiltIn: true, icon: 'clipboard-copy' },
|
{ id: 'copy', name: 'selection.action.builtin.copy', enabled: true, isBuiltIn: true, icon: 'clipboard-copy' },
|
||||||
{ id: 'refine', name: 'selection.action.builtin.refine', enabled: false, isBuiltIn: true, icon: 'wand-sparkles' },
|
{ id: 'refine', name: 'selection.action.builtin.refine', enabled: false, isBuiltIn: true, icon: 'wand-sparkles' },
|
||||||
{ id: 'quote', name: 'selection.action.builtin.quote', enabled: false, isBuiltIn: true, icon: 'quote' }
|
{ id: 'quote', name: 'selection.action.builtin.quote', enabled: false, isBuiltIn: true, icon: 'quote' }
|
||||||
]
|
] as const satisfies SelectionBuiltinActionItem[]
|
||||||
|
|
||||||
export const initialState: SelectionState = {
|
export const initialState: SelectionState = {
|
||||||
selectionEnabled: false,
|
selectionEnabled: false,
|
||||||
|
|||||||
@@ -2,14 +2,17 @@ import { Button, Tooltip } from '@cherrystudio/ui'
|
|||||||
import { usePreference } from '@data/hooks/usePreference'
|
import { usePreference } from '@data/hooks/usePreference'
|
||||||
import { isMac } from '@renderer/config/constant'
|
import { isMac } from '@renderer/config/constant'
|
||||||
import i18n from '@renderer/i18n'
|
import i18n from '@renderer/i18n'
|
||||||
|
import { getAssistantById, getDefaultModel, getTranslateModel } from '@renderer/services/AssistantService'
|
||||||
|
import { getProviderNameById } from '@renderer/services/ProviderService'
|
||||||
|
import type { Model } from '@renderer/types'
|
||||||
import { defaultLanguage } from '@shared/config/constant'
|
import { defaultLanguage } from '@shared/config/constant'
|
||||||
import type { SelectionActionItem } from '@shared/data/preference/preferenceTypes'
|
import { isSelectionBuiltinActionItem, type SelectionActionItem } from '@shared/data/preference/preferenceTypes'
|
||||||
import { IpcChannel } from '@shared/IpcChannel'
|
import { IpcChannel } from '@shared/IpcChannel'
|
||||||
import { Slider } from 'antd'
|
import { Slider } from 'antd'
|
||||||
import { Droplet, Minus, Pin, X } from 'lucide-react'
|
import { Droplet, Minus, Pin, X } from 'lucide-react'
|
||||||
import { DynamicIcon } from 'lucide-react/dynamic'
|
import { DynamicIcon } from 'lucide-react/dynamic'
|
||||||
import type { FC } from 'react'
|
import type { FC } from 'react'
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
@@ -22,6 +25,26 @@ const SelectionActionApp: FC = () => {
|
|||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const [action, setAction] = useState<SelectionActionItem | null>(null)
|
const [action, setAction] = useState<SelectionActionItem | null>(null)
|
||||||
|
const model: Model | undefined = useMemo(() => {
|
||||||
|
if (isSelectionBuiltinActionItem(action)) {
|
||||||
|
switch (action.id) {
|
||||||
|
case 'translate':
|
||||||
|
return getTranslateModel()
|
||||||
|
case 'explain':
|
||||||
|
case 'summary':
|
||||||
|
case 'refine':
|
||||||
|
return getDefaultModel()
|
||||||
|
default:
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (action?.assistantId) {
|
||||||
|
const assistant = getAssistantById(action.assistantId)
|
||||||
|
return assistant?.model
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
}, [action])
|
||||||
|
|
||||||
const isActionLoaded = useRef(false)
|
const isActionLoaded = useRef(false)
|
||||||
|
|
||||||
const [isAutoClose] = usePreference('feature.selection.auto_close')
|
const [isAutoClose] = usePreference('feature.selection.auto_close')
|
||||||
@@ -205,6 +228,11 @@ const SelectionActionApp: FC = () => {
|
|||||||
</TitleBarIcon>
|
</TitleBarIcon>
|
||||||
)}
|
)}
|
||||||
<TitleBarCaption>{action.isBuiltIn ? t(action.name) : action.name}</TitleBarCaption>
|
<TitleBarCaption>{action.isBuiltIn ? t(action.name) : action.name}</TitleBarCaption>
|
||||||
|
{model !== undefined && (
|
||||||
|
<span className="truncate text-muted-foreground">
|
||||||
|
{getProviderNameById(model.provider)} | {model.name}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
<TitleBarButtons>
|
<TitleBarButtons>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
content={isPinned ? t('selection.action.window.pinned') : t('selection.action.window.pin')}
|
content={isPinned ? t('selection.action.window.pinned') : t('selection.action.window.pin')}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import { detectLanguage } from '@renderer/utils/translate'
|
|||||||
import { defaultLanguage } from '@shared/config/constant'
|
import { defaultLanguage } from '@shared/config/constant'
|
||||||
import type { SelectionActionItem } from '@shared/data/preference/preferenceTypes'
|
import type { SelectionActionItem } from '@shared/data/preference/preferenceTypes'
|
||||||
import { ArrowRightFromLine, ArrowRightToLine, ChevronDown, CircleHelp, Globe } from 'lucide-react'
|
import { ArrowRightFromLine, ArrowRightToLine, ChevronDown, CircleHelp, Globe } from 'lucide-react'
|
||||||
import type { FC } from 'react'
|
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
@@ -31,7 +30,7 @@ interface Props {
|
|||||||
|
|
||||||
const logger = loggerService.withContext('ActionTranslate')
|
const logger = loggerService.withContext('ActionTranslate')
|
||||||
|
|
||||||
const ActionTranslate: FC<Props> = ({ action, scrollToBottom }) => {
|
const ActionTranslate = ({ action, scrollToBottom }: Props) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const [language] = usePreference('app.language')
|
const [language] = usePreference('app.language')
|
||||||
|
|||||||
Reference in New Issue
Block a user