Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,13 @@ const {
isAutoKill,
isAutoDetach,
isAutoStart,
isMainPushEnabled,
pluginHasMainPush,
toggleSettingsDropdown,
toggleAutoKill,
toggleAutoDetach,
toggleAutoStart,
toggleMainPushEnabled,
// Tab
activeTab,
availableTabs,
Expand Down Expand Up @@ -102,6 +105,8 @@ function onSwitchTab(tabId: TabId): void {
:is-auto-kill="isAutoKill"
:is-auto-detach="isAutoDetach"
:is-auto-start="isAutoStart"
:is-main-push-enabled="isMainPushEnabled"
:show-main-push-toggle="pluginHasMainPush"
@open="emit('open')"
@kill="emit('kill')"
@open-folder="emit('open-folder')"
Expand All @@ -112,6 +117,7 @@ function onSwitchTab(tabId: TabId): void {
@toggle-auto-kill="toggleAutoKill"
@toggle-auto-detach="toggleAutoDetach"
@toggle-auto-start="toggleAutoStart"
@toggle-main-push-enabled="toggleMainPushEnabled"
/>
</template>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ defineProps<{
isAutoKill: boolean
isAutoDetach: boolean
isAutoStart: boolean
isMainPushEnabled: boolean
showMainPushToggle?: boolean
}>()

const emit = defineEmits<{
Expand All @@ -27,6 +29,7 @@ const emit = defineEmits<{
(e: 'toggle-auto-kill'): void
(e: 'toggle-auto-detach'): void
(e: 'toggle-auto-start'): void
(e: 'toggle-main-push-enabled'): void
}>()

function handleDisabledToggle(event: Event): void {
Expand Down Expand Up @@ -108,6 +111,20 @@ function handleDisabledToggle(event: Event): void {
<span class="toggle-slider"></span>
</label>
</div>
<div v-if="showMainPushToggle" class="settings-dropdown-item">
<div class="settings-item-info">
<span class="settings-item-label">搜索栏推送</span>
<span class="settings-item-desc">关闭后不在搜索栏动态推送内容</span>
</div>
<label class="toggle">
<input
type="checkbox"
:checked="isMainPushEnabled"
@change="emit('toggle-main-push-enabled')"
/>
<span class="toggle-slider"></span>
</label>
</div>
<div class="settings-dropdown-item">
<div class="settings-item-info">
<span class="settings-item-label">退出即结束</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export interface PluginFeature {
explain?: string
icon?: string
cmds?: any[]
mainPush?: boolean
}

export interface PluginItem {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import { marked } from 'marked'
import { computed, onMounted, onUnmounted, ref, watch, type Ref } from 'vue'
import { useToast } from '@/components'
import type { DocItem, PluginItem, PluginUninstallOptions, TabId, TabItem } from './types'
import {
DISABLED_MAIN_PUSH_PLUGINS_KEY,
normalizeConfigList,
isMainPushPluginEnabled
} from '@shared/pluginSettings'

// 配置 marked
marked.setOptions({
Expand All @@ -26,17 +31,17 @@ export function usePluginDetail(options: UsePluginDetailOptions) {
const isAutoKill = ref(false)
const isAutoDetach = ref(false)
const isAutoStart = ref(false)
const isMainPushEnabled = ref(true)

// 当前详情页插件的有效名称(已包含 __dev 后缀)
const currentPluginName = computed(() => plugin.value.name || null)

/** 解析配置列表,兼容旧式 { pluginName, source } 和新式 string */
function normalizeConfigList(data: unknown): string[] {
if (!Array.isArray(data)) return []
return data
.map((item) => (typeof item === 'string' ? item : (item?.pluginName ?? '')))
.filter(Boolean)
}
const pluginHasMainPush = computed(() =>
Boolean(
plugin.value.features?.some(
(feature: any) => feature?.mainPush && Array.isArray(feature.cmds)
)
)
)

/** 切换字符串列表中的某项 */
function toggleInList(list: string[], name: string): string[] {
Expand Down Expand Up @@ -83,6 +88,18 @@ export function usePluginDetail(options: UsePluginDetailOptions) {
} catch (err) {
console.debug('未找到 autoStartPlugin 配置', err)
}

try {
const mainPushData = await window.ztools.internal.dbGet(DISABLED_MAIN_PUSH_PLUGINS_KEY)
if (currentPluginName.value) {
isMainPushEnabled.value = isMainPushPluginEnabled(
currentPluginName.value,
normalizeConfigList(mainPushData)
)
}
} catch (err) {
console.debug('未找到 disabledMainPushPlugin 配置', err)
}
}

// 切换「退出即结束」
Expand Down Expand Up @@ -136,6 +153,21 @@ export function usePluginDetail(options: UsePluginDetailOptions) {
isAutoStart.value = list.includes(currentPluginName.value)
}

async function toggleMainPushEnabled(): Promise<void> {
if (!currentPluginName.value) return

const nextDisabled = isMainPushEnabled.value
const result = await window.ztools.internal.setPluginMainPushDisabled(
currentPluginName.value,
nextDisabled
)
if (result.success) {
isMainPushEnabled.value = !nextDisabled
} else {
error(`更新搜索栏推送状态失败: ${result.error || '未知错误'}`)
}
}

// Tab 状态
const activeTab = ref<TabId>('detail')

Expand Down Expand Up @@ -493,11 +525,14 @@ export function usePluginDetail(options: UsePluginDetailOptions) {
isAutoKill,
isAutoDetach,
isAutoStart,
isMainPushEnabled,
pluginHasMainPush,
currentPluginName,
toggleSettingsDropdown,
toggleAutoKill,
toggleAutoDetach,
toggleAutoStart,
toggleMainPushEnabled,

// Tab 状态
activeTab,
Expand Down
4 changes: 4 additions & 0 deletions internal-plugins/setting/src/env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ declare global {
pluginPath: string,
disabled: boolean
) => Promise<{ success: boolean; error?: string }>
setPluginMainPushDisabled: (
pluginName: string,
disabled: boolean
) => Promise<{ success: boolean; error?: string }>
getAllPlugins: () => Promise<
Array<{
name: string
Expand Down
8 changes: 8 additions & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
allowBuilds:
electron: true
electron-winstaller: true
esbuild: true
lmdb: true
msgpackr-extract: true
sharp: true
uiohook-napi: true
6 changes: 6 additions & 0 deletions resources/preload.js
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,12 @@ window.ztools = {
setPluginDisabled: async (pluginPath, disabled) =>
await electron.ipcRenderer.invoke('internal:set-plugin-disabled', pluginPath, disabled),
getAllPlugins: async () => await electron.ipcRenderer.invoke('internal:get-all-plugins'),
setPluginMainPushDisabled: async (pluginName, disabled) =>
await electron.ipcRenderer.invoke(
'internal:set-plugin-main-push-disabled',
pluginName,
disabled
),
selectPluginFile: async () => await electron.ipcRenderer.invoke('internal:select-plugin-file'),
importPlugin: async () => await electron.ipcRenderer.invoke('internal:import-plugin'),
getDevProjects: async () => await electron.ipcRenderer.invoke('internal:get-dev-projects'),
Expand Down
10 changes: 10 additions & 0 deletions src/main/api/plugin/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,16 @@ export class InternalPluginAPI {
return await pluginsAPI.getAllPlugins()
})

ipcMain.handle(
'internal:set-plugin-main-push-disabled',
async (event, pluginName: string, disabled: boolean) => {
if (!requireInternalPlugin(this.pluginManager, event)) {
throw new PermissionDeniedError('internal:set-plugin-main-push-disabled')
}
return await pluginsAPI.setPluginMainPushDisabled(pluginName, disabled)
}
)

ipcMain.handle('internal:select-plugin-file', async (event) => {
if (!requireInternalPlugin(this.pluginManager, event)) {
throw new PermissionDeniedError('internal:select-plugin-file')
Expand Down
51 changes: 51 additions & 0 deletions src/main/api/renderer/plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,20 @@ import {
getPluginDataPrefix,
isDevelopmentPluginName
} from '../../../shared/pluginRuntimeNamespace'
import {
DISABLED_MAIN_PUSH_PLUGINS_KEY,
normalizeConfigList,
removePluginNameFromSettingList
} from '../../../shared/pluginSettings'

// 插件目录
const DISABLED_PLUGINS_KEY = 'disabled-plugins'
const PLUGIN_NAME_SETTING_KEYS = [
'outKillPlugin',
'autoDetachPlugin',
'autoStartPlugin',
DISABLED_MAIN_PUSH_PLUGINS_KEY
]

export interface DeletePluginOptions {
deleteData?: boolean
Expand Down Expand Up @@ -474,6 +485,7 @@ export class PluginsAPI {

if (options.deleteData !== false) {
await databaseAPI.clearPluginData(pluginInfo.name)
this.removePluginNameConfigs(PLUGIN_NAME_SETTING_KEYS, pluginInfo.name)
}

// 删除禁用插件标识
Expand Down Expand Up @@ -503,6 +515,45 @@ export class PluginsAPI {
}
}

private removePluginNameConfigs(keys: string[], pluginName: string): void {
for (const key of keys) {
const current = databaseAPI.dbGet(key)
const normalized = normalizeConfigList(current)
const next = removePluginNameFromSettingList(normalized, pluginName)
if (next.length !== normalized.length) {
databaseAPI.dbPut(key, next)
}
}
}
Comment on lines +518 to +527

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

代码简化与性能优化建议

removePluginNameConfigs 中,normalizeConfigList(current) 已经被调用了一次。接着调用 removePluginNameFromSettingList(current, pluginName) 会在内部再次调用 normalizeConfigList(current),造成了重复解析。

可以直接使用 normalized.filter 来生成 next 数组,这样既简化了代码,又避免了重复的规范化计算。此外,如果应用此优化,文件顶部的 removePluginNameFromSettingList 导入也可以一并移除。

Suggested change
private removePluginNameConfigs(keys: string[], pluginName: string): void {
for (const key of keys) {
const current = databaseAPI.dbGet(key)
const normalized = normalizeConfigList(current)
const next = removePluginNameFromSettingList(current, pluginName)
if (next.length !== normalized.length) {
databaseAPI.dbPut(key, next)
}
}
}
private removePluginNameConfigs(keys: string[], pluginName: string): void {
for (const key of keys) {
const current = databaseAPI.dbGet(key)
const normalized = normalizeConfigList(current)
const next = normalized.filter((name) => name !== pluginName)
if (next.length !== normalized.length) {
databaseAPI.dbPut(key, next)
}
}
}


public async setPluginMainPushDisabled(
pluginName: string,
disabled: boolean
): Promise<{ success: boolean; error?: string }> {
try {
const disabledPluginNames = new Set(
normalizeConfigList(databaseAPI.dbGet(DISABLED_MAIN_PUSH_PLUGINS_KEY))
)
const isCurrentlyDisabled = disabledPluginNames.has(pluginName)
if (isCurrentlyDisabled === disabled) {
return { success: true }
}

if (disabled) {
disabledPluginNames.add(pluginName)
} else {
disabledPluginNames.delete(pluginName)
}

databaseAPI.dbPut(DISABLED_MAIN_PUSH_PLUGINS_KEY, [...disabledPluginNames])
this.notifyPluginsChanged()
return { success: true }
} catch (error: unknown) {
console.error('[Plugins] 更新插件 mainPush 状态失败:', error)
return { success: false, error: error instanceof Error ? error.message : '未知错误' }
}
}

// 获取运行中的插件
public getRunningPlugins(): string[] {
if (this.pluginManager) {
Expand Down
8 changes: 1 addition & 7 deletions src/renderer/src/components/detached/DetachedTitlebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@

<script setup lang="ts">
import { onMounted, ref } from 'vue'
import { normalizeConfigList } from '@shared/pluginSettings'
import AdaptiveIcon from '../common/AdaptiveIcon.vue'

const platform = ref<'darwin' | 'win32'>('darwin')
Expand All @@ -140,13 +141,6 @@ const aiRequestStatus = ref<'idle' | 'sending' | 'receiving'>('idle') // AI 请
const primaryColor = ref('blue')
const customColor = ref('#db2777')

function normalizeConfigList(data: unknown): string[] {
if (!Array.isArray(data)) return []
return (data as any[])
.map((item) => (typeof item === 'string' ? item : (item?.pluginName ?? '')))
.filter(Boolean)
}

function getThemeColor(colorName: string, isDark: boolean): string {
const colors: Record<string, { light: string; dark: string }> = {
blue: { light: '#0284c7', dark: '#38bdf8' },
Expand Down
9 changes: 1 addition & 8 deletions src/renderer/src/components/search/SearchBox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@

<script setup lang="ts">
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
import { normalizeConfigList } from '@shared/pluginSettings'
import { DEFAULT_AVATAR, useWindowStore } from '../../stores/windowStore'
import AdaptiveIcon from '../common/AdaptiveIcon.vue'
import UpdateIcon from './UpdateIcon.vue'
Expand Down Expand Up @@ -276,14 +277,6 @@ function getCurrentPluginName(): string | null {
return windowStore.currentPlugin?.name ?? null
}

/** 解析配置列表,兼容旧式对象 */
function normalizeConfigList(data: unknown): string[] {
if (!Array.isArray(data)) return []
return data
.map((item) => (typeof item === 'string' ? item : (item?.pluginName ?? '')))
.filter(Boolean)
}

/**
* 切换当前插件在指定行为设置中的选中状态。
*/
Expand Down
Loading