Improve tags and add initial invite handling
This commit is contained in:
parent
ecdb1166e1
commit
455d9fc4c5
@ -663,7 +663,7 @@ func (c *Container) parseDirectChatInfo(evt *mautrix.Event) map[*rooms.Room]bool
|
|||||||
return directChats
|
return directChats
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) HandleDirectChatInfo(source EventSource, evt *mautrix.Event) {
|
func (c *Container) HandleDirectChatInfo(_ EventSource, evt *mautrix.Event) {
|
||||||
directChats := c.parseDirectChatInfo(evt)
|
directChats := c.parseDirectChatInfo(evt)
|
||||||
for _, room := range c.config.Rooms.Map {
|
for _, room := range c.config.Rooms.Map {
|
||||||
shouldBeDirect := directChats[room]
|
shouldBeDirect := directChats[room]
|
||||||
@ -677,7 +677,7 @@ func (c *Container) HandleDirectChatInfo(source EventSource, evt *mautrix.Event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HandlePushRules is the event handler for the m.push_rules account data event.
|
// HandlePushRules is the event handler for the m.push_rules account data event.
|
||||||
func (c *Container) HandlePushRules(source EventSource, evt *mautrix.Event) {
|
func (c *Container) HandlePushRules(_ EventSource, evt *mautrix.Event) {
|
||||||
debug.Print("Received updated push rules")
|
debug.Print("Received updated push rules")
|
||||||
var err error
|
var err error
|
||||||
c.config.PushRules, err = pushrules.EventToPushRules(evt)
|
c.config.PushRules, err = pushrules.EventToPushRules(evt)
|
||||||
@ -689,15 +689,16 @@ func (c *Container) HandlePushRules(source EventSource, evt *mautrix.Event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HandleTag is the event handler for the m.tag account data event.
|
// HandleTag is the event handler for the m.tag account data event.
|
||||||
func (c *Container) HandleTag(source EventSource, evt *mautrix.Event) {
|
func (c *Container) HandleTag(_ EventSource, evt *mautrix.Event) {
|
||||||
|
debug.Printf("Received tags for %s: %s -- %s", evt.RoomID, evt.Content.RoomTags, string(evt.Content.VeryRaw))
|
||||||
room := c.GetOrCreateRoom(evt.RoomID)
|
room := c.GetOrCreateRoom(evt.RoomID)
|
||||||
|
|
||||||
newTags := make([]rooms.RoomTag, len(evt.Content.RoomTags))
|
newTags := make([]rooms.RoomTag, len(evt.Content.RoomTags))
|
||||||
index := 0
|
index := 0
|
||||||
for tag, info := range evt.Content.RoomTags {
|
for tag, info := range evt.Content.RoomTags {
|
||||||
order := "0.5"
|
order := json.Number("0.5")
|
||||||
if len(info.Order) > 0 {
|
if len(info.Order) > 0 {
|
||||||
order = info.Order.String()
|
order = info.Order
|
||||||
}
|
}
|
||||||
newTags[index] = rooms.RoomTag{
|
newTags[index] = rooms.RoomTag{
|
||||||
Tag: tag,
|
Tag: tag,
|
||||||
@ -714,7 +715,7 @@ func (c *Container) HandleTag(source EventSource, evt *mautrix.Event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HandleTyping is the event handler for the m.typing event.
|
// HandleTyping is the event handler for the m.typing event.
|
||||||
func (c *Container) HandleTyping(source EventSource, evt *mautrix.Event) {
|
func (c *Container) HandleTyping(_ EventSource, evt *mautrix.Event) {
|
||||||
if !c.config.AuthCache.InitialSyncDone {
|
if !c.config.AuthCache.InitialSyncDone {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -723,7 +724,7 @@ func (c *Container) HandleTyping(source EventSource, evt *mautrix.Event) {
|
|||||||
|
|
||||||
func (c *Container) MarkRead(roomID, eventID string) {
|
func (c *Container) MarkRead(roomID, eventID string) {
|
||||||
urlPath := c.client.BuildURL("rooms", roomID, "receipt", "m.read", eventID)
|
urlPath := c.client.BuildURL("rooms", roomID, "receipt", "m.read", eventID)
|
||||||
c.client.MakeRequest("POST", urlPath, struct{}{}, nil)
|
_, _ = c.client.MakeRequest("POST", urlPath, struct{}{}, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
var mentionRegex = regexp.MustCompile("\\[(.+?)]\\(https://matrix.to/#/@.+?:.+?\\)")
|
var mentionRegex = regexp.MustCompile("\\[(.+?)]\\(https://matrix.to/#/@.+?:.+?\\)")
|
||||||
@ -791,10 +792,10 @@ func (c *Container) SendTyping(roomID string, typing bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if typing {
|
if typing {
|
||||||
c.client.UserTyping(roomID, true, 20000)
|
_, _ = c.client.UserTyping(roomID, true, 20000)
|
||||||
c.typing = ts + 15
|
c.typing = ts + 15
|
||||||
} else {
|
} else {
|
||||||
c.client.UserTyping(roomID, false, 0)
|
_, _ = c.client.UserTyping(roomID, false, 0)
|
||||||
c.typing = 0
|
c.typing = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
|
"maunium.net/go/gomuks/matrix/rooms"
|
||||||
"maunium.net/go/mautrix"
|
"maunium.net/go/mautrix"
|
||||||
|
|
||||||
"maunium.net/go/gomuks/lib/glob"
|
"maunium.net/go/gomuks/lib/glob"
|
||||||
@ -29,8 +30,8 @@ import (
|
|||||||
|
|
||||||
// Room is an interface with the functions that are needed for processing room-specific push conditions
|
// Room is an interface with the functions that are needed for processing room-specific push conditions
|
||||||
type Room interface {
|
type Room interface {
|
||||||
GetMember(mxid string) *mautrix.Member
|
GetMember(mxid string) *rooms.Member
|
||||||
GetMembers() map[string]*mautrix.Member
|
GetMembers() map[string]*rooms.Member
|
||||||
GetSessionOwner() string
|
GetSessionOwner() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ package rooms
|
|||||||
import (
|
import (
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
@ -49,7 +50,7 @@ type RoomTag struct {
|
|||||||
// The name of the tag.
|
// The name of the tag.
|
||||||
Tag string
|
Tag string
|
||||||
// The order of the tag.
|
// The order of the tag.
|
||||||
Order string
|
Order json.Number
|
||||||
}
|
}
|
||||||
|
|
||||||
type UnreadMessage struct {
|
type UnreadMessage struct {
|
||||||
@ -58,6 +59,13 @@ type UnreadMessage struct {
|
|||||||
Highlight bool
|
Highlight bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Member struct {
|
||||||
|
mautrix.Member
|
||||||
|
|
||||||
|
// The user who sent the membership event
|
||||||
|
Sender string `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
// Room represents a single Matrix room.
|
// Room represents a single Matrix room.
|
||||||
type Room struct {
|
type Room struct {
|
||||||
// The room ID.
|
// The room ID.
|
||||||
@ -73,7 +81,7 @@ type Room struct {
|
|||||||
LastPrevBatch string
|
LastPrevBatch string
|
||||||
// The MXID of the user whose session this room was created for.
|
// The MXID of the user whose session this room was created for.
|
||||||
SessionUserID string
|
SessionUserID string
|
||||||
SessionMember *mautrix.Member
|
SessionMember *Member
|
||||||
|
|
||||||
// The number of unread messages that were notified about.
|
// The number of unread messages that were notified about.
|
||||||
UnreadMessages []UnreadMessage
|
UnreadMessages []UnreadMessage
|
||||||
@ -95,12 +103,12 @@ type Room struct {
|
|||||||
// Room state cache.
|
// Room state cache.
|
||||||
state map[mautrix.EventType]map[string]*mautrix.Event
|
state map[mautrix.EventType]map[string]*mautrix.Event
|
||||||
// MXID -> Member cache calculated from membership events.
|
// MXID -> Member cache calculated from membership events.
|
||||||
memberCache map[string]*mautrix.Member
|
memberCache map[string]*Member
|
||||||
exMemberCache map[string]*mautrix.Member
|
exMemberCache map[string]*Member
|
||||||
// The first two non-SessionUserID members in the room. Calculated at
|
// The first two non-SessionUserID members in the room. Calculated at
|
||||||
// the same time as memberCache.
|
// the same time as memberCache.
|
||||||
firstMemberCache *mautrix.Member
|
firstMemberCache *Member
|
||||||
secondMemberCache *mautrix.Member
|
secondMemberCache *Member
|
||||||
// The name of the room. Calculated from the state event name,
|
// The name of the room. Calculated from the state event name,
|
||||||
// canonical_alias or alias or the member cache.
|
// canonical_alias or alias or the member cache.
|
||||||
NameCache string
|
NameCache string
|
||||||
@ -337,8 +345,13 @@ func (room *Room) Tags() []RoomTag {
|
|||||||
room.lock.RLock()
|
room.lock.RLock()
|
||||||
defer room.lock.RUnlock()
|
defer room.lock.RUnlock()
|
||||||
if len(room.RawTags) == 0 {
|
if len(room.RawTags) == 0 {
|
||||||
|
sessionMember := room.GetMember(room.SessionUserID)
|
||||||
if room.IsDirect {
|
if room.IsDirect {
|
||||||
return []RoomTag{{"net.maunium.gomuks.fake.direct", "0.5"}}
|
return []RoomTag{{"net.maunium.gomuks.fake.direct", "0.5"}}
|
||||||
|
} else if sessionMember != nil && sessionMember.Membership == mautrix.MembershipInvite {
|
||||||
|
return []RoomTag{{"net.maunium.gomuks.fake.invite", "0.5"}}
|
||||||
|
} else if sessionMember != nil && sessionMember.Membership != mautrix.MembershipJoin {
|
||||||
|
return []RoomTag{{"net.maunium.gomuks.fake.leave", "0.5"}}
|
||||||
}
|
}
|
||||||
return []RoomTag{{"", "0.5"}}
|
return []RoomTag{{"", "0.5"}}
|
||||||
}
|
}
|
||||||
@ -403,10 +416,11 @@ func (room *Room) UpdateState(event *mautrix.Event) {
|
|||||||
func (room *Room) updateMemberState(event *mautrix.Event) {
|
func (room *Room) updateMemberState(event *mautrix.Event) {
|
||||||
userID := event.GetStateKey()
|
userID := event.GetStateKey()
|
||||||
if userID == room.SessionUserID {
|
if userID == room.SessionUserID {
|
||||||
room.SessionMember = room.eventToMember(userID, &event.Content)
|
debug.Print("Updating session user state:", string(event.Content.VeryRaw))
|
||||||
|
room.SessionMember = room.eventToMember(userID, event.Sender, &event.Content)
|
||||||
}
|
}
|
||||||
if room.memberCache != nil {
|
if room.memberCache != nil {
|
||||||
member := room.eventToMember(userID, &event.Content)
|
member := room.eventToMember(userID, event.Sender, &event.Content)
|
||||||
if member.Membership.IsInviteOrJoin() {
|
if member.Membership.IsInviteOrJoin() {
|
||||||
existingMember, ok := room.memberCache[userID]
|
existingMember, ok := room.memberCache[userID]
|
||||||
if ok {
|
if ok {
|
||||||
@ -553,16 +567,19 @@ func (room *Room) ReplacedBy() string {
|
|||||||
return *room.replacedByCache
|
return *room.replacedByCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (room *Room) eventToMember(userID string, content *mautrix.Content) *mautrix.Member {
|
func (room *Room) eventToMember(userID string, sender string, content *mautrix.Content) *Member {
|
||||||
member := &content.Member
|
member := content.Member
|
||||||
member.Membership = content.Membership
|
member.Membership = content.Membership
|
||||||
if len(member.Displayname) == 0 {
|
if len(member.Displayname) == 0 {
|
||||||
member.Displayname = userID
|
member.Displayname = userID
|
||||||
}
|
}
|
||||||
return member
|
return &Member{
|
||||||
|
Member: member,
|
||||||
|
Sender: sender,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (room *Room) updateNthMemberCache(userID string, member *mautrix.Member) {
|
func (room *Room) updateNthMemberCache(userID string, member *Member) {
|
||||||
if userID != room.SessionUserID {
|
if userID != room.SessionUserID {
|
||||||
if room.firstMemberCache == nil {
|
if room.firstMemberCache == nil {
|
||||||
room.firstMemberCache = member
|
room.firstMemberCache = member
|
||||||
@ -573,19 +590,19 @@ func (room *Room) updateNthMemberCache(userID string, member *mautrix.Member) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// createMemberCache caches all member events into a easily processable MXID -> *Member map.
|
// createMemberCache caches all member events into a easily processable MXID -> *Member map.
|
||||||
func (room *Room) createMemberCache() map[string]*mautrix.Member {
|
func (room *Room) createMemberCache() map[string]*Member {
|
||||||
if len(room.memberCache) > 0 {
|
if len(room.memberCache) > 0 {
|
||||||
return room.memberCache
|
return room.memberCache
|
||||||
}
|
}
|
||||||
cache := make(map[string]*mautrix.Member)
|
cache := make(map[string]*Member)
|
||||||
exCache := make(map[string]*mautrix.Member)
|
exCache := make(map[string]*Member)
|
||||||
room.lock.RLock()
|
room.lock.RLock()
|
||||||
events := room.getStateEvents(mautrix.StateMember)
|
events := room.getStateEvents(mautrix.StateMember)
|
||||||
room.firstMemberCache = nil
|
room.firstMemberCache = nil
|
||||||
room.secondMemberCache = nil
|
room.secondMemberCache = nil
|
||||||
if events != nil {
|
if events != nil {
|
||||||
for userID, event := range events {
|
for userID, event := range events {
|
||||||
member := room.eventToMember(userID, &event.Content)
|
member := room.eventToMember(userID, event.Sender, &event.Content)
|
||||||
if member.Membership.IsInviteOrJoin() {
|
if member.Membership.IsInviteOrJoin() {
|
||||||
cache[userID] = member
|
cache[userID] = member
|
||||||
room.updateNthMemberCache(userID, member)
|
room.updateNthMemberCache(userID, member)
|
||||||
@ -615,7 +632,7 @@ func (room *Room) createMemberCache() map[string]*mautrix.Member {
|
|||||||
//
|
//
|
||||||
// The members are returned from the cache.
|
// The members are returned from the cache.
|
||||||
// If the cache is empty, it is updated first.
|
// If the cache is empty, it is updated first.
|
||||||
func (room *Room) GetMembers() map[string]*mautrix.Member {
|
func (room *Room) GetMembers() map[string]*Member {
|
||||||
room.Load()
|
room.Load()
|
||||||
room.createMemberCache()
|
room.createMemberCache()
|
||||||
return room.memberCache
|
return room.memberCache
|
||||||
@ -623,7 +640,7 @@ func (room *Room) GetMembers() map[string]*mautrix.Member {
|
|||||||
|
|
||||||
// GetMember returns the member with the given MXID.
|
// GetMember returns the member with the given MXID.
|
||||||
// If the member doesn't exist, nil is returned.
|
// If the member doesn't exist, nil is returned.
|
||||||
func (room *Room) GetMember(userID string) *mautrix.Member {
|
func (room *Room) GetMember(userID string) *Member {
|
||||||
if userID == room.SessionUserID && room.SessionMember != nil {
|
if userID == room.SessionUserID && room.SessionMember != nil {
|
||||||
return room.SessionMember
|
return room.SessionMember
|
||||||
}
|
}
|
||||||
|
@ -90,34 +90,38 @@ func NewCommandProcessor(parent *MainView) *CommandProcessor {
|
|||||||
},
|
},
|
||||||
commands: map[string]CommandHandler{
|
commands: map[string]CommandHandler{
|
||||||
"unknown-command": cmdUnknownCommand,
|
"unknown-command": cmdUnknownCommand,
|
||||||
"help": cmdHelp,
|
|
||||||
"me": cmdMe,
|
"id": cmdID,
|
||||||
"quit": cmdQuit,
|
"help": cmdHelp,
|
||||||
"clearcache": cmdClearCache,
|
"me": cmdMe,
|
||||||
"leave": cmdLeave,
|
"quit": cmdQuit,
|
||||||
"create": cmdCreateRoom,
|
"clearcache": cmdClearCache,
|
||||||
"pm": cmdPrivateMessage,
|
"leave": cmdLeave,
|
||||||
"join": cmdJoin,
|
"create": cmdCreateRoom,
|
||||||
"kick": cmdKick,
|
"pm": cmdPrivateMessage,
|
||||||
"ban": cmdBan,
|
"join": cmdJoin,
|
||||||
"unban": cmdUnban,
|
"kick": cmdKick,
|
||||||
"toggle": cmdToggle,
|
"ban": cmdBan,
|
||||||
"logout": cmdLogout,
|
"unban": cmdUnban,
|
||||||
"sendevent": cmdSendEvent,
|
"toggle": cmdToggle,
|
||||||
"msendevent": cmdMSendEvent,
|
"logout": cmdLogout,
|
||||||
"setstate": cmdSetState,
|
"accept": cmdAccept,
|
||||||
"msetstate": cmdMSetState,
|
"reject": cmdReject,
|
||||||
"roomnick": cmdRoomNick,
|
"sendevent": cmdSendEvent,
|
||||||
"rainbow": cmdRainbow,
|
"msendevent": cmdMSendEvent,
|
||||||
"rainbowme": cmdRainbowMe,
|
"setstate": cmdSetState,
|
||||||
"notice": cmdNotice,
|
"msetstate": cmdMSetState,
|
||||||
"tags": cmdTags,
|
"roomnick": cmdRoomNick,
|
||||||
"tag": cmdTag,
|
"rainbow": cmdRainbow,
|
||||||
"untag": cmdUntag,
|
"rainbowme": cmdRainbowMe,
|
||||||
"invite": cmdInvite,
|
"notice": cmdNotice,
|
||||||
"hprof": cmdHeapProfile,
|
"tags": cmdTags,
|
||||||
"cprof": cmdCPUProfile,
|
"tag": cmdTag,
|
||||||
"trace": cmdTrace,
|
"untag": cmdUntag,
|
||||||
|
"invite": cmdInvite,
|
||||||
|
"hprof": cmdHeapProfile,
|
||||||
|
"cprof": cmdCPUProfile,
|
||||||
|
"trace": cmdTrace,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,8 +106,44 @@ func cmdNotice(cmd *Command) {
|
|||||||
cmd.UI.Render()
|
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) {
|
func cmdTags(cmd *Command) {
|
||||||
tags := cmd.Room.MxRoom().RawTags
|
tags := cmd.Room.MxRoom().RawTags
|
||||||
|
if len(cmd.Args) > 0 && cmd.Args[0] == "--internal" {
|
||||||
|
tags = cmd.Room.MxRoom().Tags()
|
||||||
|
}
|
||||||
if len(tags) == 0 {
|
if len(tags) == 0 {
|
||||||
if cmd.Room.MxRoom().IsDirect {
|
if cmd.Room.MxRoom().IsDirect {
|
||||||
cmd.Reply("This room has no tags, but it's marked as a direct chat.")
|
cmd.Reply("This room has no tags, but it's marked as a direct chat.")
|
||||||
@ -142,7 +178,18 @@ func cmdTag(cmd *Command) {
|
|||||||
return
|
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 {
|
if err != nil {
|
||||||
cmd.Reply("Failed to add tag:", err)
|
cmd.Reply("Failed to add tag:", err)
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
"maunium.net/go/mauview"
|
"maunium.net/go/mauview"
|
||||||
"maunium.net/go/tcell"
|
"maunium.net/go/tcell"
|
||||||
|
|
||||||
|
"maunium.net/go/gomuks/matrix/rooms"
|
||||||
"maunium.net/go/gomuks/ui/widget"
|
"maunium.net/go/gomuks/ui/widget"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ func NewMemberList() *MemberList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type memberListItem struct {
|
type memberListItem struct {
|
||||||
mautrix.Member
|
rooms.Member
|
||||||
PowerLevel int
|
PowerLevel int
|
||||||
Sigil rune
|
Sigil rune
|
||||||
UserID string
|
UserID string
|
||||||
@ -63,7 +64,7 @@ func (rml roomMemberList) Swap(i, j int) {
|
|||||||
rml[i], rml[j] = rml[j], rml[i]
|
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))
|
ml.list = make(roomMemberList, len(data))
|
||||||
i := 0
|
i := 0
|
||||||
highestLevel := math.MinInt32
|
highestLevel := math.MinInt32
|
||||||
|
@ -19,6 +19,7 @@ package ui
|
|||||||
import (
|
import (
|
||||||
"math"
|
"math"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
sync "github.com/sasha-s/go-deadlock"
|
sync "github.com/sasha-s/go-deadlock"
|
||||||
@ -30,13 +31,43 @@ import (
|
|||||||
"maunium.net/go/gomuks/matrix/rooms"
|
"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 {
|
type RoomList struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
|
|
||||||
parent *MainView
|
parent *MainView
|
||||||
|
|
||||||
// The list of tags in display order.
|
// The list of tags in display order.
|
||||||
tags []string
|
tags TagNameList
|
||||||
// The list of rooms, in reverse order.
|
// The list of rooms, in reverse order.
|
||||||
items map[string]*TagRoomList
|
items map[string]*TagRoomList
|
||||||
// The selected room.
|
// The selected room.
|
||||||
@ -107,13 +138,14 @@ func (list *RoomList) checkTag(tag string) {
|
|||||||
//delete(list.items, tag)
|
//delete(list.items, tag)
|
||||||
ok = false
|
ok = false
|
||||||
}
|
}
|
||||||
|
debug.Print("Checking", tag, index, trl.IsEmpty(), ok)
|
||||||
|
|
||||||
if ok && index == -1 {
|
if ok && index == -1 {
|
||||||
list.tags = append(list.tags, tag)
|
list.tags = append(list.tags, tag)
|
||||||
} /* TODO this doesn't work properly
|
sort.Sort(list.tags)
|
||||||
else if index != -1 {
|
} else if !ok && index != -1 {
|
||||||
list.tags = append(list.tags[0:index], list.tags[index+1:]...)
|
list.tags = append(list.tags[0:index], list.tags[index+1:]...)
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *RoomList) AddToTag(tag rooms.RoomTag, room *rooms.Room) {
|
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]
|
trl, ok := list.items[tag.Tag]
|
||||||
if !ok {
|
if !ok {
|
||||||
list.items[tag.Tag] = NewTagRoomList(list, tag.Tag, NewDefaultOrderedRoom(room))
|
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)
|
list.checkTag(tag.Tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,11 +443,11 @@ func (list *RoomList) ContentHeight() (height int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *RoomList) OnKeyEvent(event mauview.KeyEvent) bool {
|
func (list *RoomList) OnKeyEvent(_ mauview.KeyEvent) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (list *RoomList) OnPasteEvent(event mauview.PasteEvent) bool {
|
func (list *RoomList) OnPasteEvent(_ mauview.PasteEvent) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -517,6 +548,10 @@ func (list *RoomList) GetTagDisplayName(tag string) string {
|
|||||||
return "System Alerts"
|
return "System Alerts"
|
||||||
case tag == "net.maunium.gomuks.fake.direct":
|
case tag == "net.maunium.gomuks.fake.direct":
|
||||||
return "People"
|
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."):
|
case strings.HasPrefix(tag, "u."):
|
||||||
return tag[len("u."):]
|
return tag[len("u."):]
|
||||||
case !nsRegex.MatchString(tag):
|
case !nsRegex.MatchString(tag):
|
||||||
|
@ -17,10 +17,12 @@
|
|||||||
package ui
|
package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"maunium.net/go/gomuks/debug"
|
||||||
"maunium.net/go/mauview"
|
"maunium.net/go/mauview"
|
||||||
"maunium.net/go/tcell"
|
"maunium.net/go/tcell"
|
||||||
|
|
||||||
@ -30,10 +32,10 @@ import (
|
|||||||
|
|
||||||
type OrderedRoom struct {
|
type OrderedRoom struct {
|
||||||
*rooms.Room
|
*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{
|
return &OrderedRoom{
|
||||||
Room: room,
|
Room: room,
|
||||||
order: order,
|
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.
|
// 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.
|
// The manual order and last received message timestamp are considered.
|
||||||
func (trl *TagRoomList) ShouldBeAfter(room1 *OrderedRoom, room2 *OrderedRoom) bool {
|
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))
|
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)
|
room := NewOrderedRoom(order, mxRoom)
|
||||||
trl.rooms = append(trl.rooms, nil)
|
|
||||||
// The default insert index is the newly added slot.
|
// 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.
|
// 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.
|
// 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++ {
|
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
|
insertAt = i
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
trl.rooms = append(trl.rooms, nil)
|
||||||
// Move newer rooms forward in the array.
|
// Move newer rooms forward in the array.
|
||||||
for i := len(trl.rooms) - 1; i > insertAt; i-- {
|
for i := len(trl.rooms) - 1; i > insertAt; i-- {
|
||||||
trl.rooms[i] = trl.rooms[i-1]
|
trl.rooms[i] = trl.rooms[i-1]
|
||||||
@ -207,7 +211,12 @@ func (trl *TagRoomList) RemoveIndex(index int) {
|
|||||||
if index < 0 || index > len(trl.rooms) {
|
if index < 0 || index > len(trl.rooms) {
|
||||||
return
|
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 {
|
func (trl *TagRoomList) Index(room *rooms.Room) int {
|
||||||
|
Loading…
Reference in New Issue
Block a user