func (m *PriceStore) Handle(payload *flux.Payload) (finished bool) { switch payload.Action.(type) { case *UpdateCountryAction, *UpdateCity: payload.Wait(m.app.City) m.price = calculatePrice(m.app.Country.GetCountry(), m.app.City.GetCity()) } return true }
func (m *CityStore) Handle(payload *flux.Payload) (finished bool) { switch action := payload.Action.(type) { case *UpdateCity: m.city = action.City case *UpdateCountryAction: payload.Wait(m.app.Country) m.city = getCapital(m.app.Country.GetCountry()) } return true }
func (m *MessageStore) Handle(payload *flux.Payload) (finished bool) { switch action := payload.Action.(type) { case *AddTopic: payload.Wait(m.app.Topics) m.messages = append(m.messages, action.Message) case *AddMessage: m.messages = append(m.messages, action.Message) } return true }
func (s *EditorStore) Handle(payload *flux.Payload) bool { switch action := payload.Action.(type) { case *actions.EditorData: action.Func(payload) case *actions.Add: payload.Wait(s.app.Branches) switch action.Direction() { case actions.New, actions.Redo: mutateAddEditor(s, action.Node, action.Parent) case actions.Undo: mutateDeleteEditor(s, action.Node, action.Parent) } case *actions.Delete: payload.Wait(s.app.Branches) switch action.Direction() { case actions.New, actions.Redo: mutateDeleteEditor(s, action.Node, action.Parent) case actions.Undo: mutateAddEditor(s, action.Node, action.Parent) } case *actions.InitialState: payload.Wait(s.app.Package, s.app.Types, s.app.Data) s.AddEditorsRecursively(s.app.Package.Node()) for _, ti := range s.app.Types.All() { s.AddEditorsRecursively(ti.Node) } case *actions.LoadFileSuccess: ni, ok := action.Branch.Contents.(models.NodeContentsInterface) if !ok { break } n := ni.GetNode() s.AddEditorsRecursively(n) } return true }
func (s *NodeStore) Handle(payload *flux.Payload) bool { switch action := payload.Action.(type) { case *actions.ToggleSystemControls: m := s.Get(action.Node) m.ShowSystemControls = !m.ShowSystemControls payload.Notify(action.Node, NodeSystemControls) case *actions.Add: payload.Wait(s.app.Actions) switch action.Direction() { case actions.New: if err := mutateAddNode(s.ctx, action.Node, action.Parent, action.Key, action.Index, action.Type, action.BranchName); err != nil { s.app.Fail <- kerr.Wrap("HUOGBUQCAO", err) break } payload.Notify(action.Node, NodeInitialised) if action.Parent != nil { payload.Notify(action.Parent, NodeChildAdded) } payload.Notify(action.Node, NodeFocus) case actions.Undo: action.Backup = node.NewNode() if err := mutateDeleteNode(s.ctx, action.Node, action.Parent, action.Backup); err != nil { s.app.Fail <- kerr.Wrap("RTAGMUIKMD", err) break } payload.Notify(action.Node, NodeDeleted) if action.Parent != nil { payload.Notify(action.Parent, NodeChildDeleted) } case actions.Redo: if err := mutateRestoreNode(s.ctx, action.Node, action.Parent, action.Backup); err != nil { s.app.Fail <- kerr.Wrap("MHUTMXOGBP", err) break } payload.Notify(action.Node, NodeInitialised) payload.Notify(action.Parent, NodeChildAdded) payload.Notify(action.Node, NodeFocus) } if action.Parent != nil { model := s.app.Nodes.Get(action.Parent) changed, err := model.Validate(s.ctx, s.app.Rule.Get(action.Parent.Root(), action.Parent)) if err != nil { s.app.Fail <- kerr.Wrap("AKIUPRWGLV", err) break } if changed { payload.Notify(action.Parent, NodeErrorsChanged) } } c := action.Parent for c != nil { payload.Notify(c, NodeDescendantChanged) c = c.Parent } case *actions.Delete: payload.Wait(s.app.Actions) switch action.Direction() { case actions.New, actions.Redo: action.Backup = node.NewNode() if err := mutateDeleteNode(s.ctx, action.Node, action.Parent, action.Backup); err != nil { s.app.Fail <- kerr.Wrap("DFHTKJRLQC", err) break } payload.Notify(action.Node, NodeDeleted) payload.Notify(action.Parent, NodeChildDeleted) case actions.Undo: if err := mutateRestoreNode(s.ctx, action.Node, action.Parent, action.Backup); err != nil { s.app.Fail <- kerr.Wrap("HAPWUOPBTW", err) break } payload.Notify(action.Node, NodeInitialised) payload.Notify(action.Parent, NodeChildAdded) payload.Notify(action.Node, NodeFocus) } if action.Parent != nil { model := s.app.Nodes.Get(action.Parent) changed, err := model.Validate(s.ctx, s.app.Rule.Get(action.Parent.Root(), action.Parent)) if err != nil { s.app.Fail <- kerr.Wrap("IOFCSITVXB", err) break } if changed { payload.Notify(action.Parent, NodeErrorsChanged) } } c := action.Parent for c != nil { payload.Notify(c, NodeDescendantChanged) c = c.Parent } case *actions.Reorder: payload.Wait(s.app.Actions) if !action.Model.Node.Type.IsNativeArray() { s.app.Fail <- kerr.New("EPBQVIICFM", "Must be array") break } from := action.Before to := action.After if action.Direction() == actions.Undo { from = action.After to = action.Before } if err := action.Model.Node.ReorderArrayChild(from, to); err != nil { s.app.Fail <- kerr.Wrap("HMIFPKVJCN", err) break } payload.Notify(action.Model.Node, NodeArrayReorder) c := action.Model.Node.Parent for c != nil { payload.Notify(c, NodeDescendantChanged) c = c.Parent } case *actions.Modify: payload.Wait(s.app.Actions) n := action.Editor.Node val := action.After if action.Direction() == actions.Undo { val = action.Before } if err := n.SetValue(s.ctx, val); err != nil { s.app.Fail <- kerr.Wrap("VIMXVIHPFY", err) break } model := s.app.Nodes.Get(n) changed, err := model.Validate(s.ctx, s.app.Rule.Get(n.Root(), n)) if err != nil { s.app.Fail <- kerr.Wrap("EEIYMGQCCA", err) break } if changed { payload.Notify(n, NodeErrorsChanged) } payload.Notify(n, NodeValueChanged) c := n.Parent for c != nil { payload.Notify(c, NodeDescendantChanged) c = c.Parent } case *actions.EditorFocus: payload.Notify(action.Editor.Node, NodeFocus) case *actions.InitialState: payload.Wait(s.app.Package, s.app.Types) n := s.app.Package.Node() if err := n.RecomputeHash(s.ctx, true); err != nil { s.app.Fail <- kerr.Wrap("NDMDVGISWR", err) } for _, ti := range s.app.Types.All() { if err := ti.Node.RecomputeHash(s.ctx, true); err != nil { s.app.Fail <- kerr.Wrap("YLRDBXIYJH", err) } } case *actions.LoadFileSuccess: nci, ok := action.Branch.Contents.(models.NodeContentsInterface) if !ok { break } if err := nci.GetNode().RecomputeHash(s.ctx, true); err != nil { s.app.Fail <- kerr.Wrap("BWUPWAFALG", err) } } if m, ok := payload.Action.(actions.Mutator); ok { n := m.CommonAncestor() c := n for c != nil { // For the actual node, we recompute the whole hash. For ancestors, // we recompute the hash without recomputing child nodes. recomputeChildren := c == n if err := c.RecomputeHash(s.ctx, recomputeChildren); err != nil { s.app.Fail <- kerr.Wrap("SWHIXHLHXM", err) } c = c.Parent } } return true }
func (s *BranchStore) Handle(payload *flux.Payload) bool { previous := s.selected switch action := payload.Action.(type) { case *actions.ChangeView: s.view = action.View s.selected = s.Root() payload.Notify(nil, ViewChanged) case *actions.Add: payload.Wait(s.app.Nodes) switch action.Direction() { case actions.New, actions.Redo: child, parent, err := mutateAppendBranch(s, action.Parent, action.Node, action.BranchName, action.BranchFile) if err != nil { s.app.Fail <- kerr.Wrap("LDBMBRHWHB", err) break } if child != nil { if ancestor := child.EnsureVisible(); ancestor != nil { payload.NotifyWithData(ancestor, BranchOpened, &BranchDescendantSelectData{ Branch: child, Op: models.BranchOpChildAdded, }) } s.selected = child payload.Notify(previous, BranchUnselectControl) payload.Notify(s.selected, BranchSelectControl) payload.Notify(s.selected, BranchSelected) } if parent != nil { payload.Notify(parent, BranchChildAdded) } case actions.Undo: _, parent, err := mutateDeleteBranch(s, action.Node) if err != nil { s.app.Fail <- kerr.Wrap("NLFWVSNNTY", err) break } if parent != nil { payload.Notify(parent, BranchChildDeleted) s.selected = parent payload.Notify(previous, BranchUnselectControl) payload.Notify(s.selected, BranchSelectControl) payload.Notify(s.selected, BranchSelected) } } case *actions.Delete: payload.Wait(s.app.Nodes) switch action.Direction() { case actions.New, actions.Redo: branch, parent, err := mutateDeleteBranch(s, action.Node) if err != nil { s.app.Fail <- kerr.Wrap("QTXPXAKXHH", err) break } if branch != nil { action.BranchIndex = branch.Index if nci, ok := branch.Contents.(models.NodeContentsInterface); ok { action.BranchName = nci.GetName() } if fci, ok := branch.Contents.(models.FileContentsInterface); ok { action.BranchFile = fci.GetFilename() } } if parent != nil { payload.Notify(parent, BranchChildDeleted) s.selected = parent payload.Notify(previous, BranchUnselectControl) payload.Notify(s.selected, BranchSelectControl) payload.Notify(s.selected, BranchSelected) } case actions.Undo: child, parent, err := mutateInsertBranch(s, action.Parent, action.Node, action.BranchIndex, action.BranchName, action.BranchFile) if err != nil { s.app.Fail <- kerr.Wrap("OOGOEWKPIL", err) break } if child != nil { if ancestor := child.EnsureVisible(); ancestor != nil { payload.NotifyWithData(ancestor, BranchOpened, &BranchDescendantSelectData{ Branch: child, Op: models.BranchOpChildAdded, }) } s.selected = child payload.Notify(previous, BranchUnselectControl) payload.Notify(s.selected, BranchSelectControl) payload.Notify(s.selected, BranchSelected) } if parent != nil { payload.Notify(parent, BranchChildAdded) } } case *actions.Reorder: payload.Wait(s.app.Nodes) parent, err := mutateReorderBranch(s, action.Model.Node) if err != nil { s.app.Fail <- kerr.Wrap("NUQOPWWXHA", err) break } if parent != nil { payload.Notify(parent, BranchChildrenReordered) } case *actions.BranchClose: if !action.Branch.CanOpen() { // branch can't open - ignore break } action.Branch.RecursiveClose() payload.Notify(action.Branch, BranchClose) case *actions.BranchOpening: if !action.Branch.CanOpen() { // branch can't open - ignore break } // The branch may not be loaded, so we don't open the branch until the BranchOpenPostLoad // action is received. This will happen immediately if the branch is loaded or not async. payload.Notify(action.Branch, BranchOpening) case *actions.BranchOpened: if !action.Branch.CanOpen() { // branch can't open - ignore break } action.Branch.Open = true payload.Notify(action.Branch, BranchOpened) case *actions.BranchSelecting: if ancestor := action.Branch.EnsureVisible(); ancestor != nil { payload.NotifyWithData(ancestor, BranchOpened, &BranchDescendantSelectData{ Branch: action.Branch, Op: action.Op, }) break } s.selected = action.Branch payload.Notify(previous, BranchUnselectControl) payload.Notify(s.selected, BranchSelectControl) if action.Op == models.BranchOpKeyboard { go func() { <-time.After(common.EditorKeyboardDebounceShort) if s.selected == action.Branch { payload.NotifyWithData( s.selected, BranchSelecting, &BranchSelectOperationData{Op: action.Op}, ) } }() } else { payload.NotifyWithData( s.selected, BranchSelecting, &BranchSelectOperationData{Op: action.Op}, ) } case *actions.BranchSelected: payload.Wait(s.app.Nodes) payload.Notify(s.selected, BranchSelected) case *actions.InitialState: payload.Wait(s.app.Package, s.app.Types, s.app.Data, s.app.Env) s.pkg = s.NewFileBranchModel(s.ctx, s.app.Package.Node(), "package", s.app.Package.Filename()) s.pkg.Root = true s.pkg.Open = true s.types = models.NewBranchModel(s.ctx, &models.TypesContents{}) s.types.Root = true s.types.Open = true for _, name := range s.app.Types.Names() { t := s.app.Types.Get(name) typeBranch := s.NewFileBranchModel(s.ctx, t.Node, name, t.File) s.types.Append(typeBranch) } s.data = models.NewBranchModel(s.ctx, &models.DataContents{}) s.data.Root = true s.data.Open = true for _, name := range s.app.Data.Names() { s.data.Append(models.NewBranchModel(s.ctx, &models.AsyncContents{ FileContents: models.FileContents{ NodeContents: models.NodeContents{ Name: name, }, Filename: s.app.Data.Get(name).File, }, })) } s.selected = s.data payload.Notify(nil, BranchInitialStateLoaded) case *actions.LoadFileSuccess: ni, ok := action.Branch.Contents.(models.NodeContentsInterface) if !ok { break } n := ni.GetNode() s.AppendNodeBranchModelChildren(action.Branch, n) s.nodeBranches[n] = action.Branch payload.Notify(action.Branch, BranchLoaded) } return true }
func (s *RuleStore) Handle(payload *flux.Payload) bool { switch action := payload.Action.(type) { case *actions.InitialState: payload.Wait(s.app.Package, s.app.Types) s.validateNodes(payload, s.build(s.app.Package.Node())) for _, t := range s.app.Types.All() { s.validateNodes(payload, s.build(t.Node)) } case *actions.LoadFileSuccess: payload.Wait(s.app.Branches) ni, ok := action.Branch.Contents.(models.NodeContentsInterface) if !ok { break } n := ni.GetNode() s.validateNodes(payload, s.build(n)) case *actions.Modify: payload.Wait(s.app.Nodes) // Node mutations that are in response to keyboard input should wait an // additional time before doing a full validation rebuild. This // operation may be expensive, so we shouldn't risk interupting the // user input. if action.Direction() != actions.New || action.Immediate { // Undo and Redo actions are from mouse input, so always immediate. // New actions are immediate if action.Immediate == true s.validateNodes(payload, s.build(action.Editor.Node.Root())) break } // Delayed actions wait an extra time before the validation rebuild. go func() { // We have already waited for EditorKeyboardDebounceShort, so we // reduce the duration by this. <-time.After(common.EditorKeyboardDebounceLong - common.EditorKeyboardDebounceShort) if action.Changed() { return } s.validateNodes(payload, s.build(action.Editor.Node.Root())) }() case *actions.Reorder: payload.Wait(s.app.Nodes) s.validateNodes(payload, s.build(action.Model.Node.Root())) case *actions.Delete: payload.Wait(s.app.Nodes) s.validateNodes(payload, s.build(action.Node.Root())) case *actions.Add: payload.Wait(s.app.Nodes) s.validateNodes(payload, s.build(action.Node.Root())) } return true }
func (s *FileStore) Handle(payload *flux.Payload) bool { switch action := payload.Action.(type) { case *actions.Add: payload.Wait(s.app.Nodes) if action.Parent != nil { // only root nodes are files break } switch action.Direction() { case actions.New, actions.Redo: n := action.Node n.RecomputeHash(s.ctx, true) fm := &models.FileModel{ Package: false, Type: *action.Type.Id == *system.NewReference("kego.io/system", "type"), Filename: action.BranchFile, Node: n, Hash: n.Hash(), } s.files[n] = fm case actions.Undo: delete(s.files, action.Node) } payload.Notify(nil, FileChangedStateChange) case *actions.SaveFileSuccess: for _, file := range action.Response.Files { f := s.fileByName(file.File) if f == nil { s.app.Fail <- kerr.New("FPXNHFJNOR", "File %s not found", file.File) } f.SaveHash = file.Hash } payload.Notify(nil, FileChangedStateChange) case *actions.InitialState: payload.Wait(s.app.Nodes) n := s.app.Package.Node() fm := &models.FileModel{ Package: true, Type: false, Filename: s.app.Package.Filename(), Node: n, Hash: n.Hash(), LoadHash: n.Hash(), } s.files[n] = fm for _, ti := range s.app.Types.All() { n := ti.Node fm := &models.FileModel{ Package: false, Type: true, Filename: ti.File, Node: n, Hash: n.Hash(), LoadHash: n.Hash(), } s.files[n] = fm } case *actions.LoadFileSuccess: sci, ok := action.Branch.Contents.(models.FileContentsInterface) if !ok { break } n := sci.GetNode() fm := &models.FileModel{ Package: false, Type: false, Filename: sci.GetFilename(), Node: n, Hash: n.Hash(), LoadHash: n.Hash(), } s.files[n] = fm } if m, ok := payload.Action.(actions.Mutator); ok { payload.Wait(s.app.Nodes) n := m.CommonAncestor().Root() f, ok := s.files[n] if ok { prevChanged := f.Changed() f.Hash = n.Hash() newChanged := f.Changed() if prevChanged != newChanged { // state changed! payload.Notify(n, FileChangedStateChange) } } } return true }