add StateController to take Client out of AppState

Signed-off-by: Jakub Sokołowski <jakub@status.im>
This commit is contained in:
Jakub Sokołowski 2019-07-02 16:52:58 -04:00 committed by Jakub
parent ecf69febbc
commit b620ad6ea6
6 changed files with 87 additions and 65 deletions

42
control.go Normal file
View File

@ -0,0 +1,42 @@
package main
import (
"log"
)
type StateController struct {
State *AppState
Client *StatusGoClient
}
// For fetching current state of peers from status-go
func (s *StateController) Fetch() {
peers, err := s.Client.getPeers()
if err != nil {
log.Panicln(err)
}
ps := s.State.GetData()
s.State.UpdatePeers(peers)
if ps.Current == -1 {
s.State.SetCurrentPeer(0)
}
}
// For removing a selected peer from connected to status-go
func (s *StateController) RemovePeer(peer *Peer) error {
success, err := s.Client.removePeer(peer.Enode)
if err != nil || success != true {
log.Panicln(err)
}
s.Fetch()
return nil
}
func (s *StateController) GetInfo() error {
info, err := s.Client.nodeInfo()
if err != nil {
return err
}
s.State.UpdateInfo(*info)
return nil
}

View File

@ -4,16 +4,16 @@ import (
"time"
)
func FetchLoop(state *AppState, interval int) {
func FetchLoop(s *StateController, interval int) {
// Get the first peers fetch going sooner
state.Fetch()
s.Fetch()
// Then fetch every `interval` seconds
for {
select {
case <-threadDone:
return
case <-time.After(time.Duration(interval) * time.Second):
state.Fetch()
s.Fetch()
}
}
}

24
main.go
View File

@ -39,19 +39,17 @@ func main() {
log.Panicln(err)
}
// Verify the RPC endpoint is available first
node, err := client.nodeInfo()
if err != nil {
log.Panicln(err)
}
log.Println("Successful connection to:", url)
log.Println("Enode:", node.Enode)
// Create a state wrapper.
state := NewState(client)
state := NewState()
// Create a state controller
stateCtrl := &StateController{
State: state,
Client: client,
}
// Subscribe rendering method to state changes.
state.Store.Subscribe(GenRenderFunc(g, state))
state.Store.Subscribe(GenRenderFunc(g, stateCtrl))
mainView := &ViewController{
Name: "main",
@ -63,7 +61,7 @@ func main() {
Current: true,
SelFgColor: gocui.ColorBlack,
SelBgColor: gocui.ColorGreen,
State: state,
StateCtrl: stateCtrl,
// corner positions
TopLeft: func(mx, my int) (int, int) { return 0, 0 },
BotRight: func(mx, my int) (int, int) { return mx - 1, my / 2 },
@ -84,7 +82,7 @@ func main() {
Placeholder: "Loading details...",
Enabled: true,
Wrap: true,
State: state,
StateCtrl: stateCtrl,
// corner positions
TopLeft: func(mx, my int) (int, int) { return 0, (my / 2) + 1 },
BotRight: func(mx, my int) (int, int) { return mx - 1, my - 1 },
@ -98,7 +96,7 @@ func main() {
g.SetManagerFunc(vm.Layout)
// Start RPC calling routine for fetching peers periodically.
go FetchLoop(state, interval)
go FetchLoop(stateCtrl, interval)
if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
log.Panicln(err)

View File

@ -8,11 +8,11 @@ import (
"github.com/jroimartin/gocui"
)
func GenRenderFunc(g *gocui.Gui, state *AppState) func() {
func GenRenderFunc(g *gocui.Gui, sc *StateController) func() {
return func() {
ps := state.GetState()
ps := sc.State.GetData()
renderPeerList(g, ps.Peers)
renderPeerInfo(g, state.GetCurrent())
renderPeerInfo(g, sc.State.GetCurrent())
updatePeerCursor(g, ps.Current)
}
}

View File

@ -1,8 +1,6 @@
package main
import (
"log"
"github.com/dannypsnl/redux/v2/rematch"
"github.com/dannypsnl/redux/v2/store"
)
@ -10,14 +8,14 @@ import (
// This might need renaming, since it also contains the Client.
// I need the client to make the RPC calls.
type AppState struct {
Reducer *AppModel
Store *store.Store
Client *StatusGoClient
updatePeers *rematch.Action
setCurrent *rematch.Action
Reducer *AppModel
Store *store.Store
setNodeInfo *rematch.Action
updatePeers *rematch.Action
setCurrentPeer *rematch.Action
}
func NewState(client *StatusGoClient) *AppState {
func NewState() *AppState {
// Generate the reducer from our model.
Reducer := &AppModel{
State: AppData{
@ -30,51 +28,34 @@ func NewState(client *StatusGoClient) *AppState {
Reducer: Reducer,
// Define the store.
Store: store.New(Reducer),
// Client for RPC calls.
Client: client,
// Define available reducers for the store.
updatePeers: Reducer.Action(Reducer.Update),
setCurrent: Reducer.Action(Reducer.Current),
setNodeInfo: Reducer.Action(Reducer.SetInfo),
updatePeers: Reducer.Action(Reducer.Update),
setCurrentPeer: Reducer.Action(Reducer.Current),
}
}
// Helpers for shorter calls.
func (s *AppState) Update(peers []Peer) {
func (s *AppState) UpdateInfo(info NodeInfo) {
s.Store.Dispatch(s.setNodeInfo.With(info))
}
func (s *AppState) UpdatePeers(peers []Peer) {
s.Store.Dispatch(s.updatePeers.With(peers))
}
func (s *AppState) GetCurrent() *Peer {
state := s.GetState()
state := s.GetData()
if state.Current == -1 {
return nil
}
return &state.Peers[state.Current]
}
func (s *AppState) SetCurrent(index int) {
s.Store.Dispatch(s.setCurrent.With(index))
func (s *AppState) SetCurrentPeer(index int) {
s.Store.Dispatch(s.setCurrentPeer.With(index))
}
func (s *AppState) GetState() AppData {
func (s *AppState) GetData() AppData {
return s.Store.StateOf(s.Reducer).(AppData)
}
// For fetching current state of peers from status-go
func (s *AppState) Fetch() {
peers, err := s.Client.getPeers()
if err != nil {
log.Panicln(err)
}
ps := s.GetState()
s.Update(peers)
if ps.Current == -1 {
s.SetCurrent(0)
}
}
// For removing a selected peer from connected to status-go
func (s *AppState) Remove(peer *Peer) error {
success, err := s.Client.removePeer(peer.Enode)
if err != nil || success != true {
log.Panicln(err)
}
s.Fetch()
return nil
}

13
view.go
View File

@ -32,7 +32,7 @@ type ViewController struct {
SelFgColor gocui.Attribute
Keybindings []Binding
// Extra field for view state. Might need different name.
State *AppState
StateCtrl *StateController
}
// To combine all existing views into one
@ -84,7 +84,6 @@ func (m *ViewManager) Layout(g *gocui.Gui) error {
func (v *ViewController) SetKeybindings(g *gocui.Gui) error {
for _, b := range v.Keybindings {
// IDEA: I can pass a method instead of a function here
if err := g.SetKeybinding("", b.Key, b.Mod, b.Handler); err != nil {
return err
}
@ -94,19 +93,21 @@ func (v *ViewController) SetKeybindings(g *gocui.Gui) error {
func (vc *ViewController) CursorUp(g *gocui.Gui, v *gocui.View) error {
// TODO propper error handling?
vc.State.SetCurrent(vc.State.GetState().Current - 1)
current := vc.StateCtrl.State.GetData().Current
vc.StateCtrl.State.SetCurrentPeer(current - 1)
return nil
}
func (vc *ViewController) CursorDown(g *gocui.Gui, v *gocui.View) error {
// TODO propper error handling?
vc.State.SetCurrent(vc.State.GetState().Current + 1)
current := vc.StateCtrl.State.GetData().Current
vc.StateCtrl.State.SetCurrentPeer(current + 1)
return nil
}
func (vc *ViewController) HandleDelete(g *gocui.Gui, v *gocui.View) error {
currentPeer := vc.State.GetCurrent()
err := vc.State.Remove(currentPeer)
currentPeer := vc.StateCtrl.State.GetCurrent()
err := vc.StateCtrl.RemovePeer(currentPeer)
if err != nil {
return err
}