From 8183a33c130f1284404edc61767ff6d29402d200 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 23 Jan 2022 17:11:45 +0100 Subject: RoomStateView This class is called to provide an arbitrary snapshot of a room state; as the first step, Room::currentState() returns an instance of this class that stores, well, the current state. Implelementation-wise it's the same hash map of two-part state event keys to const event pointers; however, RoomStateView provides additional operations: - get(), that deprecates Room::getCurrentState(), returns a pointer to a particular event if the current state has it. Unlike the original method, the pointer returned from this one can be nullptr; this is done to get rid of stubbed state events that have to be created everytime a "state miss" occurred (i.e., when getCurrentState() does not find an existing event in the current state). - eventsOfType() - this is a new place for Room::stateEventsOfType() introduced recently. - query() - this is a way to specify a piece of the state content that you need to retrieve by passing a member function or a function object that retrieves it. That is especially convenient with member functions of the event class; just pass the pointer to this member function, and query() will parse the event type it has to retrieve out of it and call that member function on the event object. Returns an Omittable<>; if the respective piece of state doesn't exist, you'll get `Quotient::none` (the same as `std::nullopt`). - queryOr() - the same but with the fallback value; instead of an Omittable<>, the fallback value will be returned if the needed event is not found. --- lib/user.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'lib/user.cpp') diff --git a/lib/user.cpp b/lib/user.cpp index 0dbc444a..f7840c40 100644 --- a/lib/user.cpp +++ b/lib/user.cpp @@ -119,12 +119,17 @@ void User::rename(const QString& newName, const Room* r) return; } // #481: take the current state and update it with the new name - auto evtC = r->getCurrentState(id())->content(); - Q_ASSERT_X(evtC.membership == Membership::Join, __FUNCTION__, - "Attempt to rename a user that's not a room member"); - evtC.displayName = sanitized(newName); - r->setState(id(), move(evtC)); - // The state will be updated locally after it arrives with sync + if (const auto& maybeEvt = r->currentState().get(id())) { + auto content = maybeEvt->content(); + if (content.membership == Membership::Join) { + content.displayName = sanitized(newName); + r->setState(id(), move(content)); + // The state will be updated locally after it arrives with sync + return; + } + } + qCCritical(MEMBERS) + << "Attempt to rename a non-member in a room context - ignored"; } template -- cgit v1.2.3 From 9ae0d4e45befc79f621b03dc4efe869cd4277e06 Mon Sep 17 00:00:00 2001 From: Alexey Rusakov Date: Sun, 23 Jan 2022 10:32:40 +0100 Subject: Refactor Room::setState() There are two important aspects here: - Introducing Room::setState(evtType, stateKey, contentJson). These components are ultimately what is getting sent to the homeserver, so it makes sense to expose a respective `setState()` overload. Unlike setState(event) the new overload can be Q_INVOKABLE. - Room::setState() is no more const. Although it doesn't cause any changes in Room class (and only transient changes in Room::Private), it ultimately initiates a change in the room state, so calling it const has always been a bit of hypocrisy. If you relied on that, you most likely do something wrong (see the fix to User::rename() in this very commit for a simple example of such wrongness). Also: the backend is simplified by calling the original templated Room::setState() instead of calling Room::Private::requestSetState() that does exactly the same thing. --- lib/user.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/user.cpp') diff --git a/lib/user.cpp b/lib/user.cpp index f7840c40..4c3fc9e2 100644 --- a/lib/user.cpp +++ b/lib/user.cpp @@ -110,7 +110,7 @@ void User::rename(const QString& newName) }); } -void User::rename(const QString& newName, const Room* r) +void User::rename(const QString& newName, Room* r) { if (!r) { qCWarning(MAIN) << "Passing a null room to two-argument User::rename()" -- cgit v1.2.3