Browser toolbar
只放与当前网页直接相关且频繁使用的动作:导航、地址、保存当前页、打开书签、外部打开和 Browser ⋯。
新建 Pane 只负责选择内容类型;进入 Browser 后才显示网页导航、书签、History 和资料导入。浏览器工具栏只处理当前网页和浏览资料,整个窗口的菜单只处理 OpenProgram 与 Pane。两类设置共用同一 Settings 页面,但使用不同入口。
当前问题来自内容入口、浏览器主页和资料管理共用一个页面。设计先分离职责,再定义每个页面出现的控件。
空白 Pane 只显示 Files、New chat、Browser、Terminal。地址栏、快捷网站、Bookmarks 和 History 不出现在这里。
Files、New chat、Browser、Terminal 都使用相同尺寸的圆角图标容器和 Lucide 线性图标;Files 使用蓝色、New chat 使用绿色、Browser 保留橙紫色、Terminal 使用紫色。颜色只帮助识别内容类型,不改变卡片层级、交互状态或可访问名称,也不引入品牌 Logo、外部素材和额外动画。
选择 Browser 后原位进入浏览器主页;主页与实际网页使用同一套地址栏和书签栏结构。主页中无当前网页语义的 Back、Forward、Reload、Home、Bookmark 和外部打开保持可见但禁用,地址输入、Bookmarks、Import 和 Browser ⋯ 可用。
地址栏右侧的星标只保存或移除当前页;相邻的 Bookmarks 按钮打开完整书签页。Browser home 只显示用户维护的快捷网站,不展开全部书签。
完整书签页顶部固定页面标题、搜索框和页级菜单;左栏只显示可折叠的文件夹树并高亮当前目录,右栏只显示当前目录的直接子项。书签行使用 favicon、标题和单一 ⋮ 菜单,文件夹行进入对应目录;不再把整棵树、URL 和编辑/删除按钮同时铺在一个列表里。左右列表行统一为 36px,搜索框沿用全局 30px 控件高度,行内图标按钮为 28px,页头为 52px;右侧列表的首屏内边距为 16px。Pane 变窄时目录树移到内容列表上方,不能直接消失。
Browser home 和实际网页默认在地址栏下方显示同一行书签。用户可以从 Browser ⋯ 或 Settings 关闭;窄分屏临时隐藏该行,仍可通过 Browser ⋯ 中的 Bookmarks 访问全部内容。
Chromium 的 Bookmarks bar 是书签栏容器,不作为普通文件夹按钮显示。该容器的直接子项按原顺序进入栏内;Other bookmarks 和 Mobile bookmarks 作为右侧文件夹入口,仅在非空时显示。普通根级书签继续作为栏内项目。
单行书签栏不出现水平滚动条;被宽度截断的项目由右侧溢出入口列出。菜单固定为 280px 宽,过长标题使用省略号;文件夹以右箭头进入下一级菜单,不把完整路径拼进一行。每一级菜单高度受当前窗口约束,并支持鼠标、触控板与键盘操作。
窗口菜单的 Settings 打开 OpenProgram 设置;Browser 的 ⋯ 直接打开其中的 Browser 分区。工具栏不增加常驻齿轮,也不实现第二套浏览器设置存储。
分屏、退出分屏和 Pane 排列适用于 Files、Chat、Browser、Terminal,不属于当前网页动作。它们放在 Tab/Pane 控件或 Tab 上下文菜单,不出现在浏览器工具栏。
Chromium 的 bookmark bar、other bookmarks 以及嵌套文件夹按原有层级和顺序进入 OpenProgram bookmark tree;导入不得把书签压平成主页下方的独立条目。
Browser ⋯ 和窗口 ⋯ 都使用各自触发按钮的实际屏幕矩形定位,菜单右边缘与按钮右边缘对齐,垂直间距为 4px;二者不能共用位置或内容。
记录按本地日期分组,每行只显示时间、favicon、标题、域名和操作;完整 URL 不再单独占用第二行。
来源浏览器、profile 和数据类型分别确认。OpenProgram 不读取或修改用户正在使用的源 profile。
浏览器区域分为当前网页、浏览器资料和整个窗口三层。按钮是否常驻由操作频率、当前页面相关性和窄分屏占用共同决定。
| 位置 | 常驻动作 | 窄分屏规则 |
|---|---|---|
| 地址栏左侧 | Back · Forward · Reload/Stop · Home | 520–719px 将 Home 移入 ⋯;低于 520px 再将 Forward 移入 ⋯。Back 与 Reload/Stop 始终保留。 |
| 地址栏 | URL、搜索输入与安全状态;加载期间 Reload 原位变为 Stop。 | 始终占据剩余宽度,最低可用宽度 160px;不换行。 |
| 地址栏右侧 | Bookmark current page · Bookmarks · Open externally · Browser menu | 520–719px 将 Bookmarks 与 Open externally 移入 ⋯;星标和 ⋯ 始终保留。 |
| 地址栏下方 | 用户可选的单行 bookmarks bar,直接显示 Bookmarks bar 的子项;非空的 Other bookmarks / Mobile bookmarks 固定在右侧,末尾是溢出入口。 | 低于 560px 不渲染该行,从 Browser ⋯ 中打开 Bookmarks;禁止水平滚动条。文件夹与溢出菜单的最大高度不得超过当前窗口可用高度,并允许纵向滚动。 |
只放与当前网页直接相关且频繁使用的动作:导航、地址、保存当前页、打开书签、外部打开和 Browser ⋯。
⋯New browser tab、Bookmarks、History、Show bookmarks bar、Import browser data、Clear browsing data、Browser settings。
New pane/window、Pane 布局、OpenProgram Settings、Help 与 About。它不再直接放 Bookmarks、History 或网页级设置。
下面是信息结构验收图。切换状态即可检查控件是否出现在正确层级。
参考产品用于确认可见行为,平台文档用于确认可实现边界。OpenProgram 不复制完整 Chromium importer。
Files、New chat、Browser、Terminal 作为一级内容类型;浏览器控件只在 Browser 内显示。
采用内置浏览器保持自己的 profile。需要既有资料时,由用户明确发起导入。
修改后采用星标保存当前页;书签栏可开关;完整管理器独立存在。OpenProgram 保留三层,但针对分屏定义更严格的收缩规则。
修改后采用内置浏览器保持独立状态,Cookies 与历史清理归桌面 App Settings。OpenProgram 增加 Browser ⋯ 深链,但不复制设置存储。
组件不作为 Electron JavaScript API 暴露,且不提供通用 Cookies import 实现。
不复制renderer 只传递 main 进程签发的 opaque source/profile id。文件路径、源浏览器可执行路径和 Cookie 值都不能通过 renderer 自由指定。
导入不是 profile 迁移。它只复制已选择的数据,并且不承诺所有网站登录态都能恢复。
| 边界 | 约束 | 失败结果 |
|---|---|---|
| renderer → main | source/profile 使用 main 返回的 opaque id;数据类型使用 allowlist;renderer 不能传文件路径或可执行路径。 | 拒绝请求 |
| 源 profile | 只读发现;真实路径必须位于已发现 browser root 内;拒绝符号链接逃逸。 | source_invalid |
| 临时数据 | 目录 0700、文件 0600;成功、失败或超时后都删除;日志只记录来源标签、类型、计数和错误码。 | cleanup + stable error |
| 目标 profile | History 和 Bookmarks 合并;Cookies 通过 Electron API 写入,不替换目标数据库。 | 保留导入前数据 |
| 并发 | 全 App 同时只允许一个导入任务;当前基线不提供执行中取消。 | import_busy |
每项验收都对应一个外部可观察结果。设计状态和实现证据分列,不以文档存在本身证明功能完成。
| 可观察结果 | 当前状态 | 实现证据 |
|---|---|---|
| 新建 Pane 只显示 Files、New chat、Browser、Terminal;四个入口使用同尺寸、不同语义色的圆角图标容器,DOM 中不存在浏览器专属控件。 | 已实现并通过默认 App 深浅主题验收 | new-tab-page.tsx;check-built-in-browser.mjs 的有效级联与语义色 mutation 检查 |
| 选择 Browser 后原位显示与网页页签相同的地址栏和书签栏结构、导入入口和快捷网站;无当前网页语义的动作保持可见但禁用。 | 已实现并通过默认 App 验收 | browser-home-page.tsx;check-built-in-browser.mjs;实际 App 中 toolbar / bookmarks bar 为 40px / 30px |
标准宽度的 Browser toolbar 按顺序显示 Back、Forward、Reload/Stop、Home、地址栏、当前页星标、Bookmarks、外部打开和 Browser ⋯;不显示分屏与 Settings 齿轮。 | 已实现 | web-tab-pane.tsx;check-built-in-browser.mjs;check-web-split.mjs |
Browser ⋯ 提供 Bookmarks、History、书签栏开关、Import、Clear browsing data 和 Browser settings;窗口主菜单只保留 App、窗口与 Pane 操作。桌面弹层按菜单的 scrollWidth/scrollHeight 回报固有尺寸,不能按当前裁剪高度递归缩小。 | 已实现并通过默认 App 弹层验收 | browser-controls.tsx;menu-overlay/context-menu/page.tsx;check-built-in-browser.mjs;实际 Browser 菜单 7 行展开后高度稳定为约 196px,History 动作可点击并打开对应页 |
书签栏默认显示;用户关闭后保持关闭;直接显示 Bookmarks bar 的子项,非空的其他根目录位于右侧;末尾溢出入口可访问被截断的项目。文件夹菜单固定为 280px 宽,标题省略,嵌套文件夹逐级展开;Pane 低于 560px 时隐藏书签栏,但 Bookmarks 页面仍可到达。 | 已实现并通过默认 App 验收 | check-bookmarks.mjs、check-built-in-browser.mjs;默认 profile 中书签栏实际可见,高度 30px |
Bookmarks manager 使用顶部搜索、左侧文件夹树和右侧当前目录列表;普通行只保留 favicon/文件夹图标、标题和 ⋮。左右列表行均为 36px,页头为 52px,窄 Pane 改为上下布局。 | 已实现并通过默认 App 密度验收 | builtin-tab-pane.tsx;center-tabs.module.css;check-bookmarks.mjs;默认 App 实测页头、文件夹行、内容行、搜索框、图标按钮分别为 52 / 36 / 36 / 30 / 28px |
Browser settings 与窗口 Settings 使用同一路由和同一配置源;Browser ⋯ 直接打开 Browser 分区,toolbar 不显示常驻齿轮。 | 已实现 | /settings/browser;browser-settings.tsx;browser-prefs.ts |
| 导入对话框列出来源浏览器、profile 和支持的数据类型;关闭对话框不产生目标变更。 | 已实现 | desktop/main.js 的 browser-import:* IPC;check-built-in-browser.mjs |
| History 按日期分组,至少 1000 条时保持 36–40px 行高,搜索和滚动可用。 | 实现完成,规模验收待补 | web-history.css 为 38px;History 分页上限 5000,搜索在 main 进程完成;存储 self-check 覆盖 5000 条上限,尚未记录 1000 条可见 UI 性能数据。 |
| Bookmarks 保留来源根目录、最多 64 层文件夹和同级顺序;无效 URL 被过滤,重复导入不产生重复 URL 或空文件夹。 | 已实现 | web/lib/bookmarks.ts;check-bookmarks.mjs |
| 窗口主菜单在桌面 App 和 Web 中都与触发按钮右对齐,按钮底部到菜单顶部的间距为 4px。桌面主菜单、Browser 菜单、书签菜单和 tab 右键菜单从 renderer 传入的 CSS 像素坐标必须按发送页面的 zoom factor 转换为 Electron DIP;在 80%、100%、125% 缩放下都保持贴近原触发按钮。 | 已实现 | main-menu.tsx;check-center-tabs.mjs;check-webtab-zoom-bounds.js |
Cookies 只进入 persist:webtabs;IPC、日志、History 和 renderer 不出现 Cookie 值。 | 已实现 | browser-profile-import.js self-check;desktop/main.js |
| 来源损坏、浏览器缺失、临时进程超时和 Cookie 部分失败返回稳定错误码并保留原数据。 | 已实现 | browser-profile-import.js 与 browsing-history-store.js self-check |
| 依赖 PTY 的全屏终端程序以及执行中取消浏览器导入。 | 当前限制 | 产品边界,不作为当前验收缺口。 |
| Passwords、自动填充、支付/地址数据和源浏览器接管。 | 明确排除 | browser-profile-import.js 的导入类型 allowlist。 |
可见验收只使用安装的 /Applications/OpenProgram.app、默认 18100 worker 和 ~/.openprogram。文档更新不改变 Agent 的网页控制协议。
本页是当前设计的规范性说明。实现发生变化时直接更新本页;历史修订由 Git 保存。