From b50149af5d1d533ed9e59bf31ebaa89902999677 Mon Sep 17 00:00:00 2001 From: Virgil Date: Thu, 2 Apr 2026 20:08:42 +0000 Subject: [PATCH] feat(display): support prompt dialogs via webview fallback --- pkg/display/FEATURES.md | 2 +- pkg/display/display.go | 55 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/pkg/display/FEATURES.md b/pkg/display/FEATURES.md index 1683875..a68b70a 100644 --- a/pkg/display/FEATURES.md +++ b/pkg/display/FEATURES.md @@ -143,7 +143,7 @@ This document tracks the implementation of display server features that enable A - [x] `dialog_open_directory` - Show directory picker - [x] `dialog_message` - Show message dialog (info/warning/error) (via notification_show) - [x] `dialog_confirm` - Show confirmation dialog -- [~] `dialog_prompt` - Show input prompt dialog (not supported natively in Wails v3) +- [x] `dialog_prompt` - Show input prompt dialog with a webview fallback when native support is unavailable ### Theme & Appearance - [x] `theme_get` - Get current theme (dark/light) diff --git a/pkg/display/display.go b/pkg/display/display.go index cc3f900..1158cab 100644 --- a/pkg/display/display.go +++ b/pkg/display/display.go @@ -2018,9 +2018,20 @@ func (s *Service) ConfirmDialog(title, message string) (bool, error) { return button == "Yes" || button == "OK", nil } -// PromptDialog shows a prompt-style dialog and returns the selected button. -// Use: button, accepted, err := svc.PromptDialog("Rename file", "Enter a new name") +// PromptDialog shows a prompt-style dialog and returns entered text when the webview +// prompt path is available, otherwise it falls back to a button-based message dialog. +// Use: value, accepted, err := svc.PromptDialog("Rename file", "Enter a new name") func (s *Service) PromptDialog(title, message string) (string, bool, error) { + if text, ok, err := s.promptViaWebView(title, message); err == nil { + if ok { + return text, true, nil + } + return "", false, nil + } + + // Fall back to the native message dialog path when no webview prompt is available. + // The returned error is intentionally ignored unless the fallback also fails. + result, handled, err := s.Core().PERFORM(dialog.TaskMessageDialog{ Opts: dialog.MessageDialogOptions{ Type: dialog.DialogInfo, @@ -2039,6 +2050,46 @@ func (s *Service) PromptDialog(title, message string) (string, bool, error) { return button, button == "OK", nil } +func (s *Service) promptViaWebView(title, message string) (string, bool, error) { + windowName := s.GetFocusedWindow() + if windowName == "" { + infos := s.ListWindowInfos() + if len(infos) > 0 { + windowName = infos[0].Name + } + } + if windowName == "" { + return "", false, fmt.Errorf("no webview window available") + } + + encodedTitle, err := json.Marshal(title) + if err != nil { + return "", false, err + } + encodedMessage, err := json.Marshal(message) + if err != nil { + return "", false, err + } + + result, handled, err := s.Core().PERFORM(webview.TaskEvaluate{ + Window: windowName, + Script: "window.prompt(" + string(encodedTitle) + "," + string(encodedMessage) + ")", + }) + if err != nil { + return "", false, err + } + if !handled { + return "", false, fmt.Errorf("webview service not available") + } + if result == nil { + return "", false, nil + } + if text, ok := result.(string); ok { + return text, true, nil + } + return fmt.Sprint(result), true, nil +} + // DialogMessage shows an informational, warning, or error message via the notification pipeline. // Use: _ = svc.DialogMessage("warning", "Build failed", "Check the log output") func (s *Service) DialogMessage(kind, title, message string) error {