Skip to content

New chat architecture

Wesmania edited this page Feb 13, 2018 · 2 revisions

This describes the new chat architecture. Note that some parts of classes or less relevant outside classes were omitted in each section, for readability. The code for the chat refactor can be found here.

Model

The Chat contains Channels that the current user is in and Chatters connected to Chat. Each Chatter can be present in many Channels - a Chatter's presence in a Channel and any attributes of such are represented by a ChannelChatter.

Channels, Chatters and ChannelChatters are core model types.

The Chat is not necessarily a representation of all existing Chatters and Channels - it's only a subset visible to the user, like all channels the user is in and chatters from these channels, or no channels or chatters if the user is disconnected.

Channels, Chatters and ChannelChatters can be added and removed. If a Channel or a Chatter is removed, its related ChannelChatters are removed as well. Channels and Chatters keep references to related ChannelChatters that are kept consistent and up-to-date, while ChannelChatters keep references to appropriate Channels and Chatters.

Model signals

In order for the view to efficiently and promptly display changes in the model, and for the model to cleanly process changes, a small framework of Qt signals is built around the core model:

Each core model type is updated and emits updates through an updated() signal. Each core model type belongs to a corresponding item set type, which emits added and removed items through corresponding signals.

In addition to the 3 set classes, a ChatterChannelRelation is used to properly add or remove relations between chatters and channels as they are added and removed, as well as remove ChannelChatters from the set when their corresponding channels or chatters are removed.

An addition or removal of an item (e.g. Channel) may cause a cascade of additions / removals / updates of other items (e.g. ChannelChatter removal). Any model qt signals related to these updates are not emitted until the cascade is over and the model is once again in a consistent state.

All the set classes and the relation class are composed together in the Chat class (along with any extra Chat attributes or data).

Controller

Communication with IRC is handled by the IrcConnection class, which adds a bit more abstraction on top of irclib. Signals from the connection are handled by the IrcController, which translates it to changes to the model (deducing things like new chatters being added and new channels joined).

TODO The controller will also have methods for interfacing with the IRC connection in a generic fashion, such as joining channels or sending messages.

View

Chat and Channel models have their view counterparts. ChatView and ChannelView classes are responsible for reacting to model changes and appropriately updating the UI. Two widget classes - ChatWidget and ChannelWidget - are wrappers for Qt widgets that are updated by the view classes.

The ChatView class is responsible for creation, bookkeeping and deletion of ChannelView instances. TODO Right now both classes also create their associated widgets. This probably won't change since we can mock them easily for testing purposes - perhaps in the far future we'll need dependency injection for something.

Since channel widgets display a chatter list, a standard Qt model / delegate pair is needed. ChatterModel is this model, and ChatterDelegate is this delegate. ChatterModelItem is a view class for ChannelChatter, reporting relevant changes to the chatter (and to the corresponding FAF player, not depicted here.) TODO Some ChatterModel functionality is shared with the GameModel class, so we'll probably factor it out.

TODO All above classes are instantiated by ChannelView. Maybe we'll need to dependency inject them one day.

TODO The channel and chat views should also be given the chat controller in order to do things like join channels or send messages. Stuff like parsing the line to send for stuff like '/join' can probably be handled by the controller as well, but maybe we can delegate it to another object?

Clone this wiki locally