// TODO: Seed random?
}
+
+// RecentActiveUsers is a slice of *Users that knows how to be sorted by the time of the last message.
+type RecentActiveUsers []*User
+
+func (a RecentActiveUsers) Len() int { return len(a) }
+func (a RecentActiveUsers) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a RecentActiveUsers) Less(i, j int) bool {
+ a[i].mu.Lock()
+ defer a[i].mu.Unlock()
+ a[j].mu.Lock()
+ defer a[j].mu.Unlock()
+ return a[i].lastMsg.After(a[j].lastMsg)
+}
"errors"
"fmt"
"io"
+ "sort"
"sync"
"github.com/shazow/ssh-chat/chat/message"
}
// NamesPrefix lists all members' names with a given prefix, used to query
-// for autocompletion purposes.
+// for autocompletion purposes. Sorted by which user was last active.
func (r *Room) NamesPrefix(prefix string) []string {
items := r.Members.ListPrefix(prefix)
- names := make([]string, len(items))
- for i, item := range items {
- names[i] = item.Value().(*Member).User.Name()
+
+ // Sort results by recently active
+ users := make([]*message.User, 0, len(items))
+ for _, item := range items {
+ users = append(users, item.Value().(*Member).User)
+ }
+ sort.Sort(message.RecentActiveUsers(users))
+
+ // Pull out names
+ names := make([]string, 0, len(items))
+ for _, user := range users {
+ names = append(names, user.Name())
}
return names
}
"time"
"github.com/shazow/ssh-chat/chat/message"
+ "github.com/shazow/ssh-chat/set"
)
// Used for testing
t.Errorf("Got: %q; Expected: %q", actual, expected)
}
}
+
+func TestRoomNamesPrefix(t *testing.T) {
+ r := NewRoom()
+
+ s := &MockScreen{}
+ members := []*Member{
+ &Member{User: message.NewUserScreen(message.SimpleID("aaa"), s)},
+ &Member{User: message.NewUserScreen(message.SimpleID("aab"), s)},
+ &Member{User: message.NewUserScreen(message.SimpleID("aac"), s)},
+ &Member{User: message.NewUserScreen(message.SimpleID("foo"), s)},
+ }
+
+ for _, m := range members {
+ if err := r.Members.Add(set.Itemize(m.ID(), m)); err != nil {
+ t.Fatal(err)
+ }
+ }
+
+ // Inject some activity
+ members[2].HandleMsg(message.NewMsg("hi")) // aac
+ members[0].HandleMsg(message.NewMsg("hi")) // aaa
+ members[3].HandleMsg(message.NewMsg("hi")) // foo
+ members[1].HandleMsg(message.NewMsg("hi")) // aab
+
+ if got, want := r.NamesPrefix("a"), []string{"aab", "aaa", "aac"}; !reflect.DeepEqual(got, want) {
+ t.Errorf("got: %q; want: %q", got, want)
+ }
+
+ members[2].HandleMsg(message.NewMsg("hi")) // aac
+ if got, want := r.NamesPrefix("a"), []string{"aac", "aab", "aaa"}; !reflect.DeepEqual(got, want) {
+ t.Errorf("got: %q; want: %q", got, want)
+ }
+
+ if got, want := r.NamesPrefix("f"), []string{"foo"}; !reflect.DeepEqual(got, want) {
+ t.Errorf("got: %q; want: %q", got, want)
+ }
+
+ if got, want := r.NamesPrefix("bar"), []string{}; !reflect.DeepEqual(got, want) {
+ t.Errorf("got: %q; want: %q", got, want)
+ }
+}