refactor(ui): use value messages in models
This commit is contained in:
parent
df7e3d0220
commit
c998580e0e
16 changed files with 83 additions and 111 deletions
2
go.mod
2
go.mod
|
|
@ -11,7 +11,7 @@ require (
|
|||
github.com/alecthomas/chroma/v2 v2.23.1
|
||||
github.com/andybalholm/brotli v1.2.1
|
||||
github.com/ayn2op/clipboard v0.0.0-20260308203959-c5ad7df3fc97
|
||||
github.com/ayn2op/tview v0.0.0-20260413170751-99e767e84007
|
||||
github.com/ayn2op/tview v0.0.0-20260413180352-1d55ccf1cda2
|
||||
github.com/deckarep/gosx-notifier v0.0.0-20180201035817-e127226297fb
|
||||
github.com/diamondburned/arikawa/v3 v3.6.1-0.20260311205148-176ad9b9440f
|
||||
github.com/diamondburned/ningen/v3 v3.0.1-0.20260306213430-5a08d3a709b4
|
||||
|
|
|
|||
4
go.sum
4
go.sum
|
|
@ -14,8 +14,8 @@ github.com/andybalholm/brotli v1.2.1 h1:R+f5xP285VArJDRgowrfb9DqL18yVK0gKAW/F+eT
|
|||
github.com/andybalholm/brotli v1.2.1/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
|
||||
github.com/ayn2op/clipboard v0.0.0-20260308203959-c5ad7df3fc97 h1:WujETUV+v0DEJyZgjeLzQvihWyL80c0Tg4qf0dDo+Io=
|
||||
github.com/ayn2op/clipboard v0.0.0-20260308203959-c5ad7df3fc97/go.mod h1:3kFnpNCa3dF6WryzOMCDao7PfZ7DTCh+pievlfuwV80=
|
||||
github.com/ayn2op/tview v0.0.0-20260413170751-99e767e84007 h1:9FrbhP2x4pl7zF5HbBmNLhMbSF/IsnBiZusmrUkwqKg=
|
||||
github.com/ayn2op/tview v0.0.0-20260413170751-99e767e84007/go.mod h1:xgkca32kuEswK7Kzkfk3Pk24WHcKPjqK4xGmDi9QqOY=
|
||||
github.com/ayn2op/tview v0.0.0-20260413180352-1d55ccf1cda2 h1:p9/lWit1O2j2DUrhiRKN6djcZM0J3vnAITdIAfUVtq0=
|
||||
github.com/ayn2op/tview v0.0.0-20260413180352-1d55ccf1cda2/go.mod h1:xgkca32kuEswK7Kzkfk3Pk24WHcKPjqK4xGmDi9QqOY=
|
||||
github.com/danieljoos/wincred v1.2.3 h1:v7dZC2x32Ut3nEfRH+vhoZGvN72+dQ/snVXo/vMFLdQ=
|
||||
github.com/danieljoos/wincred v1.2.3/go.mod h1:6qqX0WNrS4RzPZ1tnroDzq9kY3fu1KwE7MRLQK4X0bs=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ func (ap *attachmentsPicker) close() tview.Cmd {
|
|||
|
||||
func (ap *attachmentsPicker) Update(msg tview.Msg) tview.Cmd {
|
||||
switch msg := msg.(type) {
|
||||
case *picker.SelectedMsg:
|
||||
case picker.SelectedMsg:
|
||||
index, ok := msg.Reference.(int)
|
||||
if !ok {
|
||||
return nil
|
||||
|
|
@ -59,7 +59,7 @@ func (ap *attachmentsPicker) Update(msg tview.Msg) tview.Cmd {
|
|||
}
|
||||
ap.items[index].open()
|
||||
return ap.close()
|
||||
case *picker.CancelMsg:
|
||||
case picker.CancelMsg:
|
||||
return ap.close()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ func newChannelsPicker(cfg *config.Config, chat *Model) *channelsPicker {
|
|||
|
||||
func (cp *channelsPicker) Update(msg tview.Msg) tview.Cmd {
|
||||
switch msg := msg.(type) {
|
||||
case *picker.SelectedMsg:
|
||||
case picker.SelectedMsg:
|
||||
channelID, ok := msg.Reference.(discord.ChannelID)
|
||||
if !ok || !channelID.IsValid() {
|
||||
return nil
|
||||
|
|
@ -55,7 +55,7 @@ func (cp *channelsPicker) Update(msg tview.Msg) tview.Cmd {
|
|||
}
|
||||
cp.chat.closePicker()
|
||||
return selectCmd
|
||||
case *picker.CancelMsg:
|
||||
case picker.CancelMsg:
|
||||
cp.chat.closePicker()
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -385,7 +385,7 @@ func (gt *guildsTree) loadChannel(channel discord.Channel) tview.Cmd {
|
|||
if guildID := channel.GuildID; guildID.IsValid() {
|
||||
gt.chat.messagesList.requestGuildMembers(guildID, messages)
|
||||
}
|
||||
return &channelLoadedMsg{Channel: channel, Messages: messages}
|
||||
return channelLoadedMsg{Channel: channel, Messages: messages}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -405,9 +405,9 @@ func (gt *guildsTree) collapseParentNode(node *tview.TreeNode) {
|
|||
|
||||
func (gt *guildsTree) Update(msg tview.Msg) tview.Cmd {
|
||||
switch msg := msg.(type) {
|
||||
case *tview.TreeViewSelectedMsg:
|
||||
case tview.TreeViewSelectedMsg:
|
||||
return gt.onSelected(msg.Node)
|
||||
case *tview.KeyMsg:
|
||||
case tview.KeyMsg:
|
||||
handler := gt.TreeView.Update
|
||||
switch {
|
||||
case keybind.Matches(msg, gt.cfg.Keybinds.GuildsTree.CollapseParentNode.Keybind):
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ type messageInput struct {
|
|||
typingTimer *time.Timer
|
||||
}
|
||||
|
||||
type tabSuggestMsg struct{ tcell.EventTime }
|
||||
type tabSuggestMsg struct{}
|
||||
|
||||
var _ help.KeyMap = (*messageInput)(nil)
|
||||
|
||||
|
|
@ -108,9 +108,9 @@ func (mi *messageInput) stopTypingTimer() {
|
|||
func (mi *messageInput) Update(msg tview.Msg) tview.Cmd {
|
||||
handler := mi.TextArea.Update
|
||||
switch msg := msg.(type) {
|
||||
case *tabSuggestMsg:
|
||||
case tabSuggestMsg:
|
||||
return mi.tabSuggest()
|
||||
case *tview.KeyMsg:
|
||||
case tview.KeyMsg:
|
||||
switch {
|
||||
case keybind.Matches(msg, mi.cfg.Keybinds.MessageInput.Paste.Keybind):
|
||||
mi.paste()
|
||||
|
|
@ -512,7 +512,7 @@ func (mi *messageInput) searchMember(gID discord.GuildID, name string) tview.Cmd
|
|||
mi.chat.messagesList.setFetchingChunk(true, 0)
|
||||
mi.chat.state.MemberState.SearchMember(gID, name)
|
||||
mi.cache.Create(key, mi.chat.messagesList.waitForChunkEvent())
|
||||
return &tabSuggestMsg{}
|
||||
return tabSuggestMsg{}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -846,7 +846,7 @@ func (ml *messagesList) selectedMessage() (*discord.Message, error) {
|
|||
|
||||
func (ml *messagesList) Update(msg tview.Msg) tview.Cmd {
|
||||
switch msg := msg.(type) {
|
||||
case *tview.KeyMsg:
|
||||
case tview.KeyMsg:
|
||||
switch {
|
||||
case keybind.Matches(msg, ml.cfg.Keybinds.MessagesList.Cancel.Keybind):
|
||||
ml.clearSelection()
|
||||
|
|
@ -887,7 +887,7 @@ func (ml *messagesList) Update(msg tview.Msg) tview.Cmd {
|
|||
}
|
||||
return ml.Model.Update(msg)
|
||||
|
||||
case *olderMessagesLoadedMsg:
|
||||
case olderMessagesLoadedMsg:
|
||||
selectedChannel := ml.chat.SelectedChannel()
|
||||
if selectedChannel == nil || selectedChannel.ID != msg.ChannelID {
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -247,9 +247,9 @@ func (m *Model) focusNext() tview.Cmd {
|
|||
|
||||
func (m *Model) Update(msg tview.Msg) tview.Cmd {
|
||||
switch msg := msg.(type) {
|
||||
case *tview.InitMsg:
|
||||
case tview.InitMsg:
|
||||
return tview.Batch(m.openState(), m.listen())
|
||||
case *gatewayEventMsg:
|
||||
case gatewayEventMsg:
|
||||
switch eventMsg := msg.Event.(type) {
|
||||
case *ws.RawEvent:
|
||||
m.onRaw(eventMsg)
|
||||
|
|
@ -278,7 +278,7 @@ func (m *Model) Update(msg tview.Msg) tview.Cmd {
|
|||
m.onReadUpdate(eventMsg)
|
||||
}
|
||||
return m.listen()
|
||||
case *channelLoadedMsg:
|
||||
case channelLoadedMsg:
|
||||
node := m.guildsTree.GetCurrentNode()
|
||||
if node == nil {
|
||||
return nil
|
||||
|
|
@ -311,7 +311,7 @@ func (m *Model) Update(msg tview.Msg) tview.Cmd {
|
|||
}
|
||||
m.messageInput.SetPlaceholder(tview.NewLine(tview.NewSegment(text, tcell.StyleDefault.Dim(true))))
|
||||
return focusCmd
|
||||
case *QuitMsg:
|
||||
case QuitMsg:
|
||||
return tview.Batch(
|
||||
m.closeState(),
|
||||
tview.Quit(),
|
||||
|
|
@ -331,7 +331,7 @@ func (m *Model) Update(msg tview.Msg) tview.Cmd {
|
|||
}
|
||||
return focusCmd
|
||||
}
|
||||
case *tview.KeyMsg:
|
||||
case tview.KeyMsg:
|
||||
switch {
|
||||
case keybind.Matches(msg, m.cfg.Keybinds.FocusGuildsTree.Keybind):
|
||||
m.messageInput.removeMentionsList()
|
||||
|
|
@ -356,7 +356,7 @@ func (m *Model) Update(msg tview.Msg) tview.Cmd {
|
|||
case keybind.Matches(msg, m.cfg.Keybinds.Logout.Keybind):
|
||||
return tview.Batch(m.closeState(), m.logout())
|
||||
}
|
||||
case *tabSuggestMsg:
|
||||
case tabSuggestMsg:
|
||||
// Member search completes in a command goroutine; resume suggestion
|
||||
// generation on the update loop to keep UI mutations serialized.
|
||||
return m.messageInput.Update(msg)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import (
|
|||
"github.com/ayn2op/tview"
|
||||
"github.com/diamondburned/arikawa/v3/discord"
|
||||
"github.com/diamondburned/arikawa/v3/gateway"
|
||||
"github.com/gdamore/tcell/v3"
|
||||
)
|
||||
|
||||
func (m *Model) openState() tview.Cmd {
|
||||
|
|
@ -33,38 +32,35 @@ func (m *Model) closeState() tview.Cmd {
|
|||
}
|
||||
|
||||
type gatewayEventMsg struct {
|
||||
tcell.EventTime
|
||||
gateway.Event
|
||||
}
|
||||
|
||||
func (m *Model) listen() tview.Cmd {
|
||||
return func() tview.Msg {
|
||||
return &gatewayEventMsg{Event: <-m.events}
|
||||
return gatewayEventMsg{Event: <-m.events}
|
||||
}
|
||||
}
|
||||
|
||||
type channelLoadedMsg struct {
|
||||
tcell.EventTime
|
||||
Channel discord.Channel
|
||||
Messages []discord.Message
|
||||
}
|
||||
|
||||
type olderMessagesLoadedMsg struct {
|
||||
tcell.EventTime
|
||||
ChannelID discord.ChannelID
|
||||
Older []discord.Message
|
||||
}
|
||||
|
||||
func newOlderMessagesLoadedMsg(channelID discord.ChannelID, older []discord.Message) *olderMessagesLoadedMsg {
|
||||
return &olderMessagesLoadedMsg{ChannelID: channelID, Older: older}
|
||||
func newOlderMessagesLoadedMsg(channelID discord.ChannelID, older []discord.Message) olderMessagesLoadedMsg {
|
||||
return olderMessagesLoadedMsg{ChannelID: channelID, Older: older}
|
||||
}
|
||||
|
||||
type LogoutMsg struct{ tcell.EventTime }
|
||||
type LogoutMsg struct{}
|
||||
|
||||
func (m *Model) logout() tview.Cmd {
|
||||
return func() tview.Msg {
|
||||
return &LogoutMsg{}
|
||||
return LogoutMsg{}
|
||||
}
|
||||
}
|
||||
|
||||
type QuitMsg struct{ tcell.EventTime }
|
||||
type QuitMsg struct{}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ func NewModel(cfg *config.Config) *Model {
|
|||
|
||||
func (m *Model) Update(msg tview.Msg) tview.Cmd {
|
||||
switch msg := msg.(type) {
|
||||
case *errMsg:
|
||||
case errMsg:
|
||||
if m.HasLayer(errorLayerName) {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,11 +5,9 @@ import (
|
|||
|
||||
"github.com/ayn2op/discordo/internal/clipboard"
|
||||
"github.com/ayn2op/tview"
|
||||
"github.com/gdamore/tcell/v3"
|
||||
)
|
||||
|
||||
type errMsg struct {
|
||||
tcell.EventTime
|
||||
err error
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,62 +45,62 @@ func (m *Model) Label() string {
|
|||
|
||||
func (m *Model) Update(msg tview.Msg) tview.Cmd {
|
||||
switch msg := msg.(type) {
|
||||
case *tview.InitMsg:
|
||||
case tview.InitMsg:
|
||||
m.msg = "Connecting to Remote Auth Gateway..."
|
||||
return m.connect()
|
||||
case *tview.KeyMsg:
|
||||
case tview.KeyMsg:
|
||||
if msg.Key() == tcell.KeyEsc {
|
||||
m.msg = "Canceled"
|
||||
return tview.Batch(m.close(), nil)
|
||||
}
|
||||
return m.TextView.Update(msg)
|
||||
|
||||
case *connCreateMsg:
|
||||
case connCreateMsg:
|
||||
m.conn = msg.conn
|
||||
m.msg = "Connected. Handshaking..."
|
||||
return m.listen()
|
||||
case *connCloseMsg:
|
||||
case connCloseMsg:
|
||||
m.conn = nil
|
||||
return nil
|
||||
|
||||
case *helloMsg:
|
||||
case helloMsg:
|
||||
m.heartbeatInterval = time.Duration(msg.heartbeatInterval) * time.Millisecond
|
||||
return tview.Batch(m.listen(), m.heartbeat(), m.generatePrivateKey())
|
||||
case *privateKeyMsg:
|
||||
case privateKeyMsg:
|
||||
m.privateKey = msg.privateKey
|
||||
return tview.Batch(m.listen(), m.sendInit())
|
||||
case *nonceProofMsg:
|
||||
case nonceProofMsg:
|
||||
return tview.Batch(m.listen(), m.sendNonceProof(msg.encryptedNonce))
|
||||
case *pendingRemoteInitMsg:
|
||||
case pendingRemoteInitMsg:
|
||||
m.fingerprint = msg.fingerprint
|
||||
return tview.Batch(m.listen(), m.generateQRCode(msg.fingerprint))
|
||||
case *qrCodeMsg:
|
||||
case qrCodeMsg:
|
||||
m.qrCode = msg.qrCode
|
||||
m.msg = "Scan this with the Discord mobile app to log in instantly."
|
||||
return m.listen()
|
||||
case *pendingTicketMsg:
|
||||
case pendingTicketMsg:
|
||||
return tview.Batch(m.listen(), m.decryptUserPayload(msg.encryptedUserPayload))
|
||||
case *userMsg:
|
||||
case userMsg:
|
||||
name := msg.username
|
||||
if msg.discriminator != "0" {
|
||||
name += "#" + msg.discriminator
|
||||
}
|
||||
m.msg = "Check your phone! Logging in as " + name
|
||||
return m.listen()
|
||||
case *pendingLoginMsg:
|
||||
case pendingLoginMsg:
|
||||
m.msg = "Authenticating..."
|
||||
return tview.Batch(m.close(), m.exchangeTicket(msg.ticket))
|
||||
case *cancelMsg:
|
||||
case cancelMsg:
|
||||
m.msg = "Login canceled on mobile"
|
||||
return m.close()
|
||||
|
||||
case *heartbeatTickMsg:
|
||||
case heartbeatTickMsg:
|
||||
if m.conn == nil {
|
||||
return nil
|
||||
}
|
||||
return tview.Batch(m.heartbeat(), m.sendHeartbeat())
|
||||
|
||||
case *errMsg:
|
||||
case errMsg:
|
||||
m.msg = msg.err.Error()
|
||||
return m.close()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,33 +14,27 @@ import (
|
|||
"github.com/ayn2op/discordo/internal/http"
|
||||
"github.com/ayn2op/tview"
|
||||
"github.com/diamondburned/arikawa/v3/utils/httputil"
|
||||
"github.com/gdamore/tcell/v3"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/skip2/go-qrcode"
|
||||
)
|
||||
|
||||
type errMsg struct {
|
||||
tcell.EventTime
|
||||
err error
|
||||
}
|
||||
|
||||
func newErrMsg(err error) *errMsg {
|
||||
return &errMsg{err: err}
|
||||
func newErrMsg(err error) errMsg {
|
||||
return errMsg{err: err}
|
||||
}
|
||||
|
||||
type TokenMsg struct {
|
||||
tcell.EventTime
|
||||
Token string
|
||||
}
|
||||
type TokenMsg string
|
||||
|
||||
const remoteAuthGatewayURL = "wss://remote-auth-gateway.discord.gg/?v=2"
|
||||
|
||||
type connCreateMsg struct {
|
||||
tcell.EventTime
|
||||
conn *websocket.Conn
|
||||
}
|
||||
|
||||
type connCloseMsg struct{ tcell.EventTime }
|
||||
type connCloseMsg struct{}
|
||||
|
||||
func (m *Model) connect() tview.Cmd {
|
||||
return func() tview.Msg {
|
||||
|
|
@ -50,7 +44,7 @@ func (m *Model) connect() tview.Cmd {
|
|||
if err != nil {
|
||||
return newErrMsg(err)
|
||||
}
|
||||
return &connCreateMsg{conn: conn}
|
||||
return connCreateMsg{conn: conn}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -61,37 +55,32 @@ func (m *Model) close() tview.Cmd {
|
|||
return newErrMsg(err)
|
||||
}
|
||||
}
|
||||
return &connCloseMsg{}
|
||||
return connCloseMsg{}
|
||||
}
|
||||
}
|
||||
|
||||
type helloMsg struct {
|
||||
tcell.EventTime
|
||||
heartbeatInterval int
|
||||
timeoutMS int
|
||||
}
|
||||
|
||||
type nonceProofMsg struct {
|
||||
tcell.EventTime
|
||||
encryptedNonce string
|
||||
}
|
||||
|
||||
type pendingRemoteInitMsg struct {
|
||||
tcell.EventTime
|
||||
fingerprint string
|
||||
}
|
||||
|
||||
type pendingTicketMsg struct {
|
||||
tcell.EventTime
|
||||
encryptedUserPayload string
|
||||
}
|
||||
|
||||
type pendingLoginMsg struct {
|
||||
tcell.EventTime
|
||||
ticket string
|
||||
}
|
||||
|
||||
type cancelMsg struct{ tcell.EventTime }
|
||||
type cancelMsg struct{}
|
||||
|
||||
func (m *Model) listen() tview.Cmd {
|
||||
return func() tview.Msg {
|
||||
|
|
@ -120,7 +109,7 @@ func (m *Model) listen() tview.Cmd {
|
|||
if err := json.Unmarshal(data, &payload); err != nil {
|
||||
return newErrMsg(err)
|
||||
}
|
||||
return &helloMsg{heartbeatInterval: payload.HeartbeatInterval, timeoutMS: payload.TimeoutMS}
|
||||
return helloMsg{heartbeatInterval: payload.HeartbeatInterval, timeoutMS: payload.TimeoutMS}
|
||||
case "nonce_proof":
|
||||
var payload struct {
|
||||
EncryptedNonce string `json:"encrypted_nonce"`
|
||||
|
|
@ -128,7 +117,7 @@ func (m *Model) listen() tview.Cmd {
|
|||
if err := json.Unmarshal(data, &payload); err != nil {
|
||||
return newErrMsg(err)
|
||||
}
|
||||
return &nonceProofMsg{encryptedNonce: payload.EncryptedNonce}
|
||||
return nonceProofMsg{encryptedNonce: payload.EncryptedNonce}
|
||||
case "pending_remote_init":
|
||||
var payload struct {
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
|
|
@ -136,7 +125,7 @@ func (m *Model) listen() tview.Cmd {
|
|||
if err := json.Unmarshal(data, &payload); err != nil {
|
||||
return newErrMsg(err)
|
||||
}
|
||||
return &pendingRemoteInitMsg{fingerprint: payload.Fingerprint}
|
||||
return pendingRemoteInitMsg{fingerprint: payload.Fingerprint}
|
||||
case "pending_ticket":
|
||||
var payload struct {
|
||||
EncryptedUserPayload string `json:"encrypted_user_payload"`
|
||||
|
|
@ -144,9 +133,9 @@ func (m *Model) listen() tview.Cmd {
|
|||
if err := json.Unmarshal(data, &payload); err != nil {
|
||||
return newErrMsg(err)
|
||||
}
|
||||
return &pendingTicketMsg{encryptedUserPayload: payload.EncryptedUserPayload}
|
||||
return pendingTicketMsg{encryptedUserPayload: payload.EncryptedUserPayload}
|
||||
case "cancel":
|
||||
return &cancelMsg{}
|
||||
return cancelMsg{}
|
||||
case "pending_login":
|
||||
var payload struct {
|
||||
Ticket string `json:"ticket"`
|
||||
|
|
@ -154,19 +143,19 @@ func (m *Model) listen() tview.Cmd {
|
|||
if err := json.Unmarshal(data, &payload); err != nil {
|
||||
return newErrMsg(err)
|
||||
}
|
||||
return &pendingLoginMsg{ticket: payload.Ticket}
|
||||
return pendingLoginMsg{ticket: payload.Ticket}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type heartbeatTickMsg struct{ tcell.EventTime }
|
||||
type heartbeatTickMsg struct{}
|
||||
|
||||
func (m *Model) heartbeat() tview.Cmd {
|
||||
return func() tview.Msg {
|
||||
time.Sleep(m.heartbeatInterval)
|
||||
return &heartbeatTickMsg{}
|
||||
return heartbeatTickMsg{}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -186,7 +175,6 @@ func (m *Model) sendHeartbeat() tview.Cmd {
|
|||
}
|
||||
|
||||
type privateKeyMsg struct {
|
||||
tcell.EventTime
|
||||
privateKey *rsa.PrivateKey
|
||||
}
|
||||
|
||||
|
|
@ -196,7 +184,7 @@ func (m *Model) generatePrivateKey() tview.Cmd {
|
|||
if err != nil {
|
||||
return newErrMsg(err)
|
||||
}
|
||||
return &privateKeyMsg{privateKey: privateKey}
|
||||
return privateKeyMsg{privateKey: privateKey}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -246,7 +234,6 @@ func (m *Model) sendNonceProof(encryptedNonce string) tview.Cmd {
|
|||
}
|
||||
|
||||
type qrCodeMsg struct {
|
||||
tcell.EventTime
|
||||
qrCode *qrcode.QRCode
|
||||
}
|
||||
|
||||
|
|
@ -258,12 +245,11 @@ func (m *Model) generateQRCode(fingerprint string) tview.Cmd {
|
|||
return newErrMsg(err)
|
||||
}
|
||||
qrCode.DisableBorder = true
|
||||
return &qrCodeMsg{qrCode: qrCode}
|
||||
return qrCodeMsg{qrCode: qrCode}
|
||||
}
|
||||
}
|
||||
|
||||
type userMsg struct {
|
||||
tcell.EventTime
|
||||
discriminator string
|
||||
username string
|
||||
}
|
||||
|
|
@ -285,7 +271,7 @@ func (m *Model) decryptUserPayload(encryptedPayload string) tview.Cmd {
|
|||
return newErrMsg(errors.New("invalid user payload"))
|
||||
}
|
||||
|
||||
return &userMsg{discriminator: parts[1], username: parts[3]}
|
||||
return userMsg{discriminator: parts[1], username: parts[3]}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -314,6 +300,6 @@ func (m *Model) exchangeTicket(ticket string) tview.Cmd {
|
|||
if err != nil {
|
||||
return newErrMsg(err)
|
||||
}
|
||||
return &TokenMsg{Token: string(decryptedToken)}
|
||||
return TokenMsg(string(decryptedToken))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,16 +2,12 @@ package token
|
|||
|
||||
import (
|
||||
"github.com/ayn2op/tview"
|
||||
"github.com/gdamore/tcell/v3"
|
||||
)
|
||||
|
||||
type TokenMsg struct {
|
||||
tcell.EventTime
|
||||
Token string
|
||||
}
|
||||
type TokenMsg string
|
||||
|
||||
func tokenCommand(token string) tview.Cmd {
|
||||
return func() tview.Msg {
|
||||
return &TokenMsg{Token: token}
|
||||
return TokenMsg(token)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,13 +56,13 @@ func NewModel(cfg *config.Config, app *tview.Application) *Model {
|
|||
func (m *Model) showLogin() tview.Cmd {
|
||||
m.inner = login.NewModel(m.cfg)
|
||||
m.buildLayout()
|
||||
return tview.Batch(m.inner.Update(&tview.InitMsg{}), tview.SetFocus(m))
|
||||
return tview.Batch(m.inner.Update(tview.InitMsg{}), tview.SetFocus(m))
|
||||
}
|
||||
|
||||
func (m *Model) showChat(token string) tview.Cmd {
|
||||
m.inner = chat.NewModel(m.app, m.cfg, token)
|
||||
m.buildLayout()
|
||||
return tview.Batch(m.inner.Update(&tview.InitMsg{}), tview.SetFocus(m))
|
||||
return tview.Batch(m.inner.Update(tview.InitMsg{}), tview.SetFocus(m))
|
||||
}
|
||||
|
||||
func (m *Model) buildLayout() {
|
||||
|
|
@ -82,7 +82,7 @@ func (m *Model) Draw(screen tcell.Screen) {
|
|||
|
||||
func (m *Model) Update(msg tview.Msg) tview.Cmd {
|
||||
switch msg := msg.(type) {
|
||||
case *tview.InitMsg:
|
||||
case tview.InitMsg:
|
||||
var cmd tview.Cmd
|
||||
if token := os.Getenv(tokenEnvVarKey); token != "" {
|
||||
cmd = tokenCommand(token)
|
||||
|
|
@ -95,23 +95,23 @@ func (m *Model) Update(msg tview.Msg) tview.Cmd {
|
|||
cmd,
|
||||
)
|
||||
|
||||
case *loginMsg:
|
||||
case loginMsg:
|
||||
return m.showLogin()
|
||||
case *tokenMsg:
|
||||
return m.showChat(msg.token)
|
||||
case tokenMsg:
|
||||
return m.showChat(string(msg))
|
||||
|
||||
case *token.TokenMsg:
|
||||
return tview.Batch(m.showChat(msg.Token), setToken(msg.Token))
|
||||
case *qr.TokenMsg:
|
||||
return tview.Batch(m.showChat(msg.Token), setToken(msg.Token))
|
||||
case token.TokenMsg:
|
||||
return tview.Batch(m.showChat(string(msg)), setToken(string(msg)))
|
||||
case qr.TokenMsg:
|
||||
return tview.Batch(m.showChat(string(msg)), setToken(string(msg)))
|
||||
|
||||
case *chat.LogoutMsg:
|
||||
case chat.LogoutMsg:
|
||||
return tview.Batch(
|
||||
m.showLogin(),
|
||||
deleteToken(),
|
||||
)
|
||||
|
||||
case *tview.KeyMsg:
|
||||
case tview.KeyMsg:
|
||||
switch {
|
||||
case keybind.Matches(msg, m.cfg.Keybinds.ToggleHelp.Keybind):
|
||||
m.help.SetShowAll(!m.help.ShowAll())
|
||||
|
|
@ -123,7 +123,7 @@ func (m *Model) Update(msg tview.Msg) tview.Cmd {
|
|||
case keybind.Matches(msg, m.cfg.Keybinds.Quit.Keybind):
|
||||
var innerCmd tview.Cmd
|
||||
if m.inner != nil {
|
||||
innerCmd = m.inner.Update(&chat.QuitMsg{})
|
||||
innerCmd = m.inner.Update(chat.QuitMsg{})
|
||||
}
|
||||
return tview.Batch(innerCmd, tview.Quit())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,30 +6,26 @@ import (
|
|||
"github.com/ayn2op/discordo/internal/clipboard"
|
||||
"github.com/ayn2op/discordo/internal/keyring"
|
||||
"github.com/ayn2op/tview"
|
||||
"github.com/gdamore/tcell/v3"
|
||||
)
|
||||
|
||||
type tokenMsg struct {
|
||||
tcell.EventTime
|
||||
token string
|
||||
}
|
||||
type tokenMsg string
|
||||
|
||||
func tokenCommand(token string) tview.Cmd {
|
||||
return func() tview.Msg {
|
||||
return &tokenMsg{token: token}
|
||||
return tokenMsg(token)
|
||||
}
|
||||
}
|
||||
|
||||
type loginMsg struct{ tcell.EventTime }
|
||||
type loginMsg struct{}
|
||||
|
||||
func getToken() tview.Cmd {
|
||||
return func() tview.Msg {
|
||||
token, err := keyring.GetToken()
|
||||
if err != nil {
|
||||
slog.Info("failed to retrieve token from keyring", "err", err)
|
||||
return &loginMsg{}
|
||||
return loginMsg{}
|
||||
}
|
||||
return &tokenMsg{token: token}
|
||||
return tokenMsg(token)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue