From 5ba95ef6b7be3bc7f3a8333f9db78577e1c259bc Mon Sep 17 00:00:00 2001 From: fiaxh Date: Tue, 30 May 2017 22:47:16 +0200 Subject: Conversation details dialog --- main/src/ui/contact_details/dialog.vala | 120 +++++++++++++++++++ .../contact_details/muc_config_form_provider.vala | 131 +++++++++++++++++++++ main/src/ui/contact_details/settings_provider.vala | 102 ++++++++++++++++ 3 files changed, 353 insertions(+) create mode 100644 main/src/ui/contact_details/dialog.vala create mode 100644 main/src/ui/contact_details/muc_config_form_provider.vala create mode 100644 main/src/ui/contact_details/settings_provider.vala (limited to 'main/src/ui/contact_details') diff --git a/main/src/ui/contact_details/dialog.vala b/main/src/ui/contact_details/dialog.vala new file mode 100644 index 00000000..7e2f6100 --- /dev/null +++ b/main/src/ui/contact_details/dialog.vala @@ -0,0 +1,120 @@ +using Gee; +using Gtk; +using Markup; + +using Dino.Entities; + +namespace Dino.Ui.ContactDetails { + +[GtkTemplate (ui = "/org/dino-im/contact_details_dialog.ui")] +public class Dialog : Gtk.Dialog { + + [GtkChild] public Image avatar; + [GtkChild] public Label name_label; + [GtkChild] public Label jid_label; + [GtkChild] public Label account_label; + [GtkChild] public Box main_box; + + private StreamInteractor stream_interactor; + private Conversation conversation; + + private Plugins.ContactDetails contact_details = new Plugins.ContactDetails(); + private HashMap categories = new HashMap(); + private Util.LabelHybridGroup hybrid_group = new Util.LabelHybridGroup(); + + public Dialog(StreamInteractor stream_interactor, Conversation conversation) { + Object(use_header_bar : 1); + this.stream_interactor = stream_interactor; + this.conversation = conversation; + + title = conversation.type_ == Conversation.Type.GROUPCHAT ? _("Conference Details") : _("Contact Details"); + (get_header_bar() as HeaderBar).set_subtitle(Util.get_conversation_display_name(stream_interactor, conversation)); + + name_label.label = Util.get_conversation_display_name(stream_interactor, conversation); + jid_label.label = conversation.counterpart.to_string(); + account_label.label = "via " + conversation.account.bare_jid.to_string(); + Util.image_set_from_scaled_pixbuf(avatar, (new AvatarGenerator(50, 50, avatar.scale_factor)).draw_conversation(stream_interactor, conversation)); + + contact_details.add.connect(add_entry); + + Application app = GLib.Application.get_default() as Application; + app.plugin_registry.register_contact_details_entry(new SettingsProvider(stream_interactor)); + app.plugin_registry.register_contact_details_entry(new MucConfigFormProvider(stream_interactor)); + + foreach (Plugins.ContactDetailsProvider provider in app.plugin_registry.contact_details_entries) { + provider.populate(conversation, contact_details); + } + + destroy.connect(() => { + contact_details.save(); + }); + } + + public void add_entry(string category, string label, string? description, Widget w) { + add_category(category); + + ListBoxRow list_row = new ListBoxRow() { activatable=false, visible=true }; + Box row = new Box(Orientation.HORIZONTAL, 20) { margin_left=15, margin_right=15, margin_top=3, margin_bottom=3, visible=true }; + list_row.add(row); + Label label_label = new Label(label) { xalign=0, yalign=0.5f, hexpand=true, visible=true }; + if (description != null && description != "") { + Box box = new Box(Orientation.VERTICAL, 0) { visible=true }; + box.add(label_label); + Label desc_label = new Label("") { xalign=0, yalign=0.5f, hexpand=true, visible=true }; + desc_label.set_markup("%s".printf(Markup.escape_text(description))); + desc_label.get_style_context().add_class("dim-label"); + box.add(desc_label); + row.add(box); + } else { + row.add(label_label); + } + + Widget widget = w; + if (widget.get_type().is_a(typeof(Entry))) { + Util.EntryLabelHybrid hybrid = new Util.EntryLabelHybrid(widget as Entry) { xalign=1, visible=true }; + hybrid_group.add(hybrid); + widget = hybrid; + } else if (widget.get_type().is_a(typeof(ComboBoxText))) { + Util.ComboBoxTextLabelHybrid hybrid = new Util.ComboBoxTextLabelHybrid(widget as ComboBoxText) { xalign=1, visible=true }; + hybrid_group.add(hybrid); + widget = hybrid; + } + widget.margin_bottom = 5; + widget.margin_top = 5; + + + row.add(widget); + categories[category].add(list_row); + + Idle.add(() => { + int pref_height, pref_width; + get_content_area().get_preferred_height(null, out pref_height); + get_preferred_width(out pref_width, null); + resize(pref_width, int.min(500, pref_height)); + return false; + }); + } + + public void add_category(string category) { + if (!categories.has_key(category)) { + ListBox list_box = new ListBox() { selection_mode=SelectionMode.NONE, visible=true }; + categories[category] = list_box; + list_box.set_header_func((row, before_row) => { + if (row.get_header() == null && before_row != null) { + row.set_header(new Separator(Orientation.HORIZONTAL)); + } + }); + Box box = new Box(Orientation.VERTICAL, 5) { margin_top=12, margin_bottom=12, visible=true }; + Label category_label = new Label("") { xalign=0, visible=true }; + category_label.set_markup(@"$(Markup.escape_text(category))"); + box.add(category_label); + Frame frame = new Frame(null) { visible=true }; + frame.add(list_box); + box.add(frame); + main_box.add(box); + } + } +} + +} + diff --git a/main/src/ui/contact_details/muc_config_form_provider.vala b/main/src/ui/contact_details/muc_config_form_provider.vala new file mode 100644 index 00000000..44659888 --- /dev/null +++ b/main/src/ui/contact_details/muc_config_form_provider.vala @@ -0,0 +1,131 @@ +using Gee; +using Gtk; + +using Dino.Entities; +using Xmpp.Xep; + +namespace Dino.Ui.ContactDetails { + +public class MucConfigFormProvider : Plugins.ContactDetailsProvider { + public override string id { get { return "muc_config_form"; } } + private StreamInteractor stream_interactor; + + public MucConfigFormProvider(StreamInteractor stream_interactor) { + this.stream_interactor = stream_interactor; + } + + public override void populate(Conversation conversation, Plugins.ContactDetails contact_details) { + if (conversation.type_ == Conversation.Type.GROUPCHAT) { + Xmpp.Core.XmppStream? stream = stream_interactor.get_stream(conversation.account); + if (stream == null) return; + stream_interactor.get_module(MucManager.IDENTITY).get_config_form(conversation.account, conversation.counterpart, (jid, data_form, store) => { + Plugins.ContactDetails contact_details_ = store as Plugins.ContactDetails; + contact_details_.save.connect(() => { + data_form.submit(); + }); + Idle.add(() => { + for (int i = 0; i < data_form.fields.size; i++) { + DataForms.DataForm.Field field = data_form.fields[i]; + add_field(field, contact_details_); + } + return false; + }); + }, contact_details); + } + } + + public static void add_field(DataForms.DataForm.Field field, Plugins.ContactDetails contact_details) { + string label = field.label ?? ""; + string? desc = null; + switch (field.var) { + case "muc#roomconfig_roomname": + label = _("Name"); + desc = _("Name of the room"); + break; + case "muc#roomconfig_roomdesc": + label = _("Description"); + desc = _("Description of the room"); + break; + case "muc#roomconfig_persistentroom": + label = _("Persistent"); + break; + case "muc#roomconfig_publicroom": + label = _("Publicly searchable"); + break; + case "muc#roomconfig_changesubject": + label = _("Occupants may change subject"); + break; + case "muc#roomconfig_whois": + label = _("Discover real jids"); + desc = "Who may discover real jids"; + break; + case "muc#roomconfig_roomsecret": + label = _("Password"); + desc = _("Passwort required to enter the room. Leave empty for none."); + break; + case "muc#roomconfig_moderatedroom": + label = _("Moderated"); + break; + case "muc#roomconfig_membersonly": + label = _("Members only"); + desc = _("Only members may enter the room"); + break; + case "muc#roomconfig_historylength": + label = _("Message History"); + desc = _("Maximum number of history messages returned by the room"); + break; + } + + Widget? widget = get_widget(field); + if (widget != null) contact_details.add(_("Room Configuration"), label, desc, widget); + } + + private static Widget? get_widget(DataForms.DataForm.Field field) { + switch (field.type_) { + case DataForms.DataForm.Type.BOOLEAN: + DataForms.DataForm.BooleanField boolean_field = field as DataForms.DataForm.BooleanField; + Switch sw = new Switch() { active=boolean_field.value, valign=Align.CENTER, visible=true }; + sw.state_set.connect((state) => { + boolean_field.value = state; + return false; + }); + return sw; + case DataForms.DataForm.Type.JID_MULTI: + return null; + case DataForms.DataForm.Type.LIST_SINGLE: + DataForms.DataForm.ListSingleField list_single_field = field as DataForms.DataForm.ListSingleField; + ComboBoxText combobox = new ComboBoxText() { valign=Align.CENTER, visible=true }; + for (int i = 0; i < list_single_field.options.size; i++) { + DataForms.DataForm.Option option = list_single_field.options[i]; + combobox.append(option.value, option.label); + if (option.value == list_single_field.value) combobox.active = i; + } + combobox.changed.connect(() => { + list_single_field.value = combobox.get_active_id(); + }); + return combobox; + case DataForms.DataForm.Type.LIST_MULTI: + return null; + case DataForms.DataForm.Type.TEXT_PRIVATE: + DataForms.DataForm.TextPrivateField text_private_field = field as DataForms.DataForm.TextPrivateField; + Entry entry = new Entry() { text=text_private_field.value ?? "", valign=Align.CENTER, visible=true, visibility=false }; + entry.key_release_event.connect(() => { + text_private_field.value = entry.text; + return false; + }); + return entry; + case DataForms.DataForm.Type.TEXT_SINGLE: + DataForms.DataForm.TextSingleField text_single_field = field as DataForms.DataForm.TextSingleField; + Entry entry = new Entry() { text=text_single_field.value ?? "", valign=Align.CENTER, visible=true }; + entry.key_release_event.connect(() => { + text_single_field.value = entry.text; + return false; + }); + return entry; + default: + return null; + } + } +} + +} \ No newline at end of file diff --git a/main/src/ui/contact_details/settings_provider.vala b/main/src/ui/contact_details/settings_provider.vala new file mode 100644 index 00000000..fd49f9a1 --- /dev/null +++ b/main/src/ui/contact_details/settings_provider.vala @@ -0,0 +1,102 @@ +using Gtk; + +using Dino.Entities; + +namespace Dino.Ui.ContactDetails { + +public class SettingsProvider : Plugins.ContactDetailsProvider { + public override string id { get { return "chat_settings"; } } + + private StreamInteractor stream_interactor; + + public SettingsProvider(StreamInteractor stream_interactor) { + this.stream_interactor = stream_interactor; + } + + public override void populate(Conversation conversation, Plugins.ContactDetails contact_details) { + if (conversation.type_ == Conversation.Type.CHAT) { + ComboBoxText[] comboboxes = new ComboBoxText[2]; + for (int i = 0; i < 3; i++) { + comboboxes[i] = new ComboBoxText() { visible=true }; + comboboxes[i].append("default", _("Default")); + comboboxes[i].append("on", _("On")); + comboboxes[i].append("off", _("Off")); + } + + contact_details.add(_("Settings"), _("Send typing notifications"), "", comboboxes[0]); + comboboxes[0].active_id = get_setting_id(conversation.get_send_typing_setting()); + comboboxes[0].changed.connect(() => { print("changed!\n"); conversation.send_typing = get_setting(comboboxes[0].active_id); } ); + + contact_details.add(_("Settings"), _("Send message marker"), "", comboboxes[1]); + comboboxes[1].active_id = get_setting_id(conversation.get_send_marker_setting()); + comboboxes[1].changed.connect(() => { conversation.send_marker = get_setting(comboboxes[1].active_id); } ); + + contact_details.add(_("Settings"), _("Notifications"), "", comboboxes[2]); + comboboxes[2].active_id = get_notify_setting_id(conversation.get_notification_setting(stream_interactor)); + comboboxes[2].changed.connect(() => { conversation.notify_setting = get_notify_setting(comboboxes[2].active_id); } ); + } else if (conversation.type_ == Conversation.Type.GROUPCHAT) { + ComboBoxText combobox = new ComboBoxText() { visible=true }; + combobox.append("default", _("Default")); + combobox.append("hightlight", _("Only when mentioned")); + combobox.append("on", _("On")); + combobox.append("off", _("Off")); + contact_details.add(_("Local Settings"), _("Notifications"), "", combobox); + combobox.active_id = get_notify_setting_id(conversation.get_notification_setting(stream_interactor)); + combobox.changed.connect(() => { conversation.notify_setting = get_notify_setting(combobox.active_id); } ); + } + } + + public Conversation.Setting get_setting(string id) { + switch (id) { + case "default": + return Conversation.Setting.DEFAULT; + case "on": + return Conversation.Setting.ON; + case "off": + return Conversation.Setting.OFF; + } + assert_not_reached(); + } + + public Conversation.NotifySetting get_notify_setting(string id) { + switch (id) { + case "default": + return Conversation.NotifySetting.DEFAULT; + case "on": + return Conversation.NotifySetting.ON; + case "off": + return Conversation.NotifySetting.OFF; + case "highlight": + return Conversation.NotifySetting.HIGHLIGHT; + } + assert_not_reached(); + } + + public string get_setting_id(Conversation.Setting setting) { + switch (setting) { + case Conversation.Setting.DEFAULT: + return "default"; + case Conversation.Setting.ON: + return "on"; + case Conversation.Setting.OFF: + return "off"; + } + assert_not_reached(); + } + + public string get_notify_setting_id(Conversation.NotifySetting setting) { + switch (setting) { + case Conversation.NotifySetting.DEFAULT: + return "default"; + case Conversation.NotifySetting.ON: + return "on"; + case Conversation.NotifySetting.OFF: + return "off"; + case Conversation.NotifySetting.HIGHLIGHT: + return "hightlight"; + } + assert_not_reached(); + } +} + +} \ No newline at end of file -- cgit v1.2.3-70-g09d2