feat(settings/plugins): 「全部」作用域 + 浏览器独立图标 + 浏览器设置页文案精简

This commit is contained in:
Rick Ye
2026-09-11 17:53:35 +08:00
parent 70930e4952
commit b1405ee71f
5 changed files with 26 additions and 17 deletions
@@ -15,7 +15,8 @@ export const browserPlugin: BuiltinPlugin = {
minContract: '0.1.0', minContract: '0.1.0',
panel: true, panel: true,
order: 10, order: 10,
description: '受管浏览器' description: '受管浏览器',
icon: 'Globe'
}, },
/** 宿主专属二级设置页(代理设置 + 登录态导入;见 SettingsModal 插件页特判) */ /** 宿主专属二级设置页(代理设置 + 登录态导入;见 SettingsModal 插件页特判) */
settingsPage: true, settingsPage: true,
@@ -776,7 +776,7 @@ function PluginsPanel({
onNavToggle: (pluginId: string, on: boolean) => void onNavToggle: (pluginId: string, on: boolean) => void
}): ReactNode { }): ReactNode {
const plugins = usePluginList() const plugins = usePluginList()
const [scope, setScope] = useState<'user' | 'project' | 'builtin'>('user') const [scope, setScope] = useState<'all' | 'user' | 'project' | 'builtin'>('all')
/** 全局插件重载进行中(重扫目录 + 重建运行时;期间刷新按钮禁用旋转) */ /** 全局插件重载进行中(重扫目录 + 重建运行时;期间刷新按钮禁用旋转) */
const [reloading, setReloading] = useState(false) const [reloading, setReloading] = useState(false)
const [dirs, setDirs] = useState<{ user: string[]; project: string[]; global: string[] }>({ const [dirs, setDirs] = useState<{ user: string[]; project: string[]; global: string[] }>({
@@ -798,17 +798,23 @@ function PluginsPanel({
}, []) }, [])
const scoped = const scoped =
scope === 'builtin' scope === 'all'
? plugins.filter((p) => p.source === 'builtin') ? plugins
: plugins.filter((p) => p.source === 'external' && (scope === 'project' ? p.origin === 'project' : p.origin !== 'project')) : scope === 'builtin'
? plugins.filter((p) => p.source === 'builtin')
: plugins.filter((p) =>
p.source === 'external' ? (scope === 'project' ? p.origin === 'project' : p.origin !== 'project') : false
)
const scopedDirs = scope === 'user' ? dirs.global : scope === 'project' ? dirs.project : [] const scopedDirs = scope === 'user' ? dirs.global : scope === 'project' ? dirs.project : []
const scopedHints = scope === 'user' ? ['全局'] : ['项目'] const scopedHints = scope === 'user' ? ['全局'] : ['项目']
const originLabel = (p: PluginInfo): string =>
p.source === 'builtin' ? '内置' : p.origin === 'project' ? '项目' : '全局'
return ( return (
<div className="flex min-h-0 flex-col"> <div className="flex min-h-0 flex-col">
<div className="flex items-center gap-2 pb-3"> <div className="flex items-center gap-2 pb-3">
<div className="flex items-center rounded-control bg-zinc-100 p-0.5"> <div className="flex items-center rounded-control bg-zinc-100 p-0.5">
{(['user', 'project', 'builtin'] as const).map((s) => ( {(['all', 'user', 'project', 'builtin'] as const).map((s) => (
<button <button
key={s} key={s}
type="button" type="button"
@@ -817,7 +823,7 @@ function PluginsPanel({
scope === s ? 'bg-white font-medium text-zinc-900 shadow-sm' : 'text-zinc-500 hover:text-zinc-700' scope === s ? 'bg-white font-medium text-zinc-900 shadow-sm' : 'text-zinc-500 hover:text-zinc-700'
}`} }`}
> >
{s === 'user' ? '全局' : s === 'project' ? '项目' : '内置'} {s === 'all' ? '全部' : s === 'user' ? '全局' : s === 'project' ? '项目' : '内置'}
</button> </button>
))} ))}
</div> </div>
@@ -839,9 +845,15 @@ function PluginsPanel({
{scoped.length === 0 ? ( {scoped.length === 0 ? (
<div className="flex flex-col items-center justify-center gap-1 rounded-card border border-dashed border-line py-12 text-center"> <div className="flex flex-col items-center justify-center gap-1 rounded-card border border-dashed border-line py-12 text-center">
<div className="text-[13px] font-medium text-ink-2"> <div className="text-[13px] font-medium text-ink-2">
{scope === 'builtin' ? '暂无内置插件' : devBuild ? '暂无第三方插件' : '第三方插件装载已关闭(用户版构建)'} {scope === 'all'
? '暂无插件'
: scope === 'builtin'
? '暂无内置插件'
: devBuild
? '暂无第三方插件'
: '第三方插件装载已关闭(用户版构建)'}
</div> </div>
{scope !== 'builtin' && devBuild && ( {(scope === 'user' || scope === 'project') && devBuild && (
<div className="text-[11.5px] text-ink-3"> <div className="text-[11.5px] text-ink-3">
把含 manifest.json 的插件目录放入 把含 manifest.json 的插件目录放入
{scope === 'user' ? '全局(~/.pi/agent/extensions)' : '项目 .pi/extensions/'}即可自动识别 {scope === 'user' ? '全局(~/.pi/agent/extensions)' : '项目 .pi/extensions/'}即可自动识别
@@ -883,7 +895,7 @@ function PluginsPanel({
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span className="text-[12.5px] font-medium text-ink">{p.manifest.name}</span> <span className="text-[12.5px] font-medium text-ink">{p.manifest.name}</span>
<span className="rounded-control bg-hover px-1.5 py-0.5 text-[10px] text-ink-3"> <span className="rounded-control bg-hover px-1.5 py-0.5 text-[10px] text-ink-3">
{scope === 'builtin' ? '内置' : scope === 'user' ? '全局' : '项目'} v{p.manifest.version} {originLabel(p)} v{p.manifest.version}
</span> </span>
{p.dependencies.length > 0 && <PluginDepsTip deps={p.dependencies} />} {p.dependencies.length > 0 && <PluginDepsTip deps={p.dependencies} />}
</div> </div>
@@ -66,8 +66,8 @@ export function BrowserImportForm(): JSX.Element {
return ( return (
<div className="text-[12px] text-ink-2"> <div className="text-[12px] text-ink-2">
<p className="mb-3 leading-relaxed text-ink-3"> <p className="mb-3 leading-relaxed text-ink-3">
选择本机浏览器的一个配置(Profile),把其中各网站的登录态(Cookie / Local Storage)导入到内置受管浏览器。 迁移 Cookie / Local Storage 登录态。导入前请
导入前请<span className="font-medium text-ink-2">完全退出</span>该浏览器,并关闭本面板的所有标签页。 <span className="font-medium text-ink-2">完全退出</span>源浏览器,并关闭本面板所有标签页。
</p> </p>
{state?.imported && ( {state?.imported && (
@@ -68,10 +68,6 @@ export function BrowserProxyForm(): JSX.Element {
return ( return (
<div className="text-[12px] text-ink-2"> <div className="text-[12px] text-ink-2">
<p className="mb-3 leading-relaxed text-ink-3">
代理只作用于内置受管浏览器(不影响应用其他部分与系统设置),保存后立即生效。
</p>
<div className="flex w-fit items-center rounded-control border border-line bg-hover p-0.5"> <div className="flex w-fit items-center rounded-control border border-line bg-hover p-0.5">
{PROXY_MODES.map((m) => ( {PROXY_MODES.map((m) => (
<button <button
+1 -1
View File
@@ -6,7 +6,7 @@
"description": "TODO:一句话描述插件做什么", "description": "TODO:一句话描述插件做什么",
"order": 50, "order": 50,
"panel": true, "panel": true,
"icon": "Puzzle", "icon": "Blocks",
"entry": { "entry": {
"main": "main.mjs", "main": "main.mjs",
"renderer": "renderer.mjs" "renderer": "renderer.mjs"