refactor!: cleaning up messages
This commit is contained in:
parent
2fbc7c42aa
commit
105ee428a6
66
acn.go
66
acn.go
@ -23,34 +23,29 @@ const (
|
|||||||
connected
|
connected
|
||||||
)
|
)
|
||||||
|
|
||||||
func ensureConnected(m model) (bool, tea.Msg) {
|
func isConnected(m model) (bool, tea.Msg) {
|
||||||
switch m.connState {
|
switch m.acnState {
|
||||||
case offline:
|
case offline:
|
||||||
return false, offlineMsg{}
|
return false, acnOfflineMsg{}
|
||||||
case connecting:
|
case connecting:
|
||||||
return false, stillConnectingMsg{}
|
return false, acnConnectingMsg{}
|
||||||
default:
|
default:
|
||||||
return true, nil
|
return true, acnAlreadyOnlineMsg{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func attemptShutdown(m *model) tea.Msg {
|
func turnAcnOn(m *model) tea.Msg {
|
||||||
switch m.connState {
|
if ok, msg := isConnected(*m); !ok {
|
||||||
case offline:
|
switch msg.(type) {
|
||||||
close(m.statusBuffer)
|
case acnConnectingMsg:
|
||||||
return shutdownMsg{quit: true}
|
return msg
|
||||||
case connecting:
|
case acnAlreadyOnlineMsg:
|
||||||
return stillConnectingMsg{}
|
return msg
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m.app.Shutdown()
|
m.acnState = connecting
|
||||||
m.acn.Close()
|
|
||||||
close(m.statusBuffer)
|
|
||||||
|
|
||||||
return shutdownMsg{quit: true}
|
|
||||||
}
|
|
||||||
|
|
||||||
func acnOn(m *model) tea.Msg {
|
|
||||||
mrand.Seed(int64(time.Now().Nanosecond()))
|
mrand.Seed(int64(time.Now().Nanosecond()))
|
||||||
port := mrand.Intn(1000) + 9600
|
port := mrand.Intn(1000) + 9600
|
||||||
controlPort := port + 1
|
controlPort := port + 1
|
||||||
@ -58,15 +53,15 @@ func acnOn(m *model) tea.Msg {
|
|||||||
key := make([]byte, 64)
|
key := make([]byte, 64)
|
||||||
_, err := rand.Read(key)
|
_, err := rand.Read(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errMsg{Err: fmt.Errorf("unable to generate control port password: %s", err)}
|
return acnErrMsg{err: fmt.Errorf("unable to generate control port password: %s", err)}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.MkdirAll(path.Join(m.userDir, "/.tor", "tor"), 0700); err != nil {
|
if err := os.MkdirAll(path.Join(m.userDir, "/.tor", "tor"), 0700); err != nil {
|
||||||
return errMsg{Err: fmt.Errorf("unable to create tor directory: %s", err)}
|
return acnErrMsg{err: fmt.Errorf("unable to create tor directory: %s", err)}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.MkdirAll(path.Join(m.userDir, "profiles"), 0700); err != nil {
|
if err := os.MkdirAll(path.Join(m.userDir, "profiles"), 0700); err != nil {
|
||||||
return errMsg{Err: fmt.Errorf("unable to create profiles directory: %s", err)}
|
return acnErrMsg{err: fmt.Errorf("unable to create profiles directory: %s", err)}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := tor.NewTorrc().
|
if err := tor.NewTorrc().
|
||||||
@ -75,7 +70,7 @@ func acnOn(m *model) tea.Msg {
|
|||||||
WithControlPort(controlPort).
|
WithControlPort(controlPort).
|
||||||
WithHashedPassword(base64.StdEncoding.EncodeToString(key)).
|
WithHashedPassword(base64.StdEncoding.EncodeToString(key)).
|
||||||
Build(filepath.Join(m.userDir, ".tor", "tor", "torrc")); err != nil {
|
Build(filepath.Join(m.userDir, ".tor", "tor", "torrc")); err != nil {
|
||||||
return errMsg{Err: fmt.Errorf("unable to initialise torrc builder: %s", err)}
|
return acnErrMsg{err: fmt.Errorf("unable to initialise torrc builder: %s", err)}
|
||||||
}
|
}
|
||||||
|
|
||||||
m.sendStatus("Initialising Tor ACN...")
|
m.sendStatus("Initialising Tor ACN...")
|
||||||
@ -90,18 +85,18 @@ func acnOn(m *model) tea.Msg {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errMsg{Err: fmt.Errorf("unable to bootstrap tor: %s", err)}
|
return acnErrMsg{err: fmt.Errorf("unable to bootstrap tor: %s", err)}
|
||||||
}
|
}
|
||||||
|
|
||||||
m.sendStatus("Waiting for ACN to bootstrap...")
|
m.sendStatus("Waiting for ACN to bootstrap...")
|
||||||
|
|
||||||
if err := acn.WaitTillBootstrapped(); err != nil {
|
if err := acn.WaitTillBootstrapped(); err != nil {
|
||||||
return errMsg{Err: fmt.Errorf("unable to initialise tor: %s", err)}
|
return acnErrMsg{err: fmt.Errorf("unable to initialise tor: %s", err)}
|
||||||
}
|
}
|
||||||
|
|
||||||
settingsFile, err := settings.InitGlobalSettingsFile(m.userDir, "")
|
settingsFile, err := settings.InitGlobalSettingsFile(m.userDir, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errMsg{Err: fmt.Errorf("unable to initialise settings: %s", err)}
|
return acnErrMsg{err: fmt.Errorf("unable to initialise settings: %s", err)}
|
||||||
}
|
}
|
||||||
gSettings := settingsFile.ReadGlobalSettings()
|
gSettings := settingsFile.ReadGlobalSettings()
|
||||||
gSettings.ExperimentsEnabled = false
|
gSettings.ExperimentsEnabled = false
|
||||||
@ -111,27 +106,24 @@ func acnOn(m *model) tea.Msg {
|
|||||||
app := app.NewApp(acn, m.userDir, settingsFile)
|
app := app.NewApp(acn, m.userDir, settingsFile)
|
||||||
app.InstallEngineHooks(connections.DefaultEngineHooks{})
|
app.InstallEngineHooks(connections.DefaultEngineHooks{})
|
||||||
|
|
||||||
m.sendStatus("Tor ACN is up and running, all engines go")
|
return acnOnMsg{
|
||||||
|
|
||||||
return appInitialisedMsg{
|
|
||||||
app: app,
|
app: app,
|
||||||
acn: acn,
|
acn: acn,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func acnOff(m *model) tea.Msg {
|
func turnAcnOff(m *model, quitProgram bool) tea.Msg {
|
||||||
switch m.connState {
|
switch m.acnState {
|
||||||
case offline:
|
case offline:
|
||||||
return offlineMsg{}
|
if !quitProgram {
|
||||||
|
return acnOfflineMsg{}
|
||||||
|
}
|
||||||
case connecting:
|
case connecting:
|
||||||
return stillConnectingMsg{}
|
return acnConnectingMsg{}
|
||||||
}
|
}
|
||||||
|
|
||||||
m.app.Shutdown()
|
m.app.Shutdown()
|
||||||
m.acn.Close()
|
m.acn.Close()
|
||||||
|
|
||||||
return shutdownMsg{
|
return acnOffMsg{quitProgram: quitProgram}
|
||||||
quit: false,
|
|
||||||
status: "ACN successfully turned off",
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
10
input.go
10
input.go
@ -87,10 +87,10 @@ func handleCommand(cmd, hiddenInput string) tea.Msg {
|
|||||||
return cmdMsg{output: strings.Split(cmdHelp, "\n")}
|
return cmdMsg{output: strings.Split(cmdHelp, "\n")}
|
||||||
|
|
||||||
case isQuitCmd(cmds):
|
case isQuitCmd(cmds):
|
||||||
return shutdownMsg{quit: true}
|
return turnAcnOffMsg{quitProgram: true}
|
||||||
|
|
||||||
case isStartCmd(cmds):
|
case isStartCmd(cmds):
|
||||||
return startMsg{}
|
return showGettingStartedGuideMsg{}
|
||||||
|
|
||||||
case isProfileCreateCmd(cmds):
|
case isProfileCreateCmd(cmds):
|
||||||
if len(cmds) != 5 {
|
if len(cmds) != 5 {
|
||||||
@ -120,13 +120,13 @@ func handleCommand(cmd, hiddenInput string) tea.Msg {
|
|||||||
return profileInfoMsg{}
|
return profileInfoMsg{}
|
||||||
|
|
||||||
case isAcnOnCmd(cmds):
|
case isAcnOnCmd(cmds):
|
||||||
return acnOnMsg{}
|
return turnAcnOnMsg{}
|
||||||
|
|
||||||
case isAcnOffCmd(cmds):
|
case isAcnOffCmd(cmds):
|
||||||
return acnOffMsg{}
|
return turnAcnOffMsg{}
|
||||||
|
|
||||||
case isClearCmd(cmds):
|
case isClearCmd(cmds):
|
||||||
return clearMsg{}
|
return clearScreenMsg{}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return cmdMsg{output: []string{"unknown command"}}
|
return cmdMsg{output: []string{"unknown command"}}
|
||||||
|
71
message.go
71
message.go
@ -5,34 +5,50 @@ import (
|
|||||||
"git.openprivacy.ca/openprivacy/connectivity"
|
"git.openprivacy.ca/openprivacy/connectivity"
|
||||||
)
|
)
|
||||||
|
|
||||||
type sendStatusMsg struct{ lines []string }
|
// ---------------------------------------------------------------------------
|
||||||
|
// ACN messages
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
type turnAcnOnMsg struct{}
|
||||||
|
|
||||||
type renderStatusMsg struct{ line string }
|
type acnOnMsg struct {
|
||||||
|
|
||||||
type errMsg struct{ Err error }
|
|
||||||
|
|
||||||
func (e errMsg) Error() string {
|
|
||||||
return e.Err.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
type appInitialisedMsg struct {
|
|
||||||
app app.Application
|
app app.Application
|
||||||
acn connectivity.ACN
|
acn connectivity.ACN
|
||||||
}
|
}
|
||||||
|
|
||||||
type cmdMsg struct{ output []string }
|
type turnAcnOffMsg struct {
|
||||||
|
quitProgram bool
|
||||||
type offlineMsg struct{}
|
|
||||||
|
|
||||||
type startMsg struct{}
|
|
||||||
|
|
||||||
type stillConnectingMsg struct{}
|
|
||||||
|
|
||||||
type shutdownMsg struct {
|
|
||||||
quit bool
|
|
||||||
status string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type acnOffMsg struct {
|
||||||
|
quitProgram bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type acnAlreadyOnlineMsg struct{}
|
||||||
|
|
||||||
|
type acnOfflineMsg struct{}
|
||||||
|
|
||||||
|
type acnConnectingMsg struct{}
|
||||||
|
|
||||||
|
type acnErrMsg struct {
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e acnErrMsg) Error() string {
|
||||||
|
return e.err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// help messages
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
type showGettingStartedGuideMsg struct{}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// profile messages
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
type profileInfoMsg struct{}
|
||||||
|
|
||||||
|
type startProfileQueuePollMsg struct{ onion string }
|
||||||
|
|
||||||
type createProfileMsg struct {
|
type createProfileMsg struct {
|
||||||
name string
|
name string
|
||||||
password string
|
password string
|
||||||
@ -42,12 +58,13 @@ type profileUnlockMsg struct {
|
|||||||
password string
|
password string
|
||||||
}
|
}
|
||||||
|
|
||||||
type acnOffMsg struct{}
|
// ---------------------------------------------------------------------------
|
||||||
|
// TODO: categorize messages below
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
type sendStatusMsg struct{ lines []string }
|
||||||
|
|
||||||
type acnOnMsg struct{}
|
type renderStatusMsg struct{ line string }
|
||||||
|
|
||||||
type clearMsg struct{}
|
type cmdMsg struct{ output []string }
|
||||||
|
|
||||||
type profileInfoMsg struct{}
|
type clearScreenMsg struct{}
|
||||||
|
|
||||||
type startProfileQueuePollMsg struct{ onion string }
|
|
||||||
|
90
model.go
90
model.go
@ -58,7 +58,7 @@ type model struct {
|
|||||||
username string
|
username string
|
||||||
userDir string
|
userDir string
|
||||||
|
|
||||||
connState int
|
acnState int
|
||||||
|
|
||||||
menuState int
|
menuState int
|
||||||
menuBar []string
|
menuBar []string
|
||||||
@ -99,7 +99,7 @@ func newModel(username, homeDir string, debug bool) model {
|
|||||||
username: username,
|
username: username,
|
||||||
userDir: path.Join(homeDir, "/.cairde/"),
|
userDir: path.Join(homeDir, "/.cairde/"),
|
||||||
|
|
||||||
connState: offline,
|
acnState: offline,
|
||||||
|
|
||||||
menuBar: []string{"STATUS"},
|
menuBar: []string{"STATUS"},
|
||||||
menuState: 0,
|
menuState: 0,
|
||||||
@ -224,7 +224,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
switch msg.String() {
|
switch msg.String() {
|
||||||
case "ctrl+c":
|
case "ctrl+c":
|
||||||
cmds = append(cmds, func() tea.Msg {
|
cmds = append(cmds, func() tea.Msg {
|
||||||
return attemptShutdown(&m)
|
return turnAcnOff(&m, true)
|
||||||
})
|
})
|
||||||
|
|
||||||
case "enter":
|
case "enter":
|
||||||
@ -249,7 +249,9 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case "ctrl+l":
|
case "ctrl+l":
|
||||||
cmds = append(cmds, func() tea.Msg { return clearMsg{} })
|
cmds = append(cmds, func() tea.Msg {
|
||||||
|
return clearScreenMsg{}
|
||||||
|
})
|
||||||
|
|
||||||
default:
|
default:
|
||||||
hidePasswordInput(&m)
|
hidePasswordInput(&m)
|
||||||
@ -259,34 +261,59 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
m.input.Reset()
|
m.input.Reset()
|
||||||
cmds = append(cmds, m.sendStatusCmd(msg.output...))
|
cmds = append(cmds, m.sendStatusCmd(msg.output...))
|
||||||
|
|
||||||
case offlineMsg:
|
case turnAcnOffMsg:
|
||||||
|
m.input.Reset()
|
||||||
|
cmds = append(cmds, func() tea.Msg {
|
||||||
|
return turnAcnOff(&m, msg.quitProgram)
|
||||||
|
})
|
||||||
|
|
||||||
|
case acnOffMsg:
|
||||||
|
if msg.quitProgram {
|
||||||
|
return m, tea.Quit
|
||||||
|
}
|
||||||
|
cmds = append(cmds, m.sendStatusCmd("ACN successfully turned off"))
|
||||||
|
m.acnState = offline
|
||||||
|
|
||||||
|
case turnAcnOnMsg:
|
||||||
|
m.input.Reset()
|
||||||
|
cmds = append(cmds, func() tea.Msg {
|
||||||
|
return turnAcnOn(&m)
|
||||||
|
})
|
||||||
|
|
||||||
|
case acnOnMsg:
|
||||||
|
m.app = msg.app
|
||||||
|
m.acn = msg.acn
|
||||||
|
m.app.ActivateEngines(true, true, true)
|
||||||
|
m.acnState = connected
|
||||||
|
cmds = append(cmds, m.sendStatusCmd("ACN is up and running, all engines go"))
|
||||||
|
|
||||||
|
case acnAlreadyOnlineMsg:
|
||||||
|
m.input.Reset()
|
||||||
|
cmds = append(cmds, m.sendStatusCmd("ACN is already online"))
|
||||||
|
|
||||||
|
case acnOfflineMsg:
|
||||||
m.input.Reset()
|
m.input.Reset()
|
||||||
cmds = append(cmds, m.sendStatusCmd("ACN is currently offline"))
|
cmds = append(cmds, m.sendStatusCmd("ACN is currently offline"))
|
||||||
|
|
||||||
case stillConnectingMsg:
|
case acnConnectingMsg:
|
||||||
m.input.Reset()
|
m.input.Reset()
|
||||||
cmds = append(cmds, m.sendStatusCmd("Still initialising ACN, please hold"))
|
cmds = append(cmds, m.sendStatusCmd("ACN still initialising, please hold"))
|
||||||
|
|
||||||
case startMsg:
|
case acnErrMsg:
|
||||||
|
m.acnState = offline
|
||||||
|
cmds = append(cmds, m.sendStatusCmd(msg.Error()))
|
||||||
|
|
||||||
|
case showGettingStartedGuideMsg:
|
||||||
cmds = append(cmds, m.sendStatusCmd(
|
cmds = append(cmds, m.sendStatusCmd(
|
||||||
strings.Split(gettingStartedMessage, "\n")...,
|
strings.Split(gettingStartedMessage, "\n")...,
|
||||||
))
|
))
|
||||||
m.input.Reset()
|
m.input.Reset()
|
||||||
|
|
||||||
case shutdownMsg:
|
|
||||||
m.input.Reset()
|
|
||||||
if msg.quit {
|
|
||||||
return m, tea.Quit
|
|
||||||
}
|
|
||||||
if msg.status != "" {
|
|
||||||
cmds = append(cmds, m.sendStatusCmd(msg.status))
|
|
||||||
}
|
|
||||||
|
|
||||||
case createProfileMsg:
|
case createProfileMsg:
|
||||||
m.hiddenInput = ""
|
m.hiddenInput = ""
|
||||||
m.input.Reset()
|
m.input.Reset()
|
||||||
|
|
||||||
if isConnected, msg := ensureConnected(m); !isConnected {
|
if ok, msg := isConnected(m); !ok {
|
||||||
cmds = append(cmds, func() tea.Msg { return msg })
|
cmds = append(cmds, func() tea.Msg { return msg })
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -315,7 +342,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
m.hiddenInput = ""
|
m.hiddenInput = ""
|
||||||
m.input.Reset()
|
m.input.Reset()
|
||||||
|
|
||||||
if isConnected, msg := ensureConnected(m); !isConnected {
|
if ok, msg := isConnected(m); !ok {
|
||||||
cmds = append(cmds, func() tea.Msg { return msg })
|
cmds = append(cmds, func() tea.Msg { return msg })
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -339,7 +366,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
case profileInfoMsg:
|
case profileInfoMsg:
|
||||||
m.input.Reset()
|
m.input.Reset()
|
||||||
|
|
||||||
if isConnected, msg := ensureConnected(m); !isConnected {
|
if ok, msg := isConnected(m); !ok {
|
||||||
cmds = append(cmds, func() tea.Msg { return msg })
|
cmds = append(cmds, func() tea.Msg { return msg })
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -373,32 +400,11 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
m.statusViewport.GotoBottom()
|
m.statusViewport.GotoBottom()
|
||||||
cmds = append(cmds, m.receiveStatusCmd)
|
cmds = append(cmds, m.receiveStatusCmd)
|
||||||
|
|
||||||
case clearMsg:
|
case clearScreenMsg:
|
||||||
m.input.Reset()
|
m.input.Reset()
|
||||||
m.statusViewportLines = []string{}
|
m.statusViewportLines = []string{}
|
||||||
m.statusViewport.SetContent("")
|
m.statusViewport.SetContent("")
|
||||||
m.statusViewport.GotoTop()
|
m.statusViewport.GotoTop()
|
||||||
|
|
||||||
case acnOffMsg:
|
|
||||||
m.input.Reset()
|
|
||||||
cmds = append(cmds, func() tea.Msg {
|
|
||||||
return acnOff(&m)
|
|
||||||
})
|
|
||||||
|
|
||||||
case acnOnMsg:
|
|
||||||
m.input.Reset()
|
|
||||||
cmds = append(cmds, func() tea.Msg {
|
|
||||||
return acnOn(&m)
|
|
||||||
})
|
|
||||||
|
|
||||||
case appInitialisedMsg:
|
|
||||||
m.app = msg.app
|
|
||||||
m.acn = msg.acn
|
|
||||||
m.connState = connected
|
|
||||||
m.app.ActivateEngines(true, true, true)
|
|
||||||
|
|
||||||
case errMsg:
|
|
||||||
cmds = append(cmds, m.sendStatusCmd(msg.Error()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return m, tea.Batch(cmds...)
|
return m, tea.Batch(cmds...)
|
||||||
|
Reference in New Issue
Block a user