diff --git a/README.md b/README.md index 1bcf04f..90c47ec 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ go run ./cmd/updata_hfb 启动后会打开窗口: +- 上方“连接配置”默认折叠,填写过的内容会自动记住 - `服务器`:默认 `http://127.0.0.1:8080` - `上传人`:对应服务端的 `uploaderName` - `上传密钥`:服务端外部上传密钥,未配置可留空 diff --git a/internal/app/gui.go b/internal/app/gui.go index d7405c0..190529c 100644 --- a/internal/app/gui.go +++ b/internal/app/gui.go @@ -41,41 +41,38 @@ AWM子弹数量:80 func Run() { a := fyneapp.NewWithID("com.hfb.updata") w := a.NewWindow("哈夫币外部上传") - w.Resize(fyne.NewSize(920, 760)) + w.Resize(fyne.NewSize(980, 880)) + prefs := a.Preferences() serverEntry := widget.NewEntry() - serverEntry.SetText(envDefault("HFB_SERVER", "http://127.0.0.1:8080")) + serverEntry.SetText(prefStringWithFallback(prefs, "server", envDefault("HFB_SERVER", "http://127.0.0.1:8080"))) serverEntry.SetPlaceHolder("例如:http://127.0.0.1:8080") uploaderEntry := widget.NewEntry() - uploaderEntry.SetText(strings.TrimSpace(os.Getenv("HFB_UPLOADER_NAME"))) + uploaderEntry.SetText(prefStringWithFallback(prefs, "uploader", strings.TrimSpace(os.Getenv("HFB_UPLOADER_NAME")))) uploaderEntry.SetPlaceHolder("后台上传管理员名称") secretEntry := widget.NewEntry() secretEntry.Password = true - secretEntry.SetText(strings.TrimSpace(os.Getenv("HFB_UPLOAD_SECRET"))) + secretEntry.SetText(prefStringWithFallback(prefs, "secret", strings.TrimSpace(os.Getenv("HFB_UPLOAD_SECRET")))) secretEntry.SetPlaceHolder("未配置密钥可留空") timeoutEntry := widget.NewEntry() - timeoutEntry.SetText("15s") + timeoutEntry.SetText(prefStringWithFallback(prefs, "timeout", "15s")) timeoutEntry.SetPlaceHolder("例如:15s") dataEntry := widget.NewMultiLineEntry() dataEntry.Wrapping = fyne.TextWrapWord - dataEntry.SetMinRowsVisible(18) + dataEntry.SetMinRowsVisible(14) dataEntry.SetPlaceHolder(sampleText) - resultEntry := widget.NewMultiLineEntry() - resultEntry.Wrapping = fyne.TextWrapWord - resultEntry.SetMinRowsVisible(8) - resultEntry.Disable() + resultView := widget.NewRichTextWithText("") + resultView.Wrapping = fyne.TextWrapWord statusLabel := widget.NewLabel("准备就绪") setResult := func(text string) { - resultEntry.Enable() - resultEntry.SetText(text) - resultEntry.Disable() + resultView.ParseMarkdown("```json\n" + strings.TrimSpace(text) + "\n```") } setBusy := func(uploadBtn *widget.Button, previewBtn *widget.Button, busy bool) { if busy { @@ -111,17 +108,6 @@ func Run() { }, w) }) - sampleBtn := widget.NewButton("填入示例", func() { - dataEntry.SetText(sampleText) - statusLabel.SetText("已填入示例数据") - }) - - clearBtn := widget.NewButton("清空", func() { - dataEntry.SetText("") - setResult("") - statusLabel.SetText("已清空") - }) - previewBtn = widget.NewButton("预览 JSON", func() { req, err := buildRequest(uploaderEntry.Text, dataEntry.Text) if err != nil { @@ -182,26 +168,34 @@ func Run() { }) uploadBtn.Importance = widget.HighImportance - form := widget.NewForm( + serverEntry.OnChanged = func(s string) { prefs.SetString("server", strings.TrimSpace(s)) } + uploaderEntry.OnChanged = func(s string) { prefs.SetString("uploader", strings.TrimSpace(s)) } + secretEntry.OnChanged = func(s string) { prefs.SetString("secret", strings.TrimSpace(s)) } + timeoutEntry.OnChanged = func(s string) { prefs.SetString("timeout", strings.TrimSpace(s)) } + + configForm := widget.NewForm( widget.NewFormItem("服务器", serverEntry), widget.NewFormItem("上传人", uploaderEntry), widget.NewFormItem("上传密钥", secretEntry), widget.NewFormItem("超时时间", timeoutEntry), ) - toolbar := container.NewHBox(loadBtn, sampleBtn, clearBtn, previewBtn, uploadBtn) + configAccordion := widget.NewAccordion( + widget.NewAccordionItem("连接配置", configForm), + ) + configAccordion.Close(0) + toolbar := container.NewHBox(loadBtn, previewBtn, uploadBtn) content := container.NewBorder( nil, container.NewVBox(statusLabel), nil, nil, container.NewVScroll(container.NewVBox( - widget.NewLabel("连接配置"), - form, + configAccordion, toolbar, widget.NewLabel("账号数据"), dataEntry, widget.NewLabel("结果"), - resultEntry, + newMinHeightScroll(resultView, 420), )), ) @@ -234,3 +228,41 @@ func envDefault(key string, fallback string) string { } return value } + +func prefStringWithFallback(prefs fyne.Preferences, key, fallback string) string { + if prefs == nil { + return fallback + } + value := strings.TrimSpace(prefs.String(key)) + if value != "" { + return value + } + return fallback +} + +type minHeightScroll struct { + widget.BaseWidget + scroll fyne.CanvasObject + minHeight float32 +} + +func newMinHeightScroll(content fyne.CanvasObject, minHeight float32) *minHeightScroll { + panel := &minHeightScroll{ + scroll: container.NewVScroll(content), + minHeight: minHeight, + } + panel.ExtendBaseWidget(panel) + return panel +} + +func (p *minHeightScroll) CreateRenderer() fyne.WidgetRenderer { + return widget.NewSimpleRenderer(p.scroll) +} + +func (p *minHeightScroll) MinSize() fyne.Size { + size := p.scroll.MinSize() + if size.Height < p.minHeight { + size.Height = p.minHeight + } + return size +}