mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-17 04:09:07 +02:00
[client] UI refactor (#6069)
Refactor UI --------- 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: Claude <noreply@anthropic.com> Co-authored-by: riccardom <riccardomanfrin@gmail.com>
This commit is contained in:
co-authored by
Eduard Gert
braginini
Pascal Fischer
Claude
riccardom
parent
679c7182a4
commit
8b7ce337d8
@@ -0,0 +1,134 @@
|
||||
//go:build linux && !(linux && 386)
|
||||
|
||||
package main
|
||||
|
||||
// Wails v3's Linux SNI backend ignores SetDarkModeIcon (it just calls setIcon,
|
||||
// last write wins) and SNI carries no panel dark/light hint, so we detect the
|
||||
// desktop colour scheme ourselves and pick the silhouette in iconForState.
|
||||
// The live watcher is in tray_theme_watcher_linux.go.
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// startTrayTheme seeds t.panelDark and repaints on colour-scheme flips. Must
|
||||
// run before the first applyIcon so the initial paint uses the right silhouette.
|
||||
func (t *Tray) startTrayTheme() {
|
||||
w := startThemeWatcher(func() { t.applyIcon() })
|
||||
t.panelDark = w.IsDark
|
||||
}
|
||||
|
||||
// isKDE reports whether the current desktop is KDE Plasma. XDG_CURRENT_DESKTOP
|
||||
// is a colon-separated list (e.g. "ubuntu:KDE"), so match per token.
|
||||
func isKDE() bool {
|
||||
for _, d := range strings.Split(os.Getenv("XDG_CURRENT_DESKTOP"), ":") {
|
||||
if strings.EqualFold(strings.TrimSpace(d), "KDE") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// kdeglobalsPath returns the user kdeglobals path. We read only this file, not
|
||||
// the full XDG_CONFIG_DIRS cascade: Plasma writes the active scheme here, and a
|
||||
// missing Complementary group falls back to the portal.
|
||||
func kdeglobalsPath() string {
|
||||
if dir := os.Getenv("XDG_CONFIG_HOME"); dir != "" {
|
||||
return filepath.Join(dir, "kdeglobals")
|
||||
}
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return filepath.Join(home, ".config", "kdeglobals")
|
||||
}
|
||||
|
||||
// kdePanelIsDark reports whether the KDE Plasma panel is dark by the luma of
|
||||
// its "Complementary" background (the colour Plasma paints the tray with). ok
|
||||
// is false when this isn't KDE or the colour can't be read, so the caller falls
|
||||
// through to the portal/GTK path.
|
||||
func kdePanelIsDark() (dark, ok bool) {
|
||||
if !isKDE() {
|
||||
return false, false
|
||||
}
|
||||
path := kdeglobalsPath()
|
||||
if path == "" {
|
||||
return false, false
|
||||
}
|
||||
rgb, ok := readKdeComplementaryBackground(path)
|
||||
if !ok {
|
||||
return false, false
|
||||
}
|
||||
return isDarkRGB(rgb[0], rgb[1], rgb[2]), true
|
||||
}
|
||||
|
||||
// readKdeComplementaryBackground parses kdeglobals for
|
||||
// [Colors:Complementary] BackgroundNormal and returns its R,G,B (0-255).
|
||||
func readKdeComplementaryBackground(path string) (rgb [3]uint8, ok bool) {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
log.Debugf("tray theme: kdeglobals open failed, using portal: %v", err)
|
||||
return rgb, false
|
||||
}
|
||||
defer func() { _ = f.Close() }()
|
||||
|
||||
const group = "[Colors:Complementary]"
|
||||
inGroup := false
|
||||
scanner := bufio.NewScanner(f)
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
if strings.HasPrefix(line, "[") {
|
||||
inGroup = line == group
|
||||
continue
|
||||
}
|
||||
if !inGroup {
|
||||
continue
|
||||
}
|
||||
key, val, found := strings.Cut(line, "=")
|
||||
if !found || strings.TrimSpace(key) != "BackgroundNormal" {
|
||||
continue
|
||||
}
|
||||
return parseRGB(strings.TrimSpace(val))
|
||||
}
|
||||
return rgb, false
|
||||
}
|
||||
|
||||
// parseRGB parses KDE's "r,g,b" colour triple into bytes.
|
||||
func parseRGB(s string) (rgb [3]uint8, ok bool) {
|
||||
parts := strings.Split(s, ",")
|
||||
if len(parts) != 3 {
|
||||
return rgb, false
|
||||
}
|
||||
for i, p := range parts {
|
||||
n, err := strconv.Atoi(strings.TrimSpace(p))
|
||||
if err != nil || n < 0 || n > 255 {
|
||||
return rgb, false
|
||||
}
|
||||
rgb[i] = uint8(n)
|
||||
}
|
||||
return rgb, true
|
||||
}
|
||||
|
||||
// isDarkRGB reports whether a colour is dark via Rec. 601 luma, split at the
|
||||
// 128 midpoint.
|
||||
func isDarkRGB(r, g, b uint8) bool {
|
||||
luma := (299*int(r) + 587*int(g) + 114*int(b)) / 1000
|
||||
return luma < 128
|
||||
}
|
||||
|
||||
// gtkThemeIsDark inspects the GTK_THEME env var. Empty (no override) is treated
|
||||
// as dark to match the default-dark fallback used elsewhere.
|
||||
func gtkThemeIsDark() bool {
|
||||
theme := os.Getenv("GTK_THEME")
|
||||
if theme == "" {
|
||||
return true
|
||||
}
|
||||
// GTK_THEME is "Name[:variant]"; the dark variant is ":dark".
|
||||
return strings.Contains(strings.ToLower(theme), ":dark")
|
||||
}
|
||||
Reference in New Issue
Block a user