feat: add settings path actions
This commit is contained in:
+1
-1
@@ -27,7 +27,7 @@
|
|||||||
| T-202 | 本地配置持久化和实例恢复 | T-101 | DONE |
|
| T-202 | 本地配置持久化和实例恢复 | T-101 | DONE |
|
||||||
| T-203 | CLI 合约和本地事件推送 | T-103 | DONE |
|
| T-203 | CLI 合约和本地事件推送 | T-103 | DONE |
|
||||||
| T-204 | UI 全状态验收与 Windows 打包 smoke | T-201,T-202,T-203 | DONE |
|
| T-204 | UI 全状态验收与 Windows 打包 smoke | T-201,T-202,T-203 | DONE |
|
||||||
| T-205 | 设置路径字段增加 Label、选择和搜索操作 | T-201 | TODO |
|
| T-205 | 设置路径字段增加 Label、选择和搜索操作 | T-201 | DONE |
|
||||||
|
|
||||||
## Backlog
|
## Backlog
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,11 @@
|
|||||||
## 快照
|
## 快照
|
||||||
|
|
||||||
- 日期:2026-07-22
|
- 日期:2026-07-22
|
||||||
- 阶段:Phase 2 产品外壳(T-201 至 T-204 已完成)
|
- 阶段:Phase 2 产品外壳(T-201 至 T-205 已完成)
|
||||||
- 代码:已建立 Go module `chub`、`cmd/chub` 入口、logging 测试基座、浏览器 domain/application 合约、Chrome/Edge 参数/发现模块、启动 registry、Windows 身份/占用检查、优雅关闭、Job Object、真实 Chrome/Edge smoke、JSON 配置存储、启动恢复、CLI JSON 合约、应用内事件总线、UI 状态测试和 Windows smoke 脚本,T-001 至 T-003、T-101 至 T-104、T-201 至 T-204 已完成
|
- 代码:已建立 Go module `chub`、`cmd/chub` 入口、logging 测试基座、浏览器 domain/application 合约、Chrome/Edge 参数/发现模块、启动 registry、Windows 身份/占用检查、优雅关闭、Job Object、真实 Chrome/Edge smoke、JSON 配置存储、启动恢复、CLI JSON 合约、应用内事件总线、UI 状态测试和 Windows smoke 脚本,T-001 至 T-003、T-101 至 T-104、T-201 至 T-205 已完成
|
||||||
- UI:已接入 Gio v0.10.1 双页桌面壳,设置保存异步写入本地配置,启动时恢复设置和已保存实例;CLI `list/events` 已可用,`start/stop/restart` 等待 BrowserManager adapter
|
- UI:已接入 Gio v0.10.1 双页桌面壳;设置页四个路径字段均有 Label、输入框、选择按钮和搜索按钮,并提供操作反馈;CLI `list/events` 已可用,`start/stop/restart` 等待 BrowserManager adapter
|
||||||
- 浏览器核心:设计参考来自 `D:\OPC\shop_helm\internal\platform\chrome`,尚未复制或接入本项目
|
- 浏览器核心:设计参考来自 `D:\OPC\shop_helm\internal\platform\chrome`,尚未复制或接入本项目
|
||||||
- blocker:无;下一个任务为 T-205(设置路径字段增加 Label、选择和搜索操作)。
|
- blocker:无;下一步可进入 BrowserManager application adapter 和真实 UI 交互接线。
|
||||||
|
|
||||||
## 当前目录
|
## 当前目录
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -3,7 +3,7 @@ id: T-205
|
|||||||
title: 设置路径字段增加 Label、选择和搜索操作
|
title: 设置路径字段增加 Label、选择和搜索操作
|
||||||
phase: 2
|
phase: 2
|
||||||
deps: [T-201]
|
deps: [T-201]
|
||||||
status: TODO
|
status: DONE
|
||||||
created: 2026-07-22
|
created: 2026-07-22
|
||||||
owner: codex
|
owner: codex
|
||||||
---
|
---
|
||||||
@@ -28,8 +28,8 @@ owner: codex
|
|||||||
|
|
||||||
## 执行记录
|
## 执行记录
|
||||||
|
|
||||||
- 状态:TODO
|
- 状态:DONE
|
||||||
- 变更:先建立任务文档和路线图记录。
|
- 变更:设置页四个路径字段统一增加 Label、输入框、“选择”和“搜索”按钮;每个操作使用独立的持久 Clickable,并在页面中显示文字反馈。
|
||||||
- 验证:待实现。
|
- 验证:`gofmt`、`go test ./...`、`go vet ./...`、`go build -o build/chub.exe ./cmd/chub` 均通过。
|
||||||
- 阻塞:无。
|
- 阻塞:无。
|
||||||
- 残余风险:原生选择器和真实搜索需要后续 platform adapter。
|
- 残余风险:当前选择/搜索按钮完成 UI 反馈,原生 Windows 文件选择器和真实磁盘搜索需要后续异步 platform adapter。
|
||||||
|
|||||||
+54
-4
@@ -48,6 +48,14 @@ type Shell struct {
|
|||||||
backClick widget.Clickable
|
backClick widget.Clickable
|
||||||
chromeKind widget.Clickable
|
chromeKind widget.Clickable
|
||||||
edgeKind widget.Clickable
|
edgeKind widget.Clickable
|
||||||
|
chromePick widget.Clickable
|
||||||
|
chromeSearch widget.Clickable
|
||||||
|
edgePick widget.Clickable
|
||||||
|
edgeSearch widget.Clickable
|
||||||
|
dataPick widget.Clickable
|
||||||
|
dataSearch widget.Clickable
|
||||||
|
logPick widget.Clickable
|
||||||
|
logSearch widget.Clickable
|
||||||
saveClick widget.Clickable
|
saveClick widget.Clickable
|
||||||
cancelClick widget.Clickable
|
cancelClick widget.Clickable
|
||||||
|
|
||||||
@@ -60,6 +68,7 @@ type Shell struct {
|
|||||||
instanceDir widget.Editor
|
instanceDir widget.Editor
|
||||||
instanceURL widget.Editor
|
instanceURL widget.Editor
|
||||||
newBrowser string
|
newBrowser string
|
||||||
|
pathFeedback string
|
||||||
|
|
||||||
list widget.List
|
list widget.List
|
||||||
rows []InstanceRow
|
rows []InstanceRow
|
||||||
@@ -187,6 +196,30 @@ func statusLabel(theme *material.Theme, status string) layout.Widget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Shell) settings(gtx layout.Context) layout.Dimensions {
|
func (s *Shell) settings(gtx layout.Context) layout.Dimensions {
|
||||||
|
for s.chromePick.Clicked(gtx) {
|
||||||
|
s.pathFeedback = "请选择 Chrome 可执行文件"
|
||||||
|
}
|
||||||
|
for s.chromeSearch.Clicked(gtx) {
|
||||||
|
s.pathFeedback = "正在搜索 Chrome 可执行文件…"
|
||||||
|
}
|
||||||
|
for s.edgePick.Clicked(gtx) {
|
||||||
|
s.pathFeedback = "请选择 Edge 可执行文件"
|
||||||
|
}
|
||||||
|
for s.edgeSearch.Clicked(gtx) {
|
||||||
|
s.pathFeedback = "正在搜索 Edge 可执行文件…"
|
||||||
|
}
|
||||||
|
for s.dataPick.Clicked(gtx) {
|
||||||
|
s.pathFeedback = "请选择默认 User Data Dir"
|
||||||
|
}
|
||||||
|
for s.dataSearch.Clicked(gtx) {
|
||||||
|
s.pathFeedback = "正在搜索默认 User Data Dir…"
|
||||||
|
}
|
||||||
|
for s.logPick.Clicked(gtx) {
|
||||||
|
s.pathFeedback = "请选择日志目录"
|
||||||
|
}
|
||||||
|
for s.logSearch.Clicked(gtx) {
|
||||||
|
s.pathFeedback = "正在搜索日志目录…"
|
||||||
|
}
|
||||||
for s.saveClick.Clicked(gtx) {
|
for s.saveClick.Clicked(gtx) {
|
||||||
if s.onSave != nil {
|
if s.onSave != nil {
|
||||||
s.onSave(SettingsState{ChromePath: s.chromePath.Text(), EdgePath: s.edgePath.Text(), DefaultDir: s.dataDir.Text(), LogDir: s.logDir.Text(), CloseOnExit: s.closeOnExit.Value})
|
s.onSave(SettingsState{ChromePath: s.chromePath.Text(), EdgePath: s.edgePath.Text(), DefaultDir: s.dataDir.Text(), LogDir: s.logDir.Text(), CloseOnExit: s.closeOnExit.Value})
|
||||||
@@ -199,13 +232,15 @@ func (s *Shell) settings(gtx layout.Context) layout.Dimensions {
|
|||||||
layout.Rigid(material.H4(s.theme, "设置").Layout),
|
layout.Rigid(material.H4(s.theme, "设置").Layout),
|
||||||
layout.Rigid(material.Body1(s.theme, "配置浏览器可执行文件、默认目录和本地运行行为").Layout),
|
layout.Rigid(material.Body1(s.theme, "配置浏览器可执行文件、默认目录和本地运行行为").Layout),
|
||||||
layout.Rigid(layout.Spacer{Height: unit.Dp(18)}.Layout),
|
layout.Rigid(layout.Spacer{Height: unit.Dp(18)}.Layout),
|
||||||
layout.Rigid(material.Editor(s.theme, &s.chromePath, "Chrome 可执行文件").Layout),
|
layout.Rigid(s.pathField("Chrome 可执行文件", &s.chromePath, &s.chromePick, &s.chromeSearch)),
|
||||||
layout.Rigid(layout.Spacer{Height: unit.Dp(10)}.Layout),
|
layout.Rigid(layout.Spacer{Height: unit.Dp(10)}.Layout),
|
||||||
layout.Rigid(material.Editor(s.theme, &s.edgePath, "Edge 可执行文件").Layout),
|
layout.Rigid(s.pathField("Edge 可执行文件", &s.edgePath, &s.edgePick, &s.edgeSearch)),
|
||||||
layout.Rigid(layout.Spacer{Height: unit.Dp(10)}.Layout),
|
layout.Rigid(layout.Spacer{Height: unit.Dp(10)}.Layout),
|
||||||
layout.Rigid(material.Editor(s.theme, &s.dataDir, "默认 User Data Dir").Layout),
|
layout.Rigid(s.pathField("默认 User Data Dir", &s.dataDir, &s.dataPick, &s.dataSearch)),
|
||||||
layout.Rigid(layout.Spacer{Height: unit.Dp(10)}.Layout),
|
layout.Rigid(layout.Spacer{Height: unit.Dp(10)}.Layout),
|
||||||
layout.Rigid(material.Editor(s.theme, &s.logDir, "日志目录").Layout),
|
layout.Rigid(s.pathField("日志目录", &s.logDir, &s.logPick, &s.logSearch)),
|
||||||
|
layout.Rigid(layout.Spacer{Height: unit.Dp(6)}.Layout),
|
||||||
|
layout.Rigid(material.Caption(s.theme, s.pathFeedback).Layout),
|
||||||
layout.Rigid(layout.Spacer{Height: unit.Dp(10)}.Layout),
|
layout.Rigid(layout.Spacer{Height: unit.Dp(10)}.Layout),
|
||||||
layout.Rigid(material.CheckBox(s.theme, &s.closeOnExit, "退出时关闭托管浏览器").Layout),
|
layout.Rigid(material.CheckBox(s.theme, &s.closeOnExit, "退出时关闭托管浏览器").Layout),
|
||||||
layout.Rigid(layout.Spacer{Height: unit.Dp(16)}.Layout),
|
layout.Rigid(layout.Spacer{Height: unit.Dp(16)}.Layout),
|
||||||
@@ -219,6 +254,21 @@ func (s *Shell) settings(gtx layout.Context) layout.Dimensions {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Shell) pathField(label string, editor *widget.Editor, pick, search *widget.Clickable) layout.Widget {
|
||||||
|
return func(gtx layout.Context) layout.Dimensions {
|
||||||
|
return layout.Flex{Alignment: layout.Middle}.Layout(gtx,
|
||||||
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
|
return layout.Inset{Right: unit.Dp(12)}.Layout(gtx, material.Body2(s.theme, label).Layout)
|
||||||
|
}),
|
||||||
|
layout.Flexed(1, material.Editor(s.theme, editor, "请输入或粘贴路径").Layout),
|
||||||
|
layout.Rigid(layout.Spacer{Width: unit.Dp(8)}.Layout),
|
||||||
|
layout.Rigid(material.Button(s.theme, pick, "选择").Layout),
|
||||||
|
layout.Rigid(layout.Spacer{Width: unit.Dp(6)}.Layout),
|
||||||
|
layout.Rigid(material.Button(s.theme, search, "搜索").Layout),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Shell) createInstance(gtx layout.Context) layout.Dimensions {
|
func (s *Shell) createInstance(gtx layout.Context) layout.Dimensions {
|
||||||
for s.chromeKind.Clicked(gtx) {
|
for s.chromeKind.Clicked(gtx) {
|
||||||
s.newBrowser = "Chrome"
|
s.newBrowser = "Chrome"
|
||||||
|
|||||||
Reference in New Issue
Block a user