changeset 1585:9fc4120888be

browser (chat): message retraction implementation
author Goffi <goffi@goffi.org>
date Thu, 30 Nov 2023 13:25:25 +0100
parents eab815e48795
children 3baf53a3590d
files libervia/web/pages/chat/_browser/__init__.py libervia/web/server/restricted_bridge.py
diffstat 2 files changed, 30 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/libervia/web/pages/chat/_browser/__init__.py	Tue Nov 28 17:59:11 2023 +0100
+++ b/libervia/web/pages/chat/_browser/__init__.py	Thu Nov 30 13:25:25 2023 +0100
@@ -2,7 +2,7 @@
 import re
 
 from bridge import AsyncBridge as Bridge
-from browser import DOMNode, aio, bind, console as log, document, timer, window
+from browser import DOMNode, aio, console as log, document, window
 from cache import cache, identities
 import dialog
 from file_uploader import FileUploader
@@ -192,11 +192,11 @@
                 reactions_wrapper_elt.clear()
                 reactions_wrapper_elt <= reactions_elt
                 self.add_reactions_listeners(reactions_elt)
-        elif type_ == "EDIT":
+        elif type_ in ("EDIT", "RETRACT"):
             try:
                 old_message_elt = document[uid]
             except KeyError:
-                log.debug(f"Message {uid} not found, no edition to apply")
+                log.debug(f"Message {uid} not found, no {type_.lower()}ion to apply")
             else:
                 template_data = await self.message_to_template_data(
                     uid,
@@ -401,6 +401,7 @@
 
         content_elt = self.extra_menu_tpl.get_elt({
             "edit": can_edit,
+            "retract": is_own,
         })
         extra_popup = popup.create_popup(evt.target, content_elt, focus_elt=message_elt)
 
@@ -412,7 +413,8 @@
 
         for cls_name, callback in (
             ("action_quote", self.on_action_quote),
-            ("action_edit", self.on_action_edit)
+            ("action_edit", self.on_action_edit),
+            ("action_retract", self.on_action_retract),
         ):
             for elt in content_elt.select(f".{cls_name}"):
                 elt.bind("click", lambda evt, callback=callback: on_action_click(
@@ -475,6 +477,20 @@
             self.auto_resize_message_input()
             self.message_input.focus()
 
+    async def on_action_retract(self, __, message_elt) -> None:
+        confirmed = await dialog.Confirm(safe(
+            "This message will be permanently removed. Are you sure?<br><br>"
+            "WARNING: It is impossible to guarantee that other participants in the "
+            "discussion will delete this message as well. You must assume it has been "
+            "seen. If a password or other sensitive information has been accidentally "
+            "shared, please ensure to take appropriate measures to change it and "
+            "mitigate the risks."
+        )).ashow()
+        if confirmed:
+            await bridge.message_retract(message_elt["id"])
+        else:
+            log.info(f"Retraction of message {message_elt['id']} cancelled by user.")
+
     def get_reaction_panel(self, source_elt):
         emoji_picker_elt = document.createElement("emoji-picker")
         message_elt = source_elt.closest("div.is-chat-message")
--- a/libervia/web/server/restricted_bridge.py	Tue Nov 28 17:59:11 2023 +0100
+++ b/libervia/web/server/restricted_bridge.py	Thu Nov 30 13:25:25 2023 +0100
@@ -118,6 +118,7 @@
     async def message_edit(
         self, message_id: str, edit_data_s: str, profile: str
     ) -> None:
+        self.no_service_profile(profile)
         return await self.host.bridge_call(
             "message_edit", message_id, edit_data_s, profile
         )
@@ -125,10 +126,19 @@
     async def message_reactions_set(
         self, message_id: str, reactions: list[str], update_type: str, profile: str
     ) -> None:
+        self.no_service_profile(profile)
         return await self.host.bridge_call(
             "message_reactions_set", message_id, reactions, update_type, profile
         )
 
+    async def message_retract(
+        self, message_id: str, profile: str
+    ) -> None:
+        self.no_service_profile(profile)
+        return await self.host.bridge_call(
+            "message_retract", message_id, profile
+        )
+
     async def message_send(
         self, to_jid_s, message, subject, mess_type, extra_s,
         profile