1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
#pragma once
#include "connection.h"
#include <functional>
namespace Quotient {
/*! \brief Matrix resource resolver
* TODO: rewrite
* Similar to visitResource(), this class encapsulates the logic of resolving
* a Matrix identifier or a URI into Quotient object(s) and applying an action
* to the resolved object(s). Instead of using a C++ visitor pattern, it
* announces the request through Qt's signals passing the resolved object(s)
* through those (still in a typesafe way).
*
* This class is aimed primarily at clients where invoking the resolving/action
* and handling the action are happening in decoupled parts of the code; it's
* also useful to operate on Matrix identifiers and URIs from QML/JS code
* that cannot call visitResource due to QML/C++ interface limitations.
*/
class ResourceResolver : public QObject {
Q_OBJECT
public:
enum Result : short {
StillResolving = -1,
Success = 0,
UnknownMatrixId,
MalformedMatrixId,
NoAccount,
EmptyMatrixId
};
Q_ENUM(Result)
explicit ResourceResolver(QObject* parent = nullptr) : QObject(parent)
{ }
/*! \brief Decode a URI to a Matrix identifier (or a room/event pair)
*
* This accepts plain Matrix ids, MSC2312 URIs (aka matrix: URIs) and
* matrix.to URIs.
*
* \return a Matrix identifier as defined by the common identifier grammars
* or a slash separated pair of Matrix identifiers if the original
* uri/id pointed to an event in a room
*/
static QString toMatrixId(const QString& uriOrId,
QStringList uriServers = {});
/*! \brief Resolve the resource and invoke an action on it, visitor style
*
* This template function encapsulates the logic of resolving a Matrix
* identifier or URI into a Quotient object (or objects) and applying an
* appropriate action handler from the set provided by the caller to it.
* A typical use case for that is opening a room or mentioning a user in
* response to clicking on a Matrix URI or identifier.
*
* \param account The connection used as a context to resolve the identifier
*
* \param identifier The Matrix identifier or URI. MSC2312 URIs and classic
* Matrix ID scheme are supported.
*
* \sa ResourceResolver
*/
static Result
visitResource(Connection* account, const QString& identifier,
std::function<void(User*)> userHandler,
std::function<void(Room*, QString)> roomEventHandler);
/*! \brief Resolve the resource and request an action on it, signal style
*
* This method:
* 1. Resolves \p identifier into an actual object (Room or User), with
* possible additional data such as event id, in the context of
* \p account.
* 2. If the resolving is successful, depending on the type of the object,
* emits the respective signal to which the client must connect in order
* to apply the action to the resource (open a room, mention a user etc.).
* 3. Returns the result of resolving the resource.
*
* Note that the action can be applied either synchronously or entirely
* asynchronously; ResourceResolver does not restrain the client code
* to use either method. The resource resolving part is entirely synchronous
* though. If the synchronous operation is chosen, only
* direct connections to ResourceResolver signals must be used, and
* the caller should check the future's state immediately after calling
* openResource() to process any feedback from the resolver and/or action
* handler. If asynchronous operation is needed then either direct or queued
* connections to ResourceResolver's signals can be used and the caller
* must both check the ResourceFuture state right after calling openResource
* and also connect to ResourceFuture::ready() signal in order to process
* the result of resolving and action.
*/
Q_INVOKABLE Result openResource(Connection* account,
const QString& identifier,
const QString& action = {});
signals:
/// An action on a user has been requested
void userAction(Quotient::User* user, QString action);
/// An action on a room has been requested, with optional event id
void roomAction(Quotient::Room* room, QString eventId, QString action);
private:
struct IdentifierParts {
char sigil;
QString mainId {};
QString secondaryId = {};
};
static IdentifierParts parseIdentifier(const QString& identifier);
};
} // namespace Quotient
|