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