Created
July 6, 2025 18:38
-
-
Save looterz/73b17d92469db1c42a38ee8290dad886 to your computer and use it in GitHub Desktop.
Wails V3 Service issue
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// services/configservice.go | |
package services | |
import ( | |
"bytes" | |
"context" | |
"errors" | |
"log" | |
"os" | |
"path/filepath" | |
"sort" | |
"github.com/BurntSushi/toml" | |
"github.com/wailsapp/wails/v3/pkg/application" | |
) | |
// --- Configuration Structs (No Changes) --- | |
type GlobalSettings struct { | |
AutoRefresh bool `toml:"auto_refresh"` | |
ShowNotifications bool `toml:"show_notifications"` | |
RefreshInterval int `toml:"refresh_interval"` | |
MaxChanges int `toml:"max_changes"` | |
} | |
type Project struct { | |
Name string `toml:"name"` | |
Path string `toml:"path"` | |
} | |
type AppConfig struct { | |
Global GlobalSettings `toml:"global"` | |
Projects map[string]*Project `toml:"projects"` | |
} | |
type ConfigService struct { | |
ctx context.Context | |
config *AppConfig | |
filePath string | |
} | |
func NewConfigService() *ConfigService { | |
return &ConfigService{} | |
} | |
// ServiceStartup is called by Wails at the beginning of the application lifecycle. | |
// This is the correct place to initialize our service. | |
func (s *ConfigService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error { | |
s.ctx = ctx | |
// Get the path of the executable to place the config file next to it. | |
exePath, err := os.Executable() | |
if err != nil { | |
log.Println("FATAL: Failed to get executable path:", err) | |
return err | |
} | |
exeDir := filepath.Dir(exePath) | |
s.filePath = filepath.Join(exeDir, "ultragamesync.toml") | |
log.Println("Initializing ConfigService. Config file path is:", s.filePath) | |
if err := s.Load(); err != nil { | |
log.Println("FATAL: Failed to load config:", err) | |
return err | |
} | |
return nil | |
} | |
// Load reads the config.toml file from disk or creates a default one. | |
func (s *ConfigService) Load() error { | |
if _, err := os.Stat(s.filePath); errors.Is(err, os.ErrNotExist) { | |
log.Println("Config file not found. Creating default config.") | |
s.config = &AppConfig{ | |
Global: GlobalSettings{ | |
AutoRefresh: true, | |
ShowNotifications: true, | |
RefreshInterval: 5, | |
MaxChanges: 100, | |
}, | |
Projects: map[string]*Project{ | |
"MyProject": { | |
}, | |
}, | |
} | |
return s.save() | |
} | |
log.Println("Loading existing config from:", s.filePath) | |
var config AppConfig | |
if _, err := toml.DecodeFile(s.filePath, &config); err != nil { | |
return err | |
} | |
s.config = &config | |
return nil | |
} | |
// save is an internal helper to write the current config state to disk. | |
func (s *ConfigService) save() error { | |
var buf bytes.Buffer | |
encoder := toml.NewEncoder(&buf) | |
if err := encoder.Encode(s.config); err != nil { | |
return err | |
} | |
return os.WriteFile(s.filePath, buf.Bytes(), 0644) | |
} | |
// === Bound Methods === | |
// GetConfig returns the currently loaded application configuration. | |
func (s *ConfigService) GetConfig() *AppConfig { | |
// The lazy-load workaround is no longer needed because ServiceStartup will handle it. | |
return s.config | |
} | |
// SaveConfig receives a new configuration from the frontend and saves it. | |
func (s *ConfigService) SaveConfig(newConfig AppConfig) error { | |
s.config = &newConfig | |
return s.save() | |
} | |
// GetProjectNames returns a sorted list of all configured project names. | |
func (s *ConfigService) GetProjectNames() []string { | |
names := make([]string, 0, len(s.config.Projects)) | |
for name := range s.config.Projects { | |
names = append(names, name) | |
} | |
sort.Strings(names) | |
return names | |
} | |
// AddProject adds a new project to the configuration and saves it. | |
func (s *ConfigService) AddProject(newProject Project) error { | |
if _, exists := s.config.Projects[newProject.Name]; exists { | |
return errors.New("a project with this name already exists") | |
} | |
if s.config.Projects == nil { | |
s.config.Projects = make(map[string]*Project) | |
} | |
s.config.Projects[newProject.Name] = &newProject | |
return s.save() | |
} | |
// UpdateProject updates an existing project's configuration. | |
func (s *ConfigService) UpdateProject(projectName string, updatedProject Project) error { | |
if _, exists := s.config.Projects[projectName]; !exists { | |
return errors.New("project not found") | |
} | |
s.config.Projects[projectName] = &updatedProject | |
return s.save() | |
} | |
// DeleteProject removes a project from the configuration. | |
func (s *ConfigService) DeleteProject(projectName string) error { | |
if _, exists := s.config.Projects[projectName]; !exists { | |
return errors.New("project not found") | |
} | |
delete(s.config.Projects, projectName) | |
return s.save() | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
app := application.New(application.Options{ | |
Name: "Test", | |
Description: "", | |
Services: []application.Service{ | |
application.NewService(services.NewConfigService()), | |
}, | |
Assets: application.AssetOptions{ | |
Handler: application.AssetFileServerFS(assets), | |
}, | |
Mac: application.MacOptions{ | |
ApplicationShouldTerminateAfterLastWindowClosed: true, | |
}, | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment