From e2c34bf2235c9f85fc91de9c0f1b74858f4ef89e Mon Sep 17 00:00:00 2001 From: fiaxh Date: Sun, 24 Sep 2023 19:54:04 +0200 Subject: Rewrite contact details dialog --- main/src/ui/conversation_details.vala | 188 ++++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 main/src/ui/conversation_details.vala (limited to 'main/src/ui/conversation_details.vala') diff --git a/main/src/ui/conversation_details.vala b/main/src/ui/conversation_details.vala new file mode 100644 index 00000000..70c8ce6d --- /dev/null +++ b/main/src/ui/conversation_details.vala @@ -0,0 +1,188 @@ +using Dino.Entities; +using Xmpp; +using Xmpp.Xep; +using Gee; +using Gtk; + +namespace Dino.Ui.ConversationDetails { + + public void populate_dialog(Model.ConversationDetails model, Conversation conversation, StreamInteractor stream_interactor) { + model.conversation = conversation; + model.display_name = stream_interactor.get_module(ContactModels.IDENTITY).get_display_name_model(conversation); + model.blocked = stream_interactor.get_module(BlockingManager.IDENTITY).is_blocked(model.conversation.account, model.conversation.counterpart); + + if (conversation.type_ == Conversation.Type.GROUPCHAT) { + stream_interactor.get_module(MucManager.IDENTITY).get_config_form.begin(conversation.account, conversation.counterpart, (_, res) => { + model.data_form = stream_interactor.get_module(MucManager.IDENTITY).get_config_form.end(res); + model.data_form_bak = model.data_form.stanza_node.to_string(); + }); + } + } + + 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); + + model.display_name.bind_property("display-name", view_model, "name", BindingFlags.SYNC_CREATE); + model.conversation.bind_property("notify-setting", view_model, "notification", BindingFlags.SYNC_CREATE, (_, from, ref to) => { + switch (model.conversation.get_notification_setting(stream_interactor)) { + case Conversation.NotifySetting.ON: + to = ViewModel.ConversationDetails.NotificationSetting.ON; + break; + case Conversation.NotifySetting.OFF: + to = ViewModel.ConversationDetails.NotificationSetting.OFF; + break; + case Conversation.NotifySetting.HIGHLIGHT: + to = ViewModel.ConversationDetails.NotificationSetting.HIGHLIGHT; + break; + } + return true; + }); + model.conversation.bind_property("notify-setting", view_model, "notification-is-default", BindingFlags.SYNC_CREATE, (_, from, ref to) => { + var notify_setting = (Conversation.NotifySetting) from; + to = notify_setting == Conversation.NotifySetting.DEFAULT; + return true; + }); + model.conversation.bind_property("pinned", view_model, "pinned", BindingFlags.SYNC_CREATE, (_, from, ref to) => { + var from_int = (int) from; + to = from_int > 0; + return true; + }); + model.conversation.bind_property("type-", view_model, "notification-options", BindingFlags.SYNC_CREATE, (_, from, ref to) => { + var ty = (Conversation.Type) from; + to = ty == Conversation.Type.GROUPCHAT ? ViewModel.ConversationDetails.NotificationOptions.ON_HIGHLIGHT_OFF : ViewModel.ConversationDetails.NotificationOptions.ON_OFF; + return true; + }); + model.bind_property("blocked", view_model, "blocked", BindingFlags.SYNC_CREATE); + model.bind_property("data-form", view_model, "room-configuration-rows", BindingFlags.SYNC_CREATE, (_, from, ref to) => { + var data_form = (DataForms.DataForm) from; + if (data_form == null) return true; + var list_store = new GLib.ListStore(typeof(ViewModel.PreferencesRow.Any)); + + foreach (var field in data_form.fields) { + var field_view_model = Util.get_data_form_field_view_model(field); + if (field_view_model != null) { + list_store.append(field_view_model); + } + } + + to = list_store; + return true; + }); + + view_model.pin_changed.connect(() => { + model.conversation.pinned = model.conversation.pinned == 1 ? 0 : 1; + }); + view_model.block_changed.connect(() => { + if (view_model.blocked) { + stream_interactor.get_module(BlockingManager.IDENTITY).unblock(model.conversation.account, model.conversation.counterpart); + } else { + stream_interactor.get_module(BlockingManager.IDENTITY).block(model.conversation.account, model.conversation.counterpart); + } + view_model.blocked = !view_model.blocked; + }); + view_model.notification_changed.connect((setting) => { + switch (setting) { + case ON: + model.conversation.notify_setting = ON; + break; + case OFF: + model.conversation.notify_setting = OFF; + break; + case HIGHLIGHT: + model.conversation.notify_setting = HIGHLIGHT; + break; + case DEFAULT: + model.conversation.notify_setting = DEFAULT; + break; + } + }); + + view_model.notification_flipped.connect(() => { + model.conversation.notify_setting = view_model.notification == ON ? Conversation.NotifySetting.OFF : Conversation.NotifySetting.ON; + }); + } + + public Window 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); + bind_dialog(model, dialog.model, stream_interactor); + + dialog.model.about_rows.append(new ViewModel.PreferencesRow.Text() { + title = _("XMPP Address"), + text = conversation.counterpart.to_string() + }); + if (model.conversation.type_ == Conversation.Type.CHAT) { + var about_row = new ViewModel.PreferencesRow.Entry() { + title = _("Display name"), + text = dialog.model.name + }; + about_row.changed.connect(() => { + if (about_row.text != Util.get_conversation_display_name(stream_interactor, conversation)) { + stream_interactor.get_module(RosterManager.IDENTITY).set_jid_handle(conversation.account, conversation.counterpart, about_row.text); + } + }); + dialog.model.about_rows.append(about_row); + } + if (model.conversation.type_ == Conversation.Type.GROUPCHAT) { + var topic = stream_interactor.get_module(MucManager.IDENTITY).get_groupchat_subject(conversation.counterpart, conversation.account); + if (topic != null && topic != "") { + dialog.model.about_rows.append(new ViewModel.PreferencesRow.Text() { + title = _("Topic"), + text = Util.parse_add_markup(topic, null, true, true) + }); + } + } + dialog.close_request.connect(() => { + // Only send the config form if something was changed + if (model.data_form_bak != null && model.data_form_bak != model.data_form.stanza_node.to_string()) { + stream_interactor.get_module(MucManager.IDENTITY).set_config_form.begin(conversation.account, conversation.counterpart, model.data_form); + } + return false; + }); + + Plugins.ContactDetails contact_details = new Plugins.ContactDetails(); + contact_details.add.connect((c, l, d, wo) => { + add_entry(c, l, d, wo, dialog); + }); + Application app = GLib.Application.get_default() as Application; + app.plugin_registry.register_contact_details_entry(new ContactDetails.SettingsProvider(stream_interactor)); + app.plugin_registry.register_contact_details_entry(new ContactDetails.PermissionsProvider(stream_interactor)); + + foreach (Plugins.ContactDetailsProvider provider in app.plugin_registry.contact_details_entries) { + provider.populate(conversation, contact_details, Plugins.WidgetType.GTK4); + } + + return dialog; + } + + private void add_entry(string category, string label, string? description, Object wo, Dialog dialog) { + if (!(wo is Widget)) return; + + Widget widget = (Widget) wo; + if (widget.get_type().is_a(typeof(Entry))) { + Util.EntryLabelHybrid hybrid = new Util.EntryLabelHybrid.wrap(widget as Entry) { xalign=1 }; + widget = hybrid; + } else if (widget.get_type().is_a(typeof(ComboBoxText))) { + Util.ComboBoxTextLabelHybrid hybrid = new Util.ComboBoxTextLabelHybrid.wrap(widget as ComboBoxText) { xalign=1 }; + widget = hybrid; + } + + var view_model = new ViewModel.PreferencesRow.WidgetDeprecated() { + title = label, + widget = widget + }; + + 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; + } + } +} \ No newline at end of file -- cgit v1.2.3-54-g00ecf From 1e167eeea67f18f3d5788dc34d97d94e6f401499 Mon Sep 17 00:00:00 2001 From: fiaxh Date: Sat, 7 Oct 2023 14:29:26 +0200 Subject: Fix some compiler warnings --- libdino/src/service/avatar_manager.vala | 6 +++--- libdino/src/service/history_sync.vala | 3 --- libdino/src/service/message_processor.vala | 1 - main/src/ui/call_window/call_window.vala | 3 ++- .../ui/conversation_content_view/conversation_view.vala | 2 +- .../ui/conversation_content_view/file_image_widget.vala | 1 - main/src/ui/conversation_details.vala | 9 ++++++--- .../ui/conversation_selector/conversation_selector.vala | 1 - main/src/ui/notifier_gnotifications.vala | 2 ++ main/src/ui/occupant_menu/list.vala | 1 - main/src/ui/util/data_forms.vala | 1 - main/src/ui/util/label_hybrid.vala | 4 ---- plugins/rtp/src/video_widget.vala | 2 +- xmpp-vala/src/core/xmpp_stream.vala | 4 ++-- xmpp-vala/src/module/xep/0082_date_time_profiles.vala | 16 ++-------------- 15 files changed, 19 insertions(+), 37 deletions(-) (limited to 'main/src/ui/conversation_details.vala') diff --git a/libdino/src/service/avatar_manager.vala b/libdino/src/service/avatar_manager.vala index 1296856b..3bd38e72 100644 --- a/libdino/src/service/avatar_manager.vala +++ b/libdino/src/service/avatar_manager.vala @@ -52,7 +52,7 @@ public class AvatarManager : StreamInteractionModule, Object { if (hash == null) return null; File file = File.new_for_path(Path.build_filename(folder, hash)); if (!file.query_exists()) { - fetch_and_store_for_jid(account, jid_); + fetch_and_store_for_jid.begin(account, jid_); return null; } else { return file; @@ -169,7 +169,7 @@ public class AvatarManager : StreamInteractionModule, Object { ); foreach (var entry in get_avatar_hashes(account, Source.USER_AVATARS).entries) { - on_user_avatar_received(account, entry.key, entry.value); + on_user_avatar_received.begin(account, entry.key, entry.value); } foreach (var entry in get_avatar_hashes(account, Source.VCARD).entries) { @@ -179,7 +179,7 @@ public class AvatarManager : StreamInteractionModule, Object { continue; } - on_vcard_avatar_received(account, entry.key, entry.value); + on_vcard_avatar_received.begin(account, entry.key, entry.value); } } diff --git a/libdino/src/service/history_sync.vala b/libdino/src/service/history_sync.vala index 0c0571bb..8ab6d7bb 100644 --- a/libdino/src/service/history_sync.vala +++ b/libdino/src/service/history_sync.vala @@ -388,9 +388,6 @@ public class Dino.HistorySync { page_result = PageResult.NoMoreMessages; } - string selection = null; - string[] selection_args = {}; - string query_id = query_params.query_id; string? after_id = query_params.start_id; diff --git a/libdino/src/service/message_processor.vala b/libdino/src/service/message_processor.vala index 01687083..baab37ce 100644 --- a/libdino/src/service/message_processor.vala +++ b/libdino/src/service/message_processor.vala @@ -167,7 +167,6 @@ public class MessageProcessor : StreamInteractionModule, Object { new_message.counterpart = counterpart_override ?? (new_message.direction == Entities.Message.DIRECTION_SENT ? message.to : message.from); new_message.ourpart = new_message.direction == Entities.Message.DIRECTION_SENT ? message.from : message.to; - XmppStream? stream = stream_interactor.get_stream(account); Xmpp.MessageArchiveManagement.MessageFlag? mam_message_flag = Xmpp.MessageArchiveManagement.MessageFlag.get_flag(message); EntityInfo entity_info = stream_interactor.get_module(EntityInfo.IDENTITY); if (mam_message_flag != null && mam_message_flag.mam_id != null) { diff --git a/main/src/ui/call_window/call_window.vala b/main/src/ui/call_window/call_window.vala index 14b67449..08ea4b21 100644 --- a/main/src/ui/call_window/call_window.vala +++ b/main/src/ui/call_window/call_window.vala @@ -253,11 +253,12 @@ namespace Dino.Ui { } private bool on_get_child_position(Widget widget, out Gdk.Rectangle allocation) { + allocation = Gdk.Rectangle(); + if (widget == own_video_box) { int width = get_size(Orientation.HORIZONTAL); int height = get_size(Orientation.VERTICAL); - allocation = Gdk.Rectangle(); allocation.width = own_video_width; allocation.height = own_video_height; allocation.x = width - own_video_width - 20; diff --git a/main/src/ui/conversation_content_view/conversation_view.vala b/main/src/ui/conversation_content_view/conversation_view.vala index 4006a02f..33cb3b22 100644 --- a/main/src/ui/conversation_content_view/conversation_view.vala +++ b/main/src/ui/conversation_content_view/conversation_view.vala @@ -329,7 +329,7 @@ public class ConversationView : Widget, Plugins.ConversationItemCollection, Plug do_insert_item(item); } ContentMetaItem meta_item = content_populator.get_content_meta_item(content_item); - Widget w = insert_new(meta_item); + insert_new(meta_item); content_items.add(meta_item); meta_items.add(meta_item); diff --git a/main/src/ui/conversation_content_view/file_image_widget.vala b/main/src/ui/conversation_content_view/file_image_widget.vala index 43c3b74d..a3579185 100644 --- a/main/src/ui/conversation_content_view/file_image_widget.vala +++ b/main/src/ui/conversation_content_view/file_image_widget.vala @@ -45,7 +45,6 @@ public class FileImageWidget : Box { image.add_controller(gesture_click_controller); FileInfo file_info = file.query_info("*", FileQueryInfoFlags.NONE); - string? mime_type = file_info.get_content_type(); MenuButton button = new MenuButton(); button.icon_name = "view-more"; diff --git a/main/src/ui/conversation_details.vala b/main/src/ui/conversation_details.vala index 70c8ce6d..82d6ae54 100644 --- a/main/src/ui/conversation_details.vala +++ b/main/src/ui/conversation_details.vala @@ -26,15 +26,18 @@ namespace Dino.Ui.ConversationDetails { model.display_name.bind_property("display-name", view_model, "name", BindingFlags.SYNC_CREATE); model.conversation.bind_property("notify-setting", view_model, "notification", BindingFlags.SYNC_CREATE, (_, from, ref to) => { switch (model.conversation.get_notification_setting(stream_interactor)) { - case Conversation.NotifySetting.ON: + case ON: to = ViewModel.ConversationDetails.NotificationSetting.ON; break; - case Conversation.NotifySetting.OFF: + case OFF: to = ViewModel.ConversationDetails.NotificationSetting.OFF; break; - case Conversation.NotifySetting.HIGHLIGHT: + case HIGHLIGHT: to = ViewModel.ConversationDetails.NotificationSetting.HIGHLIGHT; break; + case DEFAULT: + // A "default" setting should have been resolved to the actual default value + assert_not_reached(); } return true; }); diff --git a/main/src/ui/conversation_selector/conversation_selector.vala b/main/src/ui/conversation_selector/conversation_selector.vala index 535a61b0..d16ef3ee 100644 --- a/main/src/ui/conversation_selector/conversation_selector.vala +++ b/main/src/ui/conversation_selector/conversation_selector.vala @@ -14,7 +14,6 @@ public class ConversationSelector : Widget { ListBox list_box = new ListBox() { hexpand=true }; private StreamInteractor stream_interactor; - private uint? drag_timeout; private HashMap rows = new HashMap(Conversation.hash_func, Conversation.equals_func); public ConversationSelector init(StreamInteractor stream_interactor) { diff --git a/main/src/ui/notifier_gnotifications.vala b/main/src/ui/notifier_gnotifications.vala index 90c8ca8c..4d36620d 100644 --- a/main/src/ui/notifier_gnotifications.vala +++ b/main/src/ui/notifier_gnotifications.vala @@ -109,6 +109,8 @@ namespace Dino.Ui { case ConnectionManager.ConnectionError.Source.TLS: notification.set_body("Invalid TLS certificate"); break; + default: + break; } GLib.Application.get_default().send_notification(account.id.to_string() + "-connection-error", notification); } diff --git a/main/src/ui/occupant_menu/list.vala b/main/src/ui/occupant_menu/list.vala index b9a4a74f..ce5a1981 100644 --- a/main/src/ui/occupant_menu/list.vala +++ b/main/src/ui/occupant_menu/list.vala @@ -153,7 +153,6 @@ public class List : Box { if (affiliation1 < affiliation2) return -1; else if (affiliation1 > affiliation2) return 1; else return row_wrapper1.name_label.label.collate(row_wrapper2.name_label.label); - return 0; } private int get_affiliation_ranking(Xmpp.Xep.Muc.Affiliation affiliation) { diff --git a/main/src/ui/util/data_forms.vala b/main/src/ui/util/data_forms.vala index d10196ab..39dce3ee 100644 --- a/main/src/ui/util/data_forms.vala +++ b/main/src/ui/util/data_forms.vala @@ -75,7 +75,6 @@ public static ViewModel.PreferencesRow.Any? get_data_form_field_view_model(DataF if (option.value == list_single_field.value) combobox_model.active_item = i; } combobox_model.bind_property("active-item", list_single_field, "value", BindingFlags.DEFAULT, (binding, from, ref to) => { - var src_field = (DataForms.DataForm.ListSingleField) binding.dup_target(); var active_item = (int) from; to = list_single_field.options[active_item].value; return true; diff --git a/main/src/ui/util/label_hybrid.vala b/main/src/ui/util/label_hybrid.vala index f426de7e..0059d2ae 100644 --- a/main/src/ui/util/label_hybrid.vala +++ b/main/src/ui/util/label_hybrid.vala @@ -97,10 +97,6 @@ public class EntryLabelHybrid : LabelHybrid { } } - private void on_focus_leave() { - show_label(); - } - private void update_label() { if (visibility) { label.label = entry.text; diff --git a/plugins/rtp/src/video_widget.vala b/plugins/rtp/src/video_widget.vala index f69a2ba7..05cc5a6c 100644 --- a/plugins/rtp/src/video_widget.vala +++ b/plugins/rtp/src/video_widget.vala @@ -16,7 +16,7 @@ public class Dino.Plugins.Rtp.Paintable : Gdk.Paintable, Object { public override Gdk.Paintable get_current_image() { if (image != null) return image; - return Gdk.Paintable.new_empty(0, 0); + return Gdk.Paintable.empty(0, 0); } public override int get_intrinsic_width() { diff --git a/xmpp-vala/src/core/xmpp_stream.vala b/xmpp-vala/src/core/xmpp_stream.vala index 42e90bf9..54433b67 100644 --- a/xmpp-vala/src/core/xmpp_stream.vala +++ b/xmpp-vala/src/core/xmpp_stream.vala @@ -30,9 +30,9 @@ public abstract class Xmpp.XmppStream : Object { this.remote_name = remote_name; } - public abstract async void connect() throws IOError; + public abstract new async void connect() throws IOError; - public abstract async void disconnect() throws IOError; + public abstract new async void disconnect() throws IOError; public abstract async StanzaNode read() throws IOError; diff --git a/xmpp-vala/src/module/xep/0082_date_time_profiles.vala b/xmpp-vala/src/module/xep/0082_date_time_profiles.vala index 32d4d3ac..8b40d3ac 100644 --- a/xmpp-vala/src/module/xep/0082_date_time_profiles.vala +++ b/xmpp-vala/src/module/xep/0082_date_time_profiles.vala @@ -1,23 +1,11 @@ namespace Xmpp.Xep.DateTimeProfiles { public DateTime? parse_string(string time_string) { - // TODO with glib >= 2.56 - // return new DateTime.from_iso8601(time_string, null); - - TimeVal time_val = TimeVal(); - if (time_val.from_iso8601(time_string)) { - return new DateTime.from_unix_utc(time_val.tv_sec); - } - return null; - + return new DateTime.from_iso8601(time_string, null); } - public string to_datetime(DateTime time) { - // TODO with glib >= 2.62 - // return time.to_utc().format_iso8601().to_string(); - - return time.to_utc().format("%Y-%m-%dT%H:%M:%SZ"); + return time.to_utc().format_iso8601().to_string(); } } -- cgit v1.2.3-54-g00ecf From 3de716446819550514d50a8112f5b6dd0c662702 Mon Sep 17 00:00:00 2001 From: Miquel Lionel Date: Mon, 30 Oct 2023 21:45:25 +0100 Subject: Add which account is used in conversation details in about section --- main/src/ui/conversation_details.vala | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'main/src/ui/conversation_details.vala') diff --git a/main/src/ui/conversation_details.vala b/main/src/ui/conversation_details.vala index 82d6ae54..8a09193e 100644 --- a/main/src/ui/conversation_details.vala +++ b/main/src/ui/conversation_details.vala @@ -112,6 +112,11 @@ namespace Dino.Ui.ConversationDetails { populate_dialog(model, conversation, stream_interactor); bind_dialog(model, dialog.model, stream_interactor); + dialog.model.about_rows.append(new ViewModel.PreferencesRow.Text() { + title = _("Account used for this conversation"), + text = conversation.account.bare_jid.to_string() + }); + dialog.model.about_rows.append(new ViewModel.PreferencesRow.Text() { title = _("XMPP Address"), text = conversation.counterpart.to_string() @@ -188,4 +193,4 @@ namespace Dino.Ui.ConversationDetails { break; } } -} \ No newline at end of file +} -- cgit v1.2.3-54-g00ecf