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
61
62//! Predefined login flow types
63namespace LoginFlowTypes {
64 inline constexpr auto Password = "m.login.password"_L1, SSO = "m.login.sso"_L1,
65 Token = "m.login.token"_L1;
66}
67
68//! Predefined login flows
69namespace
70#ifndef Q_MOC_RUN
71 [[deprecated("Use login flow types and Connection::getLoginFlow() instead")]]
72#endif
75 inline const LoginFlow SSO { LoginFlowTypes::SSO };
77}
78
79// To simplify comparisons of LoginFlows
80
81[[deprecated("Compare login flow types instead")]]
82inline bool operator==(const LoginFlow& lhs, const LoginFlow& rhs)
83{
84 return lhs.type == rhs.type;
85}
86
87[[deprecated("Compare login flow types instead")]]
88inline bool operator!=(const LoginFlow& lhs, const LoginFlow& rhs)
89{
90 return !(lhs == rhs);
91}
92
93class Connection;
94
95using room_factory_t =
96 std::function<Room*(Connection*, const QString&, JoinState)>;
97using user_factory_t = std::function<User*(Connection*, const QString&)>;
98
99//! \brief The default factory to create room objects
100//!
101//! Just a wrapper around operator new.
102//! \sa Connection::setRoomFactory, Connection::setRoomType
103template <typename T = Room>
104auto defaultRoomFactory(Connection* c, const QString& id, JoinState js)
105{
106 return new T(c, id, js);
107}
108
109//! \brief The default factory to create user objects
110//!
111//! Just a wrapper around operator new.
112//! \sa Connection::setUserFactory, Connection::setUserType
113template <typename T = User>
114auto defaultUserFactory(Connection* c, const QString& id)
115{
116 return new T(id, c);
117}
118
119// Room ids, rather than room pointers, are used in the direct chat
120// map types because the library keeps Invite rooms separate from
121// rooms in Join and Leave state; and direct chats in account data
122// are stored with no regard to their state.
125
128
148
149public:
151
155 }; // FIXME: Should go inside CreateRoomJob
156
157 explicit Connection(QObject* parent = nullptr);
158 explicit Connection(const QUrl& server, QObject* parent = nullptr);
160
161 //! \brief Get all rooms known within this Connection
162 //!
163 //! This includes Invite, Join and Leave rooms, in no particular order.
164 //! \note Leave rooms will only show up in the list if they have been left
165 //! in the same running session. The library doesn't cache left rooms
166 //! between runs and it doesn't retrieve the full list of left rooms
167 //! from the server.
168 //! \sa rooms, room, roomsWithTag
170
171 //! \brief Get rooms that have either of the given join state(s)
172 //!
173 //! This method returns, in no particular order, rooms which join state
174 //! matches the mask passed in \p joinStates.
175 //! \note Similar to allRooms(), this won't retrieve the full list of
176 //! Leave rooms from the server.
177 //! \sa allRooms, room, roomsWithTag
180
181 //! Get the total number of rooms in the given join state(s)
183
184 //! \brief Check whether the account has data of the given type
185 //!
186 //! Direct chats map is not supported by this method _yet_.
187 bool hasAccountData(const QString& type) const;
188
189 //! \brief Get a generic account data event of the given type
190 //!
191 //! \return an account data event of the given type stored on the server,
192 //! or nullptr if there's none of that type.
193 //! \note Direct chats map cannot be retrieved using this method _yet_;
194 //! use directChats() instead.
195 const EventPtr& accountData(const QString& type) const;
196
197 //! \brief Get an account data event of the given type
198 //!
199 //! \return the account data content for the given event type stored
200 //! on the server, or a default-constructed object if there's none
201 //! of that type.
202 //! \note Direct chats map cannot be retrieved using this method _yet_;
203 //! use directChats() instead.
204 template <EventClass EventT>
205 const EventT* accountData() const
206 {
207 // 0.9: use the default argument and fold into the next overload
209 }
210
211 template <EventClass EventT>
212 const EventT* accountData(const QString& keyName) const
213 {
215 }
216
217 //! \brief Get account data as a JSON object
218 //!
219 //! This returns the content part of the account data event
220 //! of the given type. Direct chats map cannot be retrieved using
221 //! this method _yet_; use directChats() instead.
223
224 //! Set a generic account data event of the given type
226
228 const QJsonObject& content);
229
230 //! Lists the types of account data that exist for this connection;
232
233 //! \brief Get all Invited and Joined rooms grouped by tag
234 //! \return a hashmap from tag name to a vector of room pointers,
235 //! sorted by their order in the tag - details are at
236 //! https://spec.matrix.org/v1.5/client-server-api/#room-tagging
238
239 //! Get all room tags known on this connection
241
242 //! Get the list of rooms with the specified tag
244
245 //! \brief Mark the room as a direct chat with the user
246 //!
247 //! This function marks \p room as a direct chat with \p userId.
248 //! Emits the signal synchronously, without waiting to complete
249 //! synchronisation with the server.
250 //! \sa directChatsListChanged
252
253 //! \brief Unmark the room from direct chats
254 //!
255 //! This function removes the room id from direct chats either for
256 //! a specific \p user or for all users if \p userId is empty.
257 //! The room id is used to allow removal of, e.g., ids of forgotten
258 //! rooms; a Room object need not exist. Emits the signal
259 //! immediately, without waiting to complete synchronisation with
260 //! the server.
261 //! \sa directChatsListChanged
263
264 //! Check whether the room id corresponds to a direct chat
265 bool isDirectChat(const QString& roomId) const;
266
267 //! Get the whole map from users to direct chat rooms
269
270 //! \brief Retrieve the list of member IDs the room is a direct chat with
271 //!
272 //! \return The list of member IDs for which this room is marked as
273 //! a direct chat; an empty list if the room is not a direct chat
275
276 //! Check whether a particular user id is in the ignore list
278
279 //! Check whether a particular user is in the ignore list
280 [[deprecated("Use the overload accepting UserId instead")]]
282
283 //! Get the whole list of ignored users
285
286 //! \brief Add the user to the ignore list
287 //! The change signal is emitted synchronously, without waiting
288 //! to complete synchronisation with the server.
289 //!
290 //! \sa ignoredUsersListChanged
292
293 //! \brief Remove the user from the ignore list
294 //!
295 //! Similar to adding, the change signal is emitted synchronously.
296 //! \sa ignoredUsersListChanged
298
299 //! \brief Get the entire list of users known to the current user on this homeserver
300 //! \note Be mindful that this can easily count thousands or tens of thousands, and use
301 //! sparingly; when in a room context, always use Room::members() instead
303
304 //! Get the base URL of the homeserver to connect to
306 //! Get the domain name used for ids/aliases on the server
308 //! Check if the homeserver is known to be reachable and working
309 [[deprecated("Check the result returned by Connection::loginFlows() instead")]]
310 bool isUsable() const;
311 //! Get the list of supported login flows
313 //! Get the login flow of a given type
315 //! Check whether the current homeserver supports password auth
317 //! Check whether the current homeserver supports SSO
318 bool supportsSso() const;
319 //! Find a room by its id and a mask of applicable states
321 const QString& roomId,
323 //! Find a room by its alias and a mask of applicable states
325 const QString& roomAlias,
327 //! \brief Update the internal map of room aliases to IDs
328 //!
329 //! This is used to maintain the internal index of room aliases.
330 //! It does NOT change aliases on the server,
331 //! \sa Room::setLocalAliases
334 const QStringList& roomAliases);
337 const User* user() const;
340
341 //! \brief Get an avatar object for the given user ID and media ID
343
344 //! \brief Get an avatar object for the given user ID and media ID
346
349 bool isLoggedIn() const;
350
351 //! \brief Whether the connection is successfully syncing with the server.
352 //!
353 //! \return true, if the last sync was successful, false otherwise.
354 bool isOnline() const;
357
359 const Room* room) const;
362
364 const QString& deviceId) const;
366 const QString& device) const;
367 bool hasOlmSession(const QString& user, const QString& deviceId) const;
368
369 // This assumes that an olm session already exists. If it doesn't, no message is sent.
371 const Event& event, bool encrypted);
372
373 //! Returns true if this megolm session comes from a verified device
375
376 //! Returns whether the device is verified
377 bool isVerifiedDevice(const QString& userId, const QString& deviceId) const;
378
379 //! \brief Returns whether the device is known and supports end-to-end encryption.
380 //!
381 //! This might give unexpected results for users we're not tracking,
382 //! i.e., users that we don't share an encrypted room with
384
385
389
393
395
400
402
406
408
412
413 static constexpr QStringView StableTag = u"stable";
414 bool isStable() const { return status == StableTag; }
415
417 {
419 return dbg.nospace() << v.id << '/' << v.status;
420 }
421 };
422
423 //! Find out if homeserver capabilites have been loaded
425
426 [[deprecated("Use capabilitiesReady() instead; don't forget to negate the returned value")]]
428
429 //! Get the list of Matrix CS API spec versions supported by the homeserver
431
432 //! \brief Get the room version recommended by the server
433 //!
434 //! Only works after server capabilities have been loaded.
435 //! \sa loadingCapabilities
437 //! \brief Get the room version considered stable by the server
438 //!
439 //! Only works after server capabilities have been loaded.
440 //! \sa loadingCapabilities
442 //! \brief Get all room versions supported by the server
443 //! Only works after server capabilities have been loaded.
444 //! \sa loadingCapabilities
446
447 //! Indicate if the user can change its password from the client.
448 //! This is often not the case when SSO is enabled.
449 //! \sa loadingCapabilities
450 bool canChangePassword() const;
451
452 //! \brief Check whether encryption is enabled on this connection
453 //! \sa enableEncryption
454 bool encryptionEnabled() const;
455
456 //! \brief Enable or disable encryption on this connection
457 //!
458 //! \note This has no effect if the library is compiled without E2EE support
459 //!
460 //! \sa encryptionEnabled
462
463 //! \brief Check whether encryption is enabled for new direct chats on this connection
464 //!
465 //! \note This has no effect if the library is compiled without E2EE support
466 //!
467 //! \sa enableDirectChatEncryption
469
470 //! \brief Enable or disable whether new direct chats are encrypted on this connection
471 //!
472 //! \note This has no effect if the library is compiled without E2EE support
473 //!
474 //! \sa directChatEncryptionEnabled
476
477 //! \brief Load room state from a previously saved file
478 //!
479 //! Call this before first sync.
480 //! \sa saveState
482
483 //! \brief Save the current state for all rooms to a file
484 //!
485 //! This method saves the current state of rooms (but not messages
486 //! in them) to a local cache file, so that it could be loaded by
487 //! loadState() on a next run of the client.
488 //! \sa loadState
489 Q_INVOKABLE void saveState() const;
490
491 //! This method saves the current state of a single room.
492 void saveRoomState(Room* r) const;
493
494 //! \brief Get the default directory path to save the room state to
495 //! \sa stateCacheDir
497
498 //! \brief Get the default directory to save the room state to
499 //!
500 //! This function returns the default directory to store the cached
501 //! room state, defined as follows:
502 //! \code
503 //! QStandardPaths::writeableLocation(QStandardPaths::CacheLocation) +
504 //! _safeUserId + "_state.json" \endcode where `_safeUserId` is userId() with
505 //! `:` (colon) replaced by
506 //! `_` (underscore), as colons are reserved characters on Windows.
507 //! \sa loadState, saveState, stateCachePath
509
510 //! \brief Whether or not the rooms state should be cached locally
511 //! \sa loadState, saveState
512 bool cacheState() const;
514
515 bool lazyLoading() const;
517
518 //! \brief Start a pre-made job object on this connection
519 //!
520 //! Use this overload in case when you don't want to, or cannot, use JobHandle. Internally,
521 //! this is also the function all other template wrappers ultimately call to do the real work.
524
525 //! \brief Start a pre-created job on this connection
526 //!
527 //! Use this overload if you have a job object pre-made with JobHandle<>::createFrom() when
528 //! you need to actually start (or rather, queue) the network request. It is strongly
529 //! recommended to use the job handle returned by run() instead of the original, as run() may
530 //! (in the future) attach continuations to the future interface of the handle.
531 //! \sa JobHandle::createFrom
532 template <std::derived_from<BaseJob> JobT>
535 {
537 return std::move(job);
538 }
539
540 //! \brief Start a job of a given type with specified arguments and policy
541 //!
542 //! This is a universal method to create and start a job of a type passed
543 //! as a template parameter. The policy allows to fine-tune the way
544 //! the job is executed - as of this writing it means a choice
545 //! between "foreground" and "background".
546 //!
547 //! \param runningPolicy controls how the job is executed
548 //! \param jobArgs arguments to the job constructor
549 //!
550 //! \sa BaseJob::isBackground. QNetworkRequest::BackgroundRequestAttribute
551 template <typename JobT, typename... JobArgTs>
553 {
555 }
556
557 //! \brief Start a job of a specified type with specified arguments
558 //!
559 //! This is an overload that runs the job with "foreground" policy.
560 template <typename JobT, typename... JobArgTs>
562 {
564 }
565
566 //! \brief Get a request URL for a job with specified type and arguments
567 //!
568 //! This calls JobT::makeRequestUrl() prepending the connection's homeserver
569 //! to the list of arguments.
570 template <typename JobT, typename... JobArgTs>
572 {
574 }
575
576 //! \brief Start a local HTTP server and generate a single sign-on URL
577 //!
578 //! This call does the preparatory steps to carry out single sign-on
579 //! sequence
580 //! \sa https://matrix.org/docs/guides/sso-for-client-developers
581 //! \return A proxy object holding two URLs: one for SSO on the chosen
582 //! homeserver and another for the local callback address. Normally
583 //! you won't need the callback URL unless you proxy the response
584 //! with a custom UI. You do not need to delete the SsoSession
585 //! object; the Connection that issued it will dispose of it once
586 //! the login sequence completes (with any outcome).
588 const QString& deviceId = {});
589
590 //! \brief Generate a new transaction id
591 //!
592 //! Transaction id's are unique within a single Connection object
594
595 //! Convert an mxc: URL into a CS API URL
597
599 const QString& maybeSuccessorId) const;
600
601 //! Set the E2EE default state for any Connection created further
603
604 //! Set the direct chat E2EE default state for any Connection created further
606
607 //! Set a room factory function
609
610 //! Set a user factory function
612
613 //! Get a room factory function
615
616 //! Get a user factory function
618
619 //! Set the room factory to default with the overriden room type
620 template <typename T>
621 static void setRoomType()
622 {
624 }
625
626 //! Set the user factory to default with the overriden user type
627 template <typename T>
628 static void setUserType()
629 {
631 }
632
633 //! \brief Determine and set the homeserver from MXID
634 //!
635 //! This attempts to resolve the homeserver by requesting
636 //! .well-known/matrix/client record from the server taken from the MXID
637 //! serverpart. If there is no record found, the serverpart itself is
638 //! attempted as the homeserver base URL; if the record is there but
639 //! is malformed (e.g., the homeserver base URL cannot be found in it)
640 //! resolveError() is emitted and further processing stops. Otherwise,
641 //! setHomeserver is called, preparing the Connection object for the login
642 //! attempt.
643 //! \param mxid user Matrix ID, such as @someone:example.org
644 //! \sa setHomeserver, homeserverChanged, loginFlowsChanged, resolveError
646
647 //! \brief Set the homeserver base URL and retrieve its login flows
648 //!
649 //! \sa LoginFlowsJob, loginFlows, loginFlowsChanged, homeserverChanged
651
652 //! \brief Get a future to a direct chat with the user
654
655 //! Create a direct chat with a single user, optional name and topic
656 //!
657 //! A room will always be created, unlike in requestDirectChat.
658 //! It is advised to use requestDirectChat as a default way of getting
659 //! one-on-one with a person, and only use createDirectChat when
660 //! a new creation is explicitly desired.
662 const QString& topic = {},
663 const QString& name = {});
664
666 const QStringList& serverNames = {});
667
669 const QStringList& serverNames = {});
670
671public Q_SLOTS:
672 //! \brief Log in using a username and password pair
673 //!
674 //! Before logging in, this method checks if the homeserver is valid and
675 //! supports the password login flow. If the homeserver is invalid but
676 //! a full user MXID is provided, this method calls resolveServer() using
677 //! this MXID.
678 //! \sa resolveServer, resolveError, loginError
681 const QString& deviceId = {});
682
683 //! \brief Log in using a login token
684 //!
685 //! One usual case for this method is the final stage of logging in via SSO.
686 //! Unlike loginWithPassword() and assumeIdentity(), this method cannot
687 //! resolve the server from the user name because the full user MXID is
688 //! encoded in the login token. Callers should ensure the homeserver
689 //! sanity in advance.
692 const QString& deviceId = {});
693
694 //! \brief Use an existing access token to connect to the homeserver
695 //!
696 //! Similar to loginWithPassword(), this method checks that the homeserver
697 //! URL is valid and tries to resolve it from the MXID in case it is not.
698 //! \since 0.7.2
700
701 //! \brief Request supported spec versions from the homeserver
702 //!
703 //! This call does not obtain room versions - use loadCapabilities() for that.
705
706 //! Request capabilities and room versions from the server
708
709 [[deprecated("Use loadCapabilities() instead")]] void reloadCapabilities();
710
712
713 void sync(int timeout = -1);
715
716 void stopSync();
717
723 int requestedHeight,
725
726 // QIODevice* should already be open
728 const QString& overrideContentType = {});
730 const QString& overrideContentType = {});
731 [[deprecated("Use downloadFile() instead")]] BaseJob* getContent(const QString& mediaId);
732 [[deprecated("Use downloadFile() instead")]] BaseJob* getContent(const QUrl& url);
733
734 // If localFilename is empty, a temporary file will be created
736
739 const QString& localFilename = {});
740
741 //! \brief Create a room (generic method)
742 //!
743 //! This method allows to customize room entirely to your liking,
744 //! providing all the attributes the original CS API provides.
747 const QString& presetName = {}, const QString& roomVersion = {},
748 bool isDirect = false,
751 const QJsonObject& creationContent = {});
752
753 //! \brief Get a direct chat with a single user
754 //!
755 //! This method may return synchronously or asynchoronously depending
756 //! on whether a direct chat room with the respective person exists
757 //! already.
758 //! \sa directChatAvailable
760
761 //! \brief Send /forget to the server and delete room locally
762 //!
763 //! This method is in Connection, not in Room, since it's a
764 //! room lifecycle operation, and Connection is an acting room manager.
765 //! It ensures that the local user is not a member of a room (running /leave,
766 //! if necessary) then issues a /forget request and if that one doesn't fail
767 //! deletion of the local Room object is ensured.
768 //! \param id the room id to forget
769 //! \return the ongoing /forget request to the server; note that the
770 //! success() signal of this request is connected to deleteLater()
771 //! of a respective room so by the moment this finishes, there
772 //! might be no Room object anymore.
774
777
778 [[deprecated("This method is experimental and may be removed any time")]] //
780
781 //! \deprecated Do not use this directly, use Room::leaveRoom() instead
783
785 const QString& deviceId);
786
789
791 bool enableEncryption = true);
792
794 //! \brief Initial server resolution has failed
795 //!
796 //! This signal is emitted when resolveServer() did not manage to resolve
797 //! the homeserver using its .well-known/client record or otherwise.
798 //! \sa resolveServer
800
804
805 void connected();
806 void loggedOut();
807
808 //! \brief Login data or state have changed
809 //!
810 //! This is a common change signal for userId, deviceId and
811 //! accessToken - these properties normally only change at
812 //! a successful login and logout and are constant at other times.
814
815 //! The online state has changed.
817
819
820 //! \brief A network request (job) started by callApi() has failed
821 //! \param request the pointer to the failed job
822 //! \sa callApi
824
825 //! \brief A network request (job) failed due to network problems
826 //!
827 //! This is _only_ emitted when the job will retry on its own;
828 //! once it gives up, requestFailed() will be emitted.
829 //!
830 //! \param message message about the network problem
831 //! \param details raw error details, if any available
832 //! \param retriesTaken how many retries have already been taken
833 //! \param nextRetryInMilliseconds when the job will retry again
834 //! (-1 if no next retry is scheduled)
837
838 void syncDone();
840
842
843 //! \group Signals emitted on room transitions
844 //!
845 //! Note: Rooms in Invite state are always stored separately from
846 //! rooms in Join/Leave state, because of special treatment of
847 //! invite_state in Matrix CS API (see The Spec on /sync for details).
848 //! Therefore, objects below are: r - room in Join/Leave state;
849 //! i - room in Invite state
850 //!
851 //! 1. none -> Invite: newRoom(r), invitedRoom(r,nullptr)
852 //! 2. none -> Join: newRoom(r), joinedRoom(r,nullptr)
853 //! 3. none -> Leave: newRoom(r), leftRoom(r,nullptr)
854 //! 4. Invite -> Join:
855 //! newRoom(r), joinedRoom(r,i), aboutToDeleteRoom(i)
856 //! 4a. Leave and Invite -> Join:
857 //! joinedRoom(r,i), aboutToDeleteRoom(i)
858 //! 5. Invite -> Leave:
859 //! newRoom(r), leftRoom(r,i), aboutToDeleteRoom(i)
860 //! 5a. Leave and Invite -> Leave:
861 //! leftRoom(r,i), aboutToDeleteRoom(i)
862 //! 6. Join -> Leave: leftRoom(r)
863 //! 7. Leave -> Invite: newRoom(i), invitedRoom(i,r)
864 //! 8. Leave -> Join: joinedRoom(r)
865 //! The following transitions are only possible via forgetRoom()
866 //! so far; if a room gets forgotten externally, sync won't tell
867 //! about it:
868 //! 9. any -> none: as any -> Leave, then aboutToDeleteRoom(r)
869
870 //! A new room object has been created
872
873 //! \brief A room invitation is seen for the first time
874 //!
875 //! If the same room is in Left state, it's passed in prev. Beware
876 //! that initial sync will trigger this signal for all rooms in
877 //! Invite state.
879
880 //! \brief A joined room is seen for the first time
881 //!
882 //! It's not the same as receiving a room in "join" section of sync
883 //! response (rooms will be there even after joining); it's also
884 //! not (exactly) the same as actual joining action of a user (all
885 //! rooms coming in initial sync will trigger this signal too). If
886 //! this room was in Invite state before, the respective object is
887 //! passed in prev (and it will be deleted shortly afterwards).
889
890 //! \brief A room has just been left
891 //!
892 //! If this room has been in Invite state (as in case of rejecting
893 //! an invitation), the respective object will be passed in prev
894 //! (and will be deleted shortly afterwards). Note that, similar
895 //! to invitedRoom and joinedRoom, this signal is triggered for all
896 //! Left rooms upon initial sync (not only those that were left
897 //! right before the sync).
899
900 //! The room object is about to be deleted
902
903 //! \brief The room has just been created by createRoom or requestDirectChat
904 //!
905 //! This signal is not emitted in usual room state transitions,
906 //! only as an outcome of room creation operations invoked by
907 //! the client.
908 //! \note requestDirectChat doesn't necessarily create a new chat;
909 //! directChatAvailable() is more appropriate if you need to obtain
910 //! a direct chat room after requestDirectChat().
912
913 //! \brief The first sync for the room has been completed
914 //!
915 //! This signal is emitted after the room has been synced the first
916 //! time. This is the right signal to connect to if you need to
917 //! access the room state (name, aliases, members); state transition
918 //! signals (newRoom, joinedRoom etc.) come earlier, when the room
919 //! has just been created.
921
922 //! Account data (except direct chats) have changed
924
925 //! \brief The direct chat room is ready for using
926 //!
927 //! This signal is emitted upon any successful outcome from
928 //! requestDirectChat.
930
931 //! \brief The list of direct chats has changed
932 //!
933 //! This signal is emitted every time when the mapping of users
934 //! to direct chat rooms is changed (because of either local updates
935 //! or a different list arrived from the server).
938
941
946
947 //! Encryption has been enabled or disabled
950
958
960
961 //! The account does not yet have cross-signing keys. The client should ask the user
962 //! whether to create them now and then set them up, if desired.
964
965 //! The connection is ready to be used. Most notably, the fundamental e2ee data is loaded.
966 //! This does not mean that the server was reached, a sync was performed, or the state cache was loaded.
967 void ready();
968
969 friend class ::TestCrossSigning;
970protected:
971 //! Access the underlying ConnectionData class
973
974 //! Get the homeserver data necessary to construct network requests
976
977 //! \brief Get a Room object for the given id in the given state
978 //!
979 //! Use this method when you need a Room object in the local list
980 //! of rooms, with the given state. Note that this does not interact
981 //! with the server; in particular, does not automatically create
982 //! rooms on the server. This call performs necessary join state
983 //! transitions; e.g., if it finds a room in Invite but
984 //! `joinState == JoinState::Join` then the Invite room object
985 //! will be deleted and a new room object with Join state created.
986 //! In contrast, switching between Join and Leave happens within
987 //! the same object.
988 //! \param id room id (not alias!)
989 //! \param joinState desired (target) join state of the room; if
990 //! omitted, any state will be found and return unchanged, or a
991 //! new Join room created.
992 //! \return a pointer to a Room object with the specified id and the
993 //! specified state; nullptr if roomId is empty or if roomFactory()
994 //! failed to create a Room object.
996
997 //! Process sync data from a successful sync request
998 void onSyncSuccess(SyncData&& data, bool fromCache = false);
999
1000protected Q_SLOTS:
1002
1003private:
1004 class Private;
1005 ImplPtr<Private> d;
1006
1009};
1010} // namespace Quotient
1011Q_DECLARE_METATYPE(Quotient::DirectChatsMap)
1012Q_DECLARE_METATYPE(Quotient::IgnoredUsersList)
Predefined login flow types.
Definition connection.h:63
constexpr auto Token
Definition connection.h:65
constexpr auto Password
Definition connection.h:64
Predefined login flows.
Definition connection.h:73
const LoginFlow Token
Definition connection.h:76
const LoginFlow Password
Definition connection.h:74
const LoginFlow SSO
Definition connection.h:75
bool operator!=(const LoginFlow &lhs, const LoginFlow &rhs)
Definition connection.h:88
auto defaultRoomFactory(Connection *c, const QString &id, JoinState js)
The default factory to create room objects.
Definition connection.h:104
bool operator==(const LoginFlow &lhs, const LoginFlow &rhs)
Definition connection.h:82
JoinState
Local user join-state names.
auto defaultUserFactory(Connection *c, const QString &id)
The default factory to create user objects.
Definition connection.h:114
#define QUOTIENT_API