From 5343e97ab28f6bbec9859159a31bac35bbea0cb2 Mon Sep 17 00:00:00 2001 From: bbedward Date: Fri, 13 Mar 2026 15:05:43 -0400 Subject: [PATCH] core/server: initialize geolocation async on startup --- core/.pre-commit-config.yaml | 27 ++++++-- core/internal/server/server.go | 67 ++++++++++++-------- core/internal/server/thememode/manager.go | 10 ++- core/internal/server/wayland/manager.go | 51 ++++++++------- core/internal/server/wayland/manager_test.go | 7 +- 5 files changed, 99 insertions(+), 63 deletions(-) diff --git a/core/.pre-commit-config.yaml b/core/.pre-commit-config.yaml index 2a8df7bc..7eb6228b 100644 --- a/core/.pre-commit-config.yaml +++ b/core/.pre-commit-config.yaml @@ -1,13 +1,26 @@ repos: - - repo: https://github.com/golangci/golangci-lint - rev: v2.11.3 - hooks: - - id: golangci-lint-fmt - require_serial: true - - id: golangci-lint-full - - id: golangci-lint-config-verify - repo: local hooks: + - id: golangci-lint-fmt + name: golangci-lint-fmt + entry: go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.11.3 fmt + language: system + require_serial: true + types: [go] + pass_filenames: false + - id: golangci-lint-full + name: golangci-lint-full + entry: go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.11.3 run --fix + language: system + require_serial: true + types: [go] + pass_filenames: false + - id: golangci-lint-config-verify + name: golangci-lint-config-verify + entry: go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.11.3 config verify + language: system + files: \.golangci\.(?:yml|yaml|toml|json) + pass_filenames: false - id: go-test name: go test entry: go test ./... diff --git a/core/internal/server/server.go b/core/internal/server/server.go index 72a2c7ea..f7b90dff 100644 --- a/core/internal/server/server.go +++ b/core/internal/server/server.go @@ -73,6 +73,7 @@ var dbusManager *serverDbus.Manager var wlContext *wlcontext.SharedContext var themeModeManager *thememode.Manager var locationManager *location.Manager +var geoClientInstance geolocation.Client const dbusClientID = "dms-dbus-client" @@ -191,7 +192,7 @@ func InitializeFreedeskManager() error { return nil } -func InitializeWaylandManager(geoClient geolocation.Client) error { +func InitializeWaylandManager() error { log.Info("Attempting to initialize Wayland gamma control...") if wlContext == nil { @@ -204,7 +205,7 @@ func InitializeWaylandManager(geoClient geolocation.Client) error { } config := wayland.DefaultConfig() - manager, err := wayland.NewManager(wlContext.Display(), geoClient, config) + manager, err := wayland.NewManager(wlContext.Display(), config) if err != nil { log.Errorf("Failed to initialize wayland manager: %v", err) return err @@ -385,8 +386,8 @@ func InitializeDbusManager() error { return nil } -func InitializeThemeModeManager(geoClient geolocation.Client) error { - manager := thememode.NewManager(geoClient) +func InitializeThemeModeManager() error { + manager := thememode.NewManager() themeModeManager = manager log.Info("Theme mode automation manager initialized") @@ -1330,6 +1331,9 @@ func cleanupManagers() { if locationManager != nil { locationManager.Close() } + if geoClientInstance != nil { + geoClientInstance.Close() + } } func Start(printDocs bool) error { @@ -1545,9 +1549,6 @@ func Start(printDocs bool) error { loginctlReady := make(chan struct{}) freedesktopReady := make(chan struct{}) - geoClient := geolocation.NewClient() - defer geoClient.Close() - go func() { defer close(loginctlReady) if err := InitializeLoginctlManager(); err != nil { @@ -1592,10 +1593,41 @@ func Start(printDocs bool) error { } }() - if err := InitializeWaylandManager(geoClient); err != nil { + if err := InitializeWaylandManager(); err != nil { log.Warnf("Wayland manager unavailable: %v", err) } + if err := InitializeThemeModeManager(); err != nil { + log.Warnf("Theme mode manager unavailable: %v", err) + } else { + notifyCapabilityChange() + go func() { + <-loginctlReady + if loginctlManager == nil { + return + } + themeModeManager.WatchLoginctl(loginctlManager) + }() + } + + go func() { + geoClient := geolocation.NewClient() + geoClientInstance = geoClient + + if waylandManager != nil { + waylandManager.SetGeoClient(geoClient) + } + if themeModeManager != nil { + themeModeManager.SetGeoClient(geoClient) + } + + if err := InitializeLocationManager(geoClient); err != nil { + log.Warnf("Location manager unavailable: %v", err) + } else { + notifyCapabilityChange() + } + }() + go func() { if err := InitializeBluezManager(); err != nil { log.Warnf("Bluez manager unavailable: %v", err) @@ -1624,25 +1656,6 @@ func Start(printDocs bool) error { log.Debugf("WlrOutput manager unavailable: %v", err) } - if err := InitializeThemeModeManager(geoClient); err != nil { - log.Warnf("Theme mode manager unavailable: %v", err) - } else { - notifyCapabilityChange() - go func() { - <-loginctlReady - if loginctlManager == nil { - return - } - themeModeManager.WatchLoginctl(loginctlManager) - }() - } - - if err := InitializeLocationManager(geoClient); err != nil { - log.Warnf("Location manager unavailable: %v", err) - } else { - notifyCapabilityChange() - } - fatalErrChan := make(chan error, 1) if wlrOutputManager != nil { go func() { diff --git a/core/internal/server/thememode/manager.go b/core/internal/server/thememode/manager.go index 1b0c7d63..f7644ad2 100644 --- a/core/internal/server/thememode/manager.go +++ b/core/internal/server/thememode/manager.go @@ -40,7 +40,7 @@ type Manager struct { wg sync.WaitGroup } -func NewManager(geoClient geolocation.Client) *Manager { +func NewManager() *Manager { m := &Manager{ config: Config{ Enabled: false, @@ -54,7 +54,6 @@ func NewManager(geoClient geolocation.Client) *Manager { }, stopChan: make(chan struct{}), updateTrigger: make(chan struct{}, 1), - geoClient: geoClient, } m.updateState(time.Now()) @@ -315,6 +314,10 @@ func (m *Manager) getConfig() Config { return m.config } +func (m *Manager) SetGeoClient(client geolocation.Client) { + m.geoClient = client +} + func (m *Manager) getLocation(config Config) (*float64, *float64) { if config.Latitude != nil && config.Longitude != nil { return config.Latitude, config.Longitude @@ -322,6 +325,9 @@ func (m *Manager) getLocation(config Config) (*float64, *float64) { if !config.UseIPLocation { return nil, nil } + if m.geoClient == nil { + return nil, nil + } m.locationMutex.RLock() if m.cachedIPLat != nil && m.cachedIPLon != nil { diff --git a/core/internal/server/wayland/manager.go b/core/internal/server/wayland/manager.go index 8b9e433a..0255a717 100644 --- a/core/internal/server/wayland/manager.go +++ b/core/internal/server/wayland/manager.go @@ -20,7 +20,7 @@ import ( const animKelvinStep = 25 -func NewManager(display wlclient.WaylandDisplay, geoClient geolocation.Client, config Config) (*Manager, error) { +func NewManager(display wlclient.WaylandDisplay, config Config) (*Manager, error) { if err := config.Validate(); err != nil { return nil, err } @@ -41,7 +41,6 @@ func NewManager(display wlclient.WaylandDisplay, geoClient geolocation.Client, c updateTrigger: make(chan struct{}, 1), dirty: make(chan struct{}, 1), dbusSignal: make(chan *dbus.Signal, 16), - geoClient: geoClient, } if err := m.setupRegistry(); err != nil { @@ -422,6 +421,10 @@ func (m *Manager) recalcSchedule(now time.Time) { } } +func (m *Manager) SetGeoClient(client geolocation.Client) { + m.geoClient = client +} + func (m *Manager) getLocation() (*float64, *float64) { m.configMutex.RLock() config := m.config @@ -430,27 +433,31 @@ func (m *Manager) getLocation() (*float64, *float64) { if config.Latitude != nil && config.Longitude != nil { return config.Latitude, config.Longitude } - if config.UseIPLocation { - m.locationMutex.RLock() - if m.cachedIPLat != nil && m.cachedIPLon != nil { - lat, lon := m.cachedIPLat, m.cachedIPLon - m.locationMutex.RUnlock() - return lat, lon - } - m.locationMutex.RUnlock() - - location, err := m.geoClient.GetLocation() - if err != nil { - return nil, nil - } - - m.locationMutex.Lock() - m.cachedIPLat = &location.Latitude - m.cachedIPLon = &location.Longitude - m.locationMutex.Unlock() - return m.cachedIPLat, m.cachedIPLon + if !config.UseIPLocation { + return nil, nil } - return nil, nil + if m.geoClient == nil { + return nil, nil + } + + m.locationMutex.RLock() + if m.cachedIPLat != nil && m.cachedIPLon != nil { + lat, lon := m.cachedIPLat, m.cachedIPLon + m.locationMutex.RUnlock() + return lat, lon + } + m.locationMutex.RUnlock() + + location, err := m.geoClient.GetLocation() + if err != nil { + return nil, nil + } + + m.locationMutex.Lock() + m.cachedIPLat = &location.Latitude + m.cachedIPLon = &location.Longitude + m.locationMutex.Unlock() + return m.cachedIPLat, m.cachedIPLon } func (m *Manager) hasValidSchedule() bool { diff --git a/core/internal/server/wayland/manager_test.go b/core/internal/server/wayland/manager_test.go index 03473f1d..8c001292 100644 --- a/core/internal/server/wayland/manager_test.go +++ b/core/internal/server/wayland/manager_test.go @@ -8,7 +8,6 @@ import ( "github.com/stretchr/testify/assert" - mocks_geolocation "github.com/AvengeMedia/DankMaterialShell/core/internal/mocks/geolocation" mocks_wlclient "github.com/AvengeMedia/DankMaterialShell/core/internal/mocks/wlclient" ) @@ -391,20 +390,18 @@ func TestNotifySubscribers_NonBlocking(t *testing.T) { func TestNewManager_GetRegistryError(t *testing.T) { mockDisplay := mocks_wlclient.NewMockWaylandDisplay(t) - mockGeoclient := mocks_geolocation.NewMockClient(t) mockDisplay.EXPECT().Context().Return(nil) mockDisplay.EXPECT().GetRegistry().Return(nil, errors.New("failed to get registry")) config := DefaultConfig() - _, err := NewManager(mockDisplay, mockGeoclient, config) + _, err := NewManager(mockDisplay, config) assert.Error(t, err) assert.Contains(t, err.Error(), "get registry") } func TestNewManager_InvalidConfig(t *testing.T) { mockDisplay := mocks_wlclient.NewMockWaylandDisplay(t) - mockGeoclient := mocks_geolocation.NewMockClient(t) config := Config{ LowTemp: 500, @@ -412,6 +409,6 @@ func TestNewManager_InvalidConfig(t *testing.T) { Gamma: 1.0, } - _, err := NewManager(mockDisplay, mockGeoclient, config) + _, err := NewManager(mockDisplay, config) assert.Error(t, err) }