mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-13 00:42:49 -05:00
switch hto monorepo structure
This commit is contained in:
251
backend/internal/server/freedesktop/manager.go
Normal file
251
backend/internal/server/freedesktop/manager.go
Normal file
@@ -0,0 +1,251 @@
|
||||
package freedesktop
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/godbus/dbus/v5"
|
||||
)
|
||||
|
||||
func NewManager() (*Manager, error) {
|
||||
systemConn, err := dbus.ConnectSystemBus()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to connect to system bus: %w", err)
|
||||
}
|
||||
|
||||
sessionConn, err := dbus.ConnectSessionBus()
|
||||
if err != nil {
|
||||
sessionConn = nil
|
||||
}
|
||||
|
||||
m := &Manager{
|
||||
state: &FreedeskState{
|
||||
Accounts: AccountsState{},
|
||||
Settings: SettingsState{},
|
||||
},
|
||||
stateMutex: sync.RWMutex{},
|
||||
systemConn: systemConn,
|
||||
sessionConn: sessionConn,
|
||||
currentUID: uint64(os.Getuid()),
|
||||
subscribers: make(map[string]chan FreedeskState),
|
||||
subMutex: sync.RWMutex{},
|
||||
}
|
||||
|
||||
m.initializeAccounts()
|
||||
m.initializeSettings()
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m *Manager) initializeAccounts() error {
|
||||
accountsManager := m.systemConn.Object(dbusAccountsDest, dbus.ObjectPath(dbusAccountsPath))
|
||||
|
||||
var userPath dbus.ObjectPath
|
||||
err := accountsManager.Call(dbusAccountsInterface+".FindUserById", 0, int64(m.currentUID)).Store(&userPath)
|
||||
if err != nil {
|
||||
m.stateMutex.Lock()
|
||||
m.state.Accounts.Available = false
|
||||
m.stateMutex.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
m.accountsObj = m.systemConn.Object(dbusAccountsDest, userPath)
|
||||
|
||||
m.stateMutex.Lock()
|
||||
m.state.Accounts.Available = true
|
||||
m.state.Accounts.UserPath = string(userPath)
|
||||
m.state.Accounts.UID = m.currentUID
|
||||
m.stateMutex.Unlock()
|
||||
|
||||
if err := m.updateAccountsState(); err != nil {
|
||||
return fmt.Errorf("failed to update accounts state: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) initializeSettings() error {
|
||||
if m.sessionConn == nil {
|
||||
m.stateMutex.Lock()
|
||||
m.state.Settings.Available = false
|
||||
m.stateMutex.Unlock()
|
||||
return fmt.Errorf("no session bus connection")
|
||||
}
|
||||
|
||||
m.settingsObj = m.sessionConn.Object(dbusPortalDest, dbus.ObjectPath(dbusPortalPath))
|
||||
|
||||
var variant dbus.Variant
|
||||
err := m.settingsObj.Call(dbusPortalSettingsInterface+".ReadOne", 0, "org.freedesktop.appearance", "color-scheme").Store(&variant)
|
||||
if err != nil {
|
||||
m.stateMutex.Lock()
|
||||
m.state.Settings.Available = false
|
||||
m.stateMutex.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
m.stateMutex.Lock()
|
||||
m.state.Settings.Available = true
|
||||
m.stateMutex.Unlock()
|
||||
|
||||
if err := m.updateSettingsState(); err != nil {
|
||||
return fmt.Errorf("failed to update settings state: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) updateAccountsState() error {
|
||||
if !m.state.Accounts.Available || m.accountsObj == nil {
|
||||
return fmt.Errorf("accounts service not available")
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
props, err := m.getAccountProperties(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.stateMutex.Lock()
|
||||
defer m.stateMutex.Unlock()
|
||||
|
||||
if v, ok := props["IconFile"]; ok {
|
||||
if val, ok := v.Value().(string); ok {
|
||||
m.state.Accounts.IconFile = val
|
||||
}
|
||||
}
|
||||
if v, ok := props["RealName"]; ok {
|
||||
if val, ok := v.Value().(string); ok {
|
||||
m.state.Accounts.RealName = val
|
||||
}
|
||||
}
|
||||
if v, ok := props["UserName"]; ok {
|
||||
if val, ok := v.Value().(string); ok {
|
||||
m.state.Accounts.UserName = val
|
||||
}
|
||||
}
|
||||
if v, ok := props["AccountType"]; ok {
|
||||
if val, ok := v.Value().(int32); ok {
|
||||
m.state.Accounts.AccountType = val
|
||||
}
|
||||
}
|
||||
if v, ok := props["HomeDirectory"]; ok {
|
||||
if val, ok := v.Value().(string); ok {
|
||||
m.state.Accounts.HomeDirectory = val
|
||||
}
|
||||
}
|
||||
if v, ok := props["Shell"]; ok {
|
||||
if val, ok := v.Value().(string); ok {
|
||||
m.state.Accounts.Shell = val
|
||||
}
|
||||
}
|
||||
if v, ok := props["Email"]; ok {
|
||||
if val, ok := v.Value().(string); ok {
|
||||
m.state.Accounts.Email = val
|
||||
}
|
||||
}
|
||||
if v, ok := props["Language"]; ok {
|
||||
if val, ok := v.Value().(string); ok {
|
||||
m.state.Accounts.Language = val
|
||||
}
|
||||
}
|
||||
if v, ok := props["Location"]; ok {
|
||||
if val, ok := v.Value().(string); ok {
|
||||
m.state.Accounts.Location = val
|
||||
}
|
||||
}
|
||||
if v, ok := props["Locked"]; ok {
|
||||
if val, ok := v.Value().(bool); ok {
|
||||
m.state.Accounts.Locked = val
|
||||
}
|
||||
}
|
||||
if v, ok := props["PasswordMode"]; ok {
|
||||
if val, ok := v.Value().(int32); ok {
|
||||
m.state.Accounts.PasswordMode = val
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) updateSettingsState() error {
|
||||
if !m.state.Settings.Available || m.settingsObj == nil {
|
||||
return fmt.Errorf("settings portal not available")
|
||||
}
|
||||
|
||||
var variant dbus.Variant
|
||||
err := m.settingsObj.Call(dbusPortalSettingsInterface+".ReadOne", 0, "org.freedesktop.appearance", "color-scheme").Store(&variant)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if colorScheme, ok := variant.Value().(uint32); ok {
|
||||
m.stateMutex.Lock()
|
||||
m.state.Settings.ColorScheme = colorScheme
|
||||
m.stateMutex.Unlock()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) getAccountProperties(ctx context.Context) (map[string]dbus.Variant, error) {
|
||||
var props map[string]dbus.Variant
|
||||
err := m.accountsObj.CallWithContext(ctx, dbusPropsInterface+".GetAll", 0, dbusAccountsUserInterface).Store(&props)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return props, nil
|
||||
}
|
||||
|
||||
func (m *Manager) GetState() FreedeskState {
|
||||
m.stateMutex.RLock()
|
||||
defer m.stateMutex.RUnlock()
|
||||
return *m.state
|
||||
}
|
||||
|
||||
func (m *Manager) Subscribe(id string) chan FreedeskState {
|
||||
ch := make(chan FreedeskState, 64)
|
||||
m.subMutex.Lock()
|
||||
m.subscribers[id] = ch
|
||||
m.subMutex.Unlock()
|
||||
return ch
|
||||
}
|
||||
|
||||
func (m *Manager) Unsubscribe(id string) {
|
||||
m.subMutex.Lock()
|
||||
if ch, ok := m.subscribers[id]; ok {
|
||||
close(ch)
|
||||
delete(m.subscribers, id)
|
||||
}
|
||||
m.subMutex.Unlock()
|
||||
}
|
||||
|
||||
func (m *Manager) NotifySubscribers() {
|
||||
m.subMutex.RLock()
|
||||
defer m.subMutex.RUnlock()
|
||||
|
||||
state := m.GetState()
|
||||
for _, ch := range m.subscribers {
|
||||
select {
|
||||
case ch <- state:
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Manager) Close() {
|
||||
m.subMutex.Lock()
|
||||
for id, ch := range m.subscribers {
|
||||
close(ch)
|
||||
delete(m.subscribers, id)
|
||||
}
|
||||
m.subMutex.Unlock()
|
||||
|
||||
if m.systemConn != nil {
|
||||
m.systemConn.Close()
|
||||
}
|
||||
if m.sessionConn != nil {
|
||||
m.sessionConn.Close()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user