libQuotient
A Qt library for building matrix clients
Loading...
Searching...
No Matches
connection.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: 2019 Alexey Andreyev <aa13q@ya.ru>
4// SPDX-License-Identifier: LGPL-2.1-or-later
5
6#pragma once
7
10#include "ssosession.h"
11#include "util.h"
12
13#include "csapi/create_room.h"
14#include "csapi/login.h"
15#include "csapi/content-repo.h"
16
17#include "e2ee/qolmoutboundsession.h"
18
19#include "events/accountdataevents.h"
20#include "jobs/jobhandle.h"
21#include "jobs/syncjob.h"
22
23#include <QtCore/QDir>
24#include <QtCore/QObject>
25#include <QtCore/QSize>
26#include <QtCore/QUrl>
27
28#include <functional>
29
30Q_DECLARE_METATYPE(Quotient::GetLoginFlowsJob::LoginFlow)
31
32class TestCrossSigning;
33
34namespace Quotient {
35
36class Avatar;
37class Room;
38class User;
39class ConnectionData;
40class RoomEvent;
41
42class GetVersionsJob;
43class GetCapabilitiesJob;
44class RoomMessagesJob;
45class PostReceiptJob;
46class ForgetRoomJob;
47class MediaThumbnailJob;
48class JoinRoomJob;
49class DownloadFileJob;
50class SendToDeviceJob;
51class SendMessageJob;
52class LeaveRoomJob;
53class Database;
54struct EncryptedFileMetadata;
55
56class QOlmAccount;
57class QOlmInboundGroupSession;
58
60
61//! Predefined login flows
62namespace LoginFlows {
63 inline const LoginFlow Password { "m.login.password"_L1 };
64 inline const LoginFlow SSO { "m.login.sso"_L1 };
65 inline const LoginFlow Token { "m.login.token"_L1 };
66}
67
68// To simplify comparisons of LoginFlows
69
70inline bool operator==(const LoginFlow& lhs, const LoginFlow& rhs)
71{
72 return lhs.type == rhs.type;
73}
74
75inline bool operator!=(const LoginFlow& lhs, const LoginFlow& rhs)
76{
77 return !(lhs == rhs);
78}
79
80class Connection;
81
82using room_factory_t =
83 std::function<Room*(Connection*, const QString&, JoinState)>;
84using user_factory_t = std::function<User*(Connection*, const QString&)>;
85
86//! \brief The default factory to create room objects
87//!
88//! Just a wrapper around operator new.
89//! \sa Connection::setRoomFactory, Connection::setRoomType
90template <typename T = Room>
91auto defaultRoomFactory(Connection* c, const QString& id, JoinState js)
92{
93 return new T(c, id, js);
94}
95
96//! \brief The default factory to create user objects
97//!
98//! Just a wrapper around operator new.
99//! \sa Connection::setUserFactory, Connection::setUserType
100template <typename T = User>
101auto defaultUserFactory(Connection* c, const QString& id)
102{
103 return new T(id, c);
104}
105
106// Room ids, rather than room pointers, are used in the direct chat
107// map types because the library keeps Invite rooms separate from
108// rooms in Join and Leave state; and direct chats in account data
109// are stored with no regard to their state.
112
115
135
136public:
138
142 }; // FIXME: Should go inside CreateRoomJob
143
144 explicit Connection(QObject* parent = nullptr);
145 explicit Connection(const QUrl& server, QObject* parent = nullptr);
147
148 //! \brief Get all rooms known within this Connection
149 //!
150 //! This includes Invite, Join and Leave rooms, in no particular order.
151 //! \note Leave rooms will only show up in the list if they have been left
152 //! in the same running session. The library doesn't cache left rooms
153 //! between runs and it doesn't retrieve the full list of left rooms
154 //! from the server.
155 //! \sa rooms, room, roomsWithTag
157
158 //! \brief Get rooms that have either of the given join state(s)
159 //!
160 //! This method returns, in no particular order, rooms which join state
161 //! matches the mask passed in \p joinStates.
162 //! \note Similar to allRooms(), this won't retrieve the full list of
163 //! Leave rooms from the server.
164 //! \sa allRooms, room, roomsWithTag
167
168 //! Get the total number of rooms in the given join state(s)
170
171 //! \brief Check whether the account has data of the given type
172 //!
173 //! Direct chats map is not supported by this method _yet_.
174 bool hasAccountData(const QString& type) const;
175
176 //! \brief Get a generic account data event of the given type
177 //!
178 //! \return an account data event of the given type stored on the server,
179 //! or nullptr if there's none of that type.
180 //! \note Direct chats map cannot be retrieved using this method _yet_;
181 //! use directChats() instead.
182 const EventPtr& accountData(const QString& type) const;
183
184 //! \brief Get an account data event of the given type
185 //!
186 //! \return the account data content for the given event type stored
187 //! on the server, or a default-constructed object if there's none
188 //! of that type.
189 //! \note Direct chats map cannot be retrieved using this method _yet_;
190 //! use directChats() instead.
191 template <EventClass EventT>
192 const EventT* accountData() const
193 {
194 // 0.9: use the default argument and fold into the next overload
196 }
197
198 template <EventClass EventT>
199 const EventT* accountData(const QString& keyName) const
200 {
202 }
203
204 //! \brief Get account data as a JSON object
205 //!
206 //! This returns the content part of the account data event
207 //! of the given type. Direct chats map cannot be retrieved using
208 //! this method _yet_; use directChats() instead.
210
211 //! Set a generic account data event of the given type
213
215 const QJsonObject& content);
216
217 //! Lists the types of account data that exist for this connection;
219
220 //! \brief Get all Invited and Joined rooms grouped by tag
221 //! \return a hashmap from tag name to a vector of room pointers,
222 //! sorted by their order in the tag - details are at
223 //! https://spec.matrix.org/v1.5/client-server-api/#room-tagging
225
226 //! Get all room tags known on this connection
228
229 //! Get the list of rooms with the specified tag
231
232 //! \brief Mark the room as a direct chat with the user
233 //!
234 //! This function marks \p room as a direct chat with \p userId.
235 //! Emits the signal synchronously, without waiting to complete
236 //! synchronisation with the server.
237 //! \sa directChatsListChanged
239
240 //! \brief Unmark the room from direct chats
241 //!
242 //! This function removes the room id from direct chats either for
243 //! a specific \p user or for all users if \p userId is empty.
244 //! The room id is used to allow removal of, e.g., ids of forgotten
245 //! rooms; a Room object need not exist. Emits the signal
246 //! immediately, without waiting to complete synchronisation with
247 //! the server.
248 //! \sa directChatsListChanged
250
251 //! Check whether the room id corresponds to a direct chat
252 bool isDirectChat(const QString& roomId) const;
253
254 //! Get the whole map from users to direct chat rooms
256
257 //! \brief Retrieve the list of member IDs the room is a direct chat with
258 //!
259 //! \return The list of member IDs for which this room is marked as
260 //! a direct chat; an empty list if the room is not a direct chat
262
263 //! Check whether a particular user id is in the ignore list
265
266 //! Check whether a particular user is in the ignore list
267 [[deprecated("Use the overload accepting UserId instead")]]
269
270 //! Get the whole list of ignored users
272
273 //! \brief Add the user to the ignore list
274 //! The change signal is emitted synchronously, without waiting
275 //! to complete synchronisation with the server.
276 //!
277 //! \sa ignoredUsersListChanged
279
280 //! \brief Remove the user from the ignore list
281 //!
282 //! Similar to adding, the change signal is emitted synchronously.
283 //! \sa ignoredUsersListChanged
285
286 //! \brief Get the entire list of users known to the current user on this homeserver
287 //! \note Be mindful that this can easily count thousands or tens of thousands, and use
288 //! sparingly; when in a room context, always use Room::members() instead
290
291 //! Get the base URL of the homeserver to connect to
293 //! Get the domain name used for ids/aliases on the server
295 //! Check if the homeserver is known to be reachable and working
296 [[deprecated("Check the result returned by Connection::loginFlows() instead")]]
297 bool isUsable() const;
298 //! Get the list of supported login flows
300 //! Check whether the current homeserver supports password auth
302 //! Check whether the current homeserver supports SSO
303 bool supportsSso() const;
304 //! Find a room by its id and a mask of applicable states
306 const QString& roomId,
308 //! Find a room by its alias and a mask of applicable states
310 const QString& roomAlias,
312 //! \brief Update the internal map of room aliases to IDs
313 //!
314 //! This is used to maintain the internal index of room aliases.
315 //! It does NOT change aliases on the server,
316 //! \sa Room::setLocalAliases
319 const QStringList& roomAliases);
322 const User* user() const;
325
326 //! \brief Get an avatar object for the given user ID and media ID
328
329 //! \brief Get an avatar object for the given user ID and media ID
331
334 bool isLoggedIn() const;
335
336 //! \brief Whether the connection is successfully syncing with the server.
337 //!
338 //! \return true, if the last sync was successful, false otherwise.
339 bool isOnline() const;
342
344 const Room* room) const;
347
349 const QString& deviceId) const;
351 const QString& device) const;
352 bool hasOlmSession(const QString& user, const QString& deviceId) const;
353
354 // This assumes that an olm session already exists. If it doesn't, no message is sent.
356 const Event& event, bool encrypted);
357
358 //! Returns true if this megolm session comes from a verified device
360
361 //! Returns whether the device is verified
362 bool isVerifiedDevice(const QString& userId, const QString& deviceId) const;
363
364 //! \brief Returns whether the device is known and supports end-to-end encryption.
365 //!
366 //! This might give unexpected results for users we're not tracking,
367 //! i.e., users that we don't share an encrypted room with
369
370
374
378
380
385
387
391
393
397
398 static constexpr QStringView StableTag = u"stable";
399 bool isStable() const { return status == StableTag; }
400
402 {
404 return dbg.nospace() << v.id << '/' << v.status;
405 }
406 };
407
408 //! Find out if homeserver capabilites have been loaded
410
411 [[deprecated("Use capabilitiesReady() instead; don't forget to negate the returned value")]]
413
414 //! Get the list of Matrix CS API spec versions supported by the homeserver
416
417 //! \brief Get the room version recommended by the server
418 //!
419 //! Only works after server capabilities have been loaded.
420 //! \sa loadingCapabilities
422 //! \brief Get the room version considered stable by the server
423 //!
424 //! Only works after server capabilities have been loaded.
425 //! \sa loadingCapabilities
427 //! \brief Get all room versions supported by the server
428 //! Only works after server capabilities have been loaded.
429 //! \sa loadingCapabilities
431
432 //! Indicate if the user can change its password from the client.
433 //! This is often not the case when SSO is enabled.
434 //! \sa loadingCapabilities
435 bool canChangePassword() const;
436
437 //! \brief Check whether encryption is enabled on this connection
438 //! \sa enableEncryption
439 bool encryptionEnabled() const;
440
441 //! \brief Enable or disable encryption on this connection
442 //!
443 //! \note This has no effect if the library is compiled without E2EE support
444 //!
445 //! \sa encryptionEnabled
447
448 //! \brief Check whether encryption is enabled for new direct chats on this connection
449 //!
450 //! \note This has no effect if the library is compiled without E2EE support
451 //!
452 //! \sa enableDirectChatEncryption
454
455 //! \brief Enable or disable whether new direct chats are encrypted on this connection
456 //!
457 //! \note This has no effect if the library is compiled without E2EE support
458 //!
459 //! \sa directChatEncryptionEnabled
461
462 //! \brief Load room state from a previously saved file
463 //!
464 //! Call this before first sync.
465 //! \sa saveState
467
468 //! \brief Save the current state for all rooms to a file
469 //!
470 //! This method saves the current state of rooms (but not messages
471 //! in them) to a local cache file, so that it could be loaded by
472 //! loadState() on a next run of the client.
473 //! \sa loadState
474 Q_INVOKABLE void saveState() const;
475
476 //! This method saves the current state of a single room.
477 void saveRoomState(Room* r) const;
478
479 //! \brief Get the default directory path to save the room state to
480 //! \sa stateCacheDir
482
483 //! \brief Get the default directory to save the room state to
484 //!
485 //! This function returns the default directory to store the cached
486 //! room state, defined as follows:
487 //! \code
488 //! QStandardPaths::writeableLocation(QStandardPaths::CacheLocation) +
489 //! _safeUserId + "_state.json" \endcode where `_safeUserId` is userId() with
490 //! `:` (colon) replaced by
491 //! `_` (underscore), as colons are reserved characters on Windows.
492 //! \sa loadState, saveState, stateCachePath
494
495 //! \brief Whether or not the rooms state should be cached locally
496 //! \sa loadState, saveState
497 bool cacheState() const;
499
500 bool lazyLoading() const;
502
503 //! Start a pre-created job object on this connection
505
506 //! \brief Start a pre-created job on this connection and get a job handle to it
507 //!
508 //! This is a template overload for run(BaseJob*, RunningPolicy) - if you call run() on any
509 //! derived job (99% of the cases when you're going to call it), this overload will be chosen
510 //! as a more type-safe and feature-rich version. It's not Q_INVOKABLE though.
511 template <std::derived_from<BaseJob> JobT>
514 {
515 JobHandle jh { job };
516 run(static_cast<BaseJob*>(job), runningPolicy);
517 return jh;
518 }
519
520 //! \brief Start a job of a given type with specified arguments and policy
521 //!
522 //! This is a universal method to create and start a job of a type passed
523 //! as a template parameter. The policy allows to fine-tune the way
524 //! the job is executed - as of this writing it means a choice
525 //! between "foreground" and "background".
526 //!
527 //! \param runningPolicy controls how the job is executed
528 //! \param jobArgs arguments to the job constructor
529 //!
530 //! \sa BaseJob::isBackground. QNetworkRequest::BackgroundRequestAttribute
531 template <typename JobT, typename... JobArgTs>
533 {
534 return run(new JobT(std::forward<JobArgTs>(jobArgs)...), runningPolicy);
535 }
536
537 //! \brief Start a job of a specified type with specified arguments
538 //!
539 //! This is an overload that runs the job with "foreground" policy.
540 template <typename JobT, typename... JobArgTs>
542 {
544 }
545
546 //! \brief Get a request URL for a job with specified type and arguments
547 //!
548 //! This calls JobT::makeRequestUrl() prepending the connection's homeserver
549 //! to the list of arguments.
550 template <typename JobT, typename... JobArgTs>
552 {
554 }
555
556 //! \brief Start a local HTTP server and generate a single sign-on URL
557 //!
558 //! This call does the preparatory steps to carry out single sign-on
559 //! sequence
560 //! \sa https://matrix.org/docs/guides/sso-for-client-developers
561 //! \return A proxy object holding two URLs: one for SSO on the chosen
562 //! homeserver and another for the local callback address. Normally
563 //! you won't need the callback URL unless you proxy the response
564 //! with a custom UI. You do not need to delete the SsoSession
565 //! object; the Connection that issued it will dispose of it once
566 //! the login sequence completes (with any outcome).
568 const QString& deviceId = {});
569
570 //! \brief Generate a new transaction id
571 //!
572 //! Transaction id's are unique within a single Connection object
574
575 //! Convert an mxc: URL into a CS API URL
577
579 const QString& maybeSuccessorId) const;
580
581 //! Set the E2EE default state for any Connection created further
583
584 //! Set the direct chat E2EE default state for any Connection created further
586
587 //! Set a room factory function
589
590 //! Set a user factory function
592
593 //! Get a room factory function
595
596 //! Get a user factory function
598
599 //! Set the room factory to default with the overriden room type
600 template <typename T>
601 static void setRoomType()
602 {
604 }
605
606 //! Set the user factory to default with the overriden user type
607 template <typename T>
608 static void setUserType()
609 {
611 }
612
613 //! \brief Determine and set the homeserver from MXID
614 //!
615 //! This attempts to resolve the homeserver by requesting
616 //! .well-known/matrix/client record from the server taken from the MXID
617 //! serverpart. If there is no record found, the serverpart itself is
618 //! attempted as the homeserver base URL; if the record is there but
619 //! is malformed (e.g., the homeserver base URL cannot be found in it)
620 //! resolveError() is emitted and further processing stops. Otherwise,
621 //! setHomeserver is called, preparing the Connection object for the login
622 //! attempt.
623 //! \param mxid user Matrix ID, such as @someone:example.org
624 //! \sa setHomeserver, homeserverChanged, loginFlowsChanged, resolveError
626
627 //! \brief Set the homeserver base URL and retrieve its login flows
628 //!
629 //! \sa LoginFlowsJob, loginFlows, loginFlowsChanged, homeserverChanged
631
632 //! \brief Get a future to a direct chat with the user
634
635 //! Create a direct chat with a single user, optional name and topic
636 //!
637 //! A room will always be created, unlike in requestDirectChat.
638 //! It is advised to use requestDirectChat as a default way of getting
639 //! one-on-one with a person, and only use createDirectChat when
640 //! a new creation is explicitly desired.
642 const QString& topic = {},
643 const QString& name = {});
644
646 const QStringList& serverNames = {});
647
649 const QStringList& serverNames = {});
650
651public Q_SLOTS:
652 //! \brief Log in using a username and password pair
653 //!
654 //! Before logging in, this method checks if the homeserver is valid and
655 //! supports the password login flow. If the homeserver is invalid but
656 //! a full user MXID is provided, this method calls resolveServer() using
657 //! this MXID.
658 //! \sa resolveServer, resolveError, loginError
661 const QString& deviceId = {});
662
663 //! \brief Log in using a login token
664 //!
665 //! One usual case for this method is the final stage of logging in via SSO.
666 //! Unlike loginWithPassword() and assumeIdentity(), this method cannot
667 //! resolve the server from the user name because the full user MXID is
668 //! encoded in the login token. Callers should ensure the homeserver
669 //! sanity in advance.
672 const QString& deviceId = {});
673
674 //! \brief Use an existing access token to connect to the homeserver
675 //!
676 //! Similar to loginWithPassword(), this method checks that the homeserver
677 //! URL is valid and tries to resolve it from the MXID in case it is not.
678 //! \since 0.7.2
680
681 //! \brief Request supported spec versions from the homeserver
682 //!
683 //! This call does not obtain room versions - use loadCapabilities() for that.
685
686 //! Request capabilities and room versions from the server
688
689 [[deprecated("Use loadCapabilities() instead")]] void reloadCapabilities();
690
692
693 void sync(int timeout = -1);
695
696 void stopSync();
697
698 virtual MediaThumbnailJob*
704 int requestedHeight,
706
707 // QIODevice* should already be open
709 const QString& overrideContentType = {});
711 const QString& overrideContentType = {});
712 [[deprecated("Use downloadFile() instead")]] BaseJob* getContent(const QString& mediaId);
713 [[deprecated("Use downloadFile() instead")]] BaseJob* getContent(const QUrl& url);
714
715 // If localFilename is empty, a temporary file will be created
717
720 const QString& localFilename = {});
721
722 //! \brief Create a room (generic method)
723 //!
724 //! This method allows to customize room entirely to your liking,
725 //! providing all the attributes the original CS API provides.
728 const QString& presetName = {}, const QString& roomVersion = {},
729 bool isDirect = false,
732 const QJsonObject& creationContent = {});
733
734 //! \brief Get a direct chat with a single user
735 //!
736 //! This method may return synchronously or asynchoronously depending
737 //! on whether a direct chat room with the respective person exists
738 //! already.
739 //! \sa directChatAvailable
741
742 //! \brief Send /forget to the server and delete room locally
743 //!
744 //! This method is in Connection, not in Room, since it's a
745 //! room lifecycle operation, and Connection is an acting room manager.
746 //! It ensures that the local user is not a member of a room (running /leave,
747 //! if necessary) then issues a /forget request and if that one doesn't fail
748 //! deletion of the local Room object is ensured.
749 //! \param id the room id to forget
750 //! \return the ongoing /forget request to the server; note that the
751 //! success() signal of this request is connected to deleteLater()
752 //! of a respective room so by the moment this finishes, there
753 //! might be no Room object anymore.
755
758
759 [[deprecated("This method is experimental and may be removed any time")]] //
761
762 //! \deprecated Do not use this directly, use Room::leaveRoom() instead
764
766 const QString& deviceId);
767
770
772 bool enableEncryption = true);
773
775 //! \brief Initial server resolution has failed
776 //!
777 //! This signal is emitted when resolveServer() did not manage to resolve
778 //! the homeserver using its .well-known/client record or otherwise.
779 //! \sa resolveServer
781
785
786 void connected();
787 void loggedOut();
788
789 //! \brief Login data or state have changed
790 //!
791 //! This is a common change signal for userId, deviceId and
792 //! accessToken - these properties normally only change at
793 //! a successful login and logout and are constant at other times.
795
796 //! The online state has changed.
798
800
801 //! \brief A network request (job) started by callApi() has failed
802 //! \param request the pointer to the failed job
803 //! \sa callApi
805
806 //! \brief A network request (job) failed due to network problems
807 //!
808 //! This is _only_ emitted when the job will retry on its own;
809 //! once it gives up, requestFailed() will be emitted.
810 //!
811 //! \param message message about the network problem
812 //! \param details raw error details, if any available
813 //! \param retriesTaken how many retries have already been taken
814 //! \param nextRetryInMilliseconds when the job will retry again
815 //! (-1 if no next retry is scheduled)
818
819 void syncDone();
821
823
824 //! \group Signals emitted on room transitions
825 //!
826 //! Note: Rooms in Invite state are always stored separately from
827 //! rooms in Join/Leave state, because of special treatment of
828 //! invite_state in Matrix CS API (see The Spec on /sync for details).
829 //! Therefore, objects below are: r - room in Join/Leave state;
830 //! i - room in Invite state
831 //!
832 //! 1. none -> Invite: newRoom(r), invitedRoom(r,nullptr)
833 //! 2. none -> Join: newRoom(r), joinedRoom(r,nullptr)
834 //! 3. none -> Leave: newRoom(r), leftRoom(r,nullptr)
835 //! 4. Invite -> Join:
836 //! newRoom(r), joinedRoom(r,i), aboutToDeleteRoom(i)
837 //! 4a. Leave and Invite -> Join:
838 //! joinedRoom(r,i), aboutToDeleteRoom(i)
839 //! 5. Invite -> Leave:
840 //! newRoom(r), leftRoom(r,i), aboutToDeleteRoom(i)
841 //! 5a. Leave and Invite -> Leave:
842 //! leftRoom(r,i), aboutToDeleteRoom(i)
843 //! 6. Join -> Leave: leftRoom(r)
844 //! 7. Leave -> Invite: newRoom(i), invitedRoom(i,r)
845 //! 8. Leave -> Join: joinedRoom(r)
846 //! The following transitions are only possible via forgetRoom()
847 //! so far; if a room gets forgotten externally, sync won't tell
848 //! about it:
849 //! 9. any -> none: as any -> Leave, then aboutToDeleteRoom(r)
850
851 //! A new room object has been created
853
854 //! \brief A room invitation is seen for the first time
855 //!
856 //! If the same room is in Left state, it's passed in prev. Beware
857 //! that initial sync will trigger this signal for all rooms in
858 //! Invite state.
860
861 //! \brief A joined room is seen for the first time
862 //!
863 //! It's not the same as receiving a room in "join" section of sync
864 //! response (rooms will be there even after joining); it's also
865 //! not (exactly) the same as actual joining action of a user (all
866 //! rooms coming in initial sync will trigger this signal too). If
867 //! this room was in Invite state before, the respective object is
868 //! passed in prev (and it will be deleted shortly afterwards).
870
871 //! \brief A room has just been left
872 //!
873 //! If this room has been in Invite state (as in case of rejecting
874 //! an invitation), the respective object will be passed in prev
875 //! (and will be deleted shortly afterwards). Note that, similar
876 //! to invitedRoom and joinedRoom, this signal is triggered for all
877 //! Left rooms upon initial sync (not only those that were left
878 //! right before the sync).
880
881 //! The room object is about to be deleted
883
884 //! \brief The room has just been created by createRoom or requestDirectChat
885 //!
886 //! This signal is not emitted in usual room state transitions,
887 //! only as an outcome of room creation operations invoked by
888 //! the client.
889 //! \note requestDirectChat doesn't necessarily create a new chat;
890 //! directChatAvailable() is more appropriate if you need to obtain
891 //! a direct chat room after requestDirectChat().
893
894 //! \brief The first sync for the room has been completed
895 //!
896 //! This signal is emitted after the room has been synced the first
897 //! time. This is the right signal to connect to if you need to
898 //! access the room state (name, aliases, members); state transition
899 //! signals (newRoom, joinedRoom etc.) come earlier, when the room
900 //! has just been created.
902
903 //! Account data (except direct chats) have changed
905
906 //! \brief The direct chat room is ready for using
907 //!
908 //! This signal is emitted upon any successful outcome from
909 //! requestDirectChat.
911
912 //! \brief The list of direct chats has changed
913 //!
914 //! This signal is emitted every time when the mapping of users
915 //! to direct chat rooms is changed (because of either local updates
916 //! or a different list arrived from the server).
919
922
927
928 //! Encryption has been enabled or disabled
931
939
941
942 //! The account does not yet have cross-signing keys. The client should ask the user
943 //! whether to create them now and then set them up, if desired.
945
946 //! The connection is ready to be used. Most notably, the fundamental e2ee data is loaded.
947 //! This does not mean that the server was reached, a sync was performed, or the state cache was loaded.
948 void ready();
949
950 friend class ::TestCrossSigning;
951protected:
952 //! Access the underlying ConnectionData class
954
955 //! Get the homeserver data necessary to construct network requests
957
958 //! \brief Get a Room object for the given id in the given state
959 //!
960 //! Use this method when you need a Room object in the local list
961 //! of rooms, with the given state. Note that this does not interact
962 //! with the server; in particular, does not automatically create
963 //! rooms on the server. This call performs necessary join state
964 //! transitions; e.g., if it finds a room in Invite but
965 //! `joinState == JoinState::Join` then the Invite room object
966 //! will be deleted and a new room object with Join state created.
967 //! In contrast, switching between Join and Leave happens within
968 //! the same object.
969 //! \param id room id (not alias!)
970 //! \param joinState desired (target) join state of the room; if
971 //! omitted, any state will be found and return unchanged, or a
972 //! new Join room created.
973 //! \return a pointer to a Room object with the specified id and the
974 //! specified state; nullptr if roomId is empty or if roomFactory()
975 //! failed to create a Room object.
977
978 //! Process sync data from a successful sync request
979 void onSyncSuccess(SyncData&& data, bool fromCache = false);
980
981protected Q_SLOTS:
983
984private:
985 class Private;
987
990};
991} // namespace Quotient
992Q_DECLARE_METATYPE(Quotient::DirectChatsMap)
993Q_DECLARE_METATYPE(Quotient::IgnoredUsersList)
Predefined login flows.
Definition connection.h:62
const LoginFlow Token
Definition connection.h:65
const LoginFlow Password
Definition connection.h:63
const LoginFlow SSO
Definition connection.h:64
bool operator!=(const LoginFlow &lhs, const LoginFlow &rhs)
Definition connection.h:75
auto defaultRoomFactory(Connection *c, const QString &id, JoinState js)
The default factory to create room objects.
Definition connection.h:91
bool operator==(const LoginFlow &lhs, const LoginFlow &rhs)
Definition connection.h:70
JoinState
Local user join-state names.
auto defaultUserFactory(Connection *c, const QString &id)
The default factory to create user objects.
Definition connection.h:101
#define QUOTIENT_API