nandi/oripublic Fork 0
main
Commits
Clone
git clone https://git.rickub.com/nandi/ori.git
git clone ssh://git@rickub.com/nandi/ori.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

forked from bots-garden/ori

app.go · 125 lines · 3.8 KBGo Blame HistoryRaw
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package main

import (
	"context"
	"fmt"
	"net/http"

	"github.com/wailsapp/wails/v2/pkg/runtime"

	"rickub.com/bots-garden/ori-desktop/internal/health"
	"rickub.com/bots-garden/ori-desktop/internal/settings"
)

// App holds the state shared by the Go-bound methods exposed to the frontend.
// Every exported method on App is callable from JavaScript as
// window.go.main.App.<Method>(...) and returns a Promise.
type App struct {
	ctx          context.Context
	settingsPath string
	client       *http.Client
}

// NewApp creates the application state. The settings location is resolved
// once here; if the platform exposes no user config directory the path is
// left empty and SaveConfig reports the problem instead of guessing.
func NewApp() *App {
	path, err := settings.DefaultPath()
	if err != nil {
		path = ""
	}
	return &App{
		settingsPath: path,
		client:       &http.Client{Timeout: health.DefaultTimeout},
	}
}

// startup is the Wails OnStartup hook; it keeps the runtime context needed by
// runtime.* calls such as BrowserOpenURL.
func (a *App) startup(ctx context.Context) {
	a.ctx = ctx
}

// GetConfig returns the remembered settings (defaults on a first run).
func (a *App) GetConfig() (settings.Settings, error) {
	if a.settingsPath == "" {
		return settings.Default(), nil
	}
	return settings.Load(a.settingsPath)
}

// SaveConfig normalises the server URL and persists the settings.
func (a *App) SaveConfig(s settings.Settings) error {
	if a.settingsPath == "" {
		return fmt.Errorf("no user configuration directory available on this platform")
	}
	normalized, err := settings.NormalizeURL(s.ServerURL)
	if err != nil {
		return err
	}
	s.ServerURL = normalized
	return settings.Save(a.settingsPath, s)
}

// CheckHealth probes GET <url>/healthz and reports the outcome. It never
// fails the Promise: a malformed URL or an unreachable server both come back
// as a Report with OK=false and an explanatory Detail.
func (a *App) CheckHealth(rawURL string) health.Report {
	base, err := settings.NormalizeURL(rawURL)
	if err != nil {
		return health.Report{URL: rawURL, Detail: err.Error()}
	}
	return health.Check(a.context(), a.client, base)
}

// Connect is the one-call happy path used by the connection screen: it
// normalises the URL, checks /healthz, remembers the URL on success and
// returns the normalised base URL the frontend should load. On failure the
// Promise rejects with the health Detail so the screen can show it.
func (a *App) Connect(rawURL string) (string, error) {
	base, err := settings.NormalizeURL(rawURL)
	if err != nil {
		return "", err
	}
	rep := health.Check(a.context(), a.client, base)
	if !rep.OK {
		return "", fmt.Errorf("%s", rep.Detail)
	}
	if a.settingsPath != "" {
		if err := settings.Save(a.settingsPath, settings.Settings{ServerURL: base}); err != nil {
			// Not fatal for the session: the user is connected, only the
			// memory of the URL is lost. Surface it in the returned error?
			// No — the frontend treats an error as "not connected"; log it.
			fmt.Println("ori-desktop: warning:", err)
		}
	}
	return base, nil
}

// OpenInBrowser opens the given URL (normalised first) in the system's
// default browser — the fallback when embedding is not wanted.
func (a *App) OpenInBrowser(rawURL string) error {
	base, err := settings.NormalizeURL(rawURL)
	if err != nil {
		return err
	}
	if a.ctx == nil {
		return fmt.Errorf("application runtime not ready")
	}
	runtime.BrowserOpenURL(a.ctx, base)
	return nil
}

// SettingsPath tells the frontend where the settings live, for display.
func (a *App) SettingsPath() string {
	return a.settingsPath
}

// context returns the runtime context, or a background one before startup
// (bound methods are only reachable after startup, this is belt and braces).
func (a *App) context() context.Context {
	if a.ctx != nil {
		return a.ctx
	}
	return context.Background()
}