From 678c2194dba875811ec500d5b3b818524ab93c25 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 30 Aug 2020 15:46:50 +1000 Subject: [PATCH] Add Sync Store --- runtime/store.go | 117 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 runtime/store.go diff --git a/runtime/store.go b/runtime/store.go new file mode 100644 index 000000000..a8c4b69a6 --- /dev/null +++ b/runtime/store.go @@ -0,0 +1,117 @@ +package runtime + +// Options defines the optional data that may be used +// when creating a Store +type Options struct { + + // The name of the store + Name string + + // The runtime to attach the store to + Runtime *Runtime + + // Indicates if notifying Go listeners should be notified of updates + // synchronously (on the current thread) or asynchronously using + // goroutines + NotifySynchronously bool +} + +type StoreProvider struct { + runtime *Runtime +} + +func NewStoreProvider(runtime *Runtime) *StoreProvider { + return &StoreProvider{ + runtime: runtime, + } +} + +// Store is where we keep named data +type Store struct { + name string + data interface{} + eventPrefix string + callbacks []func(interface{}) + runtime *Runtime + notifySynchronously bool +} + +// New creates a new store +func (p *StoreProvider) New(name string) *Store { + + result := Store{ + name: name, + runtime: p.runtime, + } + + result.setupListner() + + return &result +} + +// NewWithOptions creates a new store with the given options +func (p *StoreProvider) NewWithOptions(options Options) *Store { + + result := Store{ + name: options.Name, + notifySynchronously: options.NotifySynchronously, + } + + return &result +} + +func (s *Store) setupListner() { + // Setup listener + s.runtime.Events.On("wails:sync:store:updated:"+s.name, func(data ...interface{}) { + + // store the data + s.data = data[0] + + // Notify listeners + s.notify() + }) +} + +// notify the listeners of the current data state +func (s *Store) notify() { + + // Notify callbacks + for _, callback := range s.callbacks { + + if s.notifySynchronously { + callback(s.data) + } else { + go callback(s.data) + } + + } +} + +// Set will update the data held by the store +// and notify listeners of the change +func (s *Store) Set(data interface{}) { + + // Save data + s.data = data + + // Emit event + s.runtime.Events.Emit("wails:sync:store:updated:"+s.name, s.data) + + // Notify listeners + s.notify() +} + +// Subscribe will subscribe to updates to the store by +// providing a callback. Any updates to the store are sent +// to the callback +func (s *Store) Subscribe(callback func(interface{})) { + s.callbacks = append(s.callbacks, callback) +} + +// Update takes a function that is passed the current state. +// The result of that function is then set as the new state +// of the store. This will notify listeners of the change +func (s *Store) Update(updater func(interface{}) interface{}) { + newData := updater(s.data) + s.Set(newData) +}