aboutsummaryrefslogtreecommitdiff
path: root/ui
diff options
context:
space:
mode:
Diffstat (limited to 'ui')
-rw-r--r--ui/commands.go207
-rw-r--r--ui/crypto-commands.go231
-rw-r--r--ui/no-crypto-commands.go36
-rw-r--r--ui/room-view.go2
-rw-r--r--ui/verification-modal.go94
5 files changed, 320 insertions, 250 deletions
diff --git a/ui/commands.go b/ui/commands.go
index 1877c89..9d38396 100644
--- a/ui/commands.go
+++ b/ui/commands.go
@@ -37,7 +37,6 @@ import (
"github.com/russross/blackfriday/v2"
"maunium.net/go/mautrix"
- "maunium.net/go/mautrix/crypto"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/format"
"maunium.net/go/mautrix/id"
@@ -366,212 +365,6 @@ func cmdFingerprint(cmd *Command) {
}
}
-// region TODO these four functions currently use the crypto internals directly. switch to interfaces before releasing
-
-func autocompleteDeviceUserID(cmd *CommandAutocomplete) (completions []string, newText string) {
- userCompletions := cmd.Room.AutocompleteUser(cmd.Args[0])
- if len(userCompletions) == 1 {
- newText = fmt.Sprintf("/%s %s ", cmd.OrigCommand, userCompletions[0].id)
- } else {
- completions = make([]string, len(userCompletions))
- for i, completion := range userCompletions {
- completions[i] = completion.id
- }
- }
- return
-}
-
-func autocompleteDeviceDeviceID(cmd *CommandAutocomplete) (completions []string, newText string) {
- mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
- devices, err := mach.CryptoStore.GetDevices(id.UserID(cmd.Args[0]))
- if len(devices) == 0 || err != nil {
- return
- }
- var completedDeviceID id.DeviceID
- if len(cmd.Args) > 1 {
- existingID := strings.ToUpper(cmd.Args[1])
- for _, device := range devices {
- deviceIDStr := string(device.DeviceID)
- if deviceIDStr == existingID {
- // We don't want to do any autocompletion if there's already a full device ID there.
- return []string{}, ""
- } else if strings.HasPrefix(strings.ToUpper(device.Name), existingID) || strings.HasPrefix(deviceIDStr, existingID) {
- completedDeviceID = device.DeviceID
- completions = append(completions, fmt.Sprintf("%s (%s)", device.DeviceID, device.Name))
- }
- }
- } else {
- completions = make([]string, len(devices))
- i := 0
- for _, device := range devices {
- completedDeviceID = device.DeviceID
- completions[i] = fmt.Sprintf("%s (%s)", device.DeviceID, device.Name)
- i++
- }
- }
- if len(completions) == 1 {
- newText = fmt.Sprintf("/%s %s %s ", cmd.OrigCommand, cmd.Args[0], completedDeviceID)
- }
- return
-}
-
-func autocompleteDevice(cmd *CommandAutocomplete) ([]string, string) {
- if len(cmd.Args) == 0 {
- return []string{}, ""
- } else if len(cmd.Args) == 1 && !unicode.IsSpace(rune(cmd.RawArgs[len(cmd.RawArgs)-1])) {
- return autocompleteDeviceUserID(cmd)
- } else if cmd.Command != "devices" {
- return autocompleteDeviceDeviceID(cmd)
- }
- return []string{}, ""
-}
-
-func getDevice(cmd *Command) *crypto.DeviceIdentity {
- if len(cmd.Args) < 2 {
- cmd.Reply("Usage: /%s <user id> <device id> [fingerprint]", cmd.Command)
- return nil
- }
- mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
- device, err := mach.GetOrFetchDevice(id.UserID(cmd.Args[0]), id.DeviceID(cmd.Args[1]))
- if err != nil {
- cmd.Reply("Failed to get device: %v", err)
- return nil
- }
- return device
-}
-
-func putDevice(cmd *Command, device *crypto.DeviceIdentity, action string) {
- mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
- err := mach.CryptoStore.PutDevice(device.UserID, device)
- if err != nil {
- cmd.Reply("Failed to save device: %v", err)
- } else {
- cmd.Reply("Successfully %s %s/%s (%s)", action, device.UserID, device.DeviceID, device.Name)
- }
- mach.OnDevicesChanged(device.UserID)
-}
-
-func cmdDevices(cmd *Command) {
- if len(cmd.Args) == 0 {
- cmd.Reply("Usage: /devices <user id>")
- return
- }
- userID := id.UserID(cmd.Args[0])
- mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
- devices, err := mach.CryptoStore.GetDevices(userID)
- if err != nil {
- cmd.Reply("Failed to get device list: %v", err)
- }
- if len(devices) == 0 {
- cmd.Reply("Fetching device list from server...")
- devices = mach.LoadDevices(userID)
- }
- if len(devices) == 0 {
- cmd.Reply("No devices found for %s", userID)
- return
- }
- var buf strings.Builder
- for _, device := range devices {
- _, _ = fmt.Fprintf(&buf, "%s (%s) - %s\n Fingerprint: %s\n", device.DeviceID, device.Name, device.Trust.String(), device.Fingerprint())
- }
- resp := buf.String()
- cmd.Reply("%s", resp[:len(resp)-1])
-}
-
-func cmdDevice(cmd *Command) {
- device := getDevice(cmd)
- if device == nil {
- return
- }
- deviceType := "Device"
- if device.Deleted {
- deviceType = "Deleted device"
- }
- cmd.Reply("%s %s of %s\nFingerprint: %s\nIdentity key: %s\nDevice name: %s\nTrust state: %s",
- deviceType, device.DeviceID, device.UserID,
- device.Fingerprint(), device.IdentityKey,
- device.Name, device.Trust.String())
-}
-
-func cmdVerify(cmd *Command) {
- device := getDevice(cmd)
- if device == nil {
- return
- }
- if device.Trust == crypto.TrustStateVerified {
- cmd.Reply("That device is already verified")
- return
- }
- if len(cmd.Args) == 2 {
- mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
- mach.DefaultSASTimeout = 120 * time.Second
- modal := NewVerificationModal(cmd.MainView, device, mach.DefaultSASTimeout)
- cmd.MainView.ShowModal(modal)
- err := mach.NewSimpleSASVerificationWith(device, modal)
- if err != nil {
- cmd.Reply("Failed to start interactive verification: %v", err)
- return
- }
- } else {
- fingerprint := strings.Join(cmd.Args[2:], "")
- if string(device.SigningKey) != fingerprint {
- cmd.Reply("Mismatching fingerprint")
- return
- }
- action := "verified"
- if device.Trust == crypto.TrustStateBlacklisted {
- action = "unblacklisted and verified"
- }
- device.Trust = crypto.TrustStateVerified
- putDevice(cmd, device, action)
- }
-}
-
-func cmdUnverify(cmd *Command) {
- device := getDevice(cmd)
- if device == nil {
- return
- }
- if device.Trust == crypto.TrustStateUnset {
- cmd.Reply("That device is already not verified")
- return
- }
- action := "unverified"
- if device.Trust == crypto.TrustStateBlacklisted {
- action = "unblacklisted"
- }
- device.Trust = crypto.TrustStateUnset
- putDevice(cmd, device, action)
-}
-
-func cmdBlacklist(cmd *Command) {
- device := getDevice(cmd)
- if device == nil {
- return
- }
- if device.Trust == crypto.TrustStateBlacklisted {
- cmd.Reply("That device is already blacklisted")
- return
- }
- action := "blacklisted"
- if device.Trust == crypto.TrustStateVerified {
- action = "unverified and blacklisted"
- }
- device.Trust = crypto.TrustStateBlacklisted
- putDevice(cmd, device, action)
-}
-
-func cmdResetSession(cmd *Command) {
- err := cmd.Matrix.Crypto().(*crypto.OlmMachine).CryptoStore.RemoveOutboundGroupSession(cmd.Room.Room.ID)
- if err != nil {
- cmd.Reply("Failed to remove outbound group session: %v", err)
- } else {
- cmd.Reply("Removed outbound group session for this room")
- }
-}
-
-// endregion
-
func cmdHeapProfile(cmd *Command) {
if len(cmd.Args) == 0 || cmd.Args[0] != "nogc" {
runtime.GC()
diff --git a/ui/crypto-commands.go b/ui/crypto-commands.go
new file mode 100644
index 0000000..232f508
--- /dev/null
+++ b/ui/crypto-commands.go
@@ -0,0 +1,231 @@
+// gomuks - A terminal Matrix client written in Go.
+// Copyright (C) 2020 Tulir Asokan
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+// +build cgo
+
+package ui
+
+import (
+ "fmt"
+ "strings"
+ "time"
+ "unicode"
+
+ "maunium.net/go/mautrix/crypto"
+ "maunium.net/go/mautrix/id"
+)
+
+func autocompleteDeviceUserID(cmd *CommandAutocomplete) (completions []string, newText string) {
+ userCompletions := cmd.Room.AutocompleteUser(cmd.Args[0])
+ if len(userCompletions) == 1 {
+ newText = fmt.Sprintf("/%s %s ", cmd.OrigCommand, userCompletions[0].id)
+ } else {
+ completions = make([]string, len(userCompletions))
+ for i, completion := range userCompletions {
+ completions[i] = completion.id
+ }
+ }
+ return
+}
+
+func autocompleteDeviceDeviceID(cmd *CommandAutocomplete) (completions []string, newText string) {
+ mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
+ devices, err := mach.CryptoStore.GetDevices(id.UserID(cmd.Args[0]))
+ if len(devices) == 0 || err != nil {
+ return
+ }
+ var completedDeviceID id.DeviceID
+ if len(cmd.Args) > 1 {
+ existingID := strings.ToUpper(cmd.Args[1])
+ for _, device := range devices {
+ deviceIDStr := string(device.DeviceID)
+ if deviceIDStr == existingID {
+ // We don't want to do any autocompletion if there's already a full device ID there.
+ return []string{}, ""
+ } else if strings.HasPrefix(strings.ToUpper(device.Name), existingID) || strings.HasPrefix(deviceIDStr, existingID) {
+ completedDeviceID = device.DeviceID
+ completions = append(completions, fmt.Sprintf("%s (%s)", device.DeviceID, device.Name))
+ }
+ }
+ } else {
+ completions = make([]string, len(devices))
+ i := 0
+ for _, device := range devices {
+ completedDeviceID = device.DeviceID
+ completions[i] = fmt.Sprintf("%s (%s)", device.DeviceID, device.Name)
+ i++
+ }
+ }
+ if len(completions) == 1 {
+ newText = fmt.Sprintf("/%s %s %s ", cmd.OrigCommand, cmd.Args[0], completedDeviceID)
+ }
+ return
+}
+
+func autocompleteDevice(cmd *CommandAutocomplete) ([]string, string) {
+ if len(cmd.Args) == 0 {
+ return []string{}, ""
+ } else if len(cmd.Args) == 1 && !unicode.IsSpace(rune(cmd.RawArgs[len(cmd.RawArgs)-1])) {
+ return autocompleteDeviceUserID(cmd)
+ } else if cmd.Command != "devices" {
+ return autocompleteDeviceDeviceID(cmd)
+ }
+ return []string{}, ""
+}
+
+func getDevice(cmd *Command) *crypto.DeviceIdentity {
+ if len(cmd.Args) < 2 {
+ cmd.Reply("Usage: /%s <user id> <device id> [fingerprint]", cmd.Command)
+ return nil
+ }
+ mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
+ device, err := mach.GetOrFetchDevice(id.UserID(cmd.Args[0]), id.DeviceID(cmd.Args[1]))
+ if err != nil {
+ cmd.Reply("Failed to get device: %v", err)
+ return nil
+ }
+ return device
+}
+
+func putDevice(cmd *Command, device *crypto.DeviceIdentity, action string) {
+ mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
+ err := mach.CryptoStore.PutDevice(device.UserID, device)
+ if err != nil {
+ cmd.Reply("Failed to save device: %v", err)
+ } else {
+ cmd.Reply("Successfully %s %s/%s (%s)", action, device.UserID, device.DeviceID, device.Name)
+ }
+ mach.OnDevicesChanged(device.UserID)
+}
+
+func cmdDevices(cmd *Command) {
+ if len(cmd.Args) == 0 {
+ cmd.Reply("Usage: /devices <user id>")
+ return
+ }
+ userID := id.UserID(cmd.Args[0])
+ mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
+ devices, err := mach.CryptoStore.GetDevices(userID)
+ if err != nil {
+ cmd.Reply("Failed to get device list: %v", err)
+ }
+ if len(devices) == 0 {
+ cmd.Reply("Fetching device list from server...")
+ devices = mach.LoadDevices(userID)
+ }
+ if len(devices) == 0 {
+ cmd.Reply("No devices found for %s", userID)
+ return
+ }
+ var buf strings.Builder
+ for _, device := range devices {
+ _, _ = fmt.Fprintf(&buf, "%s (%s) - %s\n Fingerprint: %s\n", device.DeviceID, device.Name, device.Trust.String(), device.Fingerprint())
+ }
+ resp := buf.String()
+ cmd.Reply("%s", resp[:len(resp)-1])
+}
+
+func cmdDevice(cmd *Command) {
+ device := getDevice(cmd)
+ if device == nil {
+ return
+ }
+ deviceType := "Device"
+ if device.Deleted {
+ deviceType = "Deleted device"
+ }
+ cmd.Reply("%s %s of %s\nFingerprint: %s\nIdentity key: %s\nDevice name: %s\nTrust state: %s",
+ deviceType, device.DeviceID, device.UserID,
+ device.Fingerprint(), device.IdentityKey,
+ device.Name, device.Trust.String())
+}
+
+func cmdVerify(cmd *Command) {
+ device := getDevice(cmd)
+ if device == nil {
+ return
+ }
+ if device.Trust == crypto.TrustStateVerified {
+ cmd.Reply("That device is already verified")
+ return
+ }
+ if len(cmd.Args) == 2 {
+ mach := cmd.Matrix.Crypto().(*crypto.OlmMachine)
+ mach.DefaultSASTimeout = 120 * time.Second
+ modal := NewVerificationModal(cmd.MainView, device, mach.DefaultSASTimeout)
+ cmd.MainView.ShowModal(modal)
+ _, err := mach.NewSimpleSASVerificationWith(device, modal)
+ if err != nil {
+ cmd.Reply("Failed to start interactive verification: %v", err)
+ return
+ }
+ } else {
+ fingerprint := strings.Join(cmd.Args[2:], "")
+ if string(device.SigningKey) != fingerprint {
+ cmd.Reply("Mismatching fingerprint")
+ return
+ }
+ action := "verified"
+ if device.Trust == crypto.TrustStateBlacklisted {
+ action = "unblacklisted and verified"
+ }
+ device.Trust = crypto.TrustStateVerified
+ putDevice(cmd, device, action)
+ }
+}
+
+func cmdUnverify(cmd *Command) {
+ device := getDevice(cmd)
+ if device == nil {
+ return
+ }
+ if device.Trust == crypto.TrustStateUnset {
+ cmd.Reply("That device is already not verified")
+ return
+ }
+ action := "unverified"
+ if device.Trust == crypto.TrustStateBlacklisted {
+ action = "unblacklisted"
+ }
+ device.Trust = crypto.TrustStateUnset
+ putDevice(cmd, device, action)
+}
+
+func cmdBlacklist(cmd *Command) {
+ device := getDevice(cmd)
+ if device == nil {
+ return
+ }
+ if device.Trust == crypto.TrustStateBlacklisted {
+ cmd.Reply("That device is already blacklisted")
+ return
+ }
+ action := "blacklisted"
+ if device.Trust == crypto.TrustStateVerified {
+ action = "unverified and blacklisted"
+ }
+ device.Trust = crypto.TrustStateBlacklisted
+ putDevice(cmd, device, action)
+}
+
+func cmdResetSession(cmd *Command) {
+ err := cmd.Matrix.Crypto().(*crypto.OlmMachine).CryptoStore.RemoveOutboundGroupSession(cmd.Room.Room.ID)
+ if err != nil {
+ cmd.Reply("Failed to remove outbound group session: %v", err)
+ } else {
+ cmd.Reply("Removed outbound group session for this room")
+ }
+}
diff --git a/ui/no-crypto-commands.go b/ui/no-crypto-commands.go
new file mode 100644
index 0000000..dae85b4
--- /dev/null
+++ b/ui/no-crypto-commands.go
@@ -0,0 +1,36 @@
+// gomuks - A terminal Matrix client written in Go.
+// Copyright (C) 2020 Tulir Asokan
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+// +build !cgo
+
+package ui
+
+func autocompleteDevice(cmd *CommandAutocomplete) ([]string, string) {
+ return []string{}, ""
+}
+
+func cmdNoCrypto(cmd *Command) {
+ cmd.Reply("This gomuks was built without encryption support")
+}
+
+var (
+ cmdDevices = cmdNoCrypto
+ cmdDevice = cmdNoCrypto
+ cmdVerify = cmdNoCrypto
+ cmdUnverify = cmdNoCrypto
+ cmdBlacklist = cmdNoCrypto
+ cmdResetSession = cmdNoCrypto
+)
diff --git a/ui/room-view.go b/ui/room-view.go
index 38a561c..225e0a9 100644
--- a/ui/room-view.go
+++ b/ui/room-view.go
@@ -629,8 +629,6 @@ func (view *RoomView) InputTabComplete(text string, cursorOffset int) {
return
}
- debug.Print("Tab completing", cursorOffset, text)
-
str := runewidth.Truncate(text, cursorOffset, "")
word := findWordToTabComplete(str)
startIndex := len(str) - len(word)
diff --git a/ui/verification-modal.go b/ui/verification-modal.go
index b3fbd35..bc529c9 100644
--- a/ui/verification-modal.go
+++ b/ui/verification-modal.go
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
+// +build cgo
+
package ui
import (
@@ -32,14 +34,17 @@ import (
type EmojiView struct {
mauview.SimpleEventHandler
- Numbers *[3]uint
- Emojis *[7]crypto.VerificationEmoji
+ Data crypto.SASData
}
func (e *EmojiView) Draw(screen mauview.Screen) {
- if e.Emojis != nil {
+ if e.Data == nil {
+ return
+ }
+ switch e.Data.Type() {
+ case event.SASEmoji:
width := 10
- for i, emoji := range e.Emojis {
+ for i, emoji := range e.Data.(crypto.EmojiSASData) {
x := i*width + i
y := 0
if i >= 4 {
@@ -49,9 +54,9 @@ func (e *EmojiView) Draw(screen mauview.Screen) {
mauview.Print(screen, string(emoji.Emoji), x, y, width, mauview.AlignCenter, tcell.ColorDefault)
mauview.Print(screen, emoji.Description, x, y+1, width, mauview.AlignCenter, tcell.ColorDefault)
}
- } else if e.Numbers != nil {
+ case event.SASDecimal:
maxWidth := 43
- for i, number := range e.Numbers {
+ for i, number := range e.Data.(crypto.DecimalSASData) {
mauview.Print(screen, strconv.FormatUint(uint64(number), 10), 0, i, maxWidth, mauview.AlignCenter, tcell.ColorDefault)
}
}
@@ -69,6 +74,8 @@ type VerificationModal struct {
emojiText *EmojiView
inputBar *mauview.InputField
+ progress int
+ progressMax int
stopWaiting chan struct{}
confirmChan chan bool
done bool
@@ -85,14 +92,15 @@ func NewVerificationModal(mainView *MainView, device *crypto.DeviceIdentity, tim
done: false,
}
- progress := int(timeout.Seconds())
+ vm.progressMax = int(timeout.Seconds())
+ vm.progress = vm.progressMax
vm.waitingBar = mauview.NewProgressBar().
- SetMax(progress).
- SetProgress(progress).
+ SetMax(vm.progressMax).
+ SetProgress(vm.progress).
SetIndeterminate(false)
vm.infoText = mauview.NewTextView()
- vm.infoText.SetText(fmt.Sprintf("Waiting for %s to accept", device.UserID))
+ vm.infoText.SetText(fmt.Sprintf("Waiting for %s\nto accept", device.UserID))
vm.emojiText = &EmojiView{}
@@ -113,59 +121,58 @@ func NewVerificationModal(mainView *MainView, device *crypto.DeviceIdentity, tim
vm.Component = mauview.Center(vm.container, 45, 12).SetAlwaysFocusChild(true)
- go vm.decrementWaitingBar(progress)
+ go vm.decrementWaitingBar()
return vm
}
-func (vm *VerificationModal) decrementWaitingBar(progress int) {
+func (vm *VerificationModal) decrementWaitingBar() {
for {
select {
case <-time.Tick(time.Second):
- if progress <= 0 {
+ if vm.progress <= 0 {
+ vm.waitingBar.SetIndeterminate(true)
+ vm.parent.parent.app.SetRedrawTicker(100 * time.Millisecond)
return
}
- progress--
- vm.waitingBar.SetProgress(progress)
+ vm.progress--
+ vm.waitingBar.SetProgress(vm.progress)
vm.parent.parent.Render()
case <-vm.stopWaiting:
- vm.waitingBar.SetIndeterminate(true)
- vm.parent.parent.app.SetRedrawTicker(100 * time.Millisecond)
return
}
}
}
-func (vm *VerificationModal) VerifyEmojisMatch(emojis [7]crypto.VerificationEmoji) bool {
- vm.infoText.SetText("Check if the other device is showing the\nsame emojis as below, then type \"yes\" to\naccept, or \"no\" to reject")
- vm.inputBar.
- SetTextColor(tcell.ColorWhite).
- SetBackgroundColor(tcell.ColorDarkCyan).
- SetPlaceholder("Type \"yes\" or \"no\"").
- Focus()
- vm.emojiText.Emojis = &emojis
- vm.parent.parent.Render()
- vm.stopWaiting <- struct{}{}
- confirm := <-vm.confirmChan
- vm.emojiText.Emojis = nil
- vm.infoText.SetText(fmt.Sprintf("Waiting for %s to accept", vm.device.UserID))
- vm.parent.parent.Render()
- return confirm
+func (vm *VerificationModal) VerificationMethods() []crypto.VerificationMethod {
+ return []crypto.VerificationMethod{crypto.VerificationMethodEmoji{}, crypto.VerificationMethodDecimal{}}
}
-func (vm *VerificationModal) VerifyNumbersMatch(numbers [3]uint) bool {
- vm.infoText.SetText("Check if the other device is showing the\nsame numbers as below, then type \"yes\" to\naccept, or \"no\" to reject")
+func (vm *VerificationModal) VerifySASMatch(_ *crypto.DeviceIdentity, data crypto.SASData) bool {
+ var typeName string
+ if data.Type() == event.SASDecimal {
+ typeName = "numbers"
+ } else if data.Type() == event.SASEmoji {
+ typeName = "emojis"
+ } else {
+ return false
+ }
+ vm.infoText.SetText(fmt.Sprintf(
+ "Check if the other device is showing the\n"+
+ "same %s as below, then type \"yes\" to\n"+
+ "accept, or \"no\" to reject", typeName))
vm.inputBar.
SetTextColor(tcell.ColorWhite).
SetBackgroundColor(tcell.ColorDarkCyan).
SetPlaceholder("Type \"yes\" or \"no\"").
Focus()
- vm.emojiText.Numbers = &numbers
+ vm.emojiText.Data = data
vm.parent.parent.Render()
- vm.stopWaiting <- struct{}{}
+ vm.progress = vm.progressMax
confirm := <-vm.confirmChan
- vm.emojiText.Numbers = nil
- vm.infoText.SetText(fmt.Sprintf("Waiting for %s to accept", vm.device.UserID))
+ vm.progress = vm.progressMax
+ vm.emojiText.Data = nil
+ vm.infoText.SetText(fmt.Sprintf("Waiting for %s\nto confirm", vm.device.UserID))
vm.parent.parent.Render()
return confirm
}
@@ -179,6 +186,7 @@ func (vm *VerificationModal) OnCancel(cancelledByUs bool, reason string, _ event
vm.infoText.SetText(fmt.Sprintf("Verification cancelled by %s: %s", vm.device.UserID, reason))
}
vm.inputBar.SetPlaceholder("Press enter to close the dialog")
+ vm.stopWaiting <- struct{}{}
vm.done = true
vm.parent.parent.Render()
}
@@ -188,6 +196,7 @@ func (vm *VerificationModal) OnSuccess() {
vm.parent.parent.app.SetRedrawTicker(1 * time.Minute)
vm.infoText.SetText(fmt.Sprintf("Successfully verified %s (%s) of %s", vm.device.Name, vm.device.DeviceID, vm.device.UserID))
vm.inputBar.SetPlaceholder("Press enter to close the dialog")
+ vm.stopWaiting <- struct{}{}
vm.done = true
vm.parent.parent.Render()
if vm.parent.config.SendToVerifiedOnly {
@@ -203,7 +212,7 @@ func (vm *VerificationModal) OnKeyEvent(event mauview.KeyEvent) bool {
return true
}
return false
- } else if vm.emojiText.Emojis == nil && vm.emojiText.Numbers == nil {
+ } else if vm.emojiText.Data == nil {
debug.Print("Ignoring pre-emoji key event")
return false
}
@@ -216,8 +225,11 @@ func (vm *VerificationModal) OnKeyEvent(event mauview.KeyEvent) bool {
debug.Print("Rejecting verification")
vm.confirmChan <- false
}
- vm.inputBar.SetPlaceholder("")
- vm.inputBar.SetTextAndMoveCursor("")
+ vm.inputBar.
+ SetPlaceholder("").
+ SetTextAndMoveCursor("").
+ SetBackgroundColor(tcell.ColorDefault).
+ SetTextColor(tcell.ColorDefault)
return true
} else {
return vm.inputBar.OnKeyEvent(event)