1// SPDX-FileCopyrightText: 2015 Felix Rohrbach <kde@fxrh.de>
2// SPDX-FileCopyrightText: 2016 Kitsune Ral <Kitsune-Ral@users.sf.net>
3// SPDX-License-Identifier: LGPL-2.1-or-later
4
5#pragma once
6
7#include "avatar.h"
8#include "util.h"
9
10#include <QtCore/QObject>
11
12namespace Quotient {
13class Connection;
14class Room;
15class RoomMemberEvent;
16
17class QUOTIENT_API User : public QObject {
18 Q_OBJECT
19 Q_PROPERTY(QString id READ id CONSTANT)
20 Q_PROPERTY(bool isGuest READ isGuest CONSTANT)
21 Q_PROPERTY(int hue READ hue CONSTANT)
22 Q_PROPERTY(qreal hueF READ hueF CONSTANT)
23 Q_PROPERTY(QString name READ name NOTIFY defaultNameChanged)
24 Q_PROPERTY(QString displayName READ displayname NOTIFY defaultNameChanged STORED false)
25 Q_PROPERTY(QString fullName READ fullName NOTIFY defaultNameChanged STORED false)
26 Q_PROPERTY(QString avatarMediaId READ avatarMediaId NOTIFY defaultAvatarChanged STORED false)
27 Q_PROPERTY(QUrl avatarUrl READ avatarUrl NOTIFY defaultAvatarChanged)
28public:
29 User(QString userId, Connection* connection);
30
31 Connection* connection() const;
32
33 /** Get unique stable user id
34 * User id is generated by the server and is not changed ever.
35 */
36 QString id() const;
37
38 /** Get the name chosen by the user
39 * This may be empty if the user didn't choose the name or cleared
40 * it. If the user is bridged, the bridge postfix (such as '(IRC)')
41 * is stripped out. No disambiguation for the room is done.
42 * \sa displayName
43 */
44 QString name(const Room* room = nullptr) const;
45
46 /** Get the displayed user name
47 * When \p room is null, this method returns result of name() if
48 * the name is non-empty; otherwise it returns user id.
49 * When \p room is non-null, this call is equivalent to
50 * Room::roomMembername invocation for the user (i.e. the user's
51 * disambiguated room-specific name is returned).
52 * \sa name, id, fullName, Room::roomMembername
53 */
54 QString displayname(const Room* room = nullptr) const;
55
56 /** Get user name and id in one string
57 * The constructed string follows the format 'name (id)'
58 * which the spec recommends for users disambiguation in
59 * a room context and in other places.
60 * \sa displayName, Room::roomMembername
61 */
62 QString fullName(const Room* room = nullptr) const;
63
64 /** Whether the user is a guest
65 * As of now, the function relies on the convention used in Synapse
66 * that guests and only guests have all-numeric IDs. This may or
67 * may not work with non-Synapse servers.
68 */
69 bool isGuest() const;
70
71 /** Hue color component of this user based on id.
72 * The implementation is based on XEP-0392:
73 * https://xmpp.org/extensions/xep-0392.html
74 * Naming and ranges are the same as QColor's hue methods:
75 * https://doc.qt.io/qt-5/qcolor.html#integer-vs-floating-point-precision
76 */
77 int hue() const;
78 qreal hueF() const;
79
80 /// Get a reference to a user avatar object for a given room
81 /*! This reference should be considered short-lived: processing the next
82 * room member event for this user may (or may not) invalidate it.
83 */
84 const Avatar& avatarObject(const Room* room = nullptr) const;
85 Q_INVOKABLE QImage avatar(int dimension,
86 const Quotient::Room* room = nullptr) const;
87 Q_INVOKABLE QImage avatar(int requestedWidth, int requestedHeight,
88 const Quotient::Room* room = nullptr) const;
89 QImage avatar(int width, int height, const Room* room,
90 const Avatar::get_callback_t& callback) const;
91
92 QString avatarMediaId(const Room* room = nullptr) const;
93 QUrl avatarUrl(const Room* room = nullptr) const;
94
95public Q_SLOTS:
96 /// Set a new name in the global user profile
97 void rename(const QString& newName);
98 /// Set a new name for the user in one room
99 void rename(const QString& newName, Room* r);
100 /// Upload the file and use it as an avatar
101 bool setAvatar(const QString& fileName);
102 /// Upload contents of the QIODevice and set that as an avatar
103 bool setAvatar(QIODevice* source);
104 /// Removes the avatar from the profile
105 void removeAvatar();
106 /// Create or find a direct chat with this user
107 /*! The resulting chat is returned asynchronously via
108 * Connection::directChatAvailable()
109 */
110 void requestDirectChat();
111 /// Add the user to the ignore list
112 void ignore();
113 /// Remove the user from the ignore list
114 void unmarkIgnore();
115 /// Check whether the user is in ignore list
116 bool isIgnored() const;
117 /// Force loading displayName and avartar url. This is required in
118 /// some cases where the you need to use an user independent of the
119 /// room.
120 void load();
121
122Q_SIGNALS:
123 void defaultNameChanged();
124 void defaultAvatarChanged();
125
126private:
127 class Private;
128 ImplPtr<Private> d;
129
130 template <typename SourceT>
131 bool doSetAvatar(SourceT&& source);
132};
133} // namespace Quotient
134