refactor: break up huge file, structure now clear
This commit is contained in:
104
input.go
Normal file
104
input.go
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
)
|
||||||
|
|
||||||
|
func isHelpCmd(cmds []string) bool {
|
||||||
|
if cmds[0] == "help" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isQuitCmd(cmds []string) bool {
|
||||||
|
if cmds[0] == "quit" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isProfileCreateCmd(cmds []string) bool {
|
||||||
|
if cmds[0] == "profile" && cmds[1] == "create" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isProfileUnlockCmd(cmds []string) bool {
|
||||||
|
if cmds[0] == "profile" && cmds[1] == "unlock" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isProfileInfoCmd(cmds []string) bool {
|
||||||
|
if cmds[0] == "profile" && cmds[1] == "info" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isConnectCmd(cmds []string) bool {
|
||||||
|
if cmds[0] == "connect" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isClearCmd(cmds []string) bool {
|
||||||
|
if cmds[0] == "clear" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleCommand(cmd, hiddenInput string) tea.Msg {
|
||||||
|
cmds := strings.Split(cmd, " ")
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case isHelpCmd(cmds):
|
||||||
|
return cmdMsg{output: cmdHelp}
|
||||||
|
|
||||||
|
case isQuitCmd(cmds):
|
||||||
|
return shutdownMsg{}
|
||||||
|
|
||||||
|
case isProfileCreateCmd(cmds):
|
||||||
|
if len(cmds) != 5 {
|
||||||
|
return cmdMsg{output: cmdHelp}
|
||||||
|
}
|
||||||
|
|
||||||
|
passwords := strings.Split(strings.TrimSpace(hiddenInput), " ")
|
||||||
|
if passwords[0] != passwords[1] {
|
||||||
|
return cmdMsg{output: "profile create: passwords do not match?"}
|
||||||
|
}
|
||||||
|
|
||||||
|
return createProfileMsg{
|
||||||
|
name: cmds[2],
|
||||||
|
password: passwords[1],
|
||||||
|
}
|
||||||
|
|
||||||
|
case isProfileUnlockCmd(cmds):
|
||||||
|
if len(cmds) != 3 {
|
||||||
|
return cmdMsg{output: cmdHelp}
|
||||||
|
}
|
||||||
|
|
||||||
|
return profileUnlockMsg{
|
||||||
|
password: strings.TrimSpace(hiddenInput),
|
||||||
|
}
|
||||||
|
|
||||||
|
case isProfileInfoCmd(cmds):
|
||||||
|
return profileInfoMsg{}
|
||||||
|
|
||||||
|
case isConnectCmd(cmds):
|
||||||
|
return connectMsg{}
|
||||||
|
|
||||||
|
case isClearCmd(cmds):
|
||||||
|
return clearMsg{}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return cmdMsg{output: "unknown command"}
|
||||||
|
}
|
||||||
|
}
|
76
main.go
Normal file
76
main.go
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"os/user"
|
||||||
|
|
||||||
|
openPrivacyLog "git.openprivacy.ca/openprivacy/log"
|
||||||
|
_ "github.com/mutecomm/go-sqlcipher/v4"
|
||||||
|
|
||||||
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
help = `cairde [options]
|
||||||
|
|
||||||
|
A text-based user interface for metadata resistant online chat.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h output help
|
||||||
|
`
|
||||||
|
cmdHelp = `/clear
|
||||||
|
/connect
|
||||||
|
/help
|
||||||
|
/profile create <name> <password> <password>
|
||||||
|
/profile info
|
||||||
|
/profile unlock <password>
|
||||||
|
/quit`
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var helpFlag bool
|
||||||
|
|
||||||
|
flag.BoolVar(&helpFlag, "h", false, "output help")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if helpFlag {
|
||||||
|
fmt.Print(help)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE(d1): pending https://git.coopcloud.tech/decentral1se/cairde/issues/1
|
||||||
|
_, err := exec.LookPath("tor")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("could not find 'tor' command, is it installed?")
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := tea.LogToFile("cairde.log", "debug")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
filelogger, err := openPrivacyLog.NewFile(openPrivacyLog.LevelInfo, "cwtch.log")
|
||||||
|
if err == nil {
|
||||||
|
openPrivacyLog.SetStd(filelogger)
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := user.Current()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("unable to determine current user: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := tea.NewProgram(
|
||||||
|
newModel(user.Username, user.HomeDir),
|
||||||
|
tea.WithAltScreen(),
|
||||||
|
tea.WithMouseCellMotion(),
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := p.Start(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
@ -3,13 +3,9 @@ package main
|
|||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
mrand "math/rand"
|
mrand "math/rand"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"os/user"
|
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
@ -22,9 +18,6 @@ import (
|
|||||||
"cwtch.im/cwtch/settings"
|
"cwtch.im/cwtch/settings"
|
||||||
"git.openprivacy.ca/openprivacy/connectivity"
|
"git.openprivacy.ca/openprivacy/connectivity"
|
||||||
"git.openprivacy.ca/openprivacy/connectivity/tor"
|
"git.openprivacy.ca/openprivacy/connectivity/tor"
|
||||||
openPrivacyLog "git.openprivacy.ca/openprivacy/log"
|
|
||||||
_ "github.com/mutecomm/go-sqlcipher/v4"
|
|
||||||
|
|
||||||
"github.com/charmbracelet/bubbles/textinput"
|
"github.com/charmbracelet/bubbles/textinput"
|
||||||
"github.com/charmbracelet/bubbles/viewport"
|
"github.com/charmbracelet/bubbles/viewport"
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
@ -35,78 +28,6 @@ const (
|
|||||||
offline = iota
|
offline = iota
|
||||||
connecting
|
connecting
|
||||||
connected
|
connected
|
||||||
|
|
||||||
help = `cairde [options]
|
|
||||||
|
|
||||||
A text-based user interface for metadata resistant online chat.
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-h output help
|
|
||||||
`
|
|
||||||
cmdHelp = `/clear
|
|
||||||
/connect
|
|
||||||
/help
|
|
||||||
/profile create <name> <password> <password>
|
|
||||||
/profile info
|
|
||||||
/profile unlock <password>
|
|
||||||
/quit`
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var helpFlag bool
|
|
||||||
|
|
||||||
flag.BoolVar(&helpFlag, "h", false, "output help")
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
if helpFlag {
|
|
||||||
fmt.Print(help)
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE(d1): pending https://git.coopcloud.tech/decentral1se/cairde/issues/1
|
|
||||||
_, err := exec.LookPath("tor")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal("could not find 'tor' command, is it installed?")
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := tea.LogToFile("cairde.log", "debug")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
filelogger, err := openPrivacyLog.NewFile(openPrivacyLog.LevelInfo, "cwtch.log")
|
|
||||||
if err == nil {
|
|
||||||
openPrivacyLog.SetStd(filelogger)
|
|
||||||
}
|
|
||||||
|
|
||||||
user, err := user.Current()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("unable to determine current user: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
p := tea.NewProgram(
|
|
||||||
newModel(user.Username, user.HomeDir),
|
|
||||||
tea.WithAltScreen(),
|
|
||||||
tea.WithMouseCellMotion(),
|
|
||||||
)
|
|
||||||
|
|
||||||
if err := p.Start(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
mainStyle = lipgloss.NewStyle().
|
|
||||||
BorderStyle(lipgloss.NormalBorder())
|
|
||||||
|
|
||||||
viewportStyle = lipgloss.NewStyle()
|
|
||||||
|
|
||||||
profileNameButtonStyle = lipgloss.NewStyle()
|
|
||||||
|
|
||||||
channelBarStyle = lipgloss.NewStyle()
|
|
||||||
|
|
||||||
inputStyle = lipgloss.NewStyle()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type profile struct {
|
type profile struct {
|
||||||
@ -152,17 +73,6 @@ func newModel(username, homeDir string) model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type errMsg struct{ Err error }
|
|
||||||
|
|
||||||
func (e errMsg) Error() string {
|
|
||||||
return e.Err.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
type appInitialisedMsg struct {
|
|
||||||
app app.Application
|
|
||||||
acn connectivity.ACN
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m model) initApp() tea.Msg {
|
func (m model) initApp() tea.Msg {
|
||||||
mrand.Seed(int64(time.Now().Nanosecond()))
|
mrand.Seed(int64(time.Now().Nanosecond()))
|
||||||
port := mrand.Intn(1000) + 9600
|
port := mrand.Intn(1000) + 9600
|
||||||
@ -235,8 +145,6 @@ func (m model) initApp() tea.Msg {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type statusMsg struct{ msg string }
|
|
||||||
|
|
||||||
func (m model) handleStatusMessage() tea.Msg {
|
func (m model) handleStatusMessage() tea.Msg {
|
||||||
return statusMsg{msg: <-m.statusBuffer}
|
return statusMsg{msg: <-m.statusBuffer}
|
||||||
}
|
}
|
||||||
@ -280,124 +188,6 @@ func (m model) shutdown() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
type cmdMsg struct {
|
|
||||||
output string
|
|
||||||
}
|
|
||||||
|
|
||||||
type shutdownMsg struct{}
|
|
||||||
|
|
||||||
type createProfileMsg struct {
|
|
||||||
name string
|
|
||||||
password string
|
|
||||||
}
|
|
||||||
|
|
||||||
type profileUnlockMsg struct {
|
|
||||||
password string
|
|
||||||
}
|
|
||||||
|
|
||||||
type connectMsg struct{}
|
|
||||||
|
|
||||||
type clearMsg struct{}
|
|
||||||
|
|
||||||
type profileInfoMsg struct{}
|
|
||||||
|
|
||||||
func isHelpCmd(cmds []string) bool {
|
|
||||||
if cmds[0] == "help" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func isQuitCmd(cmds []string) bool {
|
|
||||||
if cmds[0] == "quit" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func isProfileCreateCmd(cmds []string) bool {
|
|
||||||
if cmds[0] == "profile" && cmds[1] == "create" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func isProfileUnlockCmd(cmds []string) bool {
|
|
||||||
if cmds[0] == "profile" && cmds[1] == "unlock" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func isProfileInfoCmd(cmds []string) bool {
|
|
||||||
if cmds[0] == "profile" && cmds[1] == "info" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func isConnectCmd(cmds []string) bool {
|
|
||||||
if cmds[0] == "connect" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func isClearCmd(cmds []string) bool {
|
|
||||||
if cmds[0] == "clear" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleCommand(cmd, hiddenInput string) tea.Msg {
|
|
||||||
cmds := strings.Split(cmd, " ")
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case isHelpCmd(cmds):
|
|
||||||
return cmdMsg{output: cmdHelp}
|
|
||||||
|
|
||||||
case isQuitCmd(cmds):
|
|
||||||
return shutdownMsg{}
|
|
||||||
|
|
||||||
case isProfileCreateCmd(cmds):
|
|
||||||
if len(cmds) != 5 {
|
|
||||||
return cmdMsg{output: cmdHelp}
|
|
||||||
}
|
|
||||||
|
|
||||||
passwords := strings.Split(strings.TrimSpace(hiddenInput), " ")
|
|
||||||
if passwords[0] != passwords[1] {
|
|
||||||
return cmdMsg{output: "profile create: passwords do not match?"}
|
|
||||||
}
|
|
||||||
|
|
||||||
return createProfileMsg{
|
|
||||||
name: cmds[2],
|
|
||||||
password: passwords[1],
|
|
||||||
}
|
|
||||||
|
|
||||||
case isProfileUnlockCmd(cmds):
|
|
||||||
if len(cmds) != 3 {
|
|
||||||
return cmdMsg{output: cmdHelp}
|
|
||||||
}
|
|
||||||
|
|
||||||
return profileUnlockMsg{
|
|
||||||
password: strings.TrimSpace(hiddenInput),
|
|
||||||
}
|
|
||||||
|
|
||||||
case isProfileInfoCmd(cmds):
|
|
||||||
return profileInfoMsg{}
|
|
||||||
|
|
||||||
case isConnectCmd(cmds):
|
|
||||||
return connectMsg{}
|
|
||||||
|
|
||||||
case isClearCmd(cmds):
|
|
||||||
return clearMsg{}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return cmdMsg{output: "unknown command"}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
var (
|
var (
|
||||||
cmd tea.Cmd
|
cmd tea.Cmd
|
40
msg.go
Normal file
40
msg.go
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cwtch.im/cwtch/app"
|
||||||
|
"git.openprivacy.ca/openprivacy/connectivity"
|
||||||
|
)
|
||||||
|
|
||||||
|
type statusMsg struct{ msg string }
|
||||||
|
|
||||||
|
type errMsg struct{ Err error }
|
||||||
|
|
||||||
|
func (e errMsg) Error() string {
|
||||||
|
return e.Err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
type appInitialisedMsg struct {
|
||||||
|
app app.Application
|
||||||
|
acn connectivity.ACN
|
||||||
|
}
|
||||||
|
|
||||||
|
type cmdMsg struct {
|
||||||
|
output string
|
||||||
|
}
|
||||||
|
|
||||||
|
type shutdownMsg struct{}
|
||||||
|
|
||||||
|
type createProfileMsg struct {
|
||||||
|
name string
|
||||||
|
password string
|
||||||
|
}
|
||||||
|
|
||||||
|
type profileUnlockMsg struct {
|
||||||
|
password string
|
||||||
|
}
|
||||||
|
|
||||||
|
type connectMsg struct{}
|
||||||
|
|
||||||
|
type clearMsg struct{}
|
||||||
|
|
||||||
|
type profileInfoMsg struct{}
|
16
style.go
Normal file
16
style.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/charmbracelet/lipgloss"
|
||||||
|
|
||||||
|
var (
|
||||||
|
mainStyle = lipgloss.NewStyle().
|
||||||
|
BorderStyle(lipgloss.NormalBorder())
|
||||||
|
|
||||||
|
viewportStyle = lipgloss.NewStyle()
|
||||||
|
|
||||||
|
profileNameButtonStyle = lipgloss.NewStyle()
|
||||||
|
|
||||||
|
channelBarStyle = lipgloss.NewStyle()
|
||||||
|
|
||||||
|
inputStyle = lipgloss.NewStyle()
|
||||||
|
)
|
Reference in New Issue
Block a user