Skip to content

[Feature] 插件没有角落(corner)槽位,多个插件的角落按钮会叠在一起 #1469

Description

@w1ndys

问题

多个插件都想在窗口右下角放一个常驻按钮时,按钮会完全叠在一起:宿主没有给插件任何角落锚点,pi.ui.openLayer() 又是每个插件一个独立的层,层与层之间没有任何协调机制。

真机复现(PI-Desktop 0.16.1,macOS):pi-open-in-vscode 与 pi-open-git-web 两个插件的右下角按钮位置完全重合,肉眼只看得见一颗,另一颗被压在下面。

客户端侧的事实:

  1. 渲染器插槽里没有角落类。PLUGIN_RENDERER_SLOTS 是 ["userAction", "assistantAction", "entryExtra", "toolCard", "blockRenderer", "composerControl", "composerTrigger"],没有 corner / overlay 一类。

  2. pi.ui.openLayer() 给每个插件建一个独立的层(打包产物里的层管理器):

    const div = document.createElement("div");
    const z = Math.min(899, Math.max(600 - 1, ...this.layers.values()) + 1);
    div.setAttribute("data-pi-plugin", pluginId);
    div.setAttribute("data-pi-layer", "");
    Object.assign(div.style, { position: "fixed", top: "0", left: "0", width: "0", height: "0", zIndex: String(z) });

    层是零尺寸的 fixed 元素,插件用 position: fixed 自己定位,各层之间没有共享的定位容器。

  3. injectStyle 的 CSS 又是 @scope ([data-pi-plugin="<id>"]),只在本插件自己的层里生效——插件既不该、也没法去给别的插件的元素排版。

  4. 官方 apps/desktop/src/plugins/renderer-slots/slot-shell.css 里其实已经写好了角落浮层的样式:

    .p-overlay { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; }
    .p-overlay__corner { align-items: flex-end; justify-content: flex-end; background: transparent; pointer-events: none; padding: 16px; }
    .p-overlay__corner > * { pointer-events: auto; }

    ……但宿主 JS 里没有任何地方用它(打包产物里 p-overlay__corner 只出现在 CSS 里),插件也拿不到这个容器。

结果:插件只能照 docs/plugin-plan/ui/self-dialog/ 的「角落浮层由插件自理」各自 inset: 0 + justify-content: flex-end 画自己的盒子,两颗必然落在同一个像素上。这不是某一个插件写错了,是当前接口下的必然结果。

期望改动

给插件一个宿主管理的角落锚点,让多个插件的角落元素能自动排开:

  • 首选:在 PLUGIN_RENDERER_SLOTS 里加一个角落插槽(例如 corner),宿主把各插件注册的角落元素放进同一个 .p-overlay__corner 容器,由宿主负责竖向排列、间距与 pointer-events(盒子 none、子元素 auto),插件只提供自己的元素、卸载即移除。
  • 或者退一步:暴露 pi.ui.getCornerContainer()(或等价的角落层入口),宿主保证同一个容器里的元素不重叠、插件卸载即清掉自己的元素。

两种都能把「位置」这件事收回到宿主,插件之间不必互相知道对方存在。

现状变通(如果短期不做)

我自己的两个插件之间定了一条约定,把重叠糊住了,但新插件都得照抄一遍,很脆:

  • 角落按钮带属性 data-pi-corner-button(空值);
  • 同窗口里所有带这个属性的按钮按 DOM 顺序从右下角往上排,靠后的按下面几颗按钮的高度 transform: translateY() 让位;
  • 高度取 getBoundingClientRect().height,隐藏(高度 0)的按钮跳过、不占位;
  • 每颗按钮只写自己的内联样式,不碰别人的元素。

实现(两个仓里各一份,逐字相同):https://github.com/w1ndys/pi-open-git-web/blob/main/renderer/corner-stack.mjs

缺点:跨插件强耦合、顺序只能取 DOM 顺序、尺寸或可见性变化要各自重算、新插件不知道这条约定照样会叠。

补充信息

环境:PI-Desktop 0.16.1(macOS)。

受影响的公开插件(都是我自己的):

宿主取证位置:apps/desktop/src/plugins/renderer-slots/slot-shell.css(.p-overlay__corner 样式)、渲染器层管理器(open(pluginId) 建 0×0 fixed 层),以及 SDK 的 PLUGIN_RENDERER_SLOTS。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions