diff options
-rw-r--r-- | matrix/rooms/room.go | 6 | ||||
-rw-r--r-- | matrix/sync.go | 2 | ||||
-rw-r--r-- | ui/member-list.go | 99 | ||||
-rw-r--r-- | ui/room-view.go | 27 |
4 files changed, 112 insertions, 22 deletions
diff --git a/matrix/rooms/room.go b/matrix/rooms/room.go index 47f5602..53156a3 100644 --- a/matrix/rooms/room.go +++ b/matrix/rooms/room.go @@ -399,10 +399,14 @@ func (room *Room) createMemberCache() map[string]*mautrix.Member { if events != nil { for userID, event := range events { member := &event.Content.Member + member.Membership = event.Content.Membership + if len(member.Displayname) == 0 { + member.Displayname = userID + } if room.firstMemberCache == nil && userID != room.SessionUserID { room.firstMemberCache = member } - if member.Membership != "leave" { + if member.Membership == mautrix.MembershipJoin || member.Membership == mautrix.MembershipInvite { cache[userID] = member } } diff --git a/matrix/sync.go b/matrix/sync.go index 260ba91..e610b89 100644 --- a/matrix/sync.go +++ b/matrix/sync.go @@ -207,6 +207,7 @@ func (s *GomuksSyncer) GetFilterJSON(userID string) json.RawMessage { "m.room.topic", "m.room.canonical_alias", "m.room.aliases", + "m.room.power_levels", }, }, Timeline: mautrix.FilterPart{ @@ -217,6 +218,7 @@ func (s *GomuksSyncer) GetFilterJSON(userID string) json.RawMessage { "m.room.topic", "m.room.canonical_alias", "m.room.aliases", + "m.room.power_levels", }, Limit: 50, }, diff --git a/ui/member-list.go b/ui/member-list.go new file mode 100644 index 0000000..82a6125 --- /dev/null +++ b/ui/member-list.go @@ -0,0 +1,99 @@ +// gomuks - A terminal Matrix client written in Go. +// Copyright (C) 2019 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/>. + +package ui + +import ( + "sort" + "strings" + + "github.com/mattn/go-runewidth" + + "maunium.net/go/gomuks/debug" + "maunium.net/go/gomuks/ui/widget" + "maunium.net/go/mautrix" + "maunium.net/go/mauview" + "maunium.net/go/tcell" +) + +type MemberList struct { + list roomMemberList +} + +func NewMemberList() *MemberList { + return &MemberList{} +} + +type memberListItem struct { + mautrix.Member + PowerLevel int + UserID string + Color tcell.Color +} + +type roomMemberList []*memberListItem + +func (rml roomMemberList) Len() int { + return len(rml) +} + +func (rml roomMemberList) lessMembership(i, j int) bool { + return rml[j].Membership == "invite" && rml[i].Membership == "join" +} + +func (rml roomMemberList) Less(i, j int) bool { + return rml.lessMembership(i, j) || + rml[i].PowerLevel > rml[j].PowerLevel || + strings.Compare(rml[i].Displayname, rml[j].Displayname) < 0 +} + +func (rml roomMemberList) Swap(i, j int) { + rml[i], rml[j] = rml[j], rml[i] +} + +func (ml *MemberList) Update(data map[string]*mautrix.Member, levels *mautrix.PowerLevels) *MemberList { + ml.list = make(roomMemberList, len(data)) + i := 0 + debug.Print(levels) + for userID, member := range data { + ml.list[i] = &memberListItem{ + Member: *member, + UserID: userID, + PowerLevel: levels.GetUserLevel(userID), + Color: widget.GetHashColor(userID), + } + i++ + } + sort.Sort(ml.list) + return ml +} + +func (ml *MemberList) Draw(screen mauview.Screen) { + width, _ := screen.Size() + for y, member := range ml.list { + if member.Membership == "invite" { + widget.WriteLineSimpleColor(screen, member.Displayname, 1, y, member.Color) + screen.SetCell(0, y, tcell.StyleDefault, '(') + if sw := runewidth.StringWidth(member.Displayname); sw < width { + screen.SetCell(sw+1, y, tcell.StyleDefault, ')') + } else { + screen.SetCell(width-1, y, tcell.StyleDefault, ')') + } + } else { + widget.WriteLineSimpleColor(screen, member.Displayname, 0, y, member.Color) + } + } +} diff --git a/ui/room-view.go b/ui/room-view.go index 2bb3e74..a2e1bc1 100644 --- a/ui/room-view.go +++ b/ui/room-view.go @@ -45,7 +45,7 @@ type RoomView struct { topic *mauview.TextView content *MessageView status *mauview.TextField - userList *mauview.TextView + userList *MemberList ulBorder *widget.Border input *mauview.InputArea Room *rooms.Room @@ -75,7 +75,7 @@ func NewRoomView(parent *MainView, room *rooms.Room) *RoomView { view := &RoomView{ topic: mauview.NewTextView(), status: mauview.NewTextField(), - userList: mauview.NewTextView(), + userList: NewMemberList(), ulBorder: widget.NewBorder(), input: mauview.NewInputArea(), Room: room, @@ -105,10 +105,6 @@ func NewRoomView(parent *MainView, room *rooms.Room) *RoomView { view.status.SetBackgroundColor(tcell.ColorDimGray) - view.userList. - SetDynamicColors(true). - SetWrap(false) - return view } @@ -418,22 +414,11 @@ func (view *RoomView) MxRoom() *rooms.Room { } func (view *RoomView) UpdateUserList() { - var joined strings.Builder - var invited strings.Builder - for userID, user := range view.Room.GetMembers() { - if user.Membership == "join" { - joined.WriteString(widget.AddColor(user.Displayname, widget.GetHashColorName(userID))) - joined.WriteRune('\n') - } else if user.Membership == "invite" { - invited.WriteString(widget.AddColor(user.Displayname, widget.GetHashColorName(userID))) - invited.WriteRune('\n') - } - } - view.userList.Clear() - fmt.Fprintf(view.userList, "%s\n", joined.String()) - if invited.Len() > 0 { - fmt.Fprintf(view.userList, "\nInvited:\n%s", invited.String()) + pls := &mautrix.PowerLevels{} + if plEvent := view.Room.GetStateEvent(mautrix.StatePowerLevels, ""); plEvent != nil { + pls = plEvent.Content.GetPowerLevels() } + view.userList.Update(view.Room.GetMembers(), pls) } func (view *RoomView) AddServiceMessage(text string) { |