Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v3] Added AppDataDirectory path #3823

Merged
47 changes: 47 additions & 0 deletions mkdocs-website/docs/en/API/application.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,53 @@ API: `Show()`
app.Show()
```

### Path

API: `Path(selector Path) string`

`Path(selector Path)` returns the full path for the given path type. It provides a cross-platform way to access common application directories.

The `Path` type is an enum with the following values:
- `AppData`: Returns the path to the application data directory
- `UserCache`: Returns the path to the user's cache directory
- `UserConfig`: Returns the path to the user's configuration directory

```go
// Get the application data directory path
appDataPath, err := app.Path(application.AppData)
if err != nil {
log.Fatal(err)
}
fmt.Println("AppData path:", appDataPath)

// Output: AppData path: /home/username/.local/share // Linux
// Output: AppData path: /Users/username/Library/Application Support // macOS
// Output: AppData path: C:\Users\Username\AppData\Roaming // Windows

// Get the user cache directory path
userCachePath, err := app.Path(application.UserCache)
if err != nil {
log.Fatal(err)
}
fmt.Println("UserCache path:", userCachePath)

// Output: UserCache path: /home/username/.cache // Linux
// Output: UserCache path: /Users/username/Library/Caches // macOS
// Output: UserCache path: C:\Users\Username\AppData\Local\Temp // Windows

// Get the user config directory path
userConfigPath, err := app.Path(application.UserConfig)
if err != nil {
log.Fatal(err)
}
fmt.Println("UserConfig path:", userConfigPath)

// Output: UserConfig path: /home/username/.config // Linux
// Output: UserConfig path: /Users/username/Library/Preferences // macOS
// Output: UserConfig path: C:\Users\Username\AppData\Local // Windows
```


--8<--
./docs/en/API/application_window.md
./docs/en/API/application_menu.md
Expand Down
1 change: 1 addition & 0 deletions mkdocs-website/docs/en/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Taskfile refactor by [leaanthony](https://github.com/leaanthony) in [#3748](https://github.com/wailsapp/wails/pull/3748)
- Upgrade to `go-webview2` v1.0.16 by [leaanthony](https://github.com/leaanthony)
- Fixed `Screen` type to include `ID` not `Id` by [etesam913](https://github.com/etesam913) in [#3778](https://github.com/wailsapp/wails/pull/3778)
- Add `Path` method to `application` package by [ansxuman](https://github.com/ansxuman) in [#3823](https://github.com/wailsapp/wails/pull/3823)

### Fixed
- Fixed `AlwaysOnTop` not working on Mac by [leaanthony](https://github.com/leaanthony) in [#3841](https://github.com/wailsapp/wails/pull/3841)
Expand Down
3 changes: 2 additions & 1 deletion v3/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ require (
github.com/tc-hib/winres v0.3.1
github.com/wailsapp/go-webview2 v1.0.16
github.com/wailsapp/mimetype v1.4.1
golang.org/x/sys v0.20.0
golang.org/x/sys v0.22.0
golang.org/x/term v0.20.0
golang.org/x/tools v0.21.0
modernc.org/sqlite v1.21.0
Expand All @@ -46,6 +46,7 @@ require (
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/adrg/xdg v0.5.0 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/containerd/console v1.0.4 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
Expand Down
5 changes: 5 additions & 0 deletions v3/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCv
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
github.com/adrg/xdg v0.5.0 h1:dDaZvhMXatArP1NPHhnfaQUqWBLBsmx1h1HXQdMoFCY=
github.com/adrg/xdg v0.5.0/go.mod h1:dDdY4M4DF9Rjy4kHPeNL+ilVF+p2lK8IdM9/rTSGcI4=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
Expand Down Expand Up @@ -215,6 +217,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/tc-hib/winres v0.3.1 h1:CwRjEGrKdbi5CvZ4ID+iyVhgyfatxFoizjPhzez9Io4=
github.com/tc-hib/winres v0.3.1/go.mod h1:C/JaNhH3KBvhNKVbvdlDWkbMDO9H4fKKDaN7/07SSuk=
github.com/wailsapp/go-webview2 v1.0.16 h1:wffnvnkkLvhRex/aOrA3R7FP7rkvOqL/bir1br7BekU=
Expand Down Expand Up @@ -286,6 +289,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
Expand Down
29 changes: 29 additions & 0 deletions v3/pkg/application/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ var alphaAssets embed.FS

var globalApplication *App

type Path int

const (
AppData Path = iota
UserCache
UserConfig
)

// AlphaAssets is the default assets for the alpha application
var AlphaAssets = AssetOptions{
Handler: BundledAssetFileServer(alphaAssets),
Expand Down Expand Up @@ -192,6 +200,9 @@ type (
GetFlags(options Options) map[string]any
isOnMainThread() bool
isDarkMode() bool
getAppDataPath() (string, error)
getUserCachePath() (string, error)
getUserConfigPath() (string, error)
}

runnable interface {
Expand Down Expand Up @@ -1013,3 +1024,21 @@ func (a *App) shouldQuit() bool {
}
return true
}

// Path returns the path for the given selector

func (a *App) Path(selector Path) (string, error) {
if a.impl == nil {
return "", fmt.Errorf("application not initialized")
}
switch selector {
case AppData:
return a.impl.getAppDataPath()
case UserCache:
return a.impl.getUserCachePath()
case UserConfig:
return a.impl.getUserConfigPath()
default:
return "", fmt.Errorf("unknown path selector: %v", selector)
}
}
19 changes: 19 additions & 0 deletions v3/pkg/application/application_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,10 @@ static const char* serializationNSDictionary(void *dict) {
import "C"
import (
"encoding/json"
"strings"
"unsafe"

"github.com/adrg/xdg"
"github.com/wailsapp/wails/v3/internal/operatingsystem"

"github.com/wailsapp/wails/v3/internal/assetserver/webview"
Expand Down Expand Up @@ -363,3 +365,20 @@ func (a *App) platformEnvironment() map[string]any {
func fatalHandler(errFunc func(error)) {
return
}

func (a *macosApp) getAppDataPath() (string, error) {
return xdg.DataHome, nil
}

func (a *macosApp) getUserCachePath() (string, error) {
return xdg.CacheHome, nil
}

func (a *macosApp) getUserConfigPath() (string, error) {
for _, dir := range xdg.ConfigDirs {
if strings.HasSuffix(dir, "Library/Preferences") {
return dir, nil
}
}
return "", nil
}
13 changes: 13 additions & 0 deletions v3/pkg/application/application_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"strings"
"sync"

"github.com/adrg/xdg"
"github.com/godbus/dbus/v5"
"github.com/wailsapp/wails/v3/internal/operatingsystem"
"github.com/wailsapp/wails/v3/pkg/events"
Expand Down Expand Up @@ -260,3 +261,15 @@ func fatalHandler(errFunc func(error)) {
// Stub for windows function
return
}

func (a *linuxApp) getAppDataPath() (string, error) {
return xdg.DataHome, nil
}

func (a *linuxApp) getUserCachePath() (string, error) {
return xdg.CacheHome, nil
}

func (a *linuxApp) getUserConfigPath() (string, error) {
return xdg.ConfigHome, nil
}
26 changes: 26 additions & 0 deletions v3/pkg/application/application_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ package application

import (
"fmt"
"os"
"path/filepath"
"sync"
"syscall"
"unsafe"
Expand Down Expand Up @@ -349,3 +351,27 @@ func fatalHandler(errFunc func(error)) {
w32.Fatal = errFunc
return
}

func (a *windowsApp) getAppDataPath() (string, error) {
path := os.Getenv("APPDATA")
if path == "" {
return "", fmt.Errorf("APPDATA environment variable is not set")
}
return path, nil
}

func (a *windowsApp) getUserCachePath() (string, error) {
localAppData := os.Getenv("LOCALAPPDATA")
if localAppData == "" {
return "", fmt.Errorf("LOCALAPPDATA environment variable is not set")
}
return filepath.Join(localAppData, "Temp"), nil
}

func (a *windowsApp) getUserConfigPath() (string, error) {
path := os.Getenv("LOCALAPPDATA")
if path == "" {
return "", fmt.Errorf("LOCALAPPDATA environment variable is not set")
}
return path, nil
}