mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-23 22:09:09 +02:00
[management,client] 0.75.0 release with new desktop UI (#6473)
- **Wails v3 application** (`client/ui`) with a React + TypeScript + Tailwind frontend replacing the Fyne UI: main connection view, exit-node switcher, networks/peers browser with detail panels, profile management, settings (general, network, SSH, security, troubleshooting, appearance), debug-bundle creation, and a first-run welcome flow. - **Internationalization**: go-i18n bundle with 9 locales (en, de, es, fr, hu, it, pt, ru, zh-CN) shared between the tray and the frontend. - **New system tray** implementation with per-platform theme-aware icons, including a native XEmbed host for Linux (`xembed_tray_linux.c`) and a Linux theme watcher. - **Session handling**: auth session watcher (`client/internal/auth/sessionwatch`), pending login flow, session-expiration dialog and tray notifications, and `netbird login` improvements. - **Daemon API extensions** (`daemon.proto`): status stream subscription, event stream, networks/exit-node selection endpoints, and richer full status — with probe throttling on the daemon side to protect against UI-driven request storms. - **UI preferences store** persisted per profile, autostart management via the daemon (single source of truth in HKCU on Windows). - **Build system**: Taskfile-based builds per platform (macOS, Linux, Windows), Docker cross-compilation images, MSIX/NSIS/nfpm/AppImage packaging, and a new `frontend-ui` CI workflow. Co-authored-by: Zoltan Papp <zoltan.pmail@gmail.com> Co-authored-by: Eduard Gert <kontakt@eduardgert.de> Co-authored-by: braginini <bangvalo@gmail.com> Co-authored-by: Pascal Fischer <32096965+pascal-fischer@users.noreply.github.com> Co-authored-by: riccardom <riccardomanfrin@gmail.com>
This commit is contained in:
co-authored by
Zoltan Papp
Eduard Gert
braginini
Pascal Fischer
riccardom
parent
c9d387bd0d
commit
91acb8147c
@@ -0,0 +1,97 @@
|
||||
//go:build !android && !ios && !freebsd && !js
|
||||
|
||||
// Package updater holds the auto-update domain: the typed State, the
|
||||
// daemon-SystemEvent metadata schema, and the Holder that caches the latest
|
||||
// state and broadcasts changes. No Wails dependency.
|
||||
package updater
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/netbirdio/netbird/client/proto"
|
||||
)
|
||||
|
||||
// EventStateChanged carries the full State snapshot as payload.
|
||||
const EventStateChanged = "netbird:update:state"
|
||||
|
||||
// State is the typed snapshot of the daemon's update situation. Installing is
|
||||
// driven only by the daemon's progress_window:show event; a UI-side
|
||||
// Update.Trigger() does not flip it.
|
||||
type State struct {
|
||||
Available bool `json:"available"`
|
||||
Version string `json:"version"`
|
||||
Enforced bool `json:"enforced"`
|
||||
Installing bool `json:"installing"`
|
||||
}
|
||||
|
||||
// Emitter is the broadcast dependency Holder needs; the Wails app.Event
|
||||
// processor satisfies it.
|
||||
type Emitter interface {
|
||||
Emit(name string, data ...any) bool
|
||||
}
|
||||
|
||||
// Holder caches the latest update State and broadcasts changes.
|
||||
type Holder struct {
|
||||
emitter Emitter
|
||||
|
||||
mu sync.Mutex
|
||||
state State
|
||||
}
|
||||
|
||||
// NewHolder constructs an empty-state Holder. A nil emitter skips the broadcast.
|
||||
func NewHolder(emitter Emitter) *Holder {
|
||||
return &Holder{emitter: emitter}
|
||||
}
|
||||
|
||||
// Get returns a copy of the cached State.
|
||||
func (h *Holder) Get() State {
|
||||
h.mu.Lock()
|
||||
defer h.mu.Unlock()
|
||||
return h.state
|
||||
}
|
||||
|
||||
// OnSystemEvent folds update-related metadata into the cached state, emitting
|
||||
// EventStateChanged only on an actual change so repeated daemon snapshots
|
||||
// don't produce redundant pushes.
|
||||
func (h *Holder) OnSystemEvent(ev *proto.SystemEvent) {
|
||||
md := ev.GetMetadata()
|
||||
if len(md) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
h.mu.Lock()
|
||||
changed := false
|
||||
if v, ok := md["new_version_available"]; ok {
|
||||
_, enforced := md["enforced"]
|
||||
if !h.state.Available || h.state.Version != v || h.state.Enforced != enforced {
|
||||
h.state.Available = true
|
||||
h.state.Version = v
|
||||
h.state.Enforced = enforced
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
if md["progress_window"] == "show" {
|
||||
if !h.state.Installing {
|
||||
h.state.Installing = true
|
||||
changed = true
|
||||
}
|
||||
if v, ok := md["version"]; ok && v != "" && h.state.Version != v {
|
||||
h.state.Version = v
|
||||
h.state.Available = true
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
snap := h.state
|
||||
h.mu.Unlock()
|
||||
|
||||
if !changed {
|
||||
return
|
||||
}
|
||||
log.Infof("update state: available=%v version=%q enforced=%v installing=%v",
|
||||
snap.Available, snap.Version, snap.Enforced, snap.Installing)
|
||||
if h.emitter != nil {
|
||||
h.emitter.Emit(EventStateChanged, snap)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user