wails/v3/examples/dialogs/main.go
Lea Anthony 84b9021ea9
docs: Update dialogs documentation to match actual v3 API (#4793)
* All the documentation files have been updated. Here's a summary of the changes I made:

## Summary of Documentation Updates

### Key API Corrections Made:

1. **Dialog Creation**:
   - Changed `app.InfoDialog()` → `application.InfoDialog()` (package-level functions)
   - Also documented `app.Dialog.Info()` via DialogManager

2. **Question Dialog Buttons**:
   - Removed non-existent `SetButtons("Save", "Don't Save", "Cancel")` method
   - Now uses `AddButton("label")` which returns a `*Button`
   - Button callbacks via `button.OnClick(func() { ... })`

3. **Default/Cancel Buttons**:
   - Changed `SetDefaultButton("Cancel")` (string) → `SetDefaultButton(cancelBtn)` (`*Button`)
   - Changed `SetCancelButton("Cancel")` (string) → `SetCancelButton(cancelBtn)` (`*Button`)
   - Also documented fluent `SetAsDefault()` and `SetAsCancel()` methods on Button

4. **File Dialog Filters**:
   - Changed `SetFilters([]application.FileFilter{...})` → `AddFilter("Display Name", "*.ext;*.ext2")`

5. **Save Dialog Filename**:
   - Changed `SetDefaultFilename()` → `SetFilename()`

6. **Folder Selection**:
   - Removed non-existent `app.SelectFolderDialog()`
   - Now uses `application.OpenFileDialog().CanChooseDirectories(true).CanChooseFiles(false)`

7. **Show() Return Value**:
   - Removed incorrect `result, err := dialog.Show()` pattern
   - `Show()` returns nothing - responses are handled via button callbacks

### Files Modified:
- `docs/src/content/docs/features/dialogs/message.mdx` - Complete rewrite of question dialog examples
- `docs/src/content/docs/features/dialogs/overview.mdx` - Updated all code examples
- `docs/src/content/docs/features/dialogs/file.mdx` - Updated file dialog examples
- `v3/UNRELEASED_CHANGELOG.md` - Added changelog entry

* All changes are complete. Here's a summary of what was updated:

## Summary

I've updated the Wails v3 dialogs documentation to match the actual API. The documentation now consistently uses:

### DialogManager Pattern (Recommended)
- `app.Dialog.Info()`, `app.Dialog.Question()`, `app.Dialog.Warning()`, `app.Dialog.Error()`
- `app.Dialog.OpenFile()`, `app.Dialog.SaveFile()`

This is consistent with other runtime features like `app.Window`, `app.Event`, etc.

### Key API Corrections

1. **Dialog Creation**: Both `app.Dialog.*()` (DialogManager) and `application.*Dialog()` (package-level) are documented
2. **Question Dialog Buttons**: Use `AddButton("label")` which returns `*Button`, then `button.OnClick(callback)`
3. **Default/Cancel Buttons**: `SetDefaultButton(button)` and `SetCancelButton(button)` take `*Button` pointers
4. **File Filters**: Use `AddFilter("Display Name", "*.ext")` instead of `SetFilters()`
5. **Save Dialog Filename**: Use `SetFilename()` instead of `SetDefaultFilename()`
6. **Folder Selection**: Use `app.Dialog.OpenFile().CanChooseDirectories(true).CanChooseFiles(false)`

### Files Modified
- `docs/src/content/docs/features/dialogs/overview.mdx`
- `docs/src/content/docs/features/dialogs/message.mdx`
- `docs/src/content/docs/features/dialogs/file.mdx`
- `v3/UNRELEASED_CHANGELOG.md`

* Audit complete! All documentation files now consistently use `app.Dialog.*` for all code examples. Here's the summary:

## Audit Complete

All dialog documentation has been updated to consistently use the `app.Dialog.*` pattern:

### Changes Made:

**message.mdx:**
- All examples now use `app.Dialog.Info()`, `app.Dialog.Question()`, `app.Dialog.Warning()`, `app.Dialog.Error()`
- Function signatures updated to accept `app *application.App` parameter
- Nested dialog calls within callbacks also updated

**file.mdx:**
- All examples now use `app.Dialog.OpenFile()`, `app.Dialog.SaveFile()`
- Function signatures updated to accept `app *application.App` parameter
- All error/info dialogs within file operations also updated

**overview.mdx:**
- Already consistent from earlier edits

### Documentation Structure:
Each file now properly documents both approaches in a dedicated section:

```go
// Via DialogManager (recommended when you have an app instance):
app.Dialog.Info()
app.Dialog.OpenFile()

// Package-level functions (useful in callbacks or when app isn't in scope):
application.InfoDialog()
application.OpenFileDialog()
```

But all code examples use the `app.Dialog.*` pattern for consistency with other runtime features like `app.Window`, `app.Event`, etc.

* docs: Fix reference/dialogs.mdx and reference/application.mdx API documentation

Updated docs to match actual Wails v3 Dialogs API:

- reference/dialogs.mdx: Complete rewrite with correct API
  - Use `app.Dialog.OpenFile()` and `app.Dialog.SaveFile()` instead of `app.OpenFileDialog()`
  - Use `AddFilter("name", "pattern")` instead of `SetFilters([]FileFilter{...})`
  - Use `SetFilename()` instead of `SetDefaultFilename()`
  - Use `SetDirectory()` instead of `SetDefaultDirectory()`
  - Remove non-existent `SelectFolderDialog()` - use `OpenFile().CanChooseDirectories(true).CanChooseFiles(false)`
  - Use `AddButton()` with callbacks instead of `SetButtons()`
  - Use `SetDefaultButton(*Button)` instead of `SetDefaultButton(int)`
  - Document that `Show()` returns nothing, use callbacks

- reference/application.mdx: Fix Dialog Methods section
  - Use `app.Dialog.*` manager pattern
  - Show correct Question dialog with button callbacks
  - Fix file dialog examples with `AddFilter()`
  - Remove `SelectFolderDialog()` reference

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* docs: Remove package-level dialog function references

Remove all references to package-level dialog functions
(application.InfoDialog(), application.OpenFileDialog(), etc.)
from documentation. Only the app.Dialog manager pattern
should be used.

Updated files:
- reference/dialogs.mdx
- features/dialogs/overview.mdx
- features/dialogs/message.mdx
- features/dialogs/file.mdx

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* refactor: Remove package-level dialog functions in favor of app.Dialog manager

BREAKING CHANGE: Remove package-level dialog functions. Use app.Dialog manager instead.

Removed functions:
- application.InfoDialog()
- application.QuestionDialog()
- application.WarningDialog()
- application.ErrorDialog()
- application.OpenFileDialog()
- application.SaveFileDialog()

Use the Dialog manager pattern instead:
- app.Dialog.Info()
- app.Dialog.Question()
- app.Dialog.Warning()
- app.Dialog.Error()
- app.Dialog.OpenFile()
- app.Dialog.SaveFile()

This aligns dialogs with other runtime managers like app.Window and app.Event.

Updated files:
- v3/pkg/application/application.go - Remove exported dialog functions
- v3/pkg/application/dialog_manager.go - Use internal newMessageDialog/newOpenFileDialog
- v3/pkg/application/messageprocessor_dialog.go - Use internal dialog constructors
- v3/examples/* - Update all examples to use app.Dialog pattern
- v3/internal/commands/appimage_testfiles/main.go - Update test file
- v3/UNRELEASED_CHANGELOG.md - Document breaking change

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: Use application.Get() in dialogs-basic example and correct filter docs

- Update dialogs-basic helper functions to use application.Get() instead
  of passing app through function parameters
- Fix incorrect documentation claiming space/comma delimiters work for
  filter patterns (only semicolons are supported)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-16 06:05:40 +11:00

362 lines
11 KiB
Go

package main
import (
_ "embed"
"log"
"log/slog"
"os"
"runtime"
"strings"
"github.com/wailsapp/wails/v3/pkg/icons"
"github.com/wailsapp/wails/v3/pkg/application"
)
func main() {
app := application.New(application.Options{
Name: "Dialogs Demo",
Description: "A demo of the dialogs API",
Assets: application.AlphaAssets,
Logger: application.DefaultLogger(slog.LevelDebug),
Mac: application.MacOptions{
ApplicationShouldTerminateAfterLastWindowClosed: true,
},
})
// Create a custom menu
menu := app.NewMenu()
menu.AddRole(application.AppMenu)
menu.AddRole(application.EditMenu)
menu.AddRole(application.WindowMenu)
menu.AddRole(application.ServicesMenu)
menu.AddRole(application.HelpMenu)
// Let's make a "Demo" menu
infoMenu := menu.AddSubmenu("Info")
infoMenu.Add("Info").OnClick(func(ctx *application.Context) {
dialog := app.Dialog.Info()
dialog.SetTitle("Custom Title")
dialog.SetMessage("This is a custom message")
dialog.Show()
})
infoMenu.Add("Info (Title only)").OnClick(func(ctx *application.Context) {
dialog := app.Dialog.Info()
dialog.SetTitle("Custom Title")
dialog.Show()
})
infoMenu.Add("Info (Message only)").OnClick(func(ctx *application.Context) {
dialog := app.Dialog.Info()
dialog.SetMessage("This is a custom message")
dialog.Show()
})
infoMenu.Add("Info (Custom Icon)").OnClick(func(ctx *application.Context) {
dialog := app.Dialog.Info()
dialog.SetTitle("Custom Icon Example")
dialog.SetMessage("Using a custom icon")
dialog.SetIcon(icons.ApplicationDarkMode256)
dialog.Show()
})
infoMenu.Add("About").OnClick(func(ctx *application.Context) {
app.Menu.ShowAbout()
})
questionMenu := menu.AddSubmenu("Question")
questionMenu.Add("Question (No default)").OnClick(func(ctx *application.Context) {
dialog := app.Dialog.Question()
dialog.SetMessage("No default button")
dialog.AddButton("Yes")
dialog.AddButton("No")
dialog.Show()
})
questionMenu.Add("Question (Attached to Window)").OnClick(func(ctx *application.Context) {
dialog := app.Dialog.Question()
dialog.AttachToWindow(app.Window.Current())
dialog.SetMessage("No default button")
dialog.AddButton("Yes")
dialog.AddButton("No")
dialog.Show()
})
questionMenu.Add("Question (With Default)").OnClick(func(ctx *application.Context) {
dialog := app.Dialog.Question()
dialog.SetTitle("Quit")
dialog.SetMessage("You have unsaved work. Are you sure you want to quit?")
dialog.AddButton("Yes").OnClick(func() {
app.Quit()
})
no := dialog.AddButton("No")
dialog.SetDefaultButton(no)
dialog.Show()
})
questionMenu.Add("Question (With Cancel)").OnClick(func(ctx *application.Context) {
dialog := app.Dialog.Question().
SetTitle("Update").
SetMessage("The cancel button is selected when pressing escape")
download := dialog.AddButton("📥 Download")
download.OnClick(func() {
app.Dialog.Info().SetMessage("Downloading...").Show()
})
no := dialog.AddButton("Cancel")
dialog.SetDefaultButton(download)
dialog.SetCancelButton(no)
dialog.Show()
})
questionMenu.Add("Question (Custom Icon)").OnClick(func(ctx *application.Context) {
dialog := app.Dialog.Question()
dialog.SetTitle("Custom Icon Example")
dialog.SetMessage("Using a custom icon")
dialog.SetIcon(icons.WailsLogoWhiteTransparent)
likeIt := dialog.AddButton("I like it!").OnClick(func() {
app.Dialog.Info().SetMessage("Thanks!").Show()
})
dialog.AddButton("Not so keen...").OnClick(func() {
app.Dialog.Info().SetMessage("Too bad!").Show()
})
dialog.SetDefaultButton(likeIt)
dialog.Show()
})
warningMenu := menu.AddSubmenu("Warning")
warningMenu.Add("Warning").OnClick(func(ctx *application.Context) {
app.Dialog.Warning().
SetTitle("Custom Title").
SetMessage("This is a custom message").
Show()
})
warningMenu.Add("Warning (Title only)").OnClick(func(ctx *application.Context) {
dialog := app.Dialog.Warning()
dialog.SetTitle("Custom Title")
dialog.Show()
})
warningMenu.Add("Warning (Message only)").OnClick(func(ctx *application.Context) {
dialog := app.Dialog.Warning()
dialog.SetMessage("This is a custom message")
dialog.Show()
})
warningMenu.Add("Warning (Custom Icon)").OnClick(func(ctx *application.Context) {
dialog := app.Dialog.Warning()
dialog.SetTitle("Custom Icon Example")
dialog.SetMessage("Using a custom icon")
dialog.SetIcon(icons.ApplicationLightMode256)
dialog.Show()
})
errorMenu := menu.AddSubmenu("Error")
errorMenu.Add("Error").OnClick(func(ctx *application.Context) {
dialog := app.Dialog.Error()
dialog.SetTitle("Ooops")
dialog.SetMessage("I accidentally the whole of Twitter")
dialog.Show()
})
errorMenu.Add("Error (Title Only)").OnClick(func(ctx *application.Context) {
dialog := app.Dialog.Error()
dialog.SetTitle("Custom Title")
dialog.Show()
})
errorMenu.Add("Error (Custom Message)").OnClick(func(ctx *application.Context) {
app.Dialog.Error().
SetMessage("This is a custom message").
Show()
})
errorMenu.Add("Error (Custom Icon)").OnClick(func(ctx *application.Context) {
dialog := app.Dialog.Error()
dialog.SetTitle("Custom Icon Example")
dialog.SetMessage("Using a custom icon")
dialog.SetIcon(icons.WailsLogoWhite)
dialog.Show()
})
openMenu := menu.AddSubmenu("Open")
openMenu.Add("Open File").OnClick(func(ctx *application.Context) {
result, _ := app.Dialog.OpenFile().
CanChooseFiles(true).
PromptForSingleSelection()
if result != "" {
app.Dialog.Info().SetMessage(result).Show()
} else {
app.Dialog.Info().SetMessage("No file selected").Show()
}
})
openMenu.Add("Open File (Show Hidden Files)").OnClick(func(ctx *application.Context) {
result, _ := app.Dialog.OpenFile().
CanChooseFiles(true).
CanCreateDirectories(true).
ShowHiddenFiles(true).
PromptForSingleSelection()
if result != "" {
app.Dialog.Info().SetMessage(result).Show()
} else {
app.Dialog.Info().SetMessage("No file selected").Show()
}
})
openMenu.Add("Open File (Attach to window)").OnClick(func(ctx *application.Context) {
result, _ := app.Dialog.OpenFile().
CanChooseFiles(true).
CanCreateDirectories(true).
ShowHiddenFiles(true).
AttachToWindow(app.Window.Current()).
PromptForSingleSelection()
if result != "" {
app.Dialog.Info().SetMessage(result).Show()
} else {
app.Dialog.Info().SetMessage("No file selected").Show()
}
})
openMenu.Add("Open Multiple Files (Show Hidden Files)").OnClick(func(ctx *application.Context) {
result, _ := app.Dialog.OpenFile().
CanChooseFiles(true).
CanCreateDirectories(true).
ShowHiddenFiles(true).
PromptForMultipleSelection()
if len(result) > 0 {
app.Dialog.Info().SetMessage(strings.Join(result, ",")).Show()
} else {
app.Dialog.Info().SetMessage("No file selected").Show()
}
})
openMenu.Add("Open Directory").OnClick(func(ctx *application.Context) {
result, _ := app.Dialog.OpenFile().
CanChooseDirectories(true).
CanChooseFiles(false).
PromptForSingleSelection()
if result != "" {
app.Dialog.Info().SetMessage(result).Show()
} else {
app.Dialog.Info().SetMessage("No directory selected").Show()
}
})
openMenu.Add("Open Directory (Create Directories)").OnClick(func(ctx *application.Context) {
result, _ := app.Dialog.OpenFile().
CanChooseDirectories(true).
CanCreateDirectories(true).
CanChooseFiles(false).
PromptForSingleSelection()
if result != "" {
app.Dialog.Info().SetMessage(result).Show()
} else {
app.Dialog.Info().SetMessage("No directory selected").Show()
}
})
openMenu.Add("Open Directory (Resolves Aliases)").OnClick(func(ctx *application.Context) {
result, _ := app.Dialog.OpenFile().
CanChooseDirectories(true).
CanCreateDirectories(true).
CanChooseFiles(false).
ResolvesAliases(true).
PromptForSingleSelection()
if result != "" {
app.Dialog.Info().SetMessage(result).Show()
} else {
app.Dialog.Info().SetMessage("No directory selected").Show()
}
})
openMenu.Add("Open File/Directory (Set Title)").OnClick(func(ctx *application.Context) {
dialog := app.Dialog.OpenFile().
CanChooseDirectories(true).
CanCreateDirectories(true).
ResolvesAliases(true)
if runtime.GOOS == "darwin" {
dialog.SetMessage("Select a file/directory")
} else {
dialog.SetTitle("Select a file/directory")
}
result, _ := dialog.PromptForSingleSelection()
if result != "" {
app.Dialog.Info().SetMessage(result).Show()
} else {
app.Dialog.Info().SetMessage("No file/directory selected").Show()
}
})
openMenu.Add("Open (Full Example)").OnClick(func(ctx *application.Context) {
cwd, _ := os.Getwd()
dialog := app.Dialog.OpenFile().
SetTitle("Select a file").
SetMessage("Select a file to open").
SetButtonText("Let's do this!").
SetDirectory(cwd).
CanCreateDirectories(true).
ResolvesAliases(true).
AllowsOtherFileTypes(true).
TreatsFilePackagesAsDirectories(true).
ShowHiddenFiles(true).
CanSelectHiddenExtension(true).
AddFilter("Text Files", "*.txt; *.md").
AddFilter("Video Files", "*.mov; *.mp4; *.avi")
if runtime.GOOS == "darwin" {
dialog.SetMessage("Select a file")
} else {
dialog.SetTitle("Select a file")
}
result, _ := dialog.PromptForSingleSelection()
if result != "" {
app.Dialog.Info().SetMessage(result).Show()
} else {
app.Dialog.Info().SetMessage("No file selected").Show()
}
})
saveMenu := menu.AddSubmenu("Save")
saveMenu.Add("Select File (Defaults)").OnClick(func(ctx *application.Context) {
result, _ := app.Dialog.SaveFile().
PromptForSingleSelection()
if result != "" {
app.Dialog.Info().SetMessage(result).Show()
}
})
saveMenu.Add("Select File (Attach To WebviewWindow)").OnClick(func(ctx *application.Context) {
result, _ := app.Dialog.SaveFile().
AttachToWindow(app.Window.Current()).
PromptForSingleSelection()
if result != "" {
app.Dialog.Info().SetMessage(result).Show()
}
})
saveMenu.Add("Select File (Show Hidden Files)").OnClick(func(ctx *application.Context) {
result, _ := app.Dialog.SaveFile().
ShowHiddenFiles(true).
PromptForSingleSelection()
if result != "" {
app.Dialog.Info().SetMessage(result).Show()
}
})
saveMenu.Add("Select File (Cannot Create Directories)").OnClick(func(ctx *application.Context) {
result, _ := app.Dialog.SaveFile().
CanCreateDirectories(false).
PromptForSingleSelection()
if result != "" {
app.Dialog.Info().SetMessage(result).Show()
}
})
saveMenu.Add("Select File (Full Example)").OnClick(func(ctx *application.Context) {
result, _ := app.Dialog.SaveFile().
CanCreateDirectories(false).
ShowHiddenFiles(true).
SetMessage("Select a file").
SetDirectory("/Applications").
SetButtonText("Let's do this!").
SetFilename("README.md").
HideExtension(true).
AllowsOtherFileTypes(true).
TreatsFilePackagesAsDirectories(true).
ShowHiddenFiles(true).
PromptForSingleSelection()
if result != "" {
app.Dialog.Info().SetMessage(result).Show()
}
})
app.Menu.Set(menu)
app.Window.New()
err := app.Run()
if err != nil {
log.Fatal(err.Error())
}
}