In a future patch I want to add support for viewing banned/invited
users, and it's also been mentioned that UserListModel is quite slow
too.
The biggest cost is sorting the member list (power level and
alphabetically) and this happened in a few different ways:
* When the member list updated
* The user switches rooms
* Misc events such as the palette changing
But this was pretty inefficient, because internally Quotient::Room keeps
a list of members, and we kept re-sorting that same list. Our
connections were also too broad and despite having signals for members
joining and leaving we just reloaded the entire list anyway.
So my new solution is to keep the list persistently sorted in
NeoChatRoom, and reload that in UserListModel. This model also keeps
track of *all* members - including ones that left - which will be used
for the aforementioned feature. So UserFilterModel now filters out only
the joined members, and that will be configurable in the future.
I also added two new roles to UserListModel for membership and color
respectively (which makes some dead code useful again) and fixed us
overwriting the built-in Qt roles accidentally.
This introduces a new NeoChatDateTime object that wraps a QDateTime. The intent is that it can be passed to QML and has a series of functions that format the QDateTime into the various string representations we need.
This means we only have to send the single object to QML and then the correct string can be grabbed from there, simplifying the backend. It is also easy to add a new representation if needed as a function with a QString output and Q_PROPERTY can be added and then it will be available.
I thought this was unnecessary as the push rules should take care of it
for us, but that's not entirely true. I added a comment to reflect this
reality.
This introduces a new NeoChatDateTime object that wraps a QDateTime. The intent is that it can be passed to QML and has a series of functions that format the QDateTime into the various string representations we need.
This means we only have to send the single object to QML and then the correct string can be grabbed from there, simplifying the backend. It is also easy to add a new representation if needed as a function with a QString output and Q_PROPERTY can be added and then it will be available.
There's two parts to making this work mainly:
1. Use getEvent instead of findInTimeline so the related event is
actually found.
2. Close the dialog once a reply relation is found, so you can easily
reply in the chat bar.
There's a bug in how we're using this function in room search, but we
definitely don't want it to crash. The event is technically not in the
timeline, so we were dereferencing an invalid iterator or whatever.
These are more common than we thought, good examples are pinned or
searched messages - which are not going to be in the room's history
unless you happen to have them loaded. But currently our message menu
infrastructure expects them to be, since its looked up by the room +
event ID.
To fix this is simple, we now move the job of finding the event to the
caller which may use a model instead. I didn't fix all existing
call-sites yet, mainly the message menu opening one since that was the
most obvious bug. But this opens up the door for other assumptions about
room history to be fixed too.
I had to do a bit of C++ re-jiggering in order to expose useful
functions to QML.
`decryptMessage` returns null if it fails to decode the passed message. This value
then got fed into `EventHandler::richBody` which logged a warning and cleared `m_pinnedMessage`.
If we instead retain the value as an `EncryptedEvent`, the UI will pin the encrypted event
placeholder instead of hiding the existence of pins.
This is a common feature in other chat applications (like Discord) as a
way to keep track of important information. While there isn't a standard
API for this, we can use account data to store notes.
Direct chats by their very nature is between two users, and you usually
can keep track of who said what. There's no point in including the
sender's name here, and most other chat applications exclude it for this
reason (including Element X.)
The key can be in the unstable features list, but it can be false. This
stops some features showing up and hitting API that isn't actually
implemented.
"X has put Y out of the room" is a British English style sentence. Which
is fine, but I'm using en_US, not en_UK.
Re-phrase this to sound a bit more American (which is the linguistic
style we use for the base strings), and then count on the en_UK
translators bringing back the old phrasing for en_UK.
I didn't realize when redoing the tooltip for DMs that directChatInvites
was a boolean, not an integer type. Now it's changed to an integer type,
which fixes the DM invite count.
NeoChat apparently didn't count normal room invites until now either, so
now Home is highlighted in that case. Now it should be harder to miss
these kinds of invites.
You can see this while starting NeoChat, as it always fails because
localMember() isn't valid at this point. This is called during the
ChatBar setup as we're setting up the text, which also happens during
room switch.
As seen in the bug report, this setting is a bit confusing. First, it
refers to "message activity" but in reality it does take into account
all events. This is fine in my opinion, so I clarified that point.
Another thing is that it wasn't clear that timeline visibility settings
currently affect the sorting, so I added a tip about that.
Finally I wasn't happy with these two options being called "Activity"
so the old "Activity" setting is now called "Importance". The "Last
Message Activity" setting is now called "Newest Events".
BUG: 508480
FIXED-IN: 25.12.0
If an item is added, the corresponding code should be wrapped with
beginInsertRows() and endInsertRows(), otherwise proxy or filter models
can end up with corrupted internal state.
m_members.insert() in refreshMember() should be unnecessary because
if pos is not the same as m_members.size(), then it means there's already
a member.id() item in the member list.
I guess we never tested this against a truly empty server yet, as the
"no search" message was empty. This would normally never show up since
the top public rooms are usually listed instead.