Skip to content

Commit

Permalink
Force writing preferences to file when application stops
Browse files Browse the repository at this point in the history
  • Loading branch information
nullst committed Jul 9, 2023
1 parent e050d79 commit 86eb71f
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 2 deletions.
5 changes: 5 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@ func newAppWithDriver(d fyne.Driver, id string) fyne.App {
fyne.SetCurrentApp(newApp)

newApp.prefs = newApp.newDefaultPreferences()
newApp.lifecycle.(*app.Lifecycle).SetAfterStopped(func() {
if prefs, ok := newApp.prefs.(*preferences); ok {
prefs.forceImmediateSave()
}
})
newApp.settings = loadSettings()
store := &store{a: newApp}
store.Docs = makeStoreDocs(id, newApp.prefs, store)
Expand Down
17 changes: 16 additions & 1 deletion app/preferences.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,25 @@ type preferences struct {
savedRecently bool
changedDuringSaving bool

app *fyneApp
app *fyneApp
needsSaveBeforeExit bool
}

// Declare conformity with Preferences interface
var _ fyne.Preferences = (*preferences)(nil)

// forceImmediateSave writes preferences to file immediately, ignoring the debouncing
// logic in the change listener. Does nothing if preferences are not backed with a file.
func (p *preferences) forceImmediateSave() {
if !p.needsSaveBeforeExit {
return
}
err := p.save()
if err != nil {
fyne.LogError("Failed on force saving preferences", err)
}
}

func (p *preferences) resetSavedRecently() {
go func() {
time.Sleep(time.Millisecond * 100) // writes are not always atomic. 10ms worked, 100 is safer.
Expand All @@ -49,6 +62,7 @@ func (p *preferences) saveToFile(path string) error {
p.savedRecently = true
p.prefLock.Unlock()
defer p.resetSavedRecently()

err := os.MkdirAll(filepath.Dir(path), 0700)
if err != nil { // this is not an exists error according to docs
return err
Expand Down Expand Up @@ -132,6 +146,7 @@ func newPreferences(app *fyneApp) *preferences {
return p
}

p.needsSaveBeforeExit = true
p.AddChangeListener(func() {
if p != app.prefs {
return
Expand Down
15 changes: 14 additions & 1 deletion internal/app/lifecycle.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ type Lifecycle struct {
onBackground atomic.Value // func()
onStarted atomic.Value // func()
onStopped atomic.Value // func()

internalAfterStoppedTrigger atomic.Value // func()
}

// SetAfterStopped is an internal function that lets Fyne schedule a clean-up after
// the user-provided stopped hook.
func (l *Lifecycle) SetAfterStopped(f func()) {
l.internalAfterStoppedTrigger.Store(f)
}

// SetOnEnteredForeground hooks into the the app becoming foreground.
Expand Down Expand Up @@ -64,10 +72,15 @@ func (l *Lifecycle) TriggerStarted() {
}
}

// TriggerStopped will call the stopped hook, if one is registered.
// TriggerStopped will call the stopped hook, if one is registered,
// and an internal stopped hook after that.
func (l *Lifecycle) TriggerStopped() {
f := l.onStopped.Load()
if ff, ok := f.(func()); ok && ff != nil {
ff()
}
f = l.internalAfterStoppedTrigger.Load()
if ff, ok := f.(func()); ok && ff != nil {
ff()
}
}

0 comments on commit 86eb71f

Please sign in to comment.