CI / Test (ubuntu-latest) (push) Canceled after 0s
CI / Test (windows-latest) (push) Canceled after 0s
CI / Storage tests on PostgreSQL (push) Canceled after 0s
CI / Complement (federation off) (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
CI / Smoke test the binary (push) Canceled after 0s
CI / Admin panel (push) Canceled after 0s
CI / Web client (push) Canceled after 0s
apps/desktop is the web client in a native window. It embeds the same build warp-web does and serves it through the same Go package, so every screen is shared. Unlike warp-web it proxies nothing: the client calls the homeserver directly, and the CSP allows the homeserver plus any https: and wss: origin for the call backend. - First run asks for the homeserver: a server name or address, with .well-known discovery and a /versions check; File > Change homeserver asks again. Signed-in sessions keep their own base URL, so a change never sends one server's token to another. - Links to other sites open in the system browser (/_desktop/links.js, added to index.html); only http, https and mailto are opened. - One instance at a time, since sessions and keys live in the webview's storage. - Dev builds open the DevTools Protocol on Windows when WARP_DESKTOP_REMOTE_DEBUGGING_PORT is set, for scripted testing. - Packaging: icon, version info and manifest in the Windows exe, a macOS .app with camera and microphone descriptions, Linux packages via nfpm. Make targets: desktop, desktop-run, desktop-test, desktop-resources, desktop-macos, desktop-linux. Web client: host and client move out of internal/ so the desktop app can import them, and host gains AnyCallOrigin. The Dockerfile, .dockerignore and the vite output path follow the move. Pinned to Wails v3.0.0-beta.27. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
62 lines
1.5 KiB
Go
62 lines
1.5 KiB
Go
package shell
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"io/fs"
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
)
|
|
|
|
// Settings is what the desktop app keeps between runs. The client's own
|
|
// state (sessions, keys) lives in the webview's storage, not here.
|
|
type Settings struct {
|
|
// Homeserver is the base URL new sign-ins go to, e.g.
|
|
// https://matrix.example.org. Empty until the first-run page has asked.
|
|
Homeserver string `json:"homeserver,omitempty"`
|
|
}
|
|
|
|
// Store reads and writes Settings as a JSON file.
|
|
type Store struct {
|
|
path string
|
|
mu sync.Mutex
|
|
}
|
|
|
|
// NewStore returns a store backed by the file at path. The file and its
|
|
// directory are created on the first Save.
|
|
func NewStore(path string) *Store { return &Store{path: path} }
|
|
|
|
// Load returns the saved settings, or the zero value when there are none.
|
|
func (s *Store) Load() (Settings, error) {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
var st Settings
|
|
b, err := os.ReadFile(s.path)
|
|
if errors.Is(err, fs.ErrNotExist) {
|
|
return st, nil
|
|
}
|
|
if err != nil {
|
|
return st, err
|
|
}
|
|
return st, json.Unmarshal(b, &st)
|
|
}
|
|
|
|
// Save writes the settings, replacing the file atomically.
|
|
func (s *Store) Save(st Settings) error {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
b, err := json.MarshalIndent(st, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := os.MkdirAll(filepath.Dir(s.path), 0o700); err != nil {
|
|
return err
|
|
}
|
|
tmp := s.path + ".tmp"
|
|
if err := os.WriteFile(tmp, append(b, '\n'), 0o600); err != nil {
|
|
return err
|
|
}
|
|
return os.Rename(tmp, s.path)
|
|
}
|