Example #1
0
File: branch.go Project: kego/ke
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
}