libQuotient
A Qt library for building matrix clients
Loading...
Searching...
No Matches
room.h
Go to the documentation of this file.
1
// SPDX-FileCopyrightText: 2016 Kitsune Ral <Kitsune-Ral@users.sf.net>
2
// SPDX-FileCopyrightText: 2017 Roman Plášil <me@rplasil.name>
3
// SPDX-FileCopyrightText: 2017 Marius Gripsgard <marius@ubports.com>
4
// SPDX-FileCopyrightText: 2018 Josip Delic <delijati@googlemail.com>
5
// SPDX-FileCopyrightText: 2018 Black Hat <bhat@encom.eu.org>
6
// SPDX-FileCopyrightText: 2019 Alexey Andreyev <aa13q@ya.ru>
7
// SPDX-FileCopyrightText: 2020 Ram Nad <ramnad1999@gmail.com>
8
// SPDX-License-Identifier: LGPL-2.1-or-later
9
10
#
pragma
once
11
12
#
include
"connection.h"
13
#
include
"roommember.h"
14
#
include
"roomstateview.h"
15
#
include
"eventitem.h"
16
#
include
"quotient_common.h"
17
18
#
include
"csapi/message_pagination.h"
19
20
#
include
"events/accountdataevents.h"
21
#
include
"events/encryptedevent.h"
22
#
include
"events/eventrelation.h"
23
#
include
"events/roomcreateevent.h"
24
#
include
"events/roomkeyevent.h"
25
#
include
"events/roommessageevent.h"
26
#
include
"events/roompowerlevelsevent.h"
27
#
include
"events/roomtombstoneevent.h"
28
#
include
"events/roomjoinrulesevent.h"
29
30
#
include
<
QtCore
/
QJsonObject
>
31
#
include
<
QtGui
/
QImage
>
32
#
include
<
QtQmlIntegration
/
qqmlintegration
.
h
>
33
34
#
include
<
deque
>
35
#
include
<
utility
>
36
37
namespace
Quotient
{
38
class
Event;
39
class
Avatar;
40
class
SyncRoomData;
41
class
RoomMemberEvent;
42
class
User;
43
class
RoomMember;
44
struct
MemberSorter;
45
class
LeaveRoomJob;
46
class
SetRoomStateWithKeyJob;
47
class
RedactEventJob;
48
struct
ThreadInfo;
49
class
ThreadInfos;
50
51
/** The data structure used to expose file transfer information to views
52
*
53
* This is specifically tuned to work with QML exposing all traits as
54
* Q_PROPERTY values.
55
*/
56
class
QUOTIENT_API
FileTransferInfo
{
57
Q_GADGET
58
Q_PROPERTY
(
bool
isUpload
MEMBER
isUpload
CONSTANT
)
59
Q_PROPERTY
(
bool
active
READ
active
CONSTANT
)
60
Q_PROPERTY
(
bool
started
READ
started
CONSTANT
)
61
Q_PROPERTY
(
bool
completed
READ
completed
CONSTANT
)
62
Q_PROPERTY
(
bool
failed
READ
failed
CONSTANT
)
63
Q_PROPERTY
(
int
progress
MEMBER
progress
CONSTANT
)
64
Q_PROPERTY
(
int
total
MEMBER
total
CONSTANT
)
65
Q_PROPERTY
(
QUrl
localDir
MEMBER
localDir
CONSTANT
)
66
Q_PROPERTY
(
QUrl
localPath
MEMBER
localPath
CONSTANT
)
67
public
:
68
enum
Status
{
None
,
Started
,
Completed
,
Failed
,
Cancelled
};
69
Status
status
=
None
;
70
bool
isUpload
=
false
;
71
int
progress
= 0;
72
int
total
= -1;
73
QUrl
localDir
{};
74
QUrl
localPath
{};
75
76
bool
started
()
const
{
return
status
==
Started
; }
77
bool
completed
()
const
{
return
status
==
Completed
; }
78
bool
active
()
const
{
return
started
() ||
completed
(); }
79
bool
failed
()
const
{
return
status
==
Failed
; }
80
};
81
82
//! \brief Data structure for a room member's read receipt
83
//! \sa Room::lastReadReceipt
84
class
QUOTIENT_API
ReadReceipt
{
85
Q_GADGET
86
Q_PROPERTY
(
QString
eventId
MEMBER
eventId
CONSTANT
)
87
Q_PROPERTY
(
QDateTime
timestamp
MEMBER
timestamp
CONSTANT
)
88
public
:
89
QString
eventId
;
90
QDateTime
timestamp
= {};
91
92
bool
operator
==(
const
ReadReceipt
&
other
)
const
93
{
94
return
eventId
==
other
.
eventId
&&
timestamp
==
other
.
timestamp
;
95
}
96
bool
operator
!=(
const
ReadReceipt
&
other
)
const
97
{
98
return
!
operator
==(
other
);
99
}
100
};
101
inline
void
swap
(
ReadReceipt
&
lhs
,
ReadReceipt
&
rhs
)
102
{
103
swap
(
lhs
.
eventId
,
rhs
.
eventId
);
104
swap
(
lhs
.
timestamp
,
rhs
.
timestamp
);
105
}
106
107
struct
EventStats;
108
109
struct
Notification
110
{
111
enum
Type
{
None
= 0,
Basic
,
Highlight
};
112
Q_ENUM
(
Type
)
113
114
Type
type
=
None
;
115
116
private
:
117
Q_GADGET
118
Q_PROPERTY(
Type
type MEMBER type CONSTANT)
119
};
120
121
class
QUOTIENT_API
Room
:
public
QObject
{
122
Q_OBJECT
123
QML_ELEMENT
124
QML_UNCREATABLE
(
""
)
125
126
Q_PROPERTY
(
Quotient
::
Connection
*
connection
READ
connection
CONSTANT
)
127
Q_PROPERTY
(
Quotient
::
RoomMember
localMember
READ
localMember
CONSTANT
)
128
Q_PROPERTY
(
QString
id
READ
id
CONSTANT
)
129
Q_PROPERTY
(
QString
version
READ
version
NOTIFY
baseStateLoaded
)
130
Q_PROPERTY
(
bool
isUnstable
READ
isUnstable
NOTIFY
stabilityUpdated
)
131
Q_PROPERTY
(
QString
predecessorId
READ
predecessorId
NOTIFY
baseStateLoaded
)
132
Q_PROPERTY
(
QString
successorId
READ
successorId
NOTIFY
upgraded
)
133
Q_PROPERTY
(
QString
name
READ
name
NOTIFY
namesChanged
)
134
Q_PROPERTY
(
QStringList
aliases
READ
aliases
NOTIFY
namesChanged
)
135
Q_PROPERTY
(
QStringList
altAliases
READ
altAliases
NOTIFY
namesChanged
)
136
Q_PROPERTY
(
QString
canonicalAlias
READ
canonicalAlias
NOTIFY
namesChanged
)
137
Q_PROPERTY
(
QString
displayName
READ
displayName
NOTIFY
displaynameChanged
)
138
Q_PROPERTY
(
QStringList
pinnedEventIds
READ
pinnedEventIds
WRITE
setPinnedEvents
139
NOTIFY
pinnedEventsChanged
)
140
Q_PROPERTY
(
QString
displayNameForHtml
READ
displayNameForHtml
NOTIFY
displaynameChanged
)
141
Q_PROPERTY
(
QString
topic
READ
topic
NOTIFY
topicChanged
)
142
Q_PROPERTY
(
QString
avatarMediaId
READ
avatarMediaId
NOTIFY
avatarChanged
143
STORED
false
)
144
Q_PROPERTY
(
QUrl
avatarUrl
READ
avatarUrl
NOTIFY
avatarChanged
)
145
Q_PROPERTY
(
bool
usesEncryption
READ
usesEncryption
NOTIFY
encryption
)
146
147
Q_PROPERTY
(
int
timelineSize
READ
timelineSize
NOTIFY
addedMessages
)
148
Q_PROPERTY
(
int
joinedCount
READ
joinedCount
NOTIFY
memberListChanged
)
149
Q_PROPERTY
(
int
invitedCount
READ
invitedCount
NOTIFY
memberListChanged
)
150
Q_PROPERTY
(
int
totalMemberCount
READ
totalMemberCount
NOTIFY
memberListChanged
)
151
Q_PROPERTY
(
QList
<
Quotient
::
RoomMember
>
membersTyping
READ
membersTyping
NOTIFY
typingChanged
)
152
Q_PROPERTY
(
QList
<
Quotient
::
RoomMember
>
otherMembersTyping
READ
otherMembersTyping
NOTIFY
typingChanged
)
153
Q_PROPERTY
(
int
localMemberEffectivePowerLevel
READ
memberEffectivePowerLevel
NOTIFY
changed
)
154
155
Q_PROPERTY
(
bool
displayed
READ
displayed
WRITE
setDisplayed
NOTIFY
156
displayedChanged
)
157
Q_PROPERTY
(
QString
firstDisplayedEventId
READ
firstDisplayedEventId
WRITE
158
setFirstDisplayedEventId
NOTIFY
firstDisplayedEventChanged
)
159
Q_PROPERTY
(
QString
lastDisplayedEventId
READ
lastDisplayedEventId
WRITE
160
setLastDisplayedEventId
NOTIFY
lastDisplayedEventChanged
)
161
Q_PROPERTY
(
QString
lastFullyReadEventId
READ
lastFullyReadEventId
WRITE
162
markMessagesAsRead
NOTIFY
fullyReadMarkerMoved
)
163
Q_PROPERTY
(
qsizetype
highlightCount
READ
highlightCount
164
NOTIFY
highlightCountChanged
)
165
Q_PROPERTY
(
qsizetype
notificationCount
READ
notificationCount
166
NOTIFY
notificationCountChanged
)
167
Q_PROPERTY
(
Quotient
::
EventStats
partiallyReadStats
READ
partiallyReadStats
NOTIFY
partiallyReadStatsChanged
)
168
Q_PROPERTY
(
Quotient
::
EventStats
unreadStats
READ
unreadStats
NOTIFY
unreadStatsChanged
)
169
Q_PROPERTY
(
bool
allHistoryLoaded
READ
allHistoryLoaded
NOTIFY
allHistoryLoadedChanged
170
STORED
false
)
171
Q_PROPERTY
(
QStringList
tagNames
READ
tagNames
NOTIFY
tagsChanged
)
172
Q_PROPERTY
(
bool
isFavourite
READ
isFavourite
NOTIFY
tagsChanged
STORED
false
)
173
Q_PROPERTY
(
bool
isLowPriority
READ
isLowPriority
NOTIFY
tagsChanged
STORED
false
)
174
Q_PROPERTY
(
Quotient
::
JoinRule
joinRule
READ
joinRule
WRITE
setJoinRule
NOTIFY
joinRuleChanged
)
175
Q_PROPERTY
(
QList
<
QString
>
allowIds
READ
allowIds
NOTIFY
joinRuleChanged
)
176
177
Q_PROPERTY
(
GetRoomEventsJob
*
eventsHistoryJob
READ
eventsHistoryJob
NOTIFY
eventsHistoryJobChanged
)
178
Q_PROPERTY
(
int
requestedHistorySize
READ
requestedHistorySize
NOTIFY
eventsHistoryJobChanged
)
179
180
Q_PROPERTY
(
QStringList
accountDataEventTypes
READ
accountDataEventTypes
NOTIFY
accountDataChanged
)
181
Q_PROPERTY
(
QStringList
creatorIds
READ
creatorIds
NOTIFY
baseStateLoaded
)
182
183
public
:
184
using
Timeline
=
std
::
deque
<
TimelineItem
>;
185
using
PendingEvents
=
std
::
vector
<
PendingEventItem
>;
186
using
RelatedEvents
=
QVector
<
const
RoomEvent
*>;
187
using
rev_iter_t
=
Timeline
::
const_reverse_iterator
;
188
using
timeline_iter_t
=
Timeline
::
const_iterator
;
189
190
//! \brief Room changes that can be tracked using Room::changed() signal
191
//!
192
//! This enumeration lists kinds of changes that can be tracked with
193
//! a "cumulative" changed() signal instead of using individual signals for
194
//! each change. Specific enumerators mention these individual signals.
195
//! \sa changed
196
enum
class
Change
:
quint32
{
// QFlags can't go more than 32-bit
197
None
= 0x0,
//!< No changes occurred in the room
198
RoomNames
= 0x1,
//!< \sa namesChanged, displaynameChanged
199
// NotInUse = 0x2,
200
Topic
= 0x4,
//!< \sa topicChanged
201
PartiallyReadStats
= 0x8,
//!< \sa partiallyReadStatsChanged
202
Avatar
= 0x10,
//!< \sa avatarChanged
203
JoinState
= 0x20,
//!< \sa joinStateChanged
204
Tags
= 0x40,
//!< \sa tagsChanged
205
//! \sa userAdded, userRemoved, memberRenamed, memberListChanged,
206
//! displaynameChanged
207
Members
= 0x80,
208
UnreadStats
= 0x100,
//!< \sa unreadStatsChanged
209
// AccountData pre-0.9 = 0x200,
210
Summary
= 0x400,
//!< \sa summaryChanged, displaynameChanged
211
// ReadMarker pre-0.9 = 0x800,
212
Highlights
= 0x1000,
//!< \sa highlightCountChanged
213
//! A catch-all value that covers changes not listed above (such as
214
//! encryption turned on or the room having been upgraded), as well as
215
//! changes in the room state that the library is not aware of (e.g.,
216
//! custom state events) and m.read/m.fully_read position changes.
217
//! \sa encryptionChanged, upgraded, accountDataChanged
218
Other
= 0x8000,
219
//! This is intended to test a Change/Changes value for non-emptiness;
220
//! adding <tt>& Change::Any</tt> has the same meaning as
221
//! !testFlag(Change::None) or adding <tt>!= Change::None</tt>
222
//! \note testFlag(Change::Any) tests that _all_ bits are on and
223
//! will always return false.
224
Any
= 0xFFFF
225
};
226
QUO_DECLARE_FLAGS
(
Changes
,
Change
)
227
228
Room
(
Connection
*
connection
,
QString
id
,
JoinState
initialJoinState
);
229
Q_DISABLE_COPY_MOVE
(
Room
)
230
~
Room
()
override
;
231
232
// Property accessors
233
234
Connection
*
connection
()
const
;
235
236
//! Get a RoomMember object for the local user.
237
RoomMember
localMember
()
const
;
238
const
QString
&
id
()
const
;
239
QString
version
()
const
;
240
bool
isUnstable
()
const
;
241
QString
predecessorId
()
const
;
242
/// Room predecessor
243
/** This function validates that the predecessor has a tombstone and
244
* the tombstone refers to the current room. If that's not the case,
245
* or if the predecessor is in a join state not matching \p stateFilter,
246
* the function returns nullptr.
247
*/
248
Room
*
predecessor
(
JoinStates
statesFilter
=
JoinState
::
Invite
249
|
JoinState
::
Join
)
const
;
250
QString
successorId
()
const
;
251
/// Room successor
252
/** This function validates that the successor room's creation event
253
* refers to the current room. If that's not the case, or if the successor
254
* is in a join state not matching \p stateFilter, it returns nullptr.
255
*/
256
Room
*
successor
(
JoinStates
statesFilter
=
JoinState
::
Invite
257
|
JoinState
::
Join
)
const
;
258
QString
name
()
const
;
259
QString
canonicalAlias
()
const
;
260
QStringList
altAliases
()
const
;
261
//! Get a list of both canonical and alternative aliases
262
QStringList
aliases
()
const
;
263
QString
displayName
()
const
;
264
QStringList
pinnedEventIds
()
const
;
265
// Returns events available locally, use pinnedEventIds() for full list
266
QVector
<
const
RoomEvent
*>
pinnedEvents
()
const
;
267
QString
displayNameForHtml
()
const
;
268
QString
topic
()
const
;
269
QString
avatarMediaId
()
const
;
270
QUrl
avatarUrl
()
const
;
271
const
Avatar
&
avatarObject
()
const
;
272
Q_INVOKABLE
JoinState
joinState
()
const
;
273
274
int
timelineSize
()
const
;
275
bool
usesEncryption
()
const
;
276
RoomEventPtr
decryptMessage
(
const
EncryptedEvent
&
encryptedEvent
);
277
void
handleRoomKeyEvent
(
const
RoomKeyEvent
&
roomKeyEvent
,
278
const
QString
&
senderId
,
279
const
QByteArray
&
olmSessionId
,
280
const
QByteArray
&
senderKey
,
281
const
QByteArray
&
senderEdKey
);
282
int
joinedCount
()
const
;
283
int
invitedCount
()
const
;
284
int
totalMemberCount
()
const
;
285
286
GetRoomEventsJob
*
eventsHistoryJob
()
const
;
287
288
/**
289
* Returns a square room avatar with the given size and requests it
290
* from the network if needed
291
* \return a pixmap with the avatar or a placeholder if there's none
292
* available yet
293
*/
294
Q_INVOKABLE
QImage
avatar
(
int
dimension
);
295
/**
296
* Returns a room avatar with the given dimensions and requests it
297
* from the network if needed
298
* \return a pixmap with the avatar or a placeholder if there's none
299
* available yet
300
*/
301
Q_INVOKABLE
QImage
avatar
(
int
width
,
int
height
);
302
303
//! \brief Get a RoomMember object for the given user Matrix ID
304
//!
305
//! Will return a nullptr if there is no m.room.member event for the user in
306
//! the room so needs to be null checked.
307
//!
308
//! \note This can return a member in any state that is known to the room so
309
//! check the state (using RoomMember::membershipState()) before use.
310
Q_INVOKABLE
RoomMember
member
(
const
QString
&
userId
)
const
;
311
312
//! Get a list of room members who have joined the room.
313
QList
<
RoomMember
>
joinedMembers
()
const
;
314
315
//! Get a list of all members known to the room.
316
QList
<
RoomMember
>
members
()
const
;
317
318
//! Get a list of all members known to have left the room.
319
QList
<
RoomMember
>
membersLeft
()
const
;
320
321
//! Get a list of room members who are currently sending a typing indicator.
322
QList
<
RoomMember
>
membersTyping
()
const
;
323
324
//! \brief Get a list of room members who are currently sending a typing indicator.
325
//!
326
//! The local member is excluded from this list.
327
QList
<
RoomMember
>
otherMembersTyping
()
const
;
328
329
//! Get a list of room member Matrix IDs who have joined the room.
330
QStringList
joinedMemberIds
()
const
;
331
332
//! Get a list of all member Matrix IDs known to the room.
333
QStringList
memberIds
()
const
;
334
335
//! \brief Get Matrix IDs for room creator(s)
336
//!
337
//! As long as the create event for the room is known, the returned list will start with
338
//! MXID of the room creation event sender. For room versions 12 and newer, the returned list
339
//! will further include additional creators if there are any.
340
QStringList
creatorIds
()
const
;
341
342
//! Whether the name for the given member should be disambiguated
343
bool
needsDisambiguation
(
const
QString
&
userId
)
const
;
344
345
//! \brief Check the join state of a given user in this room
346
//!
347
//! \return the given user's state with respect to the room
348
Q_INVOKABLE
Quotient
::
Membership
memberState
(
const
QString
&
userId
)
const
;
349
350
//! Check whether a user with the given id is a member of the room
351
Q_INVOKABLE
bool
isMember
(
const
QString
&
userId
)
const
;
352
353
const
Avatar
&
memberAvatarObject
(
const
QString
&
memberId
)
const
;
354
355
//! \brief Get a avatar of the specified dimensions
356
//!
357
//! This always returns immediately; if there's no avatar cached yet, the call triggers
358
//! a network request, that will emit Room::memberAvatarUpdated() once completed.
359
//! \return a pixmap with the avatar or a placeholder if there's none available yet
360
Q_INVOKABLE
QImage
memberAvatar
(
const
QString
&
memberId
,
int
width
,
int
height
);
361
362
//! \brief Get a square avatar of the specified size
363
//!
364
//! This is an overload for the case when the needed width and height are equal.
365
Q_INVOKABLE
QImage
memberAvatar
(
const
QString
&
memberId
,
int
dimension
);
366
367
const
Timeline
&
messageEvents
()
const
;
368
const
PendingEvents
&
pendingEvents
()
const
;
369
370
//! \brief Get the number of requested historical events
371
//! \return The number of requested events if there's a pending request; 0 otherwise
372
int
requestedHistorySize
()
const
;
373
374
//! Check whether all historical messages are already loaded
375
//! \return true if the "oldest" event in the timeline is a room creation event and there's
376
//! no further history to load; false otherwise
377
bool
allHistoryLoaded
()
const
;
378
379
//! \brief Get a reverse iterator at the position before the "oldest" event
380
//!
381
//! Same as messageEvents().crend()
382
rev_iter_t
historyEdge
()
const
;
383
384
const
ThreadInfos
&
threads
()
const
;
385
386
//! \brief Get an iterator for the position beyond the latest arrived event
387
//!
388
//! Same as messageEvents().cend()
389
Timeline
::
const_iterator
syncEdge
()
const
;
390
Q_INVOKABLE
Quotient
::
TimelineItem
::
index_t
minTimelineIndex
()
const
;
391
Q_INVOKABLE
Quotient
::
TimelineItem
::
index_t
maxTimelineIndex
()
const
;
392
Q_INVOKABLE
bool
isValidIndex
(
Quotient
::
TimelineItem
::
index_t
timelineIndex
)
const
;
393
394
rev_iter_t
findInTimeline
(
TimelineItem
::
index_t
index
)
const
;
395
rev_iter_t
findInTimeline
(
const
QString
&
evtId
)
const
;
396
PendingEvents
::
iterator
findPendingEvent
(
const
QString
&
txnId
);
397
PendingEvents
::
const_iterator
findPendingEvent
(
const
QString
&
txnId
)
const
;
398
399
const
RelatedEvents
relatedEvents
(
const
QString
&
evtId
,
400
EventRelation
::
typeid_t
relType
)
const
;
401
const
RelatedEvents
relatedEvents
(
const
RoomEvent
&
evt
,
402
EventRelation
::
typeid_t
relType
)
const
;
403
404
const
RoomCreateEvent
*
creation
()
const
;
405
const
RoomTombstoneEvent
*
tombstone
()
const
;
406
407
bool
displayed
()
const
;
408
/// Mark the room as currently displayed to the user
409
/**
410
* Marking the room displayed causes the room to obtain the full
411
* list of members if it's been lazy-loaded before; in the future
412
* it may do more things bound to "screen time" of the room, e.g.
413
* measure that "screen time".
414
*/
415
void
setDisplayed
(
bool
displayed
=
true
);
416
QString
firstDisplayedEventId
()
const
;
417
rev_iter_t
firstDisplayedMarker
()
const
;
418
void
setFirstDisplayedEventId
(
const
QString
&
eventId
);
419
void
setFirstDisplayedEvent
(
TimelineItem
::
index_t
index
);
420
QString
lastDisplayedEventId
()
const
;
421
rev_iter_t
lastDisplayedMarker
()
const
;
422
void
setLastDisplayedEventId
(
const
QString
&
eventId
);
423
void
setLastDisplayedEvent
(
TimelineItem
::
index_t
index
);
424
425
//! \brief Get the latest read receipt from a user
426
//!
427
//! The user id must be valid. A read receipt with an empty event id
428
//! is returned if the user id is valid but there was no read receipt
429
//! from them.
430
//! \sa usersAtEventId
431
ReadReceipt
lastReadReceipt
(
const
QString
&
userId
)
const
;
432
433
//! \brief Get the latest read receipt from the local user
434
//!
435
//! This is a shortcut for <tt>lastReadReceipt(localUserId)</tt>.
436
//! \sa lastReadReceipt
437
ReadReceipt
lastLocalReadReceipt
()
const
;
438
439
//! \brief Find the timeline item the local read receipt is at
440
//!
441
//! This is a shortcut for \code
442
//! room->findInTimeline(room->lastLocalReadReceipt().eventId);
443
//! \endcode
444
rev_iter_t
localReadReceiptMarker
()
const
;
445
446
//! \brief Get the latest event id marked as fully read
447
//!
448
//! This can be either the event id pointed to by the actual latest
449
//! m.fully_read event, or the latest event id marked locally as fully read
450
//! if markMessagesAsRead or markAllMessagesAsRead has been called and
451
//! the homeserver didn't return an updated m.fully_read event yet.
452
//! \sa markMessagesAsRead, markAllMessagesAsRead, fullyReadMarker
453
QString
lastFullyReadEventId
()
const
;
454
455
//! \brief Get the iterator to the latest timeline item marked as fully read
456
//!
457
//! This method calls findInTimeline on the result of lastFullyReadEventId.
458
//! If the fully read marker turns out to be outside the timeline (because
459
//! the event marked as fully read is too far back in the history) the
460
//! returned value will be equal to historyEdge.
461
//!
462
//! Be sure to read the caveats on iterators returned by findInTimeline.
463
//! \sa lastFullyReadEventId, findInTimeline
464
rev_iter_t
fullyReadMarker
()
const
;
465
466
//! \brief Get users whose latest read receipts point to the event
467
//!
468
//! This method is for cases when you need to show users who have read
469
//! an event. Calling it on inexistent or empty event id will return
470
//! an empty set.
471
//! \note The returned list may contain ids resolving to users that are
472
//! not loaded as room members yet (in particular, if members are not
473
//! yet lazy-loaded). For now this merely means that the user's
474
//! room-specific name and avatar will not be there; but generally
475
//! it's recommended to ensure that all room members are loaded
476
//! before operating on the result of this function.
477
//! \sa lastReadReceipt, allMembersLoaded
478
QSet
<
QString
>
userIdsAtEvent
(
const
QString
&
eventId
)
const
;
479
480
//! \brief Mark the event with uptoEventId as fully read
481
//!
482
//! Marks the event with the specified id as fully read locally and also
483
//! sends an update to m.fully_read account data to the server either
484
//! for this message or, if it's from the local user, for
485
//! the nearest non-local message before. uptoEventId must point to a known
486
//! event in the timeline; the method will do nothing if the event is behind
487
//! the current m.fully_read marker or is not loaded, to prevent
488
//! accidentally trying to move the marker back in the timeline.
489
//! \param sendPublicReceipts if true, a public read receipt (m.read) will also be sent to the server.
490
//! \sa markAllMessagesAsRead, fullyReadMarker
491
Q_INVOKABLE
void
markMessagesAsRead
(
const
QString
&
uptoEventId
,
bool
sendPublicReceipts
=
true
);
492
493
//! \brief Determine whether an event should be counted as unread
494
//!
495
//! The criteria of including an event in unread counters are described in
496
//! [MSC2654](https://github.com/matrix-org/matrix-doc/pull/2654); according
497
//! to these, the event should be counted as unread (or, in libQuotient
498
//! parlance, is "notable") if it is:
499
//! - either
500
//! - a message event that is not m.notice, or
501
//! - a state event with type being one of:
502
//! `m.room.topic`, `m.room.name`, `m.room.avatar`, `m.room.tombstone`;
503
//! - neither redacted, nor an edit (redactions cause the redacted event
504
//! to stop being notable, while edits are not notable themselves while
505
//! the original event usually is);
506
//! - from a non-local user (events from other devices of the local
507
//! user are not notable).
508
//! \sa partiallyReadStats, unreadStats
509
virtual
bool
isEventNotable
(
const
TimelineItem
&
ti
)
const
;
510
511
//! \brief Get notification details for an event
512
//!
513
//! This allows to get details on the kind of notification that should
514
//! generated for \p evt.
515
Notification
notificationFor
(
const
TimelineItem
&
ti
)
const
;
516
517
//! \brief Get event statistics since the fully read marker
518
//!
519
//! This call returns a structure containing:
520
//! - the number of notable unread events since the fully read marker;
521
//! depending on the fully read marker state with respect to the local
522
//! timeline, this number may be either exact or estimated
523
//! (see EventStats::isEstimate);
524
//! - the number of highlights (TODO).
525
//!
526
//! Note that this is different from the unread count defined by MSC2654
527
//! and from the notification/highlight numbers defined by the spec in that
528
//! it counts events since the fully read marker, not since the last
529
//! read receipt position.
530
//!
531
//! As E2EE is not supported in the library, the returned result will always
532
//! be an estimate (<tt>isEstimate == true</tt>) for encrypted rooms;
533
//! moreover, since the library doesn't know how to tackle push rules yet
534
//! the number of highlights returned here will always be zero (there's no
535
//! good substitute for that now).
536
//!
537
//! \sa isEventNotable, fullyReadMarker, unreadStats, EventStats
538
EventStats
partiallyReadStats
()
const
;
539
540
//! \brief Get event statistics since the last read receipt
541
//!
542
//! This call returns a structure that contains the following three numbers,
543
//! all counted on the timeline segment between the event pointed to by
544
//! the m.fully_read marker and the sync edge:
545
//! - the number of unread events - depending on the read receipt state
546
//! with respect to the local timeline, this number may be either precise
547
//! or estimated (see EventStats::isEstimate);
548
//! - the number of highlights (TODO).
549
//!
550
//! As E2EE is not supported in the library, the returned result will always
551
//! be an estimate (<tt>isEstimate == true</tt>) for encrypted rooms;
552
//! moreover, since the library doesn't know how to tackle push rules yet
553
//! the number of highlights returned here will always be zero - use
554
//! highlightCount() for now.
555
//!
556
//! \sa isEventNotable, lastLocalReadReceipt, partiallyReadStats,
557
//! highlightCount
558
EventStats
unreadStats
()
const
;
559
560
//! \brief Get the number of notifications since the last read receipt
561
//!
562
//! This is the same as <tt>unreadStats().notableCount</tt>.
563
//!
564
//! \sa unreadStats, lastLocalReadReceipt
565
qsizetype
notificationCount
()
const
;
566
567
//! \brief Get the number of highlights since the last read receipt
568
//!
569
//! As of 0.7, this is defined by the homeserver as Quotient doesn't process
570
//! push rules.
571
//!
572
//! \sa unreadStats, lastLocalReadReceipt
573
qsizetype
highlightCount
()
const
;
574
575
/** Check whether the room has account data of the given type
576
* Tags and read markers are not supported by this method _yet_.
577
*/
578
bool
hasAccountData
(
const
QString
&
type
)
const
;
579
580
/** Get a generic account data event of the given type
581
* This returns a generic hash map for any room account data event
582
* stored on the server. Tags and read markers cannot be retrieved
583
* using this method _yet_.
584
*/
585
const
EventPtr
&
accountData
(
const
QString
&
type
)
const
;
586
587
//! Get a list of all room account data events
588
//! \return A list of event types that exist in the room
589
QStringList
accountDataEventTypes
()
const
;
590
591
QStringList
tagNames
()
const
;
592
TagsMap
tags
()
const
;
593
Tag
tag
(
const
QString
&
name
)
const
;
594
595
/** Add a new tag to this room
596
* If this room already has this tag, nothing happens. If it's a new
597
* tag for the room, the respective tag record is added to the set
598
* of tags and the new set is sent to the server to update other
599
* clients.
600
*/
601
void
addTag
(
const
QString
&
name
,
const
Tag
&
tagData
= {});
602
Q_INVOKABLE
void
addTag
(
const
QString
&
name
,
float
order
);
603
604
/// Remove a tag from the room
605
Q_INVOKABLE
void
removeTag
(
const
QString
&
name
);
606
607
/// The scope to apply an action on
608
/*! This enumeration is used to pick a strategy to propagate certain
609
* actions on the room to its predecessors and successors.
610
*/
611
enum
ActionScope
{
612
ThisRoomOnly
,
///< Do not apply to predecessors and successors
613
WithinSameState
,
///< Apply to predecessors and successors in the same
614
///< state as the current one
615
OmitLeftState
,
///< Apply to all reachable predecessors and successors
616
///< except those in Leave state
617
WholeSequence
///< Apply to all reachable predecessors and successors
618
};
619
620
/** Overwrite the room's tags
621
* This completely replaces the existing room's tags with a set
622
* of new ones and updates the new set on the server. Unlike
623
* most other methods in Room, this one sends a signal about changes
624
* immediately, not waiting for confirmation from the server
625
* (because tags are saved in account data rather than in shared
626
* room state).
627
* \param applyOn setting this to Room::OnAllConversations will set tags
628
* on this and all _known_ predecessors and successors;
629
* by default only the current room is changed
630
*/
631
void
setTags
(
TagsMap
newTags
,
ActionScope
applyOn
=
ThisRoomOnly
);
632
633
/// Check whether the list of tags has m.favourite
634
bool
isFavourite
()
const
;
635
/// Check whether the list of tags has m.lowpriority
636
bool
isLowPriority
()
const
;
637
/// Check whether this room is for server notices (MSC1452)
638
bool
isServerNoticeRoom
()
const
;
639
640
/// Check whether this room is a direct chat
641
Q_INVOKABLE
bool
isDirectChat
()
const
;
642
643
/// Get the list of members this room is a direct chat with
644
QList
<
RoomMember
>
directChatMembers
()
const
;
645
646
Q_INVOKABLE
QUrl
makeMediaUrl
(
const
QString
&
eventId
,
647
const
QUrl
&
mxcUrl
)
const
;
648
649
Q_INVOKABLE
QUrl
urlToThumbnail
(
const
QString
&
eventId
)
const
;
650
Q_INVOKABLE
QUrl
urlToDownload
(
const
QString
&
eventId
)
const
;
651
652
/// Get a file name for downloading for a given event id
653
/*!
654
* The event MUST be RoomMessageEvent and have content
655
* for downloading. \sa RoomMessageEvent::hasContent
656
*/
657
Q_INVOKABLE
QString
fileNameToDownload
(
const
QString
&
eventId
)
const
;
658
659
/// Get information on file upload/download
660
/*!
661
* \param id uploads are identified by the corresponding event's
662
* transactionId (because uploads are done before
663
* the event is even sent), while downloads are using
664
* the normal event id for identifier.
665
*/
666
Q_INVOKABLE
Quotient
::
FileTransferInfo
667
fileTransferInfo
(
const
QString
&
id
)
const
;
668
669
/// Get the URL to the actual file source in a unified way
670
/*!
671
* For uploads it will return a URL to a local file; for downloads
672
* the URL will be taken from the corresponding room event.
673
*/
674
Q_INVOKABLE
QUrl
fileSource
(
const
QString
&
id
)
const
;
675
676
/** Pretty-prints plain text into HTML
677
* As of now, it's exactly the same as Quotient::prettyPrint();
678
* in the future, it will also linkify room aliases, mxids etc.
679
* using the room context.
680
*/
681
Q_INVOKABLE
QString
prettyPrint
(
const
QString
&
plainText
)
const
;
682
683
Q_INVOKABLE
bool
supportsCalls
()
const
;
684
685
/// Whether the current user is allowed to upgrade the room
686
Q_INVOKABLE
bool
canSwitchVersions
()
const
;
687
688
/// \brief Get the current room state
689
RoomStateView
currentState
()
const
;
690
691
//! \brief The current Join Rule for the room
692
//!
693
//! \sa https://spec.matrix.org/latest/client-server-api/#mroomjoin_rules
694
JoinRule
joinRule
()
const
;
695
696
//! \brief Set the Join Rule for the room
697
//!
698
//! If the local user does not have a high enough power level the request is rejected.
699
//!
700
//! \param newRule the new JoinRule to apply to the room
701
//! \param allowedRooms only required when the join rule is restricted. This is a
702
//! list of room IDs that members of can join without an invite.
703
//! If the rule is restricted and this list is empty it is treated as a join
704
//! rule of invite instead.
705
//!
706
//! \note While any room ID is permitted it is designed to be only spaces that are
707
//! input. I.e. only memebers of space `x` can join this room.
708
//!
709
//! \sa https://spec.matrix.org/latest/client-server-api/#mroomjoin_rules
710
Q_INVOKABLE
void
setJoinRule
(
JoinRule
newRule
,
const
QList
<
QString
>&
allowedRooms
= {});
711
712
//! \brief The list of Room IDs for when the join rule is Restricted
713
//!
714
//! This value will be empty when the Join Rule is not Restricted or
715
//! Knock-Restricted.
716
//!
717
//! \sa https://spec.matrix.org/latest/client-server-api/#mroomjoin_rules
718
QList
<
QString
>
allowIds
()
const
;
719
720
//! \brief The effective power level of the given member in the room
721
//!
722
//! This is normally the same as calling `RoomPowerLevelEvent::powerLevelForUser(userId)` but
723
//! takes into account the room context and works even if the room state has no power levels
724
//! event. It is THE recommended way to get a room member's power level to display in the UI.
725
//! \param memberId The room member ID to check; if empty, the local user will be checked
726
//! \sa RoomPowerLevelsEvent, https://spec.matrix.org/v1.11/client-server-api/#mroompower_levels
727
Q_INVOKABLE
int
memberEffectivePowerLevel
(
const
QString
&
memberId
= {})
const
;
728
729
//! \brief Get the power level required to send events of the given type
730
//!
731
//! \note This is a generic method that only gets the power level to send events with a given
732
//! type. Some operations have additional restrictions or enablers though: e.g.,
733
//! room member changes (kicks, invites) have special power levels; on the other hand,
734
//! redactions of one's own messages are allowed regardless of the power level.
735
//! The library has no method to check effective ability to perform an operation as yet;
736
//! you have to either blindly make a call to the homeserver or implement the logic
737
//! described in the Federation API and respective room versions, in the client code.
738
//! \note Unlike the template version below, this method determines at runtime whether an event
739
//! type is that of a state event, assuming unknown event types to be non-state; pass
740
//! `true` as the second parameter to override that.
741
//! \sa canSwitchVersions
742
Q_INVOKABLE
int
powerLevelFor
(
const
QString
&
eventTypeId
,
bool
forceStateEvent
=
false
)
const
;
743
744
//! \brief Get the power level required to send events of the given type
745
//!
746
//! This is an optimised version of non-template powerLevelFor() (with the same caveat about
747
//! operations based on some event types) for cases when the event type is known at build time.
748
//! \tparam EvT the event type to get the power level for
749
template
<
EventClass
EvT
>
750
int
powerLevelFor
()
const
751
{
752
return
currentState
().
get
<
RoomPowerLevelsEvent
>()->
powerLevelForEventType
<
EvT
>();
753
}
754
755
//! \brief Post a pre-created room message event
756
//!
757
//! Takes ownership of the event, deleting it once the matching one arrives with the sync.
758
//! \note Do not assume that the event is already on the road to the homeserver when this (or
759
//! any other `post*`) method returns; it can be queued internally.
760
//! \sa PendingEventItem::deliveryStatus()
761
//! \return a reference to the pending event item
762
const
PendingEventItem
&
post
(
RoomEventPtr
event
);
763
764
template
<
typename
EvT
,
typename
...
ArgTs
>
765
const
PendingEventItem
&
post
(
ArgTs
&&...
args
)
766
{
767
return
post
(
makeEvent
<
EvT
>(
std
::
forward
<
ArgTs
>(
args
)...));
768
}
769
770
//! \brief Send a text type message
771
//!
772
//! This means MessageEventType Text, Emote or Notice.
773
template
<
MessageEventType
type
=
MessageEventType
::
Text
>
774
QString
postText
(
const
QString
&
plainText
,
775
const
std
::
optional
<
QString
>&
html
=
std
::
nullopt
,
776
const
std
::
optional
<
EventRelation
>&
relatesTo
=
std
::
nullopt
)
777
{
778
static_assert
(
type
==
MessageEventType
::
Text
||
779
type
==
MessageEventType
::
Emote
||
780
type
==
MessageEventType
::
Notice
,
781
"MessageEvent type is not a text message"
782
);
783
784
std
::
unique_ptr
<
EventContent
::
TextContent
>
content
=
nullptr
;
785
if
(
html
) {
786
content
=
std
::
make_unique
<
EventContent
::
TextContent
>(*
html
, u"text/html"_s);
787
}
788
return
post
<
RoomMessageEvent
>(
plainText
,
type
,
std
::
move
(
content
),
relatesTo
)->
transactionId
();
789
}
790
791
//! Send a file with the given content
792
QString
postFile
(
const
QString
&
plainText
,
793
std
::
unique_ptr
<
EventContent
::
FileContentBase
>
fileContent
,
794
std
::
optional
<
EventRelation
>
relatesTo
=
std
::
nullopt
);
795
796
//! Send the given Json as a message
797
QString
postJson
(
const
QString
&
matrixType
,
const
QJsonObject
&
eventContent
);
798
799
//! Send a reaction on a given event with a given key
800
QString
postReaction
(
const
QString
&
eventId
,
const
QString
&
key
);
801
802
PendingEventItem
::
future_type
whenMessageMerged
(
QString
txnId
)
const
;
803
804
//! Send a request to update the room state with the given event
805
SetRoomStateWithKeyJob
*
setState
(
const
StateEvent
&
evt
);
806
807
//! \brief Set a state event of the given type with the given arguments
808
//!
809
//! This type-safe overload attempts to send a state event of the type \p EvT constructed from
810
//! \p args.
811
template
<
typename
EvT
,
typename
...
ArgTs
>
812
auto
setState
(
ArgTs
&&...
args
)
813
{
814
return
setState
(
EvT
(
std
::
forward
<
ArgTs
>(
args
)...));
815
}
816
817
void
addMegolmSessionFromBackup
(
const
QByteArray
&
sessionId
,
const
QByteArray
&
sessionKey
,
uint32_t
index
,
const
QByteArray
&
senderKey
,
const
QByteArray
&
senderEdKey
);
818
819
Q_INVOKABLE
void
startVerification
();
820
821
QJsonArray
exportMegolmSessions
();
822
823
//! \brief Upgrade the room to \p newVersion
824
//!
825
//! Triggers an upgrade process that puts the tombstone event on the current room and creates
826
//! a new room of the specified version. It is possible to specify \p additionalCreators for
827
//! room versions that support those (unfortunately it is only possible to find out whether
828
//! a given room version supports additional creators by attempting to upgrade a room).
829
//! \return a future eventually holding a new room once it arrives via sync
830
QFuture
<
std
::
expected
<
Room
*,
BaseJob
::
Status
>>
upgrade
(
831
QString
newVersion
,
const
QStringList
&
additionalCreators
= {});
832
833
public
Q_SLOTS
:
834
/** Check whether the room should be upgraded */
835
void
checkVersion
();
836
837
QString
retryMessage
(
const
QString
&
txnId
);
838
void
discardMessage
(
const
QString
&
txnId
);
839
840
//! Send a request to update the room state based on freeform inputs
841
SetRoomStateWithKeyJob
*
setState
(
const
QString
&
evtType
,
842
const
QString
&
stateKey
,
843
const
QJsonObject
&
contentJson
);
844
void
setName
(
const
QString
&
newName
);
845
void
setCanonicalAlias
(
const
QString
&
newAlias
);
846
void
setPinnedEvents
(
const
QStringList
&
events
);
847
/// Set room aliases on the user's current server
848
void
setLocalAliases
(
const
QStringList
&
aliases
);
849
void
setTopic
(
const
QString
&
newTopic
);
850
851
/// You shouldn't normally call this method; it's here for debugging
852
void
refreshDisplayName
();
853
854
JobHandle
<
GetRoomEventsJob
>
getPreviousContent
(
int
limit
= 10,
const
QString
&
filter
= {});
855
856
void
inviteToRoom
(
const
QString
&
memberId
);
857
JobHandle
<
LeaveRoomJob
>
leaveRoom
();
858
void
kickMember
(
const
QString
&
memberId
,
const
QString
&
reason
= {});
859
void
ban
(
const
QString
&
userId
,
const
QString
&
reason
= {});
860
void
unban
(
const
QString
&
userId
);
861
void
redactEvent
(
const
QString
&
eventId
,
const
QString
&
reason
= {});
862
863
void
uploadFile
(
const
QString
&
id
,
const
QUrl
&
localFilename
,
864
const
QString
&
overrideContentType
= {});
865
// If localFilename is empty a temporary file is created
866
void
downloadFile
(
const
QString
&
eventId
,
const
QUrl
&
localFilename
= {});
867
void
cancelFileTransfer
(
const
QString
&
id
);
868
869
//! \brief Set a given event as last read and post a read receipt on it
870
//!
871
//! Does nothing if the event is behind the current read receipt.
872
//! \sa lastReadReceipt, markMessagesAsRead, markAllMessagesAsRead
873
void
setReadReceipt
(
const
QString
&
atEventId
);
874
//! Put the fully-read marker at the latest message in the room
875
//! \param sendPublicReceipts if true, a public read receipt (m.read) will also be sent to the server for the latest message.
876
void
markAllMessagesAsRead
(
bool
sendPublicReceipts
=
true
);
877
878
//! Switch the room's version (aka upgrade)
879
[[
deprecated
(
"Use upgrade() instead"
)]]
880
void
switchVersion
(
QString
newVersion
);
881
882
void
inviteCall
(
const
QString
&
callId
,
const
int
lifetime
,
883
const
QString
&
sdp
);
884
void
sendCallCandidates
(
const
QString
&
callId
,
const
QJsonArray
&
candidates
);
885
void
answerCall
(
const
QString
&
callId
,
const
QString
&
sdp
);
886
void
hangupCall
(
const
QString
&
callId
);
887
888
/**
889
* Activates encryption for this room.
890
* Warning: Cannot be undone
891
*/
892
void
activateEncryption
();
893
894
//! \brief Mark this room as a direct chat, guessing which user should be the DM recipient
895
//!
896
//! This function marks this room as a direct chat. There is no option to provide a user id here.
897
//! Emits the signal synchronously, without waiting to complete
898
//! synchronisation with the server.
899
//!
900
//! This function does nothing if you are the sole user, or there are more than two users in the room
901
//!
902
//! \sa directChatsListChanged
903
void
markAsDirectChat
();
904
905
Q_SIGNALS
:
906
/// Initial set of state events has been loaded
907
/**
908
* The initial set is what comes from the initial sync for the room.
909
* This includes all basic things like RoomCreateEvent,
910
* RoomNameEvent, a (lazy-loaded, not full) set of RoomMemberEvents
911
* etc. This is a per-room reflection of Connection::loadedRoomState
912
* \sa Connection::loadedRoomState
913
*/
914
void
baseStateLoaded
();
915
void
eventsHistoryJobChanged
();
916
void
aboutToAddHistoricalMessages
(
Quotient
::
RoomEventsRange
events
);
917
void
aboutToAddNewMessages
(
Quotient
::
RoomEventsRange
events
);
918
void
addedMessages
(
int
fromIndex
,
int
toIndex
);
919
/// The event is about to be appended to the list of pending events
920
void
pendingEventAboutToAdd
(
Quotient
::
RoomEvent
*
event
);
921
/// An event has been appended to the list of pending events
922
void
pendingEventAdded
(
const
Quotient
::
RoomEvent
*
event
);
923
/// The remote echo has arrived with the sync and will be merged
924
/// with its local counterpart
925
/** NB: Requires a sync loop to be emitted */
926
void
pendingEventAboutToMerge
(
Quotient
::
RoomEvent
*
serverEvent
,
927
int
pendingEventIndex
);
928
/// The remote and local copies of the event have been merged
929
/** NB: Requires a sync loop to be emitted */
930
void
pendingEventMerged
();
931
/// An event will be removed from the list of pending events
932
void
pendingEventAboutToDiscard
(
int
pendingEventIndex
);
933
/// An event has just been removed from the list of pending events
934
void
pendingEventDiscarded
();
935
/// The status of a pending event has changed
936
/** \sa PendingEventItem::deliveryStatus */
937
void
pendingEventChanged
(
int
pendingEventIndex
);
938
/// The server accepted the message
939
/** This is emitted when an event sending request has successfully
940
* completed. This does not mean that the event is already in the
941
* local timeline, only that the server has accepted it.
942
* \param txnId transaction id assigned by the client during sending
943
* \param eventId event id assigned by the server upon acceptance
944
* \sa postEvent, postPlainText, postMessage, postHtmlMessage
945
* \sa pendingEventMerged, aboutToAddNewMessages
946
*/
947
void
messageSent
(
QString
txnId
,
QString
eventId
);
948
949
//! A new thread has been created/added in the room
950
void
newThread
(
const
QString
&
rootId
,
Quotient
::
ThreadInfo
newThread
);
951
952
/** A common signal for various kinds of changes in the room
953
* Aside from all changes in the room state
954
* @param changes a set of flags describing what changes occurred
955
* upon the last sync
956
* \sa Changes
957
*/
958
void
changed
(
Quotient
::
Room
::
Changes
changes
);
959
/**
960
* \brief The room name, the canonical alias or other aliases changed
961
*
962
* Not triggered when display name changes.
963
*/
964
void
namesChanged
(
Quotient
::
Room
*
room
);
965
void
displaynameAboutToChange
(
Quotient
::
Room
*
room
);
966
void
displaynameChanged
(
Quotient
::
Room
*
room
,
QString
oldName
);
967
void
pinnedEventsChanged
();
968
void
topicChanged
();
969
void
avatarChanged
();
970
971
//! \brief The join rule for the room has changed
972
void
joinRuleChanged
();
973
974
//! \brief A new member has joined the room
975
//!
976
//! This can be from any previous state or a member previously unknown to
977
//! the room.
978
void
memberJoined
(
RoomMember
member
);
979
980
//! \brief A member who previously joined has left
981
//!
982
//! The member will still be known to the room their membership state has changed
983
//! from Membership::Join to anything else.
984
void
memberLeft
(
RoomMember
member
);
985
986
//! A known joined member is about to update their display name
987
void
memberNameAboutToUpdate
(
RoomMember
member
,
QString
newName
);
988
989
//! A known joined member has updated their display name
990
void
memberNameUpdated
(
RoomMember
member
);
991
992
//! A known joined member has updated their avatar
993
void
memberAvatarUpdated
(
RoomMember
member
);
994
995
/// The list of members has changed
996
/** Emitted no more than once per sync, this is a good signal to
997
* for cases when some action should be done upon any change in
998
* the member list. If you need per-item granularity you should use
999
* userAdded, userRemoved and memberAboutToRename / memberRenamed
1000
* instead.
1001
*/
1002
void
memberListChanged
();
1003
1004
/// The previously lazy-loaded members list is now loaded entirely
1005
/// \sa setDisplayed
1006
void
allMembersLoaded
();
1007
void
encryption
();
1008
1009
void
joinStateChanged
(
Quotient
::
JoinState
oldState
,
1010
Quotient
::
JoinState
newState
);
1011
1012
//! The list of members sending typing indicators has changed.
1013
void
typingChanged
();
1014
1015
void
highlightCountChanged
();
///< \sa highlightCount
1016
void
notificationCountChanged
();
///< \sa notificationCount
1017
1018
void
displayedChanged
(
bool
displayed
);
1019
void
firstDisplayedEventChanged
();
1020
void
lastDisplayedEventChanged
();
1021
//! The event the m.read receipt points to has changed for the listed users
1022
//! \sa lastReadReceipt
1023
void
lastReadEventChanged
(
QVector
<
QString
>
userIds
);
1024
void
fullyReadMarkerMoved
(
QString
fromEventId
,
QString
toEventId
);
1025
void
partiallyReadStatsChanged
();
1026
void
unreadStatsChanged
();
1027
void
allHistoryLoadedChanged
();
1028
1029
void
accountDataAboutToChange
(
QString
type
);
1030
void
accountDataChanged
(
QString
type
);
1031
void
tagsAboutToChange
();
1032
void
tagsChanged
();
1033
1034
void
updatedEvent
(
QString
eventId
);
1035
void
replacedEvent
(
const
Quotient
::
RoomEvent
*
newEvent
,
1036
const
Quotient
::
RoomEvent
*
oldEvent
);
1037
1038
void
newFileTransfer
(
QString
id
,
QUrl
localFile
);
1039
void
fileTransferProgress
(
QString
id
,
qint64
progress
,
qint64
total
);
1040
void
fileTransferCompleted
(
QString
id
,
QUrl
localFile
,
1041
FileSourceInfo
fileMetadata
);
1042
void
fileTransferFailed
(
QString
id
,
QString
errorMessage
= {});
1043
// fileTransferCancelled() is no more here; use fileTransferFailed() and
1044
// check the transfer status instead
1045
1046
void
callEvent
(
Quotient
::
Room
*
room
,
const
Quotient
::
RoomEvent
*
event
);
1047
1048
/// The room's version stability may have changed
1049
void
stabilityUpdated
(
QString
recommendedDefault
,
1050
QStringList
stableVersions
);
1051
/// This room has been upgraded and won't receive updates any more
1052
void
upgraded
(
QString
serverMessage
,
Quotient
::
Room
*
successor
);
1053
/// An attempted room upgrade has failed
1054
void
upgradeFailed
(
QString
errorMessage
);
1055
1056
/// The room is about to be deleted
1057
void
beforeDestruction
(
Quotient
::
Room
*);
1058
1059
protected
:
1060
virtual
Changes
processStateEvent
(
const
RoomEvent
&
e
);
1061
virtual
Changes
processEphemeralEvent
(
EventPtr
&&
event
);
1062
virtual
Changes
processAccountDataEvent
(
EventPtr
&&
event
);
1063
virtual
void
onAddNewTimelineEvents
(
timeline_iter_t
/*from*/
) {}
1064
virtual
void
onAddHistoricalTimelineEvents
(
rev_iter_t
/*from*/
) {}
1065
virtual
void
onRedaction
(
const
RoomEvent
&
/*prevEvent*/
,
1066
const
RoomEvent
&
/*after*/
)
1067
{}
1068
virtual
QJsonObject
toJson
()
const
;
1069
virtual
void
updateData
(
SyncRoomData
&&
data
,
bool
fromCache
=
false
);
1070
virtual
Notification
checkForNotifications
(
const
TimelineItem
&
ti
);
1071
1072
private
:
1073
friend
class
Connection
;
1074
1075
class
Private
;
1076
Private
*
d
;
1077
1078
// This is called from Connection, reflecting a state change that
1079
// arrived from the server. Clients should use
1080
// Connection::joinRoom() and Room::leaveRoom() to change the state.
1081
void
setJoinState
(
JoinState
state
);
1082
};
1083
1084
template
<
typename
RangeT,
typename
ValT,
typename
CompT = MemberSorter,
1085
typename
ProjT = std::identity>
1086
requires (
std
::
indirect_strict_weak_order
<
1087
CompT
,
const
ValT
*,
std
::
projected
<
std
::
ranges
::
iterator_t
<
RangeT
>,
ProjT
>>)
1088
[[
deprecated
(
"Use std::ranges::lower_bound(range, ...) - std::ranges::begin(range)"
)]]
1089
inline
std
::
ranges
::
range_size_t
<
RangeT
>
lowerBoundMemberIndex
(
const
RangeT &rng,
const
ValT &val,
1090
CompT comp = {}, ProjT proj = {})
1091
{
1092
return
std::ranges::lower_bound(rng, val, std::move(comp), std::move(proj))
1093
- std::ranges::begin(rng);
1094
}
1095
}
// namespace Quotient
1096
Q_DECLARE_METATYPE
(
Quotient
::
FileTransferInfo
)
1097
Q_DECLARE_METATYPE(Quotient::ReadReceipt)
1098
Q_DECLARE_OPERATORS_FOR_FLAGS(Quotient::Room::Changes)
Quotient::FileTransferInfo
Definition
room.h:56
Quotient::ReadReceipt
Data structure for a room member's read receipt.
Definition
room.h:84
Quotient::Room
Definition
room.h:121
Quotient
Definition
accountregistry.h:13
Quotient::swap
void swap(ReadReceipt &lhs, ReadReceipt &rhs)
Definition
room.h:101
Quotient::lowerBoundMemberIndex
std::ranges::range_size_t< RangeT > lowerBoundMemberIndex(const RangeT &rng, const ValT &val, CompT comp={}, ProjT proj={})
Definition
room.h:1089
QUO_DECLARE_FLAGS
#define QUO_DECLARE_FLAGS(Flags, Enum)
Quotient replacement for the Q_FLAG/Q_DECLARE_FLAGS combination.
Definition
quotient_common.h:30
QUOTIENT_API
#define QUOTIENT_API
Definition
quotient_export.h:22
Quotient::Notification
Definition
room.h:110
Quotient::Notification::Type
Type
Definition
room.h:111
Quotient::Notification::None
@ None
Definition
room.h:111
Quotient::Notification::Highlight
@ Highlight
Definition
room.h:111
Quotient::Notification::Basic
@ Basic
Definition
room.h:111
Quotient
room.h
Generated by
1.9.8