Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support per-room displaynames #141

Closed
KitsuneRal opened this issue Dec 28, 2017 · 2 comments
Closed

Support per-room displaynames #141

KitsuneRal opened this issue Dec 28, 2017 · 2 comments
Assignees
Labels
enhancement A feature or change request for the library

Comments

@KitsuneRal
Copy link
Member

As per matrix-org/matrix-doc#545 discussion, the API is already in place (although Synapse discards all custom-made displaynames when a generic displayname is changed). libqmatrixclient allows to send arbitrary m.room.member events nowadays; but it only stores a single common displayname and will be confused by such events arriving over the wire. There's a need of a RoomMemberTraits structure that will store this room-specific displayname (and avatarurl, which also can be overridden per-room). The considered options in how to manage these structures are below; option 3 looks most reasonable:

  1. Aligned with the API, which means that in addition to storing a User* in Room, we store a RoomMemberTraits instance for each m.room.member event coming. We'll have to make lots of such structures, and most of them will have the same traits for a particular user. And Qt's COW won't help because these events will be parsed separately. But that's really easy to implement. Updating the current user displayname/avatar logic is also fairly straightforward.
  2. Optimised basing on the generic traits stored in the user profile. The number of structures will drastically decrease (because very few actually make use of this feature) but the logic is more complex. First of all, once a User object is created, we'll have to request its profile from the server (trying to not overload the server with such requests along the way - imagine getting profiles for 10k+ users of Matrix HQ at initial sync). Upon m.room.member arrival, we'll have to check whether the displayname/avatarurl there coincide with the generic ones; if they don't, create RoomMemberTraits and store them for this user and room (either in Room or in User, there's no preference).
  3. Optimised basing on deduplicating effort. Again, we use the fact that very few are actually using room-specific names and avatars, but instead of using generic traits as a fallback we store all variants of the user traits we've seen in User. At m.room.member arrival, simply check whether this User already has an exactly the same RoomMemberTraits for other rooms; if yes, reuse the existing traits and add the room of this member event to the rooms list associated with this RoomMemberTraits; if no, add a new RoomMemberTraits. Generic traits of a User will have to be separately retrieved upon explicit demand.
@KitsuneRal KitsuneRal added the enhancement A feature or change request for the library label Dec 28, 2017
@KitsuneRal KitsuneRal changed the title Support changing displayname per-room Support per-room displaynames Feb 19, 2018
@KitsuneRal KitsuneRal self-assigned this Feb 19, 2018
@KitsuneRal
Copy link
Member Author

After the first attempt to code:

  • RoomMemberTraits are actually not a thing; only a specific name, or only an avatar, may be overridden. Besides, RoomMemberTraits are very clumsy to index for Option 3; strings for names and urls for avatars are much better for that. So it's better to treat each trait separately.
  • Option 3 makes retrieval of user traits in a room context a linear search along available options (Room pointers can be stored into hashed sets but we still have to roll through all available, e.g., names). In case of human users this number will obviously be low; however, bots (those very few that do use this feature) are likely to have a room-specific name for each room they are in. So if I as a local user have 1500 rooms (referring to Matthew's roomlist), and some bot happens to be in the majority of them, there are 1000+ different entries in the traits list. It's still not too much (maybe several ms) if a room-specific name is retrieved, say, once a second (note that this name is mostly for displaying purposes).

@KitsuneRal
Copy link
Member Author

It's worthwhile to finally think what use-cases we have to support. I'm using display names below; per-room avatars are an even less frequent case.

  1. A human user. Relatively few (assume ~10) names and relatively few (assume ~20) rooms with name overrides; a sub-case with a single alter-name used in all the 20 rooms. Option 3 works very well for the case.
    a. A human user with a scripting engine. The number of rooms increases to ~500, the number of different names can also increase. The worst case since we have to support both coarse-grained (500 rooms) and fine-grained (per-room) name overriding.
  2. A bot. The number of names is equal to the number of rooms accessible by the local user (~1500). Option 1 is the best for the case but Option 3 is still not that bad (see the previous comment).

Overall, the whole thing is not widespread (especially because Synapse flushes all overrides when a profile name is set) so postponing it for now.

KitsuneRal added a commit that referenced this issue Feb 23, 2018
This commit includes (and has to be dissected along the lines, some of which close #141):
- Avatar does not store Connection internally anymore; it also gained upload(), which is common code from User::setAvatar
- User::Private stores two new maps (for display names and avatars respectively) and is able to retrieve and store names/avatars on a per-room basis. The "most used" trait is stored separately and room lists are not kept for it (because most people have a single name and a single avatar across all or most rooms).
- Some (pretty minor) rearranging in Room: user() (instead of Private::member) and memberJoinState() (instead of Private::hasMember) were added to the external interface; user display names and avatars are retrieved in the context of a specific Room now.
KitsuneRal added a commit that referenced this issue Feb 23, 2018
This commit includes (and has to be dissected along the lines, some of which close #141):
- Avatar does not store Connection internally anymore; it also gained upload(), which is common code from User::setAvatar
- User::Private stores two new maps (for display names and avatars respectively) and is able to retrieve and store names/avatars on a per-room basis. The "most used" trait is stored separately and room lists are not kept for it (because most people have a single name and a single avatar across all or most rooms).
- Some (pretty minor) rearranging in Room: user() (instead of Private::member) and memberJoinState() (instead of Private::hasMember) were added to the external interface; user display names and avatars are retrieved in the context of a specific Room now.
KitsuneRal added a commit that referenced this issue Feb 23, 2018
User::Private stores two new maps (for display names and avatars respectively) and is able to retrieve and store names/avatars on a per-room basis. The "most used" trait is stored separately and room lists are not kept for it (because most people have a single name and a single avatar across all or most rooms).
TODO: The avatar container should be replaced with something less clumsy; the current code doesn't even compile with MSVC. A "handle" copyable structure that would hold the Avatar is one of options.
Closes #141.
@KitsuneRal KitsuneRal moved this to Version 0.2(.x) - Released in libQuotient 1 May 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement A feature or change request for the library
Projects
Status: Version 0.2(.x) - Released
Development

No branches or pull requests

1 participant