Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-fix #2449 #2477

Merged
merged 9 commits into from Sep 30, 2021
41 changes: 31 additions & 10 deletions app/preferences.go
Expand Up @@ -14,21 +14,29 @@ import (
type preferences struct {
*internal.InMemoryPreferences

prefLock sync.RWMutex
ignoreChange bool
prefLock sync.RWMutex
loadingInProgress bool
savedRecently bool
changedDuringSaving bool

app *fyneApp
}

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

func (p *preferences) resetIgnore() {
func (p *preferences) resetSavedRecently() {
go func() {
time.Sleep(time.Millisecond * 100) // writes are not always atomic. 10ms worked, 100 is safer.
p.prefLock.Lock()
p.ignoreChange = false
p.savedRecently = false
changedDuringSaving := p.changedDuringSaving
p.changedDuringSaving = false
p.prefLock.Unlock()

if changedDuringSaving {
p.save()
}
}()
}

Expand All @@ -38,9 +46,9 @@ func (p *preferences) save() error {

func (p *preferences) saveToFile(path string) error {
p.prefLock.Lock()
p.ignoreChange = true
p.savedRecently = true
p.prefLock.Unlock()
defer p.resetIgnore()
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 @@ -95,9 +103,18 @@ func (p *preferences) loadFromFile(path string) (err error) {
}()
decode := json.NewDecoder(file)

p.prefLock.Lock()
p.loadingInProgress = true
p.prefLock.Unlock()

p.InMemoryPreferences.WriteValues(func(values map[string]interface{}) {
err = decode.Decode(&values)
})

p.prefLock.Lock()
p.loadingInProgress = false
p.prefLock.Unlock()

return err
}

Expand All @@ -112,10 +129,14 @@ func newPreferences(app *fyneApp) *preferences {
}

p.AddChangeListener(func() {
p.prefLock.RLock()
shouldIgnoreChange := p.ignoreChange
p.prefLock.RUnlock()
if shouldIgnoreChange { // callback after loading, no need to save
p.prefLock.Lock()
shouldIgnoreChange := p.savedRecently || p.loadingInProgress
if p.savedRecently && !p.loadingInProgress {
p.changedDuringSaving = true
}
p.prefLock.Unlock()

if shouldIgnoreChange { // callback after loading file, or too many updates in a row
return
}

Expand Down
2 changes: 1 addition & 1 deletion app/preferences_other.go
Expand Up @@ -17,7 +17,7 @@ func (a *fyneApp) storageRoot() string {
func (p *preferences) watch() {
watchFile(p.storagePath(), func() {
p.prefLock.RLock()
shouldIgnoreChange := p.ignoreChange
shouldIgnoreChange := p.savedRecently
p.prefLock.RUnlock()
if shouldIgnoreChange {
return
Expand Down