cli: Use host prefixes as unique identifiers
Using the contact ID (which is about to disappear, anyway) to refer to contacts in commands makes for an awkward UX. For a differently awkward UX, use the shortest (>3) unambiguous prefix of the hostname instead. This is stable, always typable, kind of memorable, and seems like a decent compromise for now.
This commit is contained in:
parent
e0b7ab9ccb
commit
914163c7de
|
@ -247,7 +247,7 @@ func (c *Conversation) printMessage(msg *ricochet.Message) {
|
||||||
if c.numUnread > 1 {
|
if c.numUnread > 1 {
|
||||||
messages += "s"
|
messages += "s"
|
||||||
}
|
}
|
||||||
fmt.Fprintf(Ui.Stdout, "\r\x1b[31m[[ \x1b[1;34m%s\x1b[0m from \x1b[1m%s\x1b[0m (\x1b[1m%d\x1b[0m) \x1b[31m]]\x1b[39m\n", messages, c.Contact.Data.Nickname, c.Contact.Data.Id)
|
fmt.Fprintf(Ui.Stdout, "\r\x1b[31m[[ \x1b[1;34m%s\x1b[0m from \x1b[1m%s\x1b[0m (\x1b[1m%s\x1b[0m) \x1b[31m]]\x1b[39m\n", messages, c.Contact.Data.Nickname, Ui.PrefixForContact(c.Contact))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/chzyer/readline"
|
"github.com/chzyer/readline"
|
||||||
|
"github.com/ricochet-im/ricochet-go/core"
|
||||||
"github.com/ricochet-im/ricochet-go/rpc"
|
"github.com/ricochet-im/ricochet-go/rpc"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"io"
|
"io"
|
||||||
|
@ -12,6 +13,10 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MinContactPrefix = 3
|
||||||
|
)
|
||||||
|
|
||||||
var Ui UI
|
var Ui UI
|
||||||
|
|
||||||
type UI struct {
|
type UI struct {
|
||||||
|
@ -61,16 +66,6 @@ func (ui *UI) Execute(line string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
words := strings.SplitN(line, " ", 2)
|
words := strings.SplitN(line, " ", 2)
|
||||||
if id, err := strconv.Atoi(words[0]); err == nil {
|
|
||||||
contact := ui.Client.Contacts.ById(int32(id))
|
|
||||||
if contact != nil {
|
|
||||||
ui.SetCurrentContact(contact)
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(ui.Stdout, "no contact %d\n", id)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
switch words[0] {
|
switch words[0] {
|
||||||
case "clear":
|
case "clear":
|
||||||
readline.ClearScreen(readline.Stdout)
|
readline.ClearScreen(readline.Stdout)
|
||||||
|
@ -113,15 +108,24 @@ func (ui *UI) Execute(line string) error {
|
||||||
ui.SetCurrentContact(nil)
|
ui.SetCurrentContact(nil)
|
||||||
|
|
||||||
case "help":
|
case "help":
|
||||||
fallthrough
|
ui.printHelp()
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fmt.Fprintf(ui.Stdout, "Commands: clear, quit, status, connect, disconnect, contacts, add-contact, delete-contact, log, close, help\n")
|
contact := ui.ContactByPrefix(line)
|
||||||
|
if contact != nil {
|
||||||
|
ui.SetCurrentContact(contact)
|
||||||
|
} else {
|
||||||
|
ui.printHelp()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ui *UI) printHelp() {
|
||||||
|
fmt.Fprintf(ui.Stdout, "Commands: clear, quit, status, connect, disconnect, contacts, add-contact, delete-contact, log, close, help\n")
|
||||||
|
}
|
||||||
|
|
||||||
func (ui *UI) PrintStatus() {
|
func (ui *UI) PrintStatus() {
|
||||||
controlStatus := ui.Client.NetworkControlStatus()
|
controlStatus := ui.Client.NetworkControlStatus()
|
||||||
connectionStatus := ui.Client.NetworkConnectionStatus()
|
connectionStatus := ui.Client.NetworkConnectionStatus()
|
||||||
|
@ -173,9 +177,9 @@ func (ui *UI) ListContacts() {
|
||||||
for _, contact := range contacts {
|
for _, contact := range contacts {
|
||||||
unreadCount := contact.Conversation.UnreadCount()
|
unreadCount := contact.Conversation.UnreadCount()
|
||||||
if unreadCount > 0 {
|
if unreadCount > 0 {
|
||||||
fmt.Fprintf(ui.Stdout, " \x1b[1m%s\x1b[0m (\x1b[1m%d\x1b[0m) -- \x1b[34;1m%d new messages\x1b[0m\n", contact.Data.Nickname, contact.Data.Id, unreadCount)
|
fmt.Fprintf(ui.Stdout, " \x1b[1m%s\x1b[0m (\x1b[1m%s\x1b[0m) -- \x1b[34;1m%d new messages\x1b[0m\n", contact.Data.Nickname, ui.PrefixForContact(contact), unreadCount)
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(ui.Stdout, " %s (\x1b[1m%d\x1b[0m)\n", contact.Data.Nickname, contact.Data.Id)
|
fmt.Fprintf(ui.Stdout, " %s (\x1b[1m%s\x1b[0m)\n", contact.Data.Nickname, ui.PrefixForContact(contact))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,7 +242,10 @@ func (ui *UI) DeleteContact(params []string) {
|
||||||
}
|
}
|
||||||
contact := ui.Client.Contacts.ById(int32(id))
|
contact := ui.Client.Contacts.ById(int32(id))
|
||||||
if contact == nil {
|
if contact == nil {
|
||||||
fmt.Fprintf(ui.Stdout, "No contact with id %d\n", id)
|
contact = ui.ContactByPrefix(params[0])
|
||||||
|
}
|
||||||
|
if contact == nil {
|
||||||
|
fmt.Fprintf(ui.Stdout, "No contact with address %s\n", params[0])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,6 +397,41 @@ func ColoredContactStatus(status ricochet.Contact_Status) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ui *UI) ContactByPrefix(prefix string) *Contact {
|
||||||
|
if len(prefix) < MinContactPrefix {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var contact *Contact
|
||||||
|
for _, c := range ui.Client.Contacts.Contacts {
|
||||||
|
host, _ := core.PlainHostFromAddress(c.Data.Address)
|
||||||
|
if prefix == host[:len(prefix)] {
|
||||||
|
if contact != nil {
|
||||||
|
// Ambiguous prefix
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
contact = c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return contact
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ui *UI) PrefixForContact(contact *Contact) string {
|
||||||
|
host, _ := core.PlainHostFromAddress(contact.Data.Address)
|
||||||
|
prefix := host[:MinContactPrefix]
|
||||||
|
|
||||||
|
for _, c := range ui.Client.Contacts.Contacts {
|
||||||
|
if c == contact {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cHost, _ := core.PlainHostFromAddress(c.Data.Address)
|
||||||
|
for prefix == cHost[:len(prefix)] && len(prefix) < len(host) {
|
||||||
|
prefix = host[:len(prefix)+1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return prefix
|
||||||
|
}
|
||||||
|
|
||||||
func (ui *UI) SetCurrentContact(contact *Contact) {
|
func (ui *UI) SetCurrentContact(contact *Contact) {
|
||||||
if ui.CurrentContact == contact {
|
if ui.CurrentContact == contact {
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue