diff --git a/libdino/src/service/conversation_manager.vala b/libdino/src/service/conversation_manager.vala index 3b48f154..18a362c6 100644 --- a/libdino/src/service/conversation_manager.vala +++ b/libdino/src/service/conversation_manager.vala @@ -62,10 +62,6 @@ public class ConversationManager : StreamInteractionModule, Object { return null; } - public Gee.List get_conversations_for_presence(Show show, Account account) { - return get_conversations(show.jid, account); - } - public Gee.List get_conversations(Jid jid, Account account) { Gee.List ret = new ArrayList(Conversation.equals_func); Conversation? bare_conversation = get_conversation(jid, account); diff --git a/libdino/src/service/muc_manager.vala b/libdino/src/service/muc_manager.vala index 15f32c44..c4941b47 100644 --- a/libdino/src/service/muc_manager.vala +++ b/libdino/src/service/muc_manager.vala @@ -100,9 +100,29 @@ public class MucManager : StreamInteractionModule, Object { if (stream != null) stream.get_module(Xep.Muc.Module.IDENTITY).change_subject(stream, jid.bare_jid, subject); } - public void change_nick(Account account, Jid jid, string new_nick) { - XmppStream? stream = stream_interactor.get_stream(account); - if (stream != null) stream.get_module(Xep.Muc.Module.IDENTITY).change_nick(stream, jid.bare_jid, new_nick); + public async void change_nick(Conversation conversation, string new_nick) { + XmppStream? stream = stream_interactor.get_stream(conversation.account); + if (stream == null) return; + + // Check if this would be a valid nick + try { + Jid jid = conversation.counterpart.with_resource(new_nick); + } catch (InvalidJidError error) { return; } + + stream.get_module(Xep.Muc.Module.IDENTITY).change_nick(stream, conversation.counterpart, new_nick); + + conversation.nickname = new_nick; + + // Update nick in bookmark + Set? conferences = yield bookmarks_provider[conversation.account].get_conferences(stream); + if (conferences == null) return; + foreach (Conference conference in conferences) { + if (conference.jid.equals(conversation.counterpart)) { + Conference new_conference = new Conference() { jid=conversation.counterpart, nick=new_nick, name=conference.name, password=conference.password, autojoin=conference.autojoin }; + bookmarks_provider[conversation.account].replace_conference.begin(stream, conversation.counterpart, new_conference); + break; + } + } } public void invite(Account account, Jid muc, Jid invitee) { @@ -403,7 +423,7 @@ public class MucManager : StreamInteractionModule, Object { foreach (Conference conference in conferences) { if (conference.jid.equals(jid)) { if (!conference.autojoin) { - Conference new_conference = new Conference() { jid=jid, nick=conference.nick, name=conference.name, password=conference.password, autojoin=true }; + Conference new_conference = new Conference() { jid=jid, nick=nick ?? conference.nick, name=conference.name, password=password ?? conference.password, autojoin=true }; bookmarks_provider[account].replace_conference.begin(stream, jid, new_conference); } return; diff --git a/libdino/src/service/presence_manager.vala b/libdino/src/service/presence_manager.vala index f494bb54..a9dc83aa 100644 --- a/libdino/src/service/presence_manager.vala +++ b/libdino/src/service/presence_manager.vala @@ -8,13 +8,12 @@ public class PresenceManager : StreamInteractionModule, Object { public static ModuleIdentity IDENTITY = new ModuleIdentity("presence_manager"); public string id { get { return IDENTITY.id; } } - public signal void show_received(Show show, Jid jid, Account account); + public signal void show_received(Jid jid, Account account); public signal void received_offline_presence(Jid jid, Account account); public signal void received_subscription_request(Jid jid, Account account); public signal void received_subscription_approval(Jid jid, Account account); private StreamInteractor stream_interactor; - private HashMap>> shows = new HashMap>>(Jid.hash_bare_func, Jid.equals_bare_func); private HashMap> resources = new HashMap>(Jid.hash_bare_func, Jid.equals_bare_func); private Gee.List subscription_requests = new ArrayList(Jid.equals_func); @@ -28,19 +27,14 @@ public class PresenceManager : StreamInteractionModule, Object { stream_interactor.account_added.connect(on_account_added); } - public Show get_last_show(Jid jid, Account account) { + public string? get_last_show(Jid jid, Account account) { XmppStream? stream = stream_interactor.get_stream(account); - if (stream != null) { - Xmpp.Presence.Stanza? presence = stream.get_flag(Presence.Flag.IDENTITY).get_presence(jid); - if (presence != null) { - return new Show(jid, presence.show, new DateTime.now_utc()); - } - } - return new Show(jid, Show.OFFLINE, new DateTime.now_utc()); - } + if (stream == null) return null; - public HashMap>? get_shows(Jid jid, Account account) { - return shows[jid]; + Xmpp.Presence.Stanza? presence = stream.get_flag(Presence.Flag.IDENTITY).get_presence(jid); + if (presence == null) return null; + + return presence.show; } public Gee.List? get_full_jids(Jid jid, Account account) { @@ -110,7 +104,7 @@ public class PresenceManager : StreamInteractionModule, Object { resources[jid].add(jid); } } - add_show(account, jid, show); + show_received(jid, account); } private void on_received_unavailable(Account account, Jid jid) { @@ -124,38 +118,5 @@ public class PresenceManager : StreamInteractionModule, Object { } received_offline_presence(jid, account); } - - private void add_show(Account account, Jid jid, string s) { - Show show = new Show(jid, s, new DateTime.now_utc()); - lock (shows) { - if (!shows.has_key(jid)) { - shows[jid] = new HashMap>(); - } - if (!shows[jid].has_key(jid)) { - shows[jid][jid] = new ArrayList(); - } - shows[jid][jid].add(show); - } - show_received(show, jid, account); - } -} - -public class Show : Object { - public const string ONLINE = Xmpp.Presence.Stanza.SHOW_ONLINE; - public const string AWAY = Xmpp.Presence.Stanza.SHOW_AWAY; - public const string CHAT = Xmpp.Presence.Stanza.SHOW_CHAT; - public const string DND = Xmpp.Presence.Stanza.SHOW_DND; - public const string XA = Xmpp.Presence.Stanza.SHOW_XA; - public const string OFFLINE = "offline"; - - public Jid jid; - public string as; - public DateTime datetime; - - public Show(Jid jid, string show, DateTime datetime) { - this.jid = jid; - this.as = show; - this.datetime = datetime; - } } } diff --git a/main/src/ui/avatar_image.vala b/main/src/ui/avatar_image.vala index ab64f5b9..b9366751 100644 --- a/main/src/ui/avatar_image.vala +++ b/main/src/ui/avatar_image.vala @@ -88,7 +88,7 @@ public class AvatarImage : Misc { } } - private void on_show_received(Show show, Jid jid, Account account) { + private void on_show_received(Jid jid, Account account) { if (!account.equals(this.account)) return; update_avatar_if_jid(jid); } diff --git a/main/src/ui/chat_input/chat_input_controller.vala b/main/src/ui/chat_input/chat_input_controller.vala index 704cec94..aca47470 100644 --- a/main/src/ui/chat_input/chat_input_controller.vala +++ b/main/src/ui/chat_input/chat_input_controller.vala @@ -127,7 +127,7 @@ public class ChatInputController : Object { } return; case "/nick": - stream_interactor.get_module(MucManager.IDENTITY).change_nick(conversation.account, conversation.counterpart, token[1]); + stream_interactor.get_module(MucManager.IDENTITY).change_nick(conversation, token[1]); return; case "/ping": Xmpp.XmppStream? stream = stream_interactor.get_stream(conversation.account); diff --git a/main/src/ui/conversation_selector/conversation_selector_row.vala b/main/src/ui/conversation_selector/conversation_selector_row.vala index 467bed70..09de3c80 100644 --- a/main/src/ui/conversation_selector/conversation_selector_row.vala +++ b/main/src/ui/conversation_selector/conversation_selector_row.vala @@ -250,7 +250,8 @@ public class ConversationSelectorRow : ListBoxRow { for (int i = 0; i < full_jids.size; i++) { Jid full_jid = full_jids[i]; - Show show = stream_interactor.get_module(PresenceManager.IDENTITY).get_last_show(full_jid, conversation.account); + string? show = stream_interactor.get_module(PresenceManager.IDENTITY).get_last_show(full_jid, conversation.account); + if (show == null) continue; Xep.ServiceDiscovery.Identity? identity = stream_interactor.get_module(EntityInfo.IDENTITY).get_identity(conversation.account, full_jid); Image image = new Image() { hexpand=false, valign=Align.START, visible=true }; @@ -260,20 +261,20 @@ public class ConversationSelectorRow : ListBoxRow { image.set_from_icon_name("dino-device-desktop-symbolic", IconSize.SMALL_TOOLBAR); } - if (show.as == Show.AWAY) { + if (show == Presence.Stanza.SHOW_AWAY) { Util.force_color(image, "#FF9800"); - } else if (show.as == Show.XA || show.as == Show.DND) { + } else if (show == Presence.Stanza.SHOW_XA || show == Presence.Stanza.SHOW_DND) { Util.force_color(image, "#FF5722"); } else { Util.force_color(image, "#4CAF50"); } string? status = null; - if (show.as == Show.AWAY) { + if (show == Presence.Stanza.SHOW_AWAY) { status = "away"; - } else if (show.as == Show.XA) { + } else if (show == Presence.Stanza.SHOW_XA) { status = "not available"; - } else if (show.as == Show.DND) { + } else if (show == Presence.Stanza.SHOW_DND) { status = "do not disturb"; } @@ -288,9 +289,7 @@ public class ConversationSelectorRow : ListBoxRow { continue; } if (status != null) { - sb.append(" ("); - sb.append(status); - sb.append(")"); + sb.append(" (").append(status).append(")"); } Label resource = new Label(sb.str) { use_markup=true, hexpand=true, xalign=0, visible=true }; diff --git a/main/src/ui/occupant_menu/list.vala b/main/src/ui/occupant_menu/list.vala index ffa98f31..960b716b 100644 --- a/main/src/ui/occupant_menu/list.vala +++ b/main/src/ui/occupant_menu/list.vala @@ -27,7 +27,7 @@ public class List : Box { search_entry.search_changed.connect(refilter); stream_interactor.get_module(PresenceManager.IDENTITY).show_received.connect(on_show_received); - stream_interactor.get_module(RosterManager.IDENTITY).updated_roster_item.connect(on_updated_roster_item); + stream_interactor.get_module(PresenceManager.IDENTITY).received_offline_presence.connect(on_received_offline_presence); initialize_for_conversation(conversation); } @@ -62,15 +62,18 @@ public class List : Box { rows.unset(jid); } - private void on_updated_roster_item(Account account, Jid jid, Xmpp.Roster.Item roster_item) { - + 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); + } + list_box.invalidate_filter(); + } } - private void on_show_received(Show show, Jid jid, Account account) { + private void on_show_received(Jid jid, Account account) { if (conversation != null && conversation.counterpart.equals_bare(jid) && jid.is_full()) { - if (show.as == Show.OFFLINE && rows.has_key(jid)) { - remove_occupant(jid); - } else if (show.as != Show.OFFLINE && !rows.has_key(jid)) { + if (!rows.has_key(jid)) { add_occupant(jid); } list_box.invalidate_filter(); diff --git a/xmpp-vala/src/module/xep/0045_muc/flag.vala b/xmpp-vala/src/module/xep/0045_muc/flag.vala index ad181922..976291b8 100644 --- a/xmpp-vala/src/module/xep/0045_muc/flag.vala +++ b/xmpp-vala/src/module/xep/0045_muc/flag.vala @@ -50,6 +50,12 @@ public class Flag : XmppStreamFlag { public string? get_muc_nick(Jid muc_jid) { return own_nicks[muc_jid.bare_jid]; } + public void set_muc_nick(Jid muc_jid) { + if (muc_jid.is_full()) { + own_nicks[muc_jid.bare_jid] = muc_jid.resourcepart; + } + } + public string? get_enter_id(Jid muc_jid) { return enter_ids[muc_jid.bare_jid]; } public bool is_muc(Jid jid) { return own_nicks[jid] != null; } @@ -98,8 +104,7 @@ public class Flag : XmppStreamFlag { enter_ids[jid.bare_jid] = presence_id; } - internal void finish_muc_enter(Jid jid, string? nick = null) { - if (nick != null) own_nicks[jid.bare_jid] = nick; + internal void finish_muc_enter(Jid jid) { enter_ids.unset(jid.bare_jid); } diff --git a/xmpp-vala/src/module/xep/0045_muc/module.vala b/xmpp-vala/src/module/xep/0045_muc/module.vala index f8845427..9734fdbc 100644 --- a/xmpp-vala/src/module/xep/0045_muc/module.vala +++ b/xmpp-vala/src/module/xep/0045_muc/module.vala @@ -337,9 +337,11 @@ public class Module : XmppStreamModule { query_affiliation.begin(stream, bare_jid, "admin"); query_affiliation.begin(stream, bare_jid, "owner"); - flag.finish_muc_enter(bare_jid, presence.from.resourcepart); + flag.finish_muc_enter(bare_jid); flag.enter_futures[bare_jid].set_value(new JoinResult() {nick=presence.from.resourcepart}); } + + flag.set_muc_nick(presence.from); } string? affiliation_str = x_node.get_deep_attribute("item", "affiliation"); Affiliation? affiliation = null;