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:
kangfenmao 2025-05-09 20:15:43 +08:00
parent 6708efdbe1
commit c0cb1693da
5 changed files with 15 additions and 126 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View 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

View File

@ -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
}
} }
] ]

View File

@ -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)

View File

@ -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>
) )