mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-23 18:10:26 +08:00
feat: replace n8n icon with SVG version and update references
* removed the old n8n.ico file * added new n8n.svg file * updated references in minapps configuration and app components to use the new SVG logo * changed file handling from 'customMiniAPP' to 'custom-minapps.json' for consistency
This commit is contained in:
parent
6708efdbe1
commit
c0cb1693da
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB |
1
src/renderer/src/assets/images/apps/n8n.svg
Normal file
1
src/renderer/src/assets/images/apps/n8n.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>n8n</title><path clip-rule="evenodd" d="M24 8.4c0 1.325-1.102 2.4-2.462 2.4-1.146 0-2.11-.765-2.384-1.8h-3.436c-.602 0-1.115.424-1.214 1.003l-.101.592a2.38 2.38 0 01-.8 1.405c.412.354.704.844.8 1.405l.1.592A1.222 1.222 0 0015.719 15h.975c.273-1.035 1.237-1.8 2.384-1.8 1.36 0 2.461 1.075 2.461 2.4S20.436 18 19.078 18c-1.147 0-2.11-.765-2.384-1.8h-.975c-1.204 0-2.23-.848-2.428-2.005l-.101-.592a1.222 1.222 0 00-1.214-1.003H10.97c-.308.984-1.246 1.7-2.356 1.7-1.11 0-2.048-.716-2.355-1.7H4.817c-.308.984-1.246 1.7-2.355 1.7C1.102 14.3 0 13.225 0 11.9s1.102-2.4 2.462-2.4c1.183 0 2.172.815 2.408 1.9h1.337c.236-1.085 1.225-1.9 2.408-1.9 1.184 0 2.172.815 2.408 1.9h.952c.601 0 1.115-.424 1.213-1.003l.102-.592c.198-1.157 1.225-2.005 2.428-2.005h3.436c.274-1.035 1.238-1.8 2.384-1.8C22.898 6 24 7.075 24 8.4zm-1.23 0c0 .663-.552 1.2-1.232 1.2-.68 0-1.23-.537-1.23-1.2 0-.663.55-1.2 1.23-1.2.68 0 1.231.537 1.231 1.2zM2.461 13.1c.68 0 1.23-.537 1.23-1.2 0-.663-.55-1.2-1.23-1.2-.68 0-1.231.537-1.231 1.2 0 .663.55 1.2 1.23 1.2zm6.153 0c.68 0 1.231-.537 1.231-1.2 0-.663-.55-1.2-1.23-1.2-.68 0-1.231.537-1.231 1.2 0 .663.55 1.2 1.23 1.2zm10.462 3.7c.68 0 1.23-.537 1.23-1.2 0-.663-.55-1.2-1.23-1.2-.68 0-1.23.537-1.23 1.2 0 .663.55 1.2 1.23 1.2z" fill="#EA4B71" fill-rule="evenodd"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.4 KiB |
@ -1,8 +1,7 @@
|
|||||||
import n8nLogo from '@renderer/assets/images/apps/n8n.ico?url'
|
|
||||||
import ApplicationLogo from '@renderer/assets/images/apps/application.png?url'
|
|
||||||
import ThreeMinTopAppLogo from '@renderer/assets/images/apps/3mintop.png?url'
|
import ThreeMinTopAppLogo from '@renderer/assets/images/apps/3mintop.png?url'
|
||||||
import AbacusLogo from '@renderer/assets/images/apps/abacus.webp?url'
|
import AbacusLogo from '@renderer/assets/images/apps/abacus.webp?url'
|
||||||
import AIStudioLogo from '@renderer/assets/images/apps/aistudio.svg?url'
|
import AIStudioLogo from '@renderer/assets/images/apps/aistudio.svg?url'
|
||||||
|
import ApplicationLogo from '@renderer/assets/images/apps/application.png?url'
|
||||||
import BaiduAiAppLogo from '@renderer/assets/images/apps/baidu-ai.png?url'
|
import BaiduAiAppLogo from '@renderer/assets/images/apps/baidu-ai.png?url'
|
||||||
import BaiduAiSearchLogo from '@renderer/assets/images/apps/baidu-ai-search.webp?url'
|
import BaiduAiSearchLogo from '@renderer/assets/images/apps/baidu-ai-search.webp?url'
|
||||||
import BaicuanAppLogo from '@renderer/assets/images/apps/baixiaoying.webp?url'
|
import BaicuanAppLogo from '@renderer/assets/images/apps/baixiaoying.webp?url'
|
||||||
@ -28,6 +27,7 @@ import LambdaChatLogo from '@renderer/assets/images/apps/lambdachat.webp?url'
|
|||||||
import LeChatLogo from '@renderer/assets/images/apps/lechat.png?url'
|
import LeChatLogo from '@renderer/assets/images/apps/lechat.png?url'
|
||||||
import MetasoAppLogo from '@renderer/assets/images/apps/metaso.webp?url'
|
import MetasoAppLogo from '@renderer/assets/images/apps/metaso.webp?url'
|
||||||
import MonicaLogo from '@renderer/assets/images/apps/monica.webp?url'
|
import MonicaLogo from '@renderer/assets/images/apps/monica.webp?url'
|
||||||
|
import n8nLogo from '@renderer/assets/images/apps/n8n.svg?url'
|
||||||
import NamiAiLogo from '@renderer/assets/images/apps/nm.png?url'
|
import NamiAiLogo from '@renderer/assets/images/apps/nm.png?url'
|
||||||
import NamiAiSearchLogo from '@renderer/assets/images/apps/nm-search.webp?url'
|
import NamiAiSearchLogo from '@renderer/assets/images/apps/nm-search.webp?url'
|
||||||
import NotebookLMAppLogo from '@renderer/assets/images/apps/notebooklm.svg?url'
|
import NotebookLMAppLogo from '@renderer/assets/images/apps/notebooklm.svg?url'
|
||||||
@ -61,11 +61,11 @@ const loadCustomMiniApp = async (): Promise<MinAppType[]> => {
|
|||||||
try {
|
try {
|
||||||
let content: string
|
let content: string
|
||||||
try {
|
try {
|
||||||
content = await window.api.file.read('customMiniAPP')
|
content = await window.api.file.read('custom-minapps.json')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// 如果文件不存在,创建一个空的 JSON 数组
|
// 如果文件不存在,创建一个空的 JSON 数组
|
||||||
content = '[]'
|
content = '[]'
|
||||||
await window.api.file.writeWithId('customMiniAPP', content)
|
await window.api.file.writeWithId('custom-minapps.json', content)
|
||||||
}
|
}
|
||||||
|
|
||||||
const customApps = JSON.parse(content)
|
const customApps = JSON.parse(content)
|
||||||
@ -455,7 +455,10 @@ const ORIGIN_DEFAULT_MIN_APPS: MinAppType[] = [
|
|||||||
name: 'n8n',
|
name: 'n8n',
|
||||||
logo: n8nLogo,
|
logo: n8nLogo,
|
||||||
url: 'https://app.n8n.cloud/',
|
url: 'https://app.n8n.cloud/',
|
||||||
bodered: true
|
bodered: true,
|
||||||
|
style: {
|
||||||
|
padding: 5
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -40,7 +40,7 @@ const App: FC<Props> = ({ app, onClick, size = 60, isLast }) => {
|
|||||||
|
|
||||||
const handleAddCustomApp = async (values: any) => {
|
const handleAddCustomApp = async (values: any) => {
|
||||||
try {
|
try {
|
||||||
const content = await window.api.file.read('customMiniAPP')
|
const content = await window.api.file.read('custom-minapps.json')
|
||||||
const customApps = JSON.parse(content)
|
const customApps = JSON.parse(content)
|
||||||
|
|
||||||
// Check for duplicate ID
|
// Check for duplicate ID
|
||||||
@ -62,7 +62,7 @@ const App: FC<Props> = ({ app, onClick, size = 60, isLast }) => {
|
|||||||
addTime: new Date().toISOString()
|
addTime: new Date().toISOString()
|
||||||
}
|
}
|
||||||
customApps.push(newApp)
|
customApps.push(newApp)
|
||||||
await window.api.file.writeWithId('customMiniAPP', JSON.stringify(customApps, null, 2))
|
await window.api.file.writeWithId('custom-minapps.json', JSON.stringify(customApps, null, 2))
|
||||||
message.success(t('settings.miniapps.custom.save_success'))
|
message.success(t('settings.miniapps.custom.save_success'))
|
||||||
setIsModalVisible(false)
|
setIsModalVisible(false)
|
||||||
form.resetFields()
|
form.resetFields()
|
||||||
@ -138,10 +138,10 @@ const App: FC<Props> = ({ app, onClick, size = 60, isLast }) => {
|
|||||||
danger: true,
|
danger: true,
|
||||||
onClick: async () => {
|
onClick: async () => {
|
||||||
try {
|
try {
|
||||||
const content = await window.api.file.read('customMiniAPP')
|
const content = await window.api.file.read('custom-minapps.json')
|
||||||
const customApps = JSON.parse(content)
|
const customApps = JSON.parse(content)
|
||||||
const updatedApps = customApps.filter((customApp: MinAppType) => customApp.id !== app.id)
|
const updatedApps = customApps.filter((customApp: MinAppType) => customApp.id !== app.id)
|
||||||
await window.api.file.writeWithId('customMiniAPP', JSON.stringify(updatedApps, null, 2))
|
await window.api.file.writeWithId('custom-minapps.json', JSON.stringify(updatedApps, null, 2))
|
||||||
message.success(t('settings.miniapps.custom.remove_success'))
|
message.success(t('settings.miniapps.custom.remove_success'))
|
||||||
const reloadedApps = [...ORIGIN_DEFAULT_MIN_APPS, ...(await loadCustomMiniApp())]
|
const reloadedApps = [...ORIGIN_DEFAULT_MIN_APPS, ...(await loadCustomMiniApp())]
|
||||||
updateDefaultMinApps(reloadedApps)
|
updateDefaultMinApps(reloadedApps)
|
||||||
|
|||||||
@ -1,10 +1,5 @@
|
|||||||
import { UndoOutlined } from '@ant-design/icons' // 导入重置图标
|
import { UndoOutlined } from '@ant-design/icons' // 导入重置图标
|
||||||
import {
|
import { DEFAULT_MIN_APPS } from '@renderer/config/minapps'
|
||||||
DEFAULT_MIN_APPS,
|
|
||||||
loadCustomMiniApp,
|
|
||||||
ORIGIN_DEFAULT_MIN_APPS,
|
|
||||||
updateDefaultMinApps
|
|
||||||
} from '@renderer/config/minapps'
|
|
||||||
import { useTheme } from '@renderer/context/ThemeProvider'
|
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||||
import { useMinapps } from '@renderer/hooks/useMinapps'
|
import { useMinapps } from '@renderer/hooks/useMinapps'
|
||||||
import { useSettings } from '@renderer/hooks/useSettings'
|
import { useSettings } from '@renderer/hooks/useSettings'
|
||||||
@ -14,7 +9,7 @@ import {
|
|||||||
setMinappsOpenLinkExternal,
|
setMinappsOpenLinkExternal,
|
||||||
setShowOpenedMinappsInSidebar
|
setShowOpenedMinappsInSidebar
|
||||||
} from '@renderer/store/settings'
|
} from '@renderer/store/settings'
|
||||||
import { Button, Input, message, Slider, Switch, Tooltip } from 'antd'
|
import { Button, message, Slider, Switch, Tooltip } from 'antd'
|
||||||
import { FC, useCallback, useEffect, useRef, useState } from 'react'
|
import { FC, useCallback, useEffect, useRef, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
@ -36,92 +31,6 @@ const MiniAppSettings: FC = () => {
|
|||||||
const [disabledMiniApps, setDisabledMiniApps] = useState(disabled || [])
|
const [disabledMiniApps, setDisabledMiniApps] = useState(disabled || [])
|
||||||
const [messageApi, contextHolder] = message.useMessage()
|
const [messageApi, contextHolder] = message.useMessage()
|
||||||
const debounceTimerRef = useRef<NodeJS.Timeout | null>(null)
|
const debounceTimerRef = useRef<NodeJS.Timeout | null>(null)
|
||||||
const [customMiniAppContent, setCustomMiniAppContent] = useState('[]')
|
|
||||||
|
|
||||||
// 加载自定义小应用配置
|
|
||||||
useEffect(() => {
|
|
||||||
const loadCustomMiniApp = async () => {
|
|
||||||
try {
|
|
||||||
const content = await window.api.file.read('customMiniAPP')
|
|
||||||
let validContent = '[]'
|
|
||||||
try {
|
|
||||||
const parsed = JSON.parse(content)
|
|
||||||
validContent = JSON.stringify(parsed)
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Invalid JSON format in custom mini app config:', e)
|
|
||||||
}
|
|
||||||
setCustomMiniAppContent(validContent)
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to load custom mini app config:', error)
|
|
||||||
setCustomMiniAppContent('[]')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
loadCustomMiniApp()
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
// 保存自定义小应用配置
|
|
||||||
const handleSaveCustomMiniApp = useCallback(async () => {
|
|
||||||
try {
|
|
||||||
// 验证 JSON 格式
|
|
||||||
if (customMiniAppContent === '') {
|
|
||||||
setCustomMiniAppContent('[]')
|
|
||||||
}
|
|
||||||
const parsedContent = JSON.parse(customMiniAppContent)
|
|
||||||
// 确保是数组
|
|
||||||
if (!Array.isArray(parsedContent)) {
|
|
||||||
throw new Error('Content must be an array')
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查自定义应用中的重复ID
|
|
||||||
const customIds = new Set<string>()
|
|
||||||
const duplicateIds = new Set<string>()
|
|
||||||
parsedContent.forEach((app: any) => {
|
|
||||||
if (app.id) {
|
|
||||||
if (customIds.has(app.id)) {
|
|
||||||
duplicateIds.add(app.id)
|
|
||||||
}
|
|
||||||
customIds.add(app.id)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 检查与默认应用的ID重复
|
|
||||||
const defaultIds = new Set(ORIGIN_DEFAULT_MIN_APPS.map((app) => app.id))
|
|
||||||
const conflictingIds = new Set<string>()
|
|
||||||
customIds.forEach((id) => {
|
|
||||||
if (defaultIds.has(id)) {
|
|
||||||
conflictingIds.add(id)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 如果有重复ID,显示错误信息
|
|
||||||
if (duplicateIds.size > 0 || conflictingIds.size > 0) {
|
|
||||||
let errorMessage = ''
|
|
||||||
if (duplicateIds.size > 0) {
|
|
||||||
errorMessage += t('settings.miniapps.custom.duplicate_ids', { ids: Array.from(duplicateIds).join(', ') })
|
|
||||||
}
|
|
||||||
if (conflictingIds.size > 0) {
|
|
||||||
console.log('conflictingIds', Array.from(conflictingIds))
|
|
||||||
if (errorMessage) errorMessage += '\n'
|
|
||||||
errorMessage += t('settings.miniapps.custom.conflicting_ids', { ids: Array.from(conflictingIds).join(', ') })
|
|
||||||
}
|
|
||||||
messageApi.error(errorMessage)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存文件
|
|
||||||
await window.api.file.writeWithId('customMiniAPP', customMiniAppContent)
|
|
||||||
messageApi.success(t('settings.miniapps.custom.save_success'))
|
|
||||||
// 重新加载应用列表
|
|
||||||
console.log('Reloading mini app list...')
|
|
||||||
const reloadedApps = [...ORIGIN_DEFAULT_MIN_APPS, ...(await loadCustomMiniApp())]
|
|
||||||
updateDefaultMinApps(reloadedApps)
|
|
||||||
console.log('Reloaded mini app list:', reloadedApps)
|
|
||||||
updateMinapps(reloadedApps)
|
|
||||||
} catch (error) {
|
|
||||||
messageApi.error(t('settings.miniapps.custom.save_error'))
|
|
||||||
console.error('Failed to save custom mini app config:', error)
|
|
||||||
}
|
|
||||||
}, [customMiniAppContent, messageApi, t, updateMinapps])
|
|
||||||
|
|
||||||
const handleResetMinApps = useCallback(() => {
|
const handleResetMinApps = useCallback(() => {
|
||||||
setVisibleMiniApps(DEFAULT_MIN_APPS)
|
setVisibleMiniApps(DEFAULT_MIN_APPS)
|
||||||
@ -235,30 +144,6 @@ const MiniAppSettings: FC = () => {
|
|||||||
onChange={(checked) => dispatch(setShowOpenedMinappsInSidebar(checked))}
|
onChange={(checked) => dispatch(setShowOpenedMinappsInSidebar(checked))}
|
||||||
/>
|
/>
|
||||||
</SettingRow>
|
</SettingRow>
|
||||||
<SettingDivider />
|
|
||||||
<SettingRow>
|
|
||||||
<SettingLabelGroup>
|
|
||||||
<SettingRowTitle>{t('settings.miniapps.custom.edit_title')}</SettingRowTitle>
|
|
||||||
<SettingDescription>{t('settings.miniapps.custom.edit_description')}</SettingDescription>
|
|
||||||
</SettingLabelGroup>
|
|
||||||
</SettingRow>
|
|
||||||
<CustomEditorContainer>
|
|
||||||
<Input.TextArea
|
|
||||||
value={customMiniAppContent}
|
|
||||||
onChange={(e) => setCustomMiniAppContent(e.target.value)}
|
|
||||||
placeholder={t('settings.miniapps.custom.placeholder')}
|
|
||||||
style={{
|
|
||||||
minHeight: 200,
|
|
||||||
fontFamily: 'monospace',
|
|
||||||
backgroundColor: 'var(--color-bg-2)',
|
|
||||||
color: 'var(--color-text)',
|
|
||||||
borderColor: 'var(--color-border)'
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Button type="primary" onClick={handleSaveCustomMiniApp} style={{ marginTop: 8 }}>
|
|
||||||
{t('settings.miniapps.custom.save')}
|
|
||||||
</Button>
|
|
||||||
</CustomEditorContainer>
|
|
||||||
</SettingGroup>
|
</SettingGroup>
|
||||||
</SettingContainer>
|
</SettingContainer>
|
||||||
)
|
)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user