mirror of
https://github.com/wassname/chatGPTBox.git
synced 2026-06-27 17:47:56 +08:00
custom selection tools (#710, #14, #322, #312, #193, #209, #134, #77, #13, #4, #719, #714, #399, #366, #357, #332, #216, #167, #395, #261, #673, #541, #523)
This commit is contained in:
@@ -133,5 +133,14 @@
|
||||
"Generating...": "Generieren...",
|
||||
"moonshot token required, please login at https://kimi.moonshot.cn first": "Moonshot-Token erforderlich, bitte zuerst bei https://kimi.moonshot.cn anmelden",
|
||||
"Hide context menu of this extension": "Kontextmenü dieser Erweiterung ausblenden",
|
||||
"Custom Claude API Url": "Benutzerdefinierte Claude-API-URL"
|
||||
"Custom Claude API Url": "Benutzerdefinierte Claude-API-URL",
|
||||
"Cancel": "Abbrechen",
|
||||
"Name is required": "Name ist erforderlich",
|
||||
"Prompt template should include {{selection}}": "Die Vorlage sollte {{selection}} enthalten",
|
||||
"Save": "Speichern",
|
||||
"Name": "Name",
|
||||
"Icon": "Symbol",
|
||||
"Prompt Template": "Vorlagen-Template",
|
||||
"Explain this: {{selection}}": "Erkläre das: {{selection}}",
|
||||
"New": "Neu"
|
||||
}
|
||||
|
||||
@@ -133,5 +133,14 @@
|
||||
"Generating...": "Generating...",
|
||||
"moonshot token required, please login at https://kimi.moonshot.cn first": "moonshot token required, please login at https://kimi.moonshot.cn first",
|
||||
"Hide context menu of this extension": "Hide context menu of this extension",
|
||||
"Custom Claude API Url": "Custom Claude API Url"
|
||||
"Custom Claude API Url": "Custom Claude API Url",
|
||||
"Cancel": "Cancel",
|
||||
"Name is required": "Name is required",
|
||||
"Prompt template should include {{selection}}": "Prompt template should include {{selection}}",
|
||||
"Save": "Save",
|
||||
"Name": "Name",
|
||||
"Icon": "Icon",
|
||||
"Prompt Template": "Prompt Template",
|
||||
"Explain this: {{selection}}": "Explain this: {{selection}}",
|
||||
"New": "New"
|
||||
}
|
||||
|
||||
@@ -133,5 +133,14 @@
|
||||
"Generating...": "Generando...",
|
||||
"moonshot token required, please login at https://kimi.moonshot.cn first": "se requiere un token de moonshot, por favor inicie sesión en https://kimi.moonshot.cn primero",
|
||||
"Hide context menu of this extension": "Ocultar menú contextual de esta extensión",
|
||||
"Custom Claude API Url": "URL personalizada de la API de Claude"
|
||||
"Custom Claude API Url": "URL personalizada de la API de Claude",
|
||||
"Cancel": "Cancelar",
|
||||
"Name is required": "Se requiere un nombre",
|
||||
"Prompt template should include {{selection}}": "La plantilla de sugerencias debe incluir {{selection}}",
|
||||
"Save": "Guardar",
|
||||
"Name": "Nombre",
|
||||
"Icon": "Icono",
|
||||
"Prompt Template": "Plantilla de sugerencias",
|
||||
"Explain this: {{selection}}": "Explicar esto: {{selection}}",
|
||||
"New": "Nuevo"
|
||||
}
|
||||
|
||||
@@ -133,5 +133,14 @@
|
||||
"Generating...": "Génération...",
|
||||
"moonshot token required, please login at https://kimi.moonshot.cn first": "jeton moonshot requis, veuillez vous connecter d'abord sur https://kimi.moonshot.cn",
|
||||
"Hide context menu of this extension": "Masquer le menu contextuel de cette extension",
|
||||
"Custom Claude API Url": "URL API Claude personnalisée"
|
||||
"Custom Claude API Url": "URL API Claude personnalisée",
|
||||
"Cancel": "Annuler",
|
||||
"Name is required": "Le nom est requis",
|
||||
"Prompt template should include {{selection}}": "Le modèle de suggestion doit inclure {{selection}}",
|
||||
"Save": "Enregistrer",
|
||||
"Name": "Nom",
|
||||
"Icon": "Icône",
|
||||
"Prompt Template": "Modèle de suggestion",
|
||||
"Explain this: {{selection}}": "Expliquer ceci : {{selection}}",
|
||||
"New": "Nouveau"
|
||||
}
|
||||
|
||||
@@ -133,5 +133,14 @@
|
||||
"Generating...": "Menghasilkan...",
|
||||
"moonshot token required, please login at https://kimi.moonshot.cn first": "diperlukan token moonshot, silakan masuk di https://kimi.moonshot.cn terlebih dahulu",
|
||||
"Hide context menu of this extension": "Sembunyikan menu konteks ekstensi ini",
|
||||
"Custom Claude API Url": "URL API Claude Kustom"
|
||||
"Custom Claude API Url": "URL API Claude Kustom",
|
||||
"Cancel": "Batal",
|
||||
"Name is required": "Nama diperlukan",
|
||||
"Prompt template should include {{selection}}": "Template prompt harus mencakup {{selection}}",
|
||||
"Save": "Simpan",
|
||||
"Name": "Nama",
|
||||
"Icon": "Ikon",
|
||||
"Prompt Template": "Template Prompt",
|
||||
"Explain this: {{selection}}": "Jelaskan ini: {{selection}}",
|
||||
"New": "Baru"
|
||||
}
|
||||
|
||||
@@ -133,5 +133,14 @@
|
||||
"Generating...": "Generazione...",
|
||||
"moonshot token required, please login at https://kimi.moonshot.cn first": "richiesto token moonshot, effettua il login su https://kimi.moonshot.cn prima",
|
||||
"Hide context menu of this extension": "Nascondi il menu contestuale di questa estensione",
|
||||
"Custom Claude API Url": "URL API Claude personalizzato"
|
||||
"Custom Claude API Url": "URL API Claude personalizzato",
|
||||
"Cancel": "Annulla",
|
||||
"Name is required": "Il nome è obbligatorio",
|
||||
"Prompt template should include {{selection}}": "Il modello di prompt dovrebbe includere {{selection}}",
|
||||
"Save": "Salva",
|
||||
"Name": "Nome",
|
||||
"Icon": "Icona",
|
||||
"Prompt Template": "Modello di prompt",
|
||||
"Explain this: {{selection}}": "Spiega questo: {{selection}}",
|
||||
"New": "Nuovo"
|
||||
}
|
||||
|
||||
@@ -133,5 +133,14 @@
|
||||
"Generating...": "生成中...",
|
||||
"moonshot token required, please login at https://kimi.moonshot.cn first": "moonshotトークンが必要です。最初に https://kimi.moonshot.cn にログインしてください",
|
||||
"Hide context menu of this extension": "この拡張機能のコンテキストメニューを非表示",
|
||||
"Custom Claude API Url": "カスタムClaude APIのURL"
|
||||
"Custom Claude API Url": "カスタムClaude APIのURL",
|
||||
"Cancel": "キャンセル",
|
||||
"Name is required": "名前は必須です",
|
||||
"Prompt template should include {{selection}}": "プロンプトテンプレートには {{selection}} を含める必要があります",
|
||||
"Save": "保存",
|
||||
"Name": "名前",
|
||||
"Icon": "アイコン",
|
||||
"Prompt Template": "プロンプトテンプレート",
|
||||
"Explain this: {{selection}}": "これを説明する: {{selection}}",
|
||||
"New": "新規"
|
||||
}
|
||||
|
||||
@@ -133,5 +133,14 @@
|
||||
"Generating...": "생성 중...",
|
||||
"moonshot token required, please login at https://kimi.moonshot.cn first": "moonshot 토큰이 필요합니다. https://kimi.moonshot.cn 에서 로그인하세요.",
|
||||
"Hide context menu of this extension": "이 확장 프로그램의 컨텍스트 메뉴 숨기기",
|
||||
"Custom Claude API Url": "사용자 정의 Claude API URL"
|
||||
"Custom Claude API Url": "사용자 정의 Claude API URL",
|
||||
"Cancel": "취소",
|
||||
"Name is required": "이름은 필수입니다",
|
||||
"Prompt template should include {{selection}}": "프롬프트 템플릿에는 {{selection}} 이 포함되어야 합니다",
|
||||
"Save": "저장",
|
||||
"Name": "이름",
|
||||
"Icon": "아이콘",
|
||||
"Prompt Template": "프롬프트 템플릿",
|
||||
"Explain this: {{selection}}": "이것을 설명하세요: {{selection}}",
|
||||
"New": "새로 만들기"
|
||||
}
|
||||
|
||||
@@ -133,5 +133,14 @@
|
||||
"Generating...": "Gerando...",
|
||||
"moonshot token required, please login at https://kimi.moonshot.cn first": "token moonshot necessário, por favor faça login em https://kimi.moonshot.cn primeiro",
|
||||
"Hide context menu of this extension": "Ocultar menu de contexto desta extensão",
|
||||
"Custom Claude API Url": "URL da API Personalizada do Claude"
|
||||
"Custom Claude API Url": "URL da API Personalizada do Claude",
|
||||
"Cancel": "Cancelar",
|
||||
"Name is required": "Nome é obrigatório",
|
||||
"Prompt template should include {{selection}}": "O modelo de prompt deve incluir {{selection}}",
|
||||
"Save": "Salvar",
|
||||
"Name": "Nome",
|
||||
"Icon": "Ícone",
|
||||
"Prompt Template": "Modelo de Prompt",
|
||||
"Explain this: {{selection}}": "Explique isso: {{selection}}",
|
||||
"New": "Novo"
|
||||
}
|
||||
|
||||
@@ -133,5 +133,14 @@
|
||||
"Generating...": "Генерация...",
|
||||
"moonshot token required, please login at https://kimi.moonshot.cn first": "требуется токен moonshot, пожалуйста, сначала войдите на https://kimi.moonshot.cn",
|
||||
"Hide context menu of this extension": "Скрыть контекстное меню этого расширения",
|
||||
"Custom Claude API Url": "Пользовательский URL API Claude"
|
||||
"Custom Claude API Url": "Пользовательский URL API Claude",
|
||||
"Cancel": "Отмена",
|
||||
"Name is required": "Имя обязательно",
|
||||
"Prompt template should include {{selection}}": "Шаблон запроса должен включать {{selection}}",
|
||||
"Save": "Сохранить",
|
||||
"Name": "Имя",
|
||||
"Icon": "Иконка",
|
||||
"Prompt Template": "Шаблон запроса",
|
||||
"Explain this: {{selection}}": "Объяснить это: {{selection}}",
|
||||
"New": "Новый"
|
||||
}
|
||||
|
||||
@@ -133,5 +133,14 @@
|
||||
"Generating...": "Üretiliyor...",
|
||||
"moonshot token required, please login at https://kimi.moonshot.cn first": "moonshot jetonu gerekiyor, lütfen önce https://kimi.moonshot.cn adresinde oturum açın",
|
||||
"Hide context menu of this extension": "Bu uzantının bağlam menüsünü gizle",
|
||||
"Custom Claude API Url": "Özel Claude API Url'si"
|
||||
"Custom Claude API Url": "Özel Claude API Url'si",
|
||||
"Cancel": "İptal",
|
||||
"Name is required": "İsim gereklidir",
|
||||
"Prompt template should include {{selection}}": "Prompt şablonu {{selection}} içermelidir",
|
||||
"Save": "Kaydet",
|
||||
"Name": "İsim",
|
||||
"Icon": "Simge",
|
||||
"Prompt Template": "Prompt Şablonu",
|
||||
"Explain this: {{selection}}": "Bunu açıkla: {{selection}}",
|
||||
"New": "Yeni"
|
||||
}
|
||||
|
||||
@@ -133,5 +133,14 @@
|
||||
"Generating...": "正在生成...",
|
||||
"moonshot token required, please login at https://kimi.moonshot.cn first": "需要moonshot token, 请先登录 https://kimi.moonshot.cn",
|
||||
"Hide context menu of this extension": "隐藏此扩展的右键菜单",
|
||||
"Custom Claude API Url": "自定义的Claude API地址"
|
||||
"Custom Claude API Url": "自定义的Claude API地址",
|
||||
"Cancel": "取消",
|
||||
"Name is required": "名称是必须的",
|
||||
"Prompt template should include {{selection}}": "提示模板应该包含 {{selection}}",
|
||||
"Save": "保存",
|
||||
"Name": "名称",
|
||||
"Icon": "图标",
|
||||
"Prompt Template": "提示模板",
|
||||
"Explain this: {{selection}}": "解释这个: {{selection}}",
|
||||
"New": "新建"
|
||||
}
|
||||
|
||||
@@ -133,5 +133,14 @@
|
||||
"Generating...": "產生中...",
|
||||
"moonshot token required, please login at https://kimi.moonshot.cn first": "需要 moonshot token,請先在 https://kimi.moonshot.cn 登入",
|
||||
"Hide context menu of this extension": "隱藏此擴充功能的右鍵選單",
|
||||
"Custom Claude API Url": "自訂 Claude API 網址"
|
||||
"Custom Claude API Url": "自訂 Claude API 網址",
|
||||
"Cancel": "取消",
|
||||
"Name is required": "名稱是必填的",
|
||||
"Prompt template should include {{selection}}": "提示模板應該包含 {{selection}}",
|
||||
"Save": "儲存",
|
||||
"Name": "名稱",
|
||||
"Icon": "圖示",
|
||||
"Prompt Template": "提示模板",
|
||||
"Explain this: {{selection}}": "解釋這個: {{selection}}",
|
||||
"New": "新增"
|
||||
}
|
||||
|
||||
@@ -113,27 +113,41 @@ function FloatingToolbar(props) {
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
if (config.activeSelectionTools.length === 0) return <div />
|
||||
if (
|
||||
config.activeSelectionTools.length === 0 &&
|
||||
config.customSelectionTools.reduce((count, tool) => count + (tool.active ? 1 : 0), 0) === 0
|
||||
)
|
||||
return <div />
|
||||
|
||||
const tools = []
|
||||
const pushTool = (iconKey, name, genPrompt) => {
|
||||
tools.push(
|
||||
cloneElement(toolsConfig[iconKey].icon, {
|
||||
size: 24,
|
||||
className: 'chatgptbox-selection-toolbar-button',
|
||||
title: name,
|
||||
onClick: async () => {
|
||||
const p = getClientPosition(props.container)
|
||||
props.container.style.position = 'fixed'
|
||||
setPosition(p)
|
||||
setPrompt(await genPrompt(selection))
|
||||
setTriggered(true)
|
||||
},
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
for (const key in toolsConfig) {
|
||||
if (config.activeSelectionTools.includes(key)) {
|
||||
const toolConfig = toolsConfig[key]
|
||||
tools.push(
|
||||
cloneElement(toolConfig.icon, {
|
||||
size: 24,
|
||||
className: 'chatgptbox-selection-toolbar-button',
|
||||
title: t(toolConfig.label),
|
||||
onClick: async () => {
|
||||
const p = getClientPosition(props.container)
|
||||
props.container.style.position = 'fixed'
|
||||
setPosition(p)
|
||||
setPrompt(await toolConfig.genPrompt(selection))
|
||||
setTriggered(true)
|
||||
},
|
||||
}),
|
||||
)
|
||||
pushTool(key, t(toolConfig.label), toolConfig.genPrompt)
|
||||
}
|
||||
}
|
||||
for (const tool of config.customSelectionTools) {
|
||||
if (tool.active) {
|
||||
pushTool(tool.iconKey, tool.name, async (selection) => {
|
||||
return tool.prompt.replace('{{selection}}', selection)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -267,6 +267,14 @@ export const defaultConfig = {
|
||||
'azureOpenAi',
|
||||
],
|
||||
activeSelectionTools: ['translate', 'summary', 'polish', 'code', 'ask'],
|
||||
customSelectionTools: [
|
||||
{
|
||||
name: '',
|
||||
iconKey: 'explain',
|
||||
prompt: 'sample prompt: {{selection}}',
|
||||
active: false,
|
||||
},
|
||||
],
|
||||
activeSiteAdapters: [
|
||||
'bilibili',
|
||||
'github',
|
||||
|
||||
@@ -1,14 +1,99 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { config as toolsConfig } from '../../content-script/selection-tools/index.mjs'
|
||||
import PropTypes from 'prop-types'
|
||||
import { useState } from 'react'
|
||||
import { defaultConfig } from '../../config/index.mjs'
|
||||
import { PencilIcon, TrashIcon } from '@primer/octicons-react'
|
||||
|
||||
SelectionTools.propTypes = {
|
||||
config: PropTypes.object.isRequired,
|
||||
updateConfig: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
const defaultTool = {
|
||||
name: '',
|
||||
iconKey: 'explain',
|
||||
prompt: 'Explain this: {{selection}}',
|
||||
active: true,
|
||||
}
|
||||
|
||||
export function SelectionTools({ config, updateConfig }) {
|
||||
const { t } = useTranslation()
|
||||
const [editing, setEditing] = useState(false)
|
||||
const [errorMessage, setErrorMessage] = useState('')
|
||||
const [editingTool, setEditingTool] = useState(defaultTool)
|
||||
const [editingIndex, setEditingIndex] = useState(-1)
|
||||
|
||||
const editingComponent = (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', '--spacing': '4px' }}>
|
||||
<div style={{ display: 'flex', gap: '12px' }}>
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
setEditing(false)
|
||||
}}
|
||||
>
|
||||
{t('Cancel')}
|
||||
</button>
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
if (!editingTool.name) {
|
||||
setErrorMessage(t('Name is required'))
|
||||
return
|
||||
}
|
||||
if (!editingTool.prompt.includes('{{selection}}')) {
|
||||
setErrorMessage(t('Prompt template should include {{selection}}'))
|
||||
return
|
||||
}
|
||||
if (editingIndex === -1) {
|
||||
updateConfig({
|
||||
customSelectionTools: [...config.customSelectionTools, editingTool],
|
||||
})
|
||||
} else {
|
||||
const customSelectionTools = [...config.customSelectionTools]
|
||||
customSelectionTools[editingIndex] = editingTool
|
||||
updateConfig({ customSelectionTools })
|
||||
}
|
||||
setEditing(false)
|
||||
}}
|
||||
>
|
||||
{t('Save')}
|
||||
</button>
|
||||
</div>
|
||||
{errorMessage && <div style={{ color: 'red' }}>{errorMessage}</div>}
|
||||
<div style={{ display: 'flex', gap: '4px', alignItems: 'center' }}>
|
||||
{t('Name')}
|
||||
<input
|
||||
type="text"
|
||||
value={editingTool.name}
|
||||
onChange={(e) => setEditingTool({ ...editingTool, name: e.target.value })}
|
||||
/>
|
||||
{t('Icon')}
|
||||
<select
|
||||
value={editingTool.iconKey}
|
||||
onChange={(e) => setEditingTool({ ...editingTool, iconKey: e.target.value })}
|
||||
>
|
||||
{defaultConfig.selectionTools.map((key) => (
|
||||
<option key={key} value={key}>
|
||||
{t(toolsConfig[key].label)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
{t('Prompt Template')}
|
||||
<textarea
|
||||
type="text"
|
||||
placeholder={t('Explain this: {{selection}}')}
|
||||
style={{
|
||||
resize: 'vertical',
|
||||
minHeight: '80px',
|
||||
}}
|
||||
value={editingTool.prompt}
|
||||
onChange={(e) => setEditingTool({ ...editingTool, prompt: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -27,6 +112,70 @@ export function SelectionTools({ config, updateConfig }) {
|
||||
{t(toolsConfig[key].label)}
|
||||
</label>
|
||||
))}
|
||||
{config.customSelectionTools.map(
|
||||
(tool, index) =>
|
||||
tool.name &&
|
||||
(editing && editingIndex === index ? (
|
||||
editingComponent
|
||||
) : (
|
||||
<label key={index} style={{ display: 'flex', alignItems: 'center' }}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={tool.active}
|
||||
onChange={(e) => {
|
||||
const customSelectionTools = [...config.customSelectionTools]
|
||||
customSelectionTools[index] = { ...tool, active: e.target.checked }
|
||||
updateConfig({ customSelectionTools })
|
||||
}}
|
||||
/>
|
||||
{tool.name}
|
||||
<div style={{ flexGrow: 1 }} />
|
||||
<div style={{ display: 'flex', gap: '12px' }}>
|
||||
<div
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
setEditing(true)
|
||||
setEditingTool(tool)
|
||||
setEditingIndex(index)
|
||||
setErrorMessage('')
|
||||
}}
|
||||
>
|
||||
<PencilIcon />
|
||||
</div>
|
||||
<div
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
const customSelectionTools = [...config.customSelectionTools]
|
||||
customSelectionTools.splice(index, 1)
|
||||
updateConfig({ customSelectionTools })
|
||||
}}
|
||||
>
|
||||
<TrashIcon />
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
)),
|
||||
)}
|
||||
<div style={{ height: '30px' }} />
|
||||
{editing ? (
|
||||
editingIndex === -1 ? (
|
||||
editingComponent
|
||||
) : undefined
|
||||
) : (
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
setEditing(true)
|
||||
setEditingTool(defaultTool)
|
||||
setEditingIndex(-1)
|
||||
setErrorMessage('')
|
||||
}}
|
||||
>
|
||||
{t('New')}
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user