Improve tags and add initial invite handling
This commit is contained in:
@ -90,34 +90,38 @@ func NewCommandProcessor(parent *MainView) *CommandProcessor {
|
||||
},
|
||||
commands: map[string]CommandHandler{
|
||||
"unknown-command": cmdUnknownCommand,
|
||||
"help": cmdHelp,
|
||||
"me": cmdMe,
|
||||
"quit": cmdQuit,
|
||||
"clearcache": cmdClearCache,
|
||||
"leave": cmdLeave,
|
||||
"create": cmdCreateRoom,
|
||||
"pm": cmdPrivateMessage,
|
||||
"join": cmdJoin,
|
||||
"kick": cmdKick,
|
||||
"ban": cmdBan,
|
||||
"unban": cmdUnban,
|
||||
"toggle": cmdToggle,
|
||||
"logout": cmdLogout,
|
||||
"sendevent": cmdSendEvent,
|
||||
"msendevent": cmdMSendEvent,
|
||||
"setstate": cmdSetState,
|
||||
"msetstate": cmdMSetState,
|
||||
"roomnick": cmdRoomNick,
|
||||
"rainbow": cmdRainbow,
|
||||
"rainbowme": cmdRainbowMe,
|
||||
"notice": cmdNotice,
|
||||
"tags": cmdTags,
|
||||
"tag": cmdTag,
|
||||
"untag": cmdUntag,
|
||||
"invite": cmdInvite,
|
||||
"hprof": cmdHeapProfile,
|
||||
"cprof": cmdCPUProfile,
|
||||
"trace": cmdTrace,
|
||||
|
||||
"id": cmdID,
|
||||
"help": cmdHelp,
|
||||
"me": cmdMe,
|
||||
"quit": cmdQuit,
|
||||
"clearcache": cmdClearCache,
|
||||
"leave": cmdLeave,
|
||||
"create": cmdCreateRoom,
|
||||
"pm": cmdPrivateMessage,
|
||||
"join": cmdJoin,
|
||||
"kick": cmdKick,
|
||||
"ban": cmdBan,
|
||||
"unban": cmdUnban,
|
||||
"toggle": cmdToggle,
|
||||
"logout": cmdLogout,
|
||||
"accept": cmdAccept,
|
||||
"reject": cmdReject,
|
||||
"sendevent": cmdSendEvent,
|
||||
"msendevent": cmdMSendEvent,
|
||||
"setstate": cmdSetState,
|
||||
"msetstate": cmdMSetState,
|
||||
"roomnick": cmdRoomNick,
|
||||
"rainbow": cmdRainbow,
|
||||
"rainbowme": cmdRainbowMe,
|
||||
"notice": cmdNotice,
|
||||
"tags": cmdTags,
|
||||
"tag": cmdTag,
|
||||
"untag": cmdUntag,
|
||||
"invite": cmdInvite,
|
||||
"hprof": cmdHeapProfile,
|
||||
"cprof": cmdCPUProfile,
|
||||
"trace": cmdTrace,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -106,8 +106,44 @@ func cmdNotice(cmd *Command) {
|
||||
cmd.UI.Render()
|
||||
}
|
||||
|
||||
func cmdAccept(cmd *Command) {
|
||||
room := cmd.Room.MxRoom()
|
||||
if room.SessionMember.Membership != "invite" {
|
||||
cmd.Reply("/accept can only be used in rooms you're invited to")
|
||||
return
|
||||
}
|
||||
_, server, _ := mautrix.ParseUserID(room.SessionMember.Sender)
|
||||
_, err := cmd.Matrix.JoinRoom(room.ID, server)
|
||||
if err != nil {
|
||||
cmd.Reply("Failed to accept invite:", err)
|
||||
} else {
|
||||
cmd.Reply("Successfully accepted invite")
|
||||
}
|
||||
}
|
||||
|
||||
func cmdReject(cmd *Command) {
|
||||
room := cmd.Room.MxRoom()
|
||||
if room.SessionMember.Membership != "invite" {
|
||||
cmd.Reply("/reject can only be used in rooms you're invited to")
|
||||
return
|
||||
}
|
||||
err := cmd.Matrix.LeaveRoom(room.ID)
|
||||
if err != nil {
|
||||
cmd.Reply("Failed to reject invite: %v", err)
|
||||
} else {
|
||||
cmd.Reply("Successfully accepted invite")
|
||||
}
|
||||
}
|
||||
|
||||
func cmdID(cmd *Command) {
|
||||
cmd.Reply("The internal ID of this room is %s", cmd.Room.MxRoom().ID)
|
||||
}
|
||||
|
||||
func cmdTags(cmd *Command) {
|
||||
tags := cmd.Room.MxRoom().RawTags
|
||||
if len(cmd.Args) > 0 && cmd.Args[0] == "--internal" {
|
||||
tags = cmd.Room.MxRoom().Tags()
|
||||
}
|
||||
if len(tags) == 0 {
|
||||
if cmd.Room.MxRoom().IsDirect {
|
||||
cmd.Reply("This room has no tags, but it's marked as a direct chat.")
|
||||
@ -142,7 +178,18 @@ func cmdTag(cmd *Command) {
|
||||
return
|
||||
}
|
||||
}
|
||||
err := cmd.Matrix.Client().AddTag(cmd.Room.MxRoom().ID, cmd.Args[0], order)
|
||||
var err error
|
||||
if len(cmd.Args) > 2 && cmd.Args[2] == "--reset" {
|
||||
tags := mautrix.Tags{
|
||||
cmd.Args[0]: {Order: json.Number(fmt.Sprintf("%f", order))},
|
||||
}
|
||||
for _, tag := range cmd.Room.MxRoom().RawTags {
|
||||
tags[tag.Tag] = mautrix.Tag{Order: tag.Order}
|
||||
}
|
||||
err = cmd.Matrix.Client().SetTags(cmd.Room.MxRoom().ID, tags)
|
||||
} else {
|
||||
err = cmd.Matrix.Client().AddTag(cmd.Room.MxRoom().ID, cmd.Args[0], order)
|
||||
}
|
||||
if err != nil {
|
||||
cmd.Reply("Failed to add tag:", err)
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"maunium.net/go/mauview"
|
||||
"maunium.net/go/tcell"
|
||||
|
||||
"maunium.net/go/gomuks/matrix/rooms"
|
||||
"maunium.net/go/gomuks/ui/widget"
|
||||
)
|
||||
|
||||
@ -39,7 +40,7 @@ func NewMemberList() *MemberList {
|
||||
}
|
||||
|
||||
type memberListItem struct {
|
||||
mautrix.Member
|
||||
rooms.Member
|
||||
PowerLevel int
|
||||
Sigil rune
|
||||
UserID string
|
||||
@ -63,7 +64,7 @@ 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 {
|
||||
func (ml *MemberList) Update(data map[string]*rooms.Member, levels *mautrix.PowerLevels) *MemberList {
|
||||
ml.list = make(roomMemberList, len(data))
|
||||
i := 0
|
||||
highestLevel := math.MinInt32
|
||||
|
@ -19,6 +19,7 @@ package ui
|
||||
import (
|
||||
"math"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
sync "github.com/sasha-s/go-deadlock"
|
||||
@ -30,13 +31,43 @@ import (
|
||||
"maunium.net/go/gomuks/matrix/rooms"
|
||||
)
|
||||
|
||||
var tagOrder = map[string]int{
|
||||
"net.maunium.gomuks.fake.invite": 4,
|
||||
"m.favourite": 3,
|
||||
"net.maunium.gomuks.fake.direct": 2,
|
||||
"": 1,
|
||||
"m.lowpriority": -1,
|
||||
"m.server_notice": -2,
|
||||
"net.maunium.gomuks.fake.leave": -3,
|
||||
}
|
||||
|
||||
// TagNameList is a list of Matrix tag names where default names are sorted in a hardcoded way.
|
||||
type TagNameList []string
|
||||
|
||||
func (tnl TagNameList) Len() int {
|
||||
return len(tnl)
|
||||
}
|
||||
|
||||
func (tnl TagNameList) Less(i, j int) bool {
|
||||
orderI, _ := tagOrder[tnl[i]]
|
||||
orderJ, _ := tagOrder[tnl[j]]
|
||||
if orderI != orderJ {
|
||||
return orderI > orderJ
|
||||
}
|
||||
return strings.Compare(tnl[i], tnl[j]) > 0
|
||||
}
|
||||
|
||||
func (tnl TagNameList) Swap(i, j int) {
|
||||
tnl[i], tnl[j] = tnl[j], tnl[i]
|
||||
}
|
||||
|
||||
type RoomList struct {
|
||||
sync.RWMutex
|
||||
|
||||
parent *MainView
|
||||
|
||||
// The list of tags in display order.
|
||||
tags []string
|
||||
tags TagNameList
|
||||
// The list of rooms, in reverse order.
|
||||
items map[string]*TagRoomList
|
||||
// The selected room.
|
||||
@ -107,13 +138,14 @@ func (list *RoomList) checkTag(tag string) {
|
||||
//delete(list.items, tag)
|
||||
ok = false
|
||||
}
|
||||
debug.Print("Checking", tag, index, trl.IsEmpty(), ok)
|
||||
|
||||
if ok && index == -1 {
|
||||
list.tags = append(list.tags, tag)
|
||||
} /* TODO this doesn't work properly
|
||||
else if index != -1 {
|
||||
sort.Sort(list.tags)
|
||||
} else if !ok && index != -1 {
|
||||
list.tags = append(list.tags[0:index], list.tags[index+1:]...)
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
func (list *RoomList) AddToTag(tag rooms.RoomTag, room *rooms.Room) {
|
||||
@ -122,10 +154,9 @@ func (list *RoomList) AddToTag(tag rooms.RoomTag, room *rooms.Room) {
|
||||
trl, ok := list.items[tag.Tag]
|
||||
if !ok {
|
||||
list.items[tag.Tag] = NewTagRoomList(list, tag.Tag, NewDefaultOrderedRoom(room))
|
||||
return
|
||||
} else {
|
||||
trl.Insert(tag.Order, room)
|
||||
}
|
||||
|
||||
trl.Insert(tag.Order, room)
|
||||
list.checkTag(tag.Tag)
|
||||
}
|
||||
|
||||
@ -412,11 +443,11 @@ func (list *RoomList) ContentHeight() (height int) {
|
||||
return
|
||||
}
|
||||
|
||||
func (list *RoomList) OnKeyEvent(event mauview.KeyEvent) bool {
|
||||
func (list *RoomList) OnKeyEvent(_ mauview.KeyEvent) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (list *RoomList) OnPasteEvent(event mauview.PasteEvent) bool {
|
||||
func (list *RoomList) OnPasteEvent(_ mauview.PasteEvent) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -517,6 +548,10 @@ func (list *RoomList) GetTagDisplayName(tag string) string {
|
||||
return "System Alerts"
|
||||
case tag == "net.maunium.gomuks.fake.direct":
|
||||
return "People"
|
||||
case tag == "net.maunium.gomuks.fake.invite":
|
||||
return "Invites"
|
||||
case tag == "net.maunium.gomuks.fake.leave":
|
||||
return "Historical"
|
||||
case strings.HasPrefix(tag, "u."):
|
||||
return tag[len("u."):]
|
||||
case !nsRegex.MatchString(tag):
|
||||
|
@ -17,10 +17,12 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"maunium.net/go/gomuks/debug"
|
||||
"maunium.net/go/mauview"
|
||||
"maunium.net/go/tcell"
|
||||
|
||||
@ -30,10 +32,10 @@ import (
|
||||
|
||||
type OrderedRoom struct {
|
||||
*rooms.Room
|
||||
order string
|
||||
order json.Number
|
||||
}
|
||||
|
||||
func NewOrderedRoom(order string, room *rooms.Room) *OrderedRoom {
|
||||
func NewOrderedRoom(order json.Number, room *rooms.Room) *OrderedRoom {
|
||||
return &OrderedRoom{
|
||||
Room: room,
|
||||
order: order,
|
||||
@ -153,23 +155,25 @@ func (trl *TagRoomList) HasVisibleRooms() bool {
|
||||
// ShouldBeBefore returns if the first room should be after the second room in the room list.
|
||||
// The manual order and last received message timestamp are considered.
|
||||
func (trl *TagRoomList) ShouldBeAfter(room1 *OrderedRoom, room2 *OrderedRoom) bool {
|
||||
orderComp := strings.Compare(room1.order, room2.order)
|
||||
orderComp := strings.Compare(string(room1.order), string(room2.order))
|
||||
return orderComp == 1 || (orderComp == 0 && room2.LastReceivedMessage.After(room1.LastReceivedMessage))
|
||||
}
|
||||
|
||||
func (trl *TagRoomList) Insert(order string, mxRoom *rooms.Room) {
|
||||
func (trl *TagRoomList) Insert(order json.Number, mxRoom *rooms.Room) {
|
||||
room := NewOrderedRoom(order, mxRoom)
|
||||
trl.rooms = append(trl.rooms, nil)
|
||||
// The default insert index is the newly added slot.
|
||||
// That index will be used if all other rooms in the list have the same LastReceivedMessage timestamp.
|
||||
insertAt := len(trl.rooms) - 1
|
||||
insertAt := len(trl.rooms)
|
||||
// Find the spot where the new room should be put according to the last received message timestamps.
|
||||
for i := 0; i < len(trl.rooms)-1; i++ {
|
||||
if trl.ShouldBeAfter(room, trl.rooms[i]) {
|
||||
if trl.rooms[i].Room == mxRoom {
|
||||
debug.Printf("Warning: tried to re-insert room %s into tag %s", mxRoom.ID, trl.name)
|
||||
return
|
||||
} else if trl.ShouldBeAfter(room, trl.rooms[i]) {
|
||||
insertAt = i
|
||||
break
|
||||
}
|
||||
}
|
||||
trl.rooms = append(trl.rooms, nil)
|
||||
// Move newer rooms forward in the array.
|
||||
for i := len(trl.rooms) - 1; i > insertAt; i-- {
|
||||
trl.rooms[i] = trl.rooms[i-1]
|
||||
@ -207,7 +211,12 @@ func (trl *TagRoomList) RemoveIndex(index int) {
|
||||
if index < 0 || index > len(trl.rooms) {
|
||||
return
|
||||
}
|
||||
trl.rooms = append(trl.rooms[0:index], trl.rooms[index+1:]...)
|
||||
last := len(trl.rooms) - 1
|
||||
if index < last {
|
||||
copy(trl.rooms[index:], trl.rooms[index+1:])
|
||||
}
|
||||
trl.rooms[last] = nil
|
||||
trl.rooms = trl.rooms[:last]
|
||||
}
|
||||
|
||||
func (trl *TagRoomList) Index(room *rooms.Room) int {
|
||||
|
Reference in New Issue
Block a user