diff options
author | fiaxh <git@lightrise.org> | 2024-12-24 16:02:13 +0100 |
---|---|---|
committer | fiaxh <git@lightrise.org> | 2025-01-12 19:35:58 +0100 |
commit | 5ee322cbd987d36497522b82b876659e1d19da43 (patch) | |
tree | c22d0bdbf92b30207b64ec74e925af4263ce91fc /main/src | |
parent | d78ec0562288fa4ed7d414d2269c00b7b8c2c588 (diff) | |
download | dino-5ee322cbd987d36497522b82b876659e1d19da43.tar.gz dino-5ee322cbd987d36497522b82b876659e1d19da43.zip |
Contact details dialog: Add encryption tab
Diffstat (limited to 'main/src')
-rw-r--r-- | main/src/ui/application.vala | 14 | ||||
-rw-r--r-- | main/src/ui/contact_details/permissions_provider.vala | 5 | ||||
-rw-r--r-- | main/src/ui/contact_details/settings_provider.vala | 5 | ||||
-rw-r--r-- | main/src/ui/conversation_details.vala | 26 | ||||
-rw-r--r-- | main/src/ui/conversation_titlebar/menu_entry.vala | 3 | ||||
-rw-r--r-- | main/src/ui/util/preference_group.vala | 154 | ||||
-rw-r--r-- | main/src/view_model/conversation_details.vala | 83 | ||||
-rw-r--r-- | main/src/windows/conversation_details.vala | 67 |
8 files changed, 269 insertions, 88 deletions
diff --git a/main/src/ui/application.vala b/main/src/ui/application.vala index 3c816a77..796146f8 100644 --- a/main/src/ui/application.vala +++ b/main/src/ui/application.vala @@ -145,6 +145,20 @@ public class Dino.Ui.Application : Adw.Application, Dino.Application { }); add_action(open_conversation_action); + SimpleAction open_conversation_details_action = new SimpleAction("open-conversation-details", new VariantType.tuple(new VariantType[]{VariantType.INT32, VariantType.STRING})); + open_conversation_details_action.activate.connect((variant) => { + int conversation_id = variant.get_child_value(0).get_int32(); + Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation_by_id(conversation_id); + if (conversation == null) return; + + string stack_value = variant.get_child_value(1).get_string(); + + var conversation_details = ConversationDetails.setup_dialog(conversation, stream_interactor, window); + conversation_details.stack.visible_child_name = stack_value; + conversation_details.present(); + }); + add_action(open_conversation_details_action); + SimpleAction deny_subscription_action = new SimpleAction("deny-subscription", VariantType.INT32); deny_subscription_action.activate.connect((variant) => { Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation_by_id(variant.get_int32()); diff --git a/main/src/ui/contact_details/permissions_provider.vala b/main/src/ui/contact_details/permissions_provider.vala index c7ea4a1c..a0ca4d13 100644 --- a/main/src/ui/contact_details/permissions_provider.vala +++ b/main/src/ui/contact_details/permissions_provider.vala @@ -6,6 +6,7 @@ namespace Dino.Ui.ContactDetails { public class PermissionsProvider : Plugins.ContactDetailsProvider, Object { public string id { get { return "permissions"; } } + public string tab { get { return "about"; } } private StreamInteractor stream_interactor; @@ -25,6 +26,10 @@ public class PermissionsProvider : Plugins.ContactDetailsProvider, Object { contact_details.add("Permissions", _("Request permission to send messages"), "", voice_request); } } + + public Object? get_widget(Conversation conversation) { + return null; + } } } diff --git a/main/src/ui/contact_details/settings_provider.vala b/main/src/ui/contact_details/settings_provider.vala index 6a680f64..c6b87652 100644 --- a/main/src/ui/contact_details/settings_provider.vala +++ b/main/src/ui/contact_details/settings_provider.vala @@ -6,6 +6,7 @@ namespace Dino.Ui.ContactDetails { public class SettingsProvider : Plugins.ContactDetailsProvider, Object { public string id { get { return "chat_settings"; } } + public string tab { get { return "about"; } } private StreamInteractor stream_interactor; @@ -69,6 +70,10 @@ public class SettingsProvider : Plugins.ContactDetailsProvider, Object { combobox.append("off", _("Off")); return combobox; } + + public Object? get_widget(Conversation conversation) { + return null; + } } } diff --git a/main/src/ui/conversation_details.vala b/main/src/ui/conversation_details.vala index 4c6a0481..4b8a53b3 100644 --- a/main/src/ui/conversation_details.vala +++ b/main/src/ui/conversation_details.vala @@ -1,3 +1,4 @@ +using Dino; using Dino.Entities; using Xmpp; using Xmpp.Xep; @@ -24,6 +25,17 @@ namespace Dino.Ui.ConversationDetails { public void bind_dialog(Model.ConversationDetails model, ViewModel.ConversationDetails view_model, StreamInteractor stream_interactor) { view_model.avatar = new ViewModel.CompatAvatarPictureModel(stream_interactor).set_conversation(model.conversation); view_model.show_blocked = model.conversation.type_ == Conversation.Type.CHAT && stream_interactor.get_module(BlockingManager.IDENTITY).is_supported(model.conversation.account); + view_model.members_sorted.set_model(model.members); + view_model.members.set_map_func((item) => { + var conference_member = (Ui.Model.ConferenceMember) item; + Jid? nick_jid = stream_interactor.get_module(MucManager.IDENTITY).get_occupant_jid(model.conversation.account, model.conversation.counterpart, conference_member.jid); + return new Ui.ViewModel.ConferenceMemberListRow() { + avatar = new ViewModel.CompatAvatarPictureModel(stream_interactor).add_participant(model.conversation, conference_member.jid), + name = nick_jid != null ? nick_jid.resourcepart : conference_member.jid.localpart, + jid = conference_member.jid.to_string(), + affiliation = conference_member.affiliation + }; + }); if (model.domain_blocked) { view_model.blocked = DOMAIN; @@ -123,10 +135,11 @@ namespace Dino.Ui.ConversationDetails { }); } - public Window setup_dialog(Conversation conversation, StreamInteractor stream_interactor, Window parent) { + public Dialog setup_dialog(Conversation conversation, StreamInteractor stream_interactor, Window parent) { var dialog = new Dialog() { transient_for = parent }; var model = new Model.ConversationDetails(); - populate_dialog(model, conversation, stream_interactor); + model.populate(stream_interactor, conversation); +// populate_dialog(model, conversation, stream_interactor); bind_dialog(model, dialog.model, stream_interactor); dialog.model.about_rows.append(new ViewModel.PreferencesRow.Text() { @@ -171,6 +184,10 @@ namespace Dino.Ui.ConversationDetails { app.plugin_registry.register_contact_details_entry(new ContactDetails.PermissionsProvider(stream_interactor)); foreach (Plugins.ContactDetailsProvider provider in app.plugin_registry.contact_details_entries) { + var preferences_group = (Adw.PreferencesGroup) provider.get_widget(conversation); + if (preferences_group != null) { + dialog.add_encryption_tab_element((Adw.PreferencesGroup) provider.get_widget(conversation)); + } provider.populate(conversation, contact_details, Plugins.WidgetType.GTK4); } @@ -195,14 +212,13 @@ namespace Dino.Ui.ConversationDetails { }; switch (category) { - case "Encryption": - dialog.model.encryption_rows.append(view_model); - break; case "Permissions": case "Local Settings": case "Settings": dialog.model.settings_rows.append(view_model); break; + default: + break; } } } diff --git a/main/src/ui/conversation_titlebar/menu_entry.vala b/main/src/ui/conversation_titlebar/menu_entry.vala index 8a3d525f..7a6688ae 100644 --- a/main/src/ui/conversation_titlebar/menu_entry.vala +++ b/main/src/ui/conversation_titlebar/menu_entry.vala @@ -25,7 +25,8 @@ class MenuEntry : Plugins.ConversationTitlebarEntry, Object { SimpleActionGroup action_group = new SimpleActionGroup(); SimpleAction details_action = new SimpleAction("details", null); details_action.activate.connect((parameter) => { - open_conversation_details(); + var variant = new Variant.tuple(new Variant[] {new Variant.int32(conversation.id), new Variant.string("about")}); + GLib.Application.get_default().activate_action("open-conversation-details", variant); }); action_group.insert(details_action); SimpleAction close_action = new SimpleAction("close", null); diff --git a/main/src/ui/util/preference_group.vala b/main/src/ui/util/preference_group.vala index 8f3a34f3..fca3d677 100644 --- a/main/src/ui/util/preference_group.vala +++ b/main/src/ui/util/preference_group.vala @@ -11,96 +11,98 @@ namespace Dino.Ui.Util { for (int preference_group_i = 0; preference_group_i < row_view_models.get_n_items(); preference_group_i++) { var preferences_row = (ViewModel.PreferencesRow.Any) row_view_models.get_item(preference_group_i); - Widget? w = null; + Widget? w = row_to_preference_row(preferences_row); + if (w == null) continue; - var entry_view_model = preferences_row as ViewModel.PreferencesRow.Entry; - if (entry_view_model != null) { - Adw.EntryRow view = new Adw.EntryRow() { title = entry_view_model.title, show_apply_button=true }; - entry_view_model.bind_property("text", view, "text", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL, (_, from, ref to) => { - var str = (string) from; - to = str ?? ""; - return true; - }); - view.apply.connect(() => { - entry_view_model.changed(); - }); - w = view; - } + preference_group.add(w); + } - var password_view_model = preferences_row as ViewModel.PreferencesRow.PrivateText; - if (password_view_model != null) { - Adw.PasswordEntryRow view = new Adw.PasswordEntryRow() { title = password_view_model.title, show_apply_button=true }; - password_view_model.bind_property("text", view, "text", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL, (_, from, ref to) => { - var str = (string) from; - to = str ?? ""; - return true; - }); - view.apply.connect(() => { - password_view_model.changed(); - }); + return preference_group; + } - w = view; - } + public Adw.PreferencesRow? row_to_preference_row(ViewModel.PreferencesRow.Any preferences_row) { + var entry_view_model = preferences_row as ViewModel.PreferencesRow.Entry; + if (entry_view_model != null) { + Adw.EntryRow view = new Adw.EntryRow() { title = entry_view_model.title, show_apply_button=true }; + entry_view_model.bind_property("text", view, "text", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL, (_, from, ref to) => { + var str = (string) from; + to = str ?? ""; + return true; + }); + view.apply.connect(() => { + entry_view_model.changed(); + }); + return view; + } + + var password_view_model = preferences_row as ViewModel.PreferencesRow.PrivateText; + if (password_view_model != null) { + Adw.PasswordEntryRow view = new Adw.PasswordEntryRow() { title = password_view_model.title, show_apply_button=true }; + password_view_model.bind_property("text", view, "text", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL, (_, from, ref to) => { + var str = (string) from; + to = str ?? ""; + return true; + }); + view.apply.connect(() => { + password_view_model.changed(); + }); + + return view; + } - var row_text = preferences_row as ViewModel.PreferencesRow.Text; - if (row_text != null) { - w = new Adw.ActionRow() { - title = row_text.title, - subtitle = row_text.text, + var row_text = preferences_row as ViewModel.PreferencesRow.Text; + if (row_text != null) { + var view = new Adw.ActionRow() { + title = row_text.title, + subtitle = row_text.text, #if Adw_1_3 - subtitle_selectable = true, + subtitle_selectable = true, #endif - }; - w.add_css_class("property"); + }; + view.add_css_class("property"); - Util.force_css(w, "row.property > box.header > box.title > .title { font-weight: 400; font-size: 9pt; opacity: 0.55; }"); - Util.force_css(w, "row.property > box.header > box.title > .subtitle { font-size: inherit; opacity: 1; }"); - } + Util.force_css(view, "row.property > box.header > box.title > .title { font-weight: 400; font-size: 9pt; opacity: 0.55; }"); + Util.force_css(view, "row.property > box.header > box.title > .subtitle { font-size: inherit; opacity: 1; }"); + return view; + } - var toggle_view_model = preferences_row as ViewModel.PreferencesRow.Toggle; - if (toggle_view_model != null) { - var view = new Adw.ActionRow() { title = toggle_view_model.title, subtitle = toggle_view_model.subtitle }; - var toggle = new Switch() { valign = Align.CENTER }; - view.activatable_widget = toggle; - view.add_suffix(toggle); - toggle_view_model.bind_property("state", toggle, "active", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL); - w = view; - } + var toggle_view_model = preferences_row as ViewModel.PreferencesRow.Toggle; + if (toggle_view_model != null) { + var view = new Adw.ActionRow() { title = toggle_view_model.title, subtitle = toggle_view_model.subtitle }; + var toggle = new Switch() { valign = Align.CENTER }; + view.activatable_widget = toggle; + view.add_suffix(toggle); + toggle_view_model.bind_property("state", toggle, "active", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL); + return view; + } - var combobox_view_model = preferences_row as ViewModel.PreferencesRow.ComboBox; - if (combobox_view_model != null) { - var string_list = new StringList(null); - foreach (string text in combobox_view_model.items) { - string_list.append(text); - } + var combobox_view_model = preferences_row as ViewModel.PreferencesRow.ComboBox; + if (combobox_view_model != null) { + var string_list = new StringList(null); + foreach (string text in combobox_view_model.items) { + string_list.append(text); + } #if Adw_1_4 - var view = new Adw.ComboRow() { title = combobox_view_model.title }; - view.model = string_list; - combobox_view_model.bind_property("active-item", view, "selected", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL); + var view = new Adw.ComboRow() { title = combobox_view_model.title }; + view.model = string_list; + combobox_view_model.bind_property("active-item", view, "selected", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL); #else - var view = new Adw.ActionRow() { title = combobox_view_model.title }; - var drop_down = new DropDown(string_list, null) { valign = Align.CENTER }; - combobox_view_model.bind_property("active-item", drop_down, "selected", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL); - view.activatable_widget = drop_down; - view.add_suffix(drop_down); + var view = new Adw.ActionRow() { title = combobox_view_model.title }; + var drop_down = new DropDown(string_list, null) { valign = Align.CENTER }; + combobox_view_model.bind_property("active-item", drop_down, "selected", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL); + view.activatable_widget = drop_down; + view.add_suffix(drop_down); #endif - w = view; - } - - var widget_view_model = preferences_row as ViewModel.PreferencesRow.WidgetDeprecated; - if (widget_view_model != null) { - var view = new Adw.ActionRow() { title = widget_view_model.title }; - view.add_suffix(widget_view_model.widget); - w = view; - } - - if (w == null) { - continue; - } + return view; + } - preference_group.add(w); + var widget_view_model = preferences_row as ViewModel.PreferencesRow.WidgetDeprecated; + if (widget_view_model != null) { + var view = new Adw.ActionRow() { title = widget_view_model.title }; + view.add_suffix(widget_view_model.widget); + return view; } - return preference_group; + return null; } }
\ No newline at end of file diff --git a/main/src/view_model/conversation_details.vala b/main/src/view_model/conversation_details.vala index 75fc9669..3641d584 100644 --- a/main/src/view_model/conversation_details.vala +++ b/main/src/view_model/conversation_details.vala @@ -39,13 +39,42 @@ public class Dino.Ui.ViewModel.ConversationDetails : Object { public bool show_blocked { get; set; } public BlockState blocked { get; set; } - public GLib.ListStore preferences_rows = new GLib.ListStore(typeof(PreferencesRow.Any)); public GLib.ListStore about_rows = new GLib.ListStore(typeof(PreferencesRow.Any)); - public GLib.ListStore encryption_rows = new GLib.ListStore(typeof(PreferencesRow.Any)); public GLib.ListStore settings_rows = new GLib.ListStore(typeof(PreferencesRow.Any)); public GLib.ListStore room_configuration_rows { get; set; } + public MapListModel members = new MapListModel(null, null); + public SortListModel members_sorted = new SortListModel(null, new MucMemberSorter()); + + construct { + members = new MapListModel(members_sorted, null); + } } +public class MucMemberSorter : Sorter { + + public override Gtk.Ordering compare(GLib.Object? item1, GLib.Object? item2) { + var member_list_row1 = (Dino.Ui.Model.ConferenceMember) item1; + var member_list_row2 = (Dino.Ui.Model.ConferenceMember) item2; + var test = new Xmpp.Xep.Muc.Affiliation[] { OWNER, ADMIN, MEMBER }; + var affiliation_ordering = new ArrayList<Xmpp.Xep.Muc.Affiliation>.wrap(test); + + var affiliation_sorting = affiliation_ordering.index_of(member_list_row1.affiliation) - affiliation_ordering.index_of(member_list_row2.affiliation); + if (affiliation_sorting == 0) { + return Ordering.from_cmpfunc(member_list_row1.name.collate(member_list_row2.name)); + } + + return Ordering.from_cmpfunc(affiliation_sorting); + } + + public override Gtk.SorterOrder get_order() { + return SorterOrder.TOTAL; + } +} + +//public class Dino.Ui.ViewModel.ConferenceDetails : Dino.Ui.ViewModel.ConversationDetails { +// public static +//} + public class Dino.Ui.Model.ConversationDetails : Object { public Conversation conversation { get; set; } public Dino.Model.ConversationDisplayName display_name { get; set; } @@ -53,4 +82,54 @@ public class Dino.Ui.Model.ConversationDetails : Object { public string? data_form_bak; public bool blocked { get; set; } public bool domain_blocked { get; set; } + + public GLib.ListStore members = new GLib.ListStore(typeof(Ui.Model.ConferenceMember)); + + public void populate(StreamInteractor stream_interactor, Conversation conversation) { + Ui.ConversationDetails.populate_dialog(this, conversation, stream_interactor); + + if (conversation.type_ == GROUPCHAT) { + Gee.List<Jid>? occupants = stream_interactor.get_module(MucManager.IDENTITY).get_offline_members(conversation.counterpart, conversation.account); + if (occupants != null) { + foreach (Jid occupant in occupants) { + var affiliation = stream_interactor.get_module(MucManager.IDENTITY).get_affiliation(conversation.counterpart, occupant, conversation.account); + members.append(new Dino.Ui.Model.ConferenceMember() { + name = occupant.to_string(), + jid = occupant, + affiliation = affiliation + }); + } + } + } + } +} + +public class Dino.Ui.Model.ConferenceMember : Object { + public string name { get; set; } + public Jid jid { get; set; } + public Xmpp.Xep.Muc.Affiliation affiliation { get; set; } } + +public class Dino.Ui.ViewModel.ConferenceMemberListRow : Object { + public ViewModel.CompatAvatarPictureModel avatar { get; set; } + public string name { get; set; } + public string jid { get; set; } + public Xmpp.Xep.Muc.Affiliation affiliation { get; set; } + public string? affiliation_str { get; set; } + + construct { + this.bind_property("affiliation", this, "affiliation-str", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL, (_, from_value, ref to_value) => { + to_value = affiliation_to_str((Xmpp.Xep.Muc.Affiliation) from_value); + return true; + }); + } + + private string? affiliation_to_str(Xmpp.Xep.Muc.Affiliation affiliation) { + switch (affiliation) { + case OWNER: return _("Owner"); + case ADMIN: return _("Admin"); + case MEMBER: return _("Member"); + default: return null; + } + } +}
\ No newline at end of file diff --git a/main/src/windows/conversation_details.vala b/main/src/windows/conversation_details.vala index c2484db8..5c0c78b3 100644 --- a/main/src/windows/conversation_details.vala +++ b/main/src/windows/conversation_details.vala @@ -8,6 +8,7 @@ namespace Dino.Ui.ConversationDetails { [GtkTemplate (ui = "/im/dino/Dino/conversation_details.ui")] public class Dialog : Adw.Window { + [GtkChild] public unowned Stack stack; [GtkChild] public unowned Box about_box; [GtkChild] public unowned Button pin_button; [GtkChild] public unowned Adw.ButtonContent pin_button_content; @@ -22,6 +23,12 @@ namespace Dino.Ui.ConversationDetails { [GtkChild] public unowned ViewModel.ConversationDetails model { get; } + public StackPage? encryption_stack_page = null; + public Box? encryption_box = null; + + public StackPage? member_stack_page = null; + public Box? member_box = null; + private SimpleAction block_action = new SimpleAction.stateful("block", VariantType.INT32, new Variant.int32(ViewModel.ConversationDetails.BlockState.UNBLOCK)); class construct { @@ -44,10 +51,12 @@ namespace Dino.Ui.ConversationDetails { model.notify["notification-is-default"].connect(update_notification_button_visibility); model.about_rows.items_changed.connect(create_preferences_rows); - model.encryption_rows.items_changed.connect(create_preferences_rows); model.settings_rows.items_changed.connect(create_preferences_rows); model.notify["room-configuration-rows"].connect(create_preferences_rows); + model.notify["members"].connect(create_members); + create_members(); + // Create block action SimpleActionGroup block_action_group = new SimpleActionGroup(); block_action = new SimpleAction.stateful("block", VariantType.INT32, new Variant.int32(0)); @@ -145,6 +154,30 @@ namespace Dino.Ui.ConversationDetails { } } + private void create_members() { + if (model.members_sorted.n_items == 0) return; + + var selection_model = new NoSelection(model.members_sorted); + var item_factory = new BuilderListItemFactory.from_resource(null, "/im/dino/Dino/muc_member_list_row.ui"); + var list_view = new ListView(selection_model, item_factory) { single_click_activate = true }; + list_view.add_css_class("card"); + list_view.activate.connect((position) => { +// var widget = (Gtk.Widget) list_view.observe_children().get_item(position); +// var name_label = widget.get_template_child(Type.OBJECT, "name-label"); +// print(widget.get_type().name()); + +// var popover = new Popover(); +// popover.parent = widget; +// popover.popup(); + + + var row_view_model = (Ui.Model.ConferenceMember) model.members_sorted.get_item(position); + print(@"$(position) $(row_view_model.name)\n"); + }); + + add_members_tab_element(list_view); + } + private void create_preferences_rows() { var widget = about_box.get_first_child(); while (widget != null) { @@ -155,9 +188,6 @@ namespace Dino.Ui.ConversationDetails { if (model.about_rows.get_n_items() > 0) { about_box.append(Util.rows_to_preference_group(model.about_rows, _("About"))); } - if (model.encryption_rows.get_n_items() > 0) { - about_box.append(Util.rows_to_preference_group(model.encryption_rows, _("Encryption"))); - } if (model.settings_rows.get_n_items() > 0) { about_box.append(Util.rows_to_preference_group(model.settings_rows, _("Settings"))); } @@ -165,5 +195,34 @@ namespace Dino.Ui.ConversationDetails { about_box.append(Util.rows_to_preference_group(model.room_configuration_rows, _("Room Configuration"))); } } + + public void add_encryption_tab_element(Adw.PreferencesGroup preferences_group) { + if (encryption_stack_page == null) { + encryption_box = new Box(Orientation.VERTICAL, 12) { margin_end = 12, margin_start = 12, margin_top = 18, margin_bottom = 40 }; + var scrolled_window = new ScrolledWindow() { vexpand = true }; + var clamp = new Adw.Clamp(); + clamp.set_child(encryption_box); + scrolled_window.set_child(clamp); + encryption_stack_page = stack.add_child(scrolled_window); + encryption_stack_page.title = _("Encryption"); + encryption_stack_page.name = "encryption"; + } + encryption_box.append(preferences_group); + } + + public void add_members_tab_element(Widget widget) { + if (member_stack_page == null) { + member_box = new Box(Orientation.VERTICAL, 12) { margin_end = 12, margin_start = 12, margin_top = 18 }; + member_stack_page = stack.add_child(member_box); + member_stack_page.title = _("Members"); + member_stack_page.name = "member"; + } + member_box.append(widget); + } + } + + [GtkTemplate (ui = "/im/dino/Dino/muc_member_list_row.ui")] + public class Dino.Ui.ConversationDetails.MemberListItem : Gtk.Widget { + } } |