From 01070d089dc21687f957a3aac807aa8ab83cc4f9 Mon Sep 17 00:00:00 2001 From: Xavier Del Campo Romero Date: Sat, 1 Apr 2023 02:45:50 +0200 Subject: [PATCH] Show modal dialog to select default encryption if unknown Thanks to mbeko for the UX suggestions. --- main/CMakeLists.txt | 1 + main/data/default_encryption_dialog.ui | 77 +++++++++++++++++ main/data/gresource.xml | 1 + .../ui/chat_input/chat_input_controller.vala | 2 +- main/src/ui/conversation_view_controller.vala | 85 +++++++++++++++++++ 5 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 main/data/default_encryption_dialog.ui diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 0f660898..b3ba9255 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -67,6 +67,7 @@ set(RESOURCE_LIST conversation_list_titlebar_csd.ui conversation_row.ui conversation_view.ui + default_encryption_dialog.ui file_default_widget.ui file_send_overlay.ui global_search.ui diff --git a/main/data/default_encryption_dialog.ui b/main/data/default_encryption_dialog.ui new file mode 100644 index 00000000..08a29660 --- /dev/null +++ b/main/data/default_encryption_dialog.ui @@ -0,0 +1,77 @@ + + + + + + True + True + 320 + 260 + + + + + + False + vertical + + + True + False + vertical + + + True + False + You are opening a new conversation without having set end-to-end encryption by default. + +It is strongly recommended to enable it to prevent your messages from being read by third parties. + +Please select an option to start this conversation with. Choosing one of the encryption methods will also set it as default in the global settings. + + True + + + + + OMEMO (automatic setup) + True + True + False + False + + + + + OpenPGP (external setup required) + True + True + False + False + omemo + + + + + Unencrypted + True + True + False + False + omemo + + + + + Apply + True + True + True + + + + + + + + diff --git a/main/data/gresource.xml b/main/data/gresource.xml index a2e3f047..797fb86e 100644 --- a/main/data/gresource.xml +++ b/main/data/gresource.xml @@ -16,6 +16,7 @@ conversation_list_titlebar_csd.ui conversation_row.ui conversation_view.ui + default_encryption_dialog.ui dino-conversation-list-placeholder-arrow.svg file_default_widget.ui file_send_overlay.ui diff --git a/main/src/ui/chat_input/chat_input_controller.vala b/main/src/ui/chat_input/chat_input_controller.vala index d1c42d35..fa8c08a3 100644 --- a/main/src/ui/chat_input/chat_input_controller.vala +++ b/main/src/ui/chat_input/chat_input_controller.vala @@ -103,7 +103,7 @@ public class ChatInputController : Object { private void on_encryption_changed(Encryption encryption) { reset_input_field_status(); - if (encryption == Encryption.NONE) return; + if (encryption == Encryption.NONE || encryption == Encryption.UNKNOWN) return; Application app = GLib.Application.get_default() as Application; var encryption_entry = app.plugin_registry.encryption_list_entries[encryption]; diff --git a/main/src/ui/conversation_view_controller.vala b/main/src/ui/conversation_view_controller.vala index 5b768271..51ad8daf 100644 --- a/main/src/ui/conversation_view_controller.vala +++ b/main/src/ui/conversation_view_controller.vala @@ -114,6 +114,89 @@ public class ConversationViewController : Object { ((Gtk.Window)view.get_root()).add_shortcut(shortcut); } + private void update_conversation_encryption(Conversation? conversation) { + if (conversation == null) { + return; + } + + bool visible = false; + + // FIXME duplicate logic from encryption_button.vala + switch (conversation.type_) { + case Conversation.Type.CHAT: + visible = true; + break; + case Conversation.Type.GROUPCHAT_PM: + visible = false; + break; + case Conversation.Type.GROUPCHAT: + visible = stream_interactor.get_module(MucManager.IDENTITY).is_private_room(conversation.account, conversation.counterpart); + break; + } + + if (visible && conversation.encryption == UNKNOWN) { + Dino.Entities.Settings settings = Dino.Application.get_default().settings; + + if (settings.default_encryption == UNKNOWN) { + var selection_dialog_builder = new Builder.from_resource("/im/dino/Dino/default_encryption_dialog.ui"); + var selection_dialog = selection_dialog_builder.get_object("dialog") as Dialog; + var accept_button = selection_dialog_builder.get_object("accept_button") as Button; + var omemo_radio = selection_dialog_builder.get_object("omemo") as CheckButton; + var openpgp_radio = selection_dialog_builder.get_object("openpgp") as CheckButton; + var none_radio = selection_dialog_builder.get_object("none") as CheckButton; + Encryption selected_default = UNKNOWN; + + accept_button.sensitive = false; + + omemo_radio.toggled.connect(() => { + accept_button.sensitive = true; + }); + + openpgp_radio.toggled.connect(() => { + accept_button.sensitive = true; + }); + + none_radio.toggled.connect(() => { + accept_button.sensitive = true; + }); + + accept_button.clicked.connect(() => { + if (omemo_radio.active) {selected_default = OMEMO;} + else if (openpgp_radio.active) {selected_default = PGP;} + else if (none_radio.active) {selected_default = NONE;} + + selection_dialog.response(selected_default); + selection_dialog.close(); + }); + + selection_dialog.response.connect((response_id) => { + if (response_id == Gtk.ResponseType.DELETE_EVENT) { + conversation.encryption = NONE; + } + else { + conversation.encryption = response_id; + + if (selected_default != NONE) { + settings.default_encryption = response_id; + } + else { + // Set conversation as unencrypted, but keep + // default encryption setting as undecided. + } + } + }); + + selection_dialog.show(); + } + else { + conversation.encryption = settings.default_encryption; + } + } + else if (!visible) { + conversation.encryption = Encryption.NONE; + } + } + public void select_conversation(Conversation? conversation, bool default_initialize_conversation) { if (this.conversation != null) { conversation.notify["encryption"].disconnect(update_file_upload_status); @@ -124,6 +207,8 @@ public class ConversationViewController : Object { this.conversation = conversation; + update_conversation_encryption(conversation); + // Set list model onto list view // Dino.Application app = GLib.Application.get_default() as Dino.Application; // var map_list_model = get_conversation_content_model(new ContentItemMetaModel(app.db, conversation, stream_interactor), stream_interactor);