experimental: display online/offline status for conversation members
This commit is contained in:
parent
f2096694c6
commit
7976859639
|
@ -60,7 +60,7 @@ public class Dino.CallState : Object {
|
|||
XmppStream stream = stream_interactor.get_stream(call.account);
|
||||
if (stream == null) return;
|
||||
|
||||
Gee.List<Jid> occupants = stream_interactor.get_module(MucManager.IDENTITY).get_other_occupants(muc, call.account);
|
||||
Gee.List<Jid> occupants = stream_interactor.get_module(MucManager.IDENTITY).get_other_members(muc, call.account);
|
||||
foreach (Jid occupant in occupants) {
|
||||
Jid? real_jid = stream_interactor.get_module(MucManager.IDENTITY).get_real_jid(occupant, call.account);
|
||||
if (real_jid == null) continue;
|
||||
|
|
|
@ -259,27 +259,46 @@ public class MucManager : StreamInteractionModule, Object {
|
|||
return is_groupchat(jid, account) && !is_private_room(account, jid);
|
||||
}
|
||||
|
||||
public Gee.List<Jid>? get_occupants(Jid jid, Account account) {
|
||||
public Gee.List<Jid>? get_all_members(Jid jid, Account account) {
|
||||
if (is_groupchat(jid, account)) {
|
||||
Gee.List<Jid> ret = new ArrayList<Jid>(Jid.equals_func);
|
||||
Gee.List<Jid>? full_jids = get_offline_members(jid, account);
|
||||
|
||||
// This should return all members of the chat
|
||||
Gee.List<Jid>? members = get_offline_members(jid, account);
|
||||
if (members != null) {
|
||||
ret.add_all(members);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Gee.List<Jid>? get_members(Jid jid, Account account) {
|
||||
if (is_groupchat(jid, account)) {
|
||||
Gee.List<Jid> ret = new ArrayList<Jid>(Jid.equals_func);
|
||||
Gee.List<Jid>? full_jids = stream_interactor.get_module(PresenceManager.IDENTITY).get_full_jids(jid, account);
|
||||
if (full_jids != null) {
|
||||
ret.add_all(full_jids);
|
||||
// Remove eventual presence from bare jid
|
||||
ret.remove(jid);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Gee.List<Jid>? get_other_occupants(Jid jid, Account account) {
|
||||
Gee.List<Jid>? occupants = get_occupants(jid, account);
|
||||
public Gee.List<Jid>? get_other_members(Jid jid, Account account) {
|
||||
Gee.List<Jid>? members = get_members(jid, account);
|
||||
Jid? own_jid = get_own_jid(jid, account);
|
||||
if (occupants != null && own_jid != null) {
|
||||
occupants.remove(own_jid);
|
||||
if (members != null && own_jid != null) {
|
||||
members.remove(own_jid);
|
||||
}
|
||||
return occupants;
|
||||
|
||||
return members;
|
||||
}
|
||||
|
||||
public bool is_groupchat(Jid jid, Account account) {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<property name="margin-start">7</property>
|
||||
<property name="margin-bottom">3</property>
|
||||
<property name="margin-end">7</property>
|
||||
<property name="column-spacing">10</property>
|
||||
<property name="column-spacing">5</property>
|
||||
<child>
|
||||
<object class="DinoUiAvatarPicture" id="picture">
|
||||
<property name="height-request">30</property>
|
||||
|
@ -25,5 +25,17 @@
|
|||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="status_label">
|
||||
<property name="max_width_chars">1</property>
|
||||
<property name="ellipsize">end</property>
|
||||
<property name="hexpand">1</property>
|
||||
<property name="xalign">0</property>
|
||||
<layout>
|
||||
<property name="column">2</property>
|
||||
<property name="row">0</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
|
@ -107,7 +107,7 @@ public class OccupantsTabCompletor {
|
|||
Gee.List<string> ret = generate_completions_from_messages(prefix);
|
||||
|
||||
// Then, suggest other nicks in alphabetical order
|
||||
Gee.List<Jid>? occupants = stream_interactor.get_module(MucManager.IDENTITY).get_other_occupants(conversation.counterpart, conversation.account);
|
||||
Gee.List<Jid>? occupants = stream_interactor.get_module(MucManager.IDENTITY).get_other_members(conversation.counterpart, conversation.account);
|
||||
Gee.List<string> filtered_occupants = new ArrayList<string>();
|
||||
if (occupants != null) {
|
||||
foreach (Jid jid in occupants) {
|
||||
|
|
|
@ -17,7 +17,9 @@ public class List : Box {
|
|||
|
||||
private Conversation conversation;
|
||||
private string[]? filter_values;
|
||||
private HashMap<Jid, Widget> rows = new HashMap<Jid, Widget>(Jid.hash_func, Jid.equals_func);
|
||||
|
||||
// List of all chat members with corresponding widgets
|
||||
private HashMap<string, Widget> rows = new HashMap<string, Widget>();
|
||||
public HashMap<Widget, ListRow> row_wrappers = new HashMap<Widget, ListRow>();
|
||||
|
||||
public List(StreamInteractor stream_interactor, Conversation conversation) {
|
||||
|
@ -27,18 +29,46 @@ public class List : Box {
|
|||
list_box.set_filter_func(filter);
|
||||
search_entry.search_changed.connect(refilter);
|
||||
|
||||
stream_interactor.get_module(PresenceManager.IDENTITY).show_received.connect(on_show_received);
|
||||
stream_interactor.get_module(PresenceManager.IDENTITY).show_received.connect(on_received_online_presence);
|
||||
stream_interactor.get_module(PresenceManager.IDENTITY).received_offline_presence.connect(on_received_offline_presence);
|
||||
|
||||
initialize_for_conversation(conversation);
|
||||
}
|
||||
|
||||
public bool get_status(Jid jid, Account account) {
|
||||
Gee.List<Jid>? full_jids = stream_interactor.get_module(PresenceManager.IDENTITY).get_full_jids(jid, account);
|
||||
|
||||
debug("Get presence status for %s", jid.bare_jid.to_string());
|
||||
string presence_str = null;
|
||||
if (full_jids != null){
|
||||
// Iterate over all connected devices
|
||||
for (int i = 0; i < full_jids.size; i++) {
|
||||
Jid full_jid = full_jids[i];
|
||||
presence_str = stream_interactor.get_module(PresenceManager.IDENTITY).get_last_show(full_jid, account);
|
||||
switch(presence_str) {
|
||||
case "online": {
|
||||
// Return online status if user is online on at least one device
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void initialize_for_conversation(Conversation conversation) {
|
||||
this.conversation = conversation;
|
||||
Gee.List<Jid>? occupants = stream_interactor.get_module(MucManager.IDENTITY).get_occupants(conversation.counterpart, conversation.account);
|
||||
if (occupants != null) {
|
||||
foreach (Jid occupant in occupants) {
|
||||
add_occupant(occupant);
|
||||
|
||||
var identity = stream_interactor.get_module(MucManager.IDENTITY);
|
||||
Gee.List<Jid>? members = identity.get_all_members(conversation.counterpart, conversation.account);
|
||||
if (members != null) {
|
||||
// Add all members and their status to the list
|
||||
foreach (Jid member in members) {
|
||||
bool online = get_status(member, conversation.account);
|
||||
add_member(member, online);
|
||||
}
|
||||
}
|
||||
list_box.invalidate_filter();
|
||||
|
@ -53,34 +83,75 @@ public class List : Box {
|
|||
list_box.invalidate_filter();
|
||||
}
|
||||
|
||||
public void add_occupant(Jid jid) {
|
||||
var row_wrapper = new ListRow(stream_interactor, conversation, jid);
|
||||
var widget = row_wrapper.get_widget();
|
||||
public void add_member(Jid jid, bool online) {
|
||||
// HACK:
|
||||
// Here we track members based on their names (not jids)
|
||||
// Sometimes the same member can be referenced with different jids, for example:
|
||||
// When initializing the conversation (see initialize_for_conversation function),
|
||||
// we reference members like this:
|
||||
// test_user@test_domain (using a local part, without a resource)
|
||||
// However when updating status, we get the jid in the following format
|
||||
// local_domain@test_domain/test_user (using a resource)
|
||||
string member_name = null;
|
||||
if (jid.resourcepart != null) {
|
||||
member_name = jid.resourcepart;
|
||||
} else {
|
||||
member_name = jid.localpart;
|
||||
}
|
||||
|
||||
row_wrappers[widget] = row_wrapper;
|
||||
rows[jid] = widget;
|
||||
list_box.append(widget);
|
||||
}
|
||||
if (member_name == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
public void remove_occupant(Jid jid) {
|
||||
list_box.remove(rows[jid]);
|
||||
rows.unset(jid);
|
||||
if (!rows.has_key(member_name)) {
|
||||
debug("adding new member %s", jid.to_string());
|
||||
debug("local %s", jid.localpart);
|
||||
debug("domain %s", jid.domainpart);
|
||||
debug("resource %s", jid.resourcepart);
|
||||
|
||||
var row_wrapper = new ListRow(stream_interactor, conversation, jid);
|
||||
var widget = row_wrapper.get_widget();
|
||||
|
||||
if (online) {
|
||||
row_wrapper.set_online();
|
||||
} else {
|
||||
row_wrapper.set_offline();
|
||||
}
|
||||
|
||||
row_wrappers[widget] = row_wrapper;
|
||||
rows[member_name] = widget;
|
||||
list_box.append(widget);
|
||||
}
|
||||
}
|
||||
|
||||
private void on_received_offline_presence(Jid jid, Account account) {
|
||||
if (conversation != null && conversation.counterpart.equals_bare(jid) && jid.is_full()) {
|
||||
if (rows.has_key(jid)) {
|
||||
remove_occupant(jid);
|
||||
var member_name = jid.resourcepart;
|
||||
if (member_name == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (rows.has_key(member_name)) {
|
||||
row_wrappers[rows[member_name]].set_offline();
|
||||
debug("%s is now offline", jid.to_string());
|
||||
}
|
||||
list_box.invalidate_filter();
|
||||
}
|
||||
}
|
||||
|
||||
private void on_show_received(Jid jid, Account account) {
|
||||
private void on_received_online_presence(Jid jid, Account account) {
|
||||
if (conversation != null && conversation.counterpart.equals_bare(jid) && jid.is_full()) {
|
||||
if (!rows.has_key(jid)) {
|
||||
add_occupant(jid);
|
||||
var member_name = jid.resourcepart;
|
||||
if (member_name == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rows.has_key(member_name)) {
|
||||
add_member(jid, true);
|
||||
}
|
||||
|
||||
row_wrappers[rows[member_name]].set_online();
|
||||
debug("%s is now online", jid.to_string());
|
||||
list_box.invalidate_filter();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,9 @@ public class ListRow : Object {
|
|||
private AvatarPicture picture;
|
||||
public Label name_label;
|
||||
|
||||
// TODO: use something more visual for status
|
||||
public Label status;
|
||||
|
||||
public Conversation? conversation;
|
||||
public Jid? jid;
|
||||
|
||||
|
@ -19,6 +22,8 @@ public class ListRow : Object {
|
|||
main_grid = (Grid) builder.get_object("main_grid");
|
||||
picture = (AvatarPicture) builder.get_object("picture");
|
||||
name_label = (Label) builder.get_object("name_label");
|
||||
status = (Label) builder.get_object("status_label");
|
||||
status.label = "(unknown)";
|
||||
}
|
||||
|
||||
public ListRow(StreamInteractor stream_interactor, Conversation conversation, Jid jid) {
|
||||
|
@ -37,6 +42,14 @@ public class ListRow : Object {
|
|||
public Widget get_widget() {
|
||||
return main_grid;
|
||||
}
|
||||
|
||||
public void set_online() {
|
||||
status.label = ("");
|
||||
}
|
||||
|
||||
public void set_offline() {
|
||||
status.label = ("(offline)");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -154,7 +154,7 @@ public class BadMessagesWidget : Box {
|
|||
} else if (conversation.type_ == Conversation.Type.GROUPCHAT) {
|
||||
who = jid.to_string();
|
||||
// `jid` is a real JID. In MUCs, try to show nicks instead (given that the JID is currently online)
|
||||
var occupants = plugin.app.stream_interactor.get_module(MucManager.IDENTITY).get_occupants(conversation.counterpart, conversation.account);
|
||||
var occupants = plugin.app.stream_interactor.get_module(MucManager.IDENTITY).get_members(conversation.counterpart, conversation.account);
|
||||
if (occupants == null) return;
|
||||
foreach (Jid occupant in occupants) {
|
||||
if (jid.equals_bare(plugin.app.stream_interactor.get_module(MucManager.IDENTITY).get_real_jid(occupant, conversation.account))) {
|
||||
|
|
|
@ -53,7 +53,7 @@ private class EncryptionListEntry : Plugins.EncryptionListEntry, Object {
|
|||
}
|
||||
} else if (conversation.type_ == Conversation.Type.GROUPCHAT) {
|
||||
Gee.List<Jid> muc_jids = new Gee.ArrayList<Jid>();
|
||||
Gee.List<Jid>? occupants = stream_interactor.get_module(MucManager.IDENTITY).get_occupants(conversation.counterpart, conversation.account);
|
||||
Gee.List<Jid>? occupants = stream_interactor.get_module(MucManager.IDENTITY).get_members(conversation.counterpart, conversation.account);
|
||||
if (occupants != null) muc_jids.add_all(occupants);
|
||||
Gee.List<Jid>? offline_members = stream_interactor.get_module(MucManager.IDENTITY).get_offline_members(conversation.counterpart, conversation.account);
|
||||
if (offline_members != null) muc_jids.add_all(offline_members);
|
||||
|
|
|
@ -36,7 +36,7 @@ public class Manager : StreamInteractionModule, Object {
|
|||
keys.add(db.get_account_key(conversation.account));
|
||||
if (conversation.type_ == Conversation.Type.GROUPCHAT) {
|
||||
Gee.List<Jid> muc_jids = new Gee.ArrayList<Jid>();
|
||||
Gee.List<Jid>? occupants = stream_interactor.get_module(MucManager.IDENTITY).get_occupants(conversation.counterpart, conversation.account);
|
||||
Gee.List<Jid>? occupants = stream_interactor.get_module(MucManager.IDENTITY).get_members(conversation.counterpart, conversation.account);
|
||||
if (occupants != null) muc_jids.add_all(occupants);
|
||||
Gee.List<Jid>? offline_members = stream_interactor.get_module(MucManager.IDENTITY).get_offline_members(conversation.counterpart, conversation.account);
|
||||
if (occupants != null) muc_jids.add_all(offline_members);
|
||||
|
|
Loading…
Reference in a new issue