diff --git a/briar-gtk/briar_gtk/actions/window.py b/briar-gtk/briar_gtk/actions/window.py index 2a3acd977197c3dffc621063cff9aa093091ed25..7751e605ca84c6978ce35753a50472f828d169b4 100644 --- a/briar-gtk/briar_gtk/actions/window.py +++ b/briar-gtk/briar_gtk/actions/window.py @@ -23,6 +23,7 @@ class WindowActions(Actions): def _setup_actions(self): self._setup_back_to_sidebar_action() + self._setup_delete_contact_action() self._setup_open_about_page_action() self._setup_open_add_contact_action() self._setup_open_main_window_action() @@ -34,6 +35,9 @@ class WindowActions(Actions): f"{WINDOW_PREFIX}.back-to-sidebar", ["<Ctrl>w"] ) + def _setup_delete_contact_action(self): + self._setup_action("delete-contact", None, self._delete_contact) + def _setup_open_about_page_action(self): self._setup_action("open-about-dialog", None, self._open_about_page) @@ -52,6 +56,10 @@ class WindowActions(Actions): if isinstance(self.widget.current_container, MainWindowContainer): self.widget.current_container.show_sidebar() + # pylint: disable=unused-argument + def _delete_contact(self, action, parameter): + self.widget.current_container.delete_contact() + # pylint: disable=unused-argument def _open_about_page(self, action, parameter): self.widget.current_container.open_about_page() diff --git a/briar-gtk/briar_gtk/containers/main_window.py b/briar-gtk/briar_gtk/containers/main_window.py index d96b4f1e93f02a578aa4f0a926ab958860f85af0..911181d964b7dcea1255939b2d74112501acf198 100644 --- a/briar-gtk/briar_gtk/containers/main_window.py +++ b/briar-gtk/briar_gtk/containers/main_window.py @@ -5,6 +5,7 @@ # Initial version based on GNOME Fractal # https://gitlab.gnome.org/GNOME/fractal/-/tags/4.2.2 +from gettext import gettext as _ from gi.repository import GLib from briar_wrapper.models.contacts import Contacts @@ -14,12 +15,16 @@ from briar_gtk.containers.private_chat import PrivateChatContainer from briar_gtk.define import APP from briar_gtk.widgets.about_dialog import AboutDialogWidget from briar_gtk.widgets.contact_row import ContactRowWidget +from briar_gtk.widgets.undo_notification import UndoNotification class MainWindowContainer(Container): CONTAINER_UI = "main_window.ui" - MENU_UI = "main_menu.ui" + MAIN_MENU_UI = "main_menu.ui" + CHAT_MENU_UI = "chat_menu.ui" + + _current_contact_id = 0 def __init__(self): super().__init__() @@ -72,6 +77,7 @@ class MainWindowContainer(Container): contact_name = self._get_contact_name(contact_id) self._prepare_chat_view(contact_name) self._setup_private_chat_widget(contact_name, contact_id) + self._current_contact_id = contact_id def show_sidebar(self): self.main_window_leaflet.set_visible_child( @@ -81,6 +87,23 @@ class MainWindowContainer(Container): self._clear_history_container() self.contacts_list_box.unselect_all() self.contact_name_label.set_text("") + self._current_contact_id = 0 + + def delete_contact(self): + if self._current_contact_id == 0: + raise Exception("Can't delete contact with ID 0") + + def _timeout_action(): + Contacts(APP().api).delete(self._current_contact_id) + self._refresh_contacts() + self.show_sidebar() + + notification = UndoNotification( + _("Contact will be deleted"), + _timeout_action) + self.add_overlay(notification) + notification.show() + notification.set_reveal_child(True) def _prepare_chat_view(self, contact_name): if self._no_chat_opened(): @@ -92,6 +115,7 @@ class MainWindowContainer(Container): self.main_window_leaflet.set_visible_child( self.main_content_container) self.contact_name_label.set_text(contact_name) + self.builder.get_object("chat_menu_button").show() def _setup_private_chat_widget(self, contact_name, contact_id): private_chat_widget = PrivateChatContainer(contact_name, contact_id) @@ -131,13 +155,15 @@ class MainWindowContainer(Container): del self._selected_contact def _setup_view(self): - self._add_from_resource(self.MENU_UI) + self._add_from_resource(self.MAIN_MENU_UI) + self._add_from_resource(self.CHAT_MENU_UI) self._add_from_resource(self.CONTAINER_UI) self.builder.connect_signals(self) self._setup_main_window_stack() self._setup_headerbar_stack_holder() self.contact_name_label.set_text("") + self.builder.get_object("chat_menu_button").hide() self._setup_destroy_listener() def _setup_main_window_stack(self): diff --git a/briar-gtk/briar_gtk/widgets/undo_notification.py b/briar-gtk/briar_gtk/widgets/undo_notification.py new file mode 100644 index 0000000000000000000000000000000000000000..ce5b3ce9b807d8a0d7b7585ccc6156a853ee61e0 --- /dev/null +++ b/briar-gtk/briar_gtk/widgets/undo_notification.py @@ -0,0 +1,58 @@ +# Copyright (c) 2020 Nico Alt +# Copyright (c) 2014-2020 Cedric Bellegarde <cedric.bellegarde@adishatz.org> +# SPDX-License-Identifier: AGPL-3.0-only +# License-Filename: LICENSE.md +# +# Initial version based on GNOME Lollypop +# https://gitlab.gnome.org/World/lollypop/-/blob/1.3.6/lollypop/app_notification.py + +from gettext import gettext as _ +from gi.repository import Gtk, GLib, Pango + + +class UndoNotification(Gtk.Revealer): + + _TIMEOUT = 5000 + + _execute_action = True + + def __init__(self, message, timeout_action): + """ + Implementation of + https://developer.gnome.org/hig/stable/in-app-notifications.html.en + + Parameters + ========== + message: str + timeout_action: callback + """ + Gtk.Revealer.__init__(self) + widget = Gtk.Grid() + widget.get_style_context().add_class("app-notification") + widget.set_column_spacing(5) + label = Gtk.Label.new(message) + label.set_line_wrap_mode(Pango.WrapMode.WORD) + label.set_line_wrap(True) + widget.add(label) + + button = Gtk.Button.new() + button.set_label(_("Undo")) + button.connect("clicked", self._on_undo_clicked) + button.set_property("valign", Gtk.Align.START) + widget.add(button) + widget.show_all() + self.add(widget) + self.set_property("halign", Gtk.Align.CENTER) + self.set_property("valign", Gtk.Align.START) + GLib.timeout_add(self._TIMEOUT, self._on_destroy, timeout_action) + + # pylint: disable=unused-argument + def _on_undo_clicked(self, button, action=None): + self._execute_action = False + self.destroy() + + # pylint: disable=unused-argument + def _on_destroy(self, action): + if self._execute_action: + action() + self.destroy() diff --git a/briar-gtk/data/ui/app.briar.gtk.gresource.xml b/briar-gtk/data/ui/app.briar.gtk.gresource.xml index ad294a08778673a120adeef609c14814187d78b8..6767e4c02d9983d6c1dd3acf90a61f01e5eec70f 100644 --- a/briar-gtk/data/ui/app.briar.gtk.gresource.xml +++ b/briar-gtk/data/ui/app.briar.gtk.gresource.xml @@ -3,6 +3,7 @@ <gresource prefix="/app/briar/gtk"> <file compressed="true">application.css</file> <file compressed="true" preprocess="xml-stripblanks">add_contact.ui</file> + <file compressed="true" preprocess="xml-stripblanks">chat_menu.ui</file> <file compressed="true" preprocess="xml-stripblanks">login.ui</file> <file compressed="true" preprocess="xml-stripblanks">main_menu.ui</file> <file compressed="true" preprocess="xml-stripblanks">main_window.ui</file> diff --git a/briar-gtk/data/ui/chat_menu.ui b/briar-gtk/data/ui/chat_menu.ui new file mode 100644 index 0000000000000000000000000000000000000000..619ecbcd4b6813111cc83cf99178f8c642729c83 --- /dev/null +++ b/briar-gtk/data/ui/chat_menu.ui @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright (c) 2020 Nico Alt + SPDX-License-Identifier: AGPL-3.0-only + License-Filename: LICENSE.md + + Based on parts of GNOME Fractal + https://gitlab.gnome.org/GNOME/fractal/-/blob/4.2.2/fractal-gtk/res/ui/main_menu.ui +--> +<interface> + <requires lib="gtk+" version="3.20"/> + <object class="GtkPopoverMenu" id="chat_menu_popover"> + <property name="can_focus">False</property> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="margin_left">6</property> + <property name="margin_right">6</property> + <property name="margin_top">6</property> + <property name="margin_bottom">6</property> + <property name="orientation">vertical</property> + <property name="width_request">200</property> + <child> + <object class="GtkModelButton" id="delete-menu-entry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="action_name">win.delete-contact</property> + <property name="text" translatable="yes">Delete contact</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="submenu">main</property> + <property name="position">1</property> + </packing> + </child> + </object> +</interface> + diff --git a/briar-gtk/data/ui/main_window.ui b/briar-gtk/data/ui/main_window.ui index 7392d68dc061a04dc4905709ff614672e054d725..755bd267f8e7eb2aade6e04abd29f7273de66b8e 100644 --- a/briar-gtk/data/ui/main_window.ui +++ b/briar-gtk/data/ui/main_window.ui @@ -355,13 +355,40 @@ <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">0</property> + <property name="position">1</property> </packing> </child> </object> </child> </object> </child> + <child> + <object class="GtkMenuButton" id="chat_menu_button"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="popover">chat_menu_popover</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon_name">open-menu-symbolic</property> + </object> + </child> + <accessibility> + + </accessibility> + <child internal-child="accessible"> + <object class="AtkObject" id="a11y-chat_menu_button"> + <property name="AtkObject::accessible_name" translatable="yes">Chat menu</property> + </object> + </child> + </object> + <packing> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> </object> <packing> <property name="name">main_content</property> diff --git a/briar-gtk/po/ar.po b/briar-gtk/po/ar.po index d7c7b6cb61fc846ef0801896a1227f88d17b6815..cbcdc1b512fc84d1352d7df149459e0d6a6027ab 100644 --- a/briar-gtk/po/ar.po +++ b/briar-gtk/po/ar.po @@ -91,6 +91,9 @@ msgstr "Ø¥Ø¶Ø§ÙØ© جهة إتصال" msgid "Next" msgstr "التالي" +msgid "Delete contact" +msgstr "" + msgid "Password" msgstr "كلمة السّر" @@ -122,6 +125,9 @@ msgstr "" msgid "Back" msgstr "" +msgid "Chat menu" +msgstr "" + msgid "Welcome to Briar" msgstr "Ù…Ø±ØØ¨Ù‹Ø§ بك ÙÙŠ Briar (براير)" @@ -146,6 +152,12 @@ msgstr "" msgid "Myself" msgstr "" +msgid "Undo" +msgstr "" + +msgid "Contact will be deleted" +msgstr "" + msgid "Please enter a password" msgstr "" diff --git a/briar-gtk/po/briar-gtk.pot b/briar-gtk/po/briar-gtk.pot index 65096d054d3c0e05bf91c77a24d7736d6dd4d109..453ed04c8046b902e7ef0a896b7bba42eaf64da6 100644 --- a/briar-gtk/po/briar-gtk.pot +++ b/briar-gtk/po/briar-gtk.pot @@ -101,6 +101,9 @@ msgstr "" msgid "Next" msgstr "" +msgid "Delete contact" +msgstr "" + msgid "Password" msgstr "" @@ -132,6 +135,9 @@ msgstr "" msgid "Back" msgstr "" +msgid "Chat menu" +msgstr "" + msgid "Welcome to Briar" msgstr "" @@ -156,6 +162,12 @@ msgstr "" msgid "Myself" msgstr "" +msgid "Undo" +msgstr "" + +msgid "Contact will be deleted" +msgstr "" + msgid "Please enter a password" msgstr "" diff --git a/briar-gtk/po/de.po b/briar-gtk/po/de.po index bca096109327040f9723d939da46050f603efec1..eeee68b9c0b978bfad19780d9d60b6ae99991fa0 100644 --- a/briar-gtk/po/de.po +++ b/briar-gtk/po/de.po @@ -91,6 +91,9 @@ msgstr "Kontak hinzufügen" msgid "Next" msgstr "Weiter" +msgid "Delete contact" +msgstr "Kontakt entfernen" + msgid "Password" msgstr "Passwort" @@ -122,6 +125,9 @@ msgstr "Hauptmenü" msgid "Back" msgstr "Zurück" +msgid "Chat menu" +msgstr "Chat-Menü" + msgid "Welcome to Briar" msgstr "Willkommen bei Briar" @@ -146,6 +152,12 @@ msgstr "Briar-Funktionalität von" msgid "Myself" msgstr "Ich" +msgid "Undo" +msgstr "Rückgängig machen" + +msgid "Contact will be deleted" +msgstr "Kontakt wird gelöscht" + msgid "Please enter a password" msgstr "Bitte gib ein Passwort ein" diff --git a/briar-gtk/po/es.po b/briar-gtk/po/es.po index ab0602083002e5e331a9b03042ca8d07ba748e7c..a947760680bd134303b10f648a62a26a3df31c01 100644 --- a/briar-gtk/po/es.po +++ b/briar-gtk/po/es.po @@ -91,6 +91,9 @@ msgstr "Añadir el contacto" msgid "Next" msgstr "Seguir" +msgid "Delete contact" +msgstr "Eliminar contacto" + msgid "Password" msgstr "Contraseña" @@ -122,6 +125,9 @@ msgstr "Menú principal" msgid "Back" msgstr "Regresar" +msgid "Chat menu" +msgstr "Menú chat" + msgid "Welcome to Briar" msgstr "Bienvenida a Briar" @@ -146,6 +152,12 @@ msgstr "Funcionalidad de Briar de" msgid "Myself" msgstr "Yo" +msgid "Undo" +msgstr "Deshacer" + +msgid "Contact will be deleted" +msgstr "Contacto será eliminado" + msgid "Please enter a password" msgstr "Por favor, introduce una contraseña" diff --git a/briar-wrapper b/briar-wrapper index e851a46c77350ddce4d21d1112c931438579f131..df60279f98a3d954ebcaaca92192c5078304b666 160000 --- a/briar-wrapper +++ b/briar-wrapper @@ -1 +1 @@ -Subproject commit e851a46c77350ddce4d21d1112c931438579f131 +Subproject commit df60279f98a3d954ebcaaca92192c5078304b666 diff --git a/debian/control b/debian/control index b89f4016a23ec7414f596bc3749018a4dab0bb3b..1f6f14933b2e09bc7dc968c577ba9293dc1e0203 100644 --- a/debian/control +++ b/debian/control @@ -23,7 +23,7 @@ Depends: ${misc:Depends}, gir1.2-handy-1 (>= 0.90.0), python3, - python3-briar-wrapper, + python3-briar-wrapper(>= 0.0.4), python3-gi Description: Secure messaging, anywhere Briar is a messaging app designed for activists, journalists, and anyone diff --git a/requirements.txt b/requirements.txt index 841b2709bc3b838ce110bee786550eed85330176..cd30991072af58f2e43b87a0d25a432212da7b50 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,4 @@ # SPDX-License-Identifier: AGPL-3.0-only # License-Filename: LICENSE.md -briar-wrapper>=0.0.3 +briar-wrapper>=0.0.4