feat(ui): 开机自启动 + 窗口大小记忆

- win32/autostart: SetAutoStart/IsAutoStartEnabled 操作 HKCU Run 键
- win32/window_size: GetWindowSize 通过 GetWindowRect 获取窗口尺寸
- config: 新增 AutoStart、WindowWidth、WindowHeight 字段
- store: Preferences/SetPreferences 扩展支持 autoStart + windowSize
- dialog_preferences: 新增"开机自启动"复选框
- app.go: 启动时恢复窗口大小,关闭时通过 SetWindowSize 保存
- i18n: label_auto_start / hint_auto_start 三语翻译
This commit is contained in:
2026-06-12 11:10:25 +08:00
parent cb4d88ebdd
commit 1605b5b7ae
11 changed files with 278 additions and 17 deletions
+27 -3
View File
@@ -33,6 +33,9 @@ type store struct {
theme string
autoLockMinutes int
minimizeToTray bool
autoStart bool
windowWidth int
windowHeight int
// dirty signals a save is pending. The worker reads & resets it.
dirty bool
@@ -47,21 +50,24 @@ type store struct {
// Preferences returns the persisted top-level prefs. UI code reads these
// after Load to seed dialog defaults.
func (s *store) Preferences() (language, theme string, autoLockMinutes int, minimizeToTray bool) {
func (s *store) Preferences() (language, theme string, autoLockMinutes int, minimizeToTray, autoStart bool, windowWidth, windowHeight int) {
s.mu.Lock()
defer s.mu.Unlock()
return s.language, s.theme, s.autoLockMinutes, s.minimizeToTray
return s.language, s.theme, s.autoLockMinutes, s.minimizeToTray, s.autoStart, s.windowWidth, s.windowHeight
}
// SetPreferences updates the persisted top-level prefs and schedules a
// save. Callers pass the current value for each field — there is no
// per-field "leave unchanged" sentinel.
func (s *store) SetPreferences(language, theme string, autoLockMinutes int, minimizeToTray bool) {
func (s *store) SetPreferences(language, theme string, autoLockMinutes int, minimizeToTray, autoStart bool, windowWidth, windowHeight int) {
s.mu.Lock()
s.language = language
s.theme = theme
s.autoLockMinutes = autoLockMinutes
s.minimizeToTray = minimizeToTray
s.autoStart = autoStart
s.windowWidth = windowWidth
s.windowHeight = windowHeight
s.mu.Unlock()
s.Push()
}
@@ -119,6 +125,9 @@ func (s *store) Load(passphrase []byte) (*config.Config, error) {
s.theme = cfg.Theme
s.autoLockMinutes = cfg.AutoLockMinutes
s.minimizeToTray = cfg.MinimizeToTray
s.autoStart = cfg.AutoStart
s.windowWidth = cfg.WindowWidth
s.windowHeight = cfg.WindowHeight
s.mu.Unlock()
logger.WithField("entries", len(cfg.Entries)).Debug("config loaded into store")
return cfg, nil
@@ -160,6 +169,15 @@ func (s *store) Encrypted() bool {
return s.encrypted
}
// SetWindowSize updates the stored window dimensions and schedules a save.
func (s *store) SetWindowSize(w, h int) {
s.mu.Lock()
s.windowWidth = w
s.windowHeight = h
s.mu.Unlock()
s.Push()
}
// Push schedules a save. Calls within ~300ms of each other coalesce into
// a single write.
func (s *store) Push() {
@@ -196,6 +214,9 @@ func (s *store) run() {
theme := s.theme
autoLock := s.autoLockMinutes
minToTray := s.minimizeToTray
autoStart := s.autoStart
winW := s.windowWidth
winH := s.windowHeight
s.mu.Unlock()
entries := s.snapshotFn()
@@ -205,6 +226,9 @@ func (s *store) run() {
Theme: theme,
AutoLockMinutes: autoLock,
MinimizeToTray: minToTray,
AutoStart: autoStart,
WindowWidth: winW,
WindowHeight: winH,
Encrypted: enc,
Entries: entries,
}