annotate libervia/web/pages/chat/_browser/__init__.py @ 1598:86c7a3a625d5

server: always start a new session on connection: The session was kept when a user was connecting from service profile (but not from other profiles), this was leading to session fixation vulnerability (an attacker on the same machine could get service profile session cookie, and use it when a victim would log-in). This patch fixes it by always starting a new session on connection. fix 443
author Goffi <goffi@goffi.org>
date Fri, 23 Feb 2024 13:35:24 +0100
parents 52098b5bab8d
children 19c83dd943df
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
1 import json
1541
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
2 import re
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
3
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
4 from bridge import AsyncBridge as Bridge
1585
9fc4120888be browser (chat): message retraction implementation
Goffi <goffi@goffi.org>
parents: 1584
diff changeset
5 from browser import DOMNode, aio, console as log, document, window
1541
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
6 from cache import cache, identities
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
7 import dialog
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
8 from file_uploader import FileUploader
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
9 import jid
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
10 from js_modules import emoji_picker_element
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
11 from js_modules.tippy_js import tippy
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
12 import popup
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
13 from template import Template, safe
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
14 from tools import is_touch_device
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
15
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
16 log.warning = log.warn
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
17 profile = window.profile or ""
1595
7941444c1671 pages: set `own_local_jid` to avoid confusion with `own_jid`:
Goffi <goffi@goffi.org>
parents: 1585
diff changeset
18 # JID used in the local chat (real JID for one2one, room JID otherwise)
7941444c1671 pages: set `own_local_jid` to avoid confusion with `own_jid`:
Goffi <goffi@goffi.org>
parents: 1585
diff changeset
19 own_local_jid = jid.JID(window.own_local_jid)
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
20 target_jid = jid.JID(window.target_jid)
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
21 chat_type = window.chat_type
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
22 bridge = Bridge()
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
23
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
24 # Sensible value to consider that user is at the bottom
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
25 SCROLL_SENSITIVITY = 200
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
26
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
27 INPUT_MODES = {"normal", "edit", "quote"}
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
28 MODE_CLASS = "mode_{}"
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
29
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
30
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
31 class LiberviaWebChat:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
32 def __init__(self):
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
33 self._input_mode = "normal"
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
34 self.input_data = {}
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
35 self.message_tpl = Template("chat/message.html")
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
36 self.extra_menu_tpl = Template("chat/extra_menu.html")
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
37 self.reactions_tpl = Template("chat/reactions.html")
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
38 self.reactions_details_tpl = Template("chat/reactions_details.html")
1541
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
39 self.url_preview_control_tpl = Template("components/url_preview_control.html")
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
40 self.url_preview_tpl = Template("components/url_preview.html")
1542
fb31d3dba0c3 browser (chat): add marker for new messages when page is not visible
Goffi <goffi@goffi.org>
parents: 1541
diff changeset
41 self.new_messages_marker_elt = Template("chat/new_messages_marker.html").get_elt()
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
42 self.editions_tpl = Template("chat/editions.html")
1541
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
43
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
44 self.messages_elt = document["messages"]
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
45
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
46 # attachments
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
47 self.file_uploader = FileUploader(
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
48 "", "chat/attachment_preview.html", on_delete_cb=self.on_attachment_delete
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
49 )
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
50 self.attachments_elt = document["attachments"]
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
51 self.message_input = document["message_input"]
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
52
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
53 close_button = document.select_one(".modal-close")
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
54 close_button.bind("click", self.close_modal)
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
55
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
56 # hide/show attachments
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
57 MutationObserver = window.MutationObserver
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
58 observer = MutationObserver.new(lambda *__: self.update_attachments_visibility())
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
59 observer.observe(self.attachments_elt, {"childList": True})
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
60
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
61 # we want the message scroll to be initially at the bottom
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
62 self.messages_elt.scrollTop = self.messages_elt.scrollHeight
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
63
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
64 # listeners/dynamic updates
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
65 self.add_message_event_listeners()
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
66 self.handle_url_previews()
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
67 self.add_reactions_listeners()
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
68
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
69 # input
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
70 self.auto_resize_message_input()
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
71 self.message_input.focus()
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
72
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
73 @property
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
74 def input_mode(self) -> str:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
75 return self._input_mode
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
76
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
77 @input_mode.setter
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
78 def input_mode(self, new_mode: str) -> None:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
79 if new_mode == self.input_mode:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
80 return
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
81 if new_mode not in INPUT_MODES:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
82 raise ValueError(f"Invalid input mode: {new_mode!r}")
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
83 target_elt = self.message_input
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
84 target_elt.classList.remove(MODE_CLASS.format(self._input_mode))
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
85 self._input_mode = new_mode
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
86 target_elt.classList.add(MODE_CLASS.format(new_mode))
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
87 self.input_data.clear()
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
88
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
89 @property
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
90 def is_at_bottom(self):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
91 return (
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
92 self.messages_elt.scrollHeight
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
93 - self.messages_elt.scrollTop
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
94 - self.messages_elt.clientHeight
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
95 <= SCROLL_SENSITIVITY
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
96 )
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
97
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
98 async def send_message(self):
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
99 """Send message currently in input area
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
100
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
101 The message and corresponding attachment will be sent
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
102 """
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
103 message = self.message_input.value.rstrip()
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
104 log.info(f"{message=}")
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
105
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
106 # attachments
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
107 attachments = []
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
108 for attachment_elt in self.attachments_elt.children:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
109 file_data = json.loads(attachment_elt.getAttribute("data-file"))
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
110 attachments.append(file_data)
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
111
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
112 if message or attachments:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
113 extra = {}
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
114
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
115 if attachments:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
116 extra["attachments"] = attachments
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
117
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
118 # now we send the message
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
119 try:
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
120 if self.input_mode == "edit":
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
121 message_id = self.input_data["id"]
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
122 edit_data = {
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
123 "message": {"": message},
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
124 "extra": extra
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
125 }
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
126 await bridge.message_edit(
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
127 message_id, json.dumps(edit_data, ensure_ascii=False)
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
128 )
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
129 else:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
130 await bridge.message_send(
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
131 str(target_jid),
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
132 {"": message}, {}, "auto", json.dumps(extra, ensure_ascii=False)
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
133 )
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
134 except Exception as e:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
135 dialog.notification.show(f"Can't send message: {e}", "error")
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
136 else:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
137 self.message_input.value = ""
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
138 self.attachments_elt.clear()
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
139 self.input_mode = "normal"
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
140
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
141 def _on_message_new(
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
142 self,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
143 uid: str,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
144 timestamp: float,
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
145 from_jid_s: str,
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
146 to_jid_s: str,
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
147 message: dict,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
148 subject: dict,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
149 mess_type: str,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
150 extra_s: str,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
151 profile: str,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
152 ) -> None:
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
153 from_jid = jid.JID(from_jid_s)
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
154 to_jid = jid.JID(to_jid_s)
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
155 if (
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
156 from_jid.bare == window.target_jid
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
157 or to_jid.bare == window.target_jid
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
158 ):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
159 aio.run(
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
160 self.on_message_new(
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
161 uid,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
162 timestamp,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
163 from_jid,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
164 to_jid,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
165 message,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
166 subject,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
167 mess_type,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
168 json.loads(extra_s),
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
169 profile,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
170 )
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
171 )
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
172
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
173 def _on_message_update(
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
174 self, uid: str, type_: str, update_data_s: str, profile: str
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
175 ) -> None:
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
176 aio.run(self.on_message_update(uid, type_, update_data_s, profile))
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
177
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
178 async def on_message_update(
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
179 self, uid: str, type_: str, update_data_s: str, profile: str
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
180 ) -> None:
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
181 update_data = json.loads(update_data_s)
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
182 is_at_bottom = self.is_at_bottom
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
183 if type_ == "REACTION":
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
184 reactions = update_data["reactions"]
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
185 log.debug(f"new reactions: {reactions}")
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
186 try:
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
187 reactions_wrapper_elt = document[f"msg_reactions_{uid}"]
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
188 except KeyError:
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
189 log.debug(f"Message {uid} not found, no reactions to update")
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
190 else:
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
191 log.debug(f"Message {uid} found, new reactions: {reactions}")
1596
52098b5bab8d browser (chat): add data for reactions
Goffi <goffi@goffi.org>
parents: 1595
diff changeset
192 reactions_elt = self.reactions_tpl.get_elt(
52098b5bab8d browser (chat): add data for reactions
Goffi <goffi@goffi.org>
parents: 1595
diff changeset
193 {
52098b5bab8d browser (chat): add data for reactions
Goffi <goffi@goffi.org>
parents: 1595
diff changeset
194 "chat_type": chat_type,
52098b5bab8d browser (chat): add data for reactions
Goffi <goffi@goffi.org>
parents: 1595
diff changeset
195 "own_local_jid": str(own_local_jid),
52098b5bab8d browser (chat): add data for reactions
Goffi <goffi@goffi.org>
parents: 1595
diff changeset
196 "reactions": reactions
52098b5bab8d browser (chat): add data for reactions
Goffi <goffi@goffi.org>
parents: 1595
diff changeset
197 })
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
198 reactions_wrapper_elt.clear()
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
199 reactions_wrapper_elt <= reactions_elt
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
200 self.add_reactions_listeners(reactions_elt)
1585
9fc4120888be browser (chat): message retraction implementation
Goffi <goffi@goffi.org>
parents: 1584
diff changeset
201 elif type_ in ("EDIT", "RETRACT"):
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
202 try:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
203 old_message_elt = document[uid]
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
204 except KeyError:
1585
9fc4120888be browser (chat): message retraction implementation
Goffi <goffi@goffi.org>
parents: 1584
diff changeset
205 log.debug(f"Message {uid} not found, no {type_.lower()}ion to apply")
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
206 else:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
207 template_data = await self.message_to_template_data(
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
208 uid,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
209 update_data["timestamp"],
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
210 jid.JID(update_data["from"]),
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
211 jid.JID(update_data["to"]),
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
212 update_data["message"],
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
213 update_data["subject"],
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
214 update_data["type"],
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
215 update_data["extra"]
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
216 )
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
217
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
218 new_message_elt = self.message_tpl.get_elt(
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
219 template_data
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
220 )
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
221 old_message_elt.replaceWith(new_message_elt)
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
222 self.add_message_event_listeners(new_message_elt)
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
223 self.handle_url_previews(new_message_elt)
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
224 else:
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
225 log.warning(f"Unsupported update type: {type_!r}")
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
226
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
227 # If user was at the bottom, keep the scroll at the bottom
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
228 if is_at_bottom:
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
229 self.messages_elt.scrollTop = self.messages_elt.scrollHeight
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
230
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
231 async def message_to_template_data(
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
232 self,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
233 uid: str,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
234 timestamp: float,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
235 from_jid: jid.JID,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
236 to_jid: jid.JID,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
237 message_data: dict,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
238 subject_data: dict,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
239 mess_type: str,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
240 extra: dict,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
241 ) -> dict:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
242 """Generate template data to use with [message_tpl]
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
243
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
244 @return: template data
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
245 """
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
246 xhtml_data = extra.get("xhtml")
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
247 if not xhtml_data:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
248 xhtml = None
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
249 else:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
250 try:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
251 xhtml = xhtml_data[""]
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
252 except KeyError:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
253 xhtml = next(iter(xhtml_data.values()))
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
254
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
255 if chat_type == "group":
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
256 await cache.fill_identities([str(from_jid)])
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
257 else:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
258 await cache.fill_identities([str(jid.JID(from_jid).bare)])
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
259 from_jid = from_jid.bare
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
260
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
261 return {
1595
7941444c1671 pages: set `own_local_jid` to avoid confusion with `own_jid`:
Goffi <goffi@goffi.org>
parents: 1585
diff changeset
262 "own_local_jid": str(own_local_jid),
7941444c1671 pages: set `own_local_jid` to avoid confusion with `own_jid`:
Goffi <goffi@goffi.org>
parents: 1585
diff changeset
263 "chat_type": chat_type,
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
264 "msg": {
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
265 "id": uid,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
266 "timestamp": extra.get("updated", timestamp),
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
267 "type": mess_type,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
268 "from_": str(from_jid),
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
269 "text": message_data.get("") or next(iter(message_data.values()), ""),
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
270 "subject": subject_data.get("") or next(iter(subject_data.values()), ""),
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
271 "type": mess_type,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
272 "thread": extra.get("thread"),
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
273 "thread_parent": extra.get("thread_parent"),
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
274 "reeceived": extra.get("received_timestamp") or timestamp,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
275 "delay_sender": extra.get("delay_sender"),
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
276 "info_type": extra.get("info_type"),
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
277 "html": safe(xhtml) if xhtml else None,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
278 "encrypted": extra.get("encrypted", False),
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
279 "received": extra.get("received", False),
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
280 "attachments": extra.get("attachments", []),
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
281 "extra": extra
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
282 },
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
283 "identities": identities,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
284 }
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
285
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
286 async def on_message_new(
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
287 self,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
288 uid: str,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
289 timestamp: float,
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
290 from_jid: jid.JID,
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
291 to_jid: jid.JID,
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
292 message_data: dict,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
293 subject_data: dict,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
294 mess_type: str,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
295 extra: dict,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
296 profile: str,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
297 ) -> None:
1542
fb31d3dba0c3 browser (chat): add marker for new messages when page is not visible
Goffi <goffi@goffi.org>
parents: 1541
diff changeset
298 # FIXME: visibilityState doesn't detect OS events such as `Alt + Tab`, using focus
fb31d3dba0c3 browser (chat): add marker for new messages when page is not visible
Goffi <goffi@goffi.org>
parents: 1541
diff changeset
299 # event may help to get those use cases, but it gives false positives.
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
300 if (
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
301 document.visibilityState == "hidden"
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
302 and self.new_messages_marker_elt.parent is None
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
303 ):
1542
fb31d3dba0c3 browser (chat): add marker for new messages when page is not visible
Goffi <goffi@goffi.org>
parents: 1541
diff changeset
304 # the page is not visible, and we have no new messages marker yet, so we add
fb31d3dba0c3 browser (chat): add marker for new messages when page is not visible
Goffi <goffi@goffi.org>
parents: 1541
diff changeset
305 # it
fb31d3dba0c3 browser (chat): add marker for new messages when page is not visible
Goffi <goffi@goffi.org>
parents: 1541
diff changeset
306 self.messages_elt <= self.new_messages_marker_elt
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
307
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
308 template_data = await self.message_to_template_data(
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
309 uid,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
310 timestamp,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
311 from_jid,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
312 to_jid,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
313 message_data,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
314 subject_data,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
315 mess_type,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
316 extra
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
317 )
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
318
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
319 message_elt = self.message_tpl.get_elt(
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
320 template_data
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
321 )
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
322
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
323 # Check if user is viewing older messages or is at the bottom
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
324 is_at_bottom = self.is_at_bottom
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
325
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
326 self.messages_elt <= message_elt
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
327 self.add_message_event_listeners(message_elt)
1541
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
328 # we add preview in parallel on purpose, as they can be slow to get
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
329 self.handle_url_previews(message_elt)
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
330
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
331 # If user was at the bottom, keep the scroll at the bottom
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
332 if is_at_bottom:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
333 self.messages_elt.scrollTop = self.messages_elt.scrollHeight
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
334
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
335 def auto_resize_message_input(self):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
336 """Resize the message input field according to content."""
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
337
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
338 is_at_bottom = self.is_at_bottom
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
339
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
340 # The textarea's height is first reset to 'auto' to ensure it's not influenced by
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
341 # the previous content.
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
342 self.message_input.style.height = "auto"
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
343
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
344 # Then the height is set to the scrollHeight of the textarea (which is the height
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
345 # of the content), plus the vertical border, resulting in a textarea that grows as
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
346 # more lines of text are added.
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
347 self.message_input.style.height = f"{self.message_input.scrollHeight + 2}px"
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
348
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
349 if is_at_bottom:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
350 # we want the message are to still display the last message
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
351 self.messages_elt.scrollTop = self.messages_elt.scrollHeight
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
352
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
353 def on_message_keydown(self, evt):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
354 """Handle the 'keydown' event of the message input field
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
355
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
356 @param evt: The event object. 'target' refers to the textarea element.
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
357 """
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
358 if evt.keyCode == 13: # <Enter> key
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
359 if not window.navigator.maxTouchPoints:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
360 # we have a non touch device, we send message on <Enter>
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
361 if not evt.shiftKey:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
362 evt.preventDefault() # Prevents line break
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
363 aio.run(self.send_message())
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
364 elif evt.keyCode == 27: # <ESC> key
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
365 evt.preventDefault()
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
366 self.message_input.value = ''
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
367 self.input_mode = 'normal'
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
368 self.auto_resize_message_input()
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
369 elif evt.keyCode == 38: # <Up> arrow key
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
370 if self.input_mode == "normal" and self.message_input.value.strip() == "":
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
371 evt.preventDefault()
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
372 own_msgs = document.getElementsByClassName('own_msg')
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
373 if own_msgs.length > 0:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
374 last_msg = own_msgs[own_msgs.length - 1]
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
375 aio.run(self.on_action_edit(None, last_msg))
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
376
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
377 def update_attachments_visibility(self):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
378 if len(self.attachments_elt.children):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
379 self.attachments_elt.classList.remove("is-contracted")
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
380 else:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
381 self.attachments_elt.classList.add("is-contracted")
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
382
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
383 def on_file_selected(self, evt):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
384 """Handle file selection"""
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
385 log.info("file selected")
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
386 files = evt.currentTarget.files
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
387 self.file_uploader.upload_files(files, self.attachments_elt)
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
388 self.message_input.focus()
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
389
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
390 def on_attachment_delete(self, evt):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
391 evt.stopPropagation()
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
392 target = evt.currentTarget
1540
b4342176fa0a browser (chat): minor reformatting
Goffi <goffi@goffi.org>
parents: 1536
diff changeset
393 item_elt = DOMNode(target.closest(".attachment-preview"))
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
394 item_elt.remove()
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
395
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
396 def on_attach_button_click(self, evt):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
397 document["file_input"].click()
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
398
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
399 def on_extra_btn_click(self, evt):
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
400 message_elt = evt.target.closest("div.is-chat-message")
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
401 is_own = message_elt.classList.contains("own_msg")
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
402 if is_own:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
403 own_messages = document.select('.own_msg')
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
404 # with XMPP, we can currently only edit our last message
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
405 can_edit = own_messages and message_elt is own_messages[-1]
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
406 else:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
407 can_edit = False
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
408
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
409 content_elt = self.extra_menu_tpl.get_elt({
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
410 "edit": can_edit,
1585
9fc4120888be browser (chat): message retraction implementation
Goffi <goffi@goffi.org>
parents: 1584
diff changeset
411 "retract": is_own,
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
412 })
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
413 extra_popup = popup.create_popup(evt.target, content_elt, focus_elt=message_elt)
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
414
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
415 def on_action_click(evt, callback):
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
416 extra_popup.hide()
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
417 aio.run(
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
418 callback(evt, message_elt)
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
419 )
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
420
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
421 for cls_name, callback in (
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
422 ("action_quote", self.on_action_quote),
1585
9fc4120888be browser (chat): message retraction implementation
Goffi <goffi@goffi.org>
parents: 1584
diff changeset
423 ("action_edit", self.on_action_edit),
9fc4120888be browser (chat): message retraction implementation
Goffi <goffi@goffi.org>
parents: 1584
diff changeset
424 ("action_retract", self.on_action_retract),
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
425 ):
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
426 for elt in content_elt.select(f".{cls_name}"):
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
427 elt.bind("click", lambda evt, callback=callback: on_action_click(
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
428 evt, callback
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
429 ))
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
430
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
431 def on_reaction_click(self, evt, message_elt):
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
432 window.evt = evt
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
433 aio.run(
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
434 bridge.message_reactions_set(
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
435 message_elt["id"], [evt.detail["unicode"]], "toggle"
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
436 )
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
437 )
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
438 if evt.deltaY != 0:
1540
b4342176fa0a browser (chat): minor reformatting
Goffi <goffi@goffi.org>
parents: 1536
diff changeset
439 document["attachments"].scrollLeft += evt.deltaY * 0.8
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
440 evt.preventDefault()
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
441
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
442 async def get_message_tuple(self, message_elt) -> tuple|None:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
443 """Retrieve message tuple from as sent by [message_new]
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
444
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
445 If not corresponding message data is found, an error will shown, and None is
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
446 returned.
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
447 @param message_elt: message element, it's "id" attribute will be use to retrieve
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
448 message data
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
449 @return: message data as a tuple, or None if not message with this ID is found.
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
450 """
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
451 message_id = message_elt['id']
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
452 history_data = await bridge.history_get(
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
453 "", "", -2, True, {"id": message_elt['id']}
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
454 )
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
455 if not history_data:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
456 dialog.notification.show(f"Can't find message {message_id}", "error")
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
457 return None
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
458 return history_data[0]
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
459
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
460 async def on_action_quote(self, __, message_elt) -> None:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
461 message_data = await self.get_message_tuple(message_elt)
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
462 if message_data is not None:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
463 messages = message_data[4]
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
464 body = next(iter(messages.values()), "")
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
465 quote = "\n".join(f"> {l}" for l in body.split("\n"))
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
466 self.message_input.value = f"{quote}\n{self.message_input.value}"
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
467 self.input_mode = "quote"
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
468 self.input_data["id"] = message_elt["id"]
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
469 self.auto_resize_message_input()
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
470 self.message_input.focus()
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
471
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
472 async def on_action_edit(self, __, message_elt) -> None:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
473 message_data = await self.get_message_tuple(message_elt)
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
474 if message_data is not None:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
475 messages = message_data[4]
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
476 body = next(iter(messages.values()), "")
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
477 if not body:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
478 dialog.notification.show("No content found in message, nothing to edit")
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
479 return
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
480
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
481 self.message_input.value = body
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
482 self.input_mode = "edit"
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
483 self.input_data["id"] = message_elt["id"]
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
484 self.auto_resize_message_input()
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
485 self.message_input.focus()
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
486
1585
9fc4120888be browser (chat): message retraction implementation
Goffi <goffi@goffi.org>
parents: 1584
diff changeset
487 async def on_action_retract(self, __, message_elt) -> None:
9fc4120888be browser (chat): message retraction implementation
Goffi <goffi@goffi.org>
parents: 1584
diff changeset
488 confirmed = await dialog.Confirm(safe(
9fc4120888be browser (chat): message retraction implementation
Goffi <goffi@goffi.org>
parents: 1584
diff changeset
489 "This message will be permanently removed. Are you sure?<br><br>"
9fc4120888be browser (chat): message retraction implementation
Goffi <goffi@goffi.org>
parents: 1584
diff changeset
490 "WARNING: It is impossible to guarantee that other participants in the "
9fc4120888be browser (chat): message retraction implementation
Goffi <goffi@goffi.org>
parents: 1584
diff changeset
491 "discussion will delete this message as well. You must assume it has been "
9fc4120888be browser (chat): message retraction implementation
Goffi <goffi@goffi.org>
parents: 1584
diff changeset
492 "seen. If a password or other sensitive information has been accidentally "
9fc4120888be browser (chat): message retraction implementation
Goffi <goffi@goffi.org>
parents: 1584
diff changeset
493 "shared, please ensure to take appropriate measures to change it and "
9fc4120888be browser (chat): message retraction implementation
Goffi <goffi@goffi.org>
parents: 1584
diff changeset
494 "mitigate the risks."
9fc4120888be browser (chat): message retraction implementation
Goffi <goffi@goffi.org>
parents: 1584
diff changeset
495 )).ashow()
9fc4120888be browser (chat): message retraction implementation
Goffi <goffi@goffi.org>
parents: 1584
diff changeset
496 if confirmed:
9fc4120888be browser (chat): message retraction implementation
Goffi <goffi@goffi.org>
parents: 1584
diff changeset
497 await bridge.message_retract(message_elt["id"])
9fc4120888be browser (chat): message retraction implementation
Goffi <goffi@goffi.org>
parents: 1584
diff changeset
498 else:
9fc4120888be browser (chat): message retraction implementation
Goffi <goffi@goffi.org>
parents: 1584
diff changeset
499 log.info(f"Retraction of message {message_elt['id']} cancelled by user.")
9fc4120888be browser (chat): message retraction implementation
Goffi <goffi@goffi.org>
parents: 1584
diff changeset
500
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
501 def get_reaction_panel(self, source_elt):
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
502 emoji_picker_elt = document.createElement("emoji-picker")
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
503 message_elt = source_elt.closest("div.is-chat-message")
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
504 emoji_picker_elt.bind(
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
505 "emoji-click", lambda evt: self.on_reaction_click(evt, message_elt)
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
506 )
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
507
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
508 return emoji_picker_elt
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
509
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
510 def add_message_event_listeners(self, parent_elt=None):
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
511 """Prepare a message to be dynamic
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
512
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
513 - make attachments dynamically clickable
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
514 - make the extra button clickable
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
515 """
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
516 ## attachments
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
517 # FIXME: only handle images for now, and display them in a modal
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
518 if parent_elt is None:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
519 parent_elt = document
1540
b4342176fa0a browser (chat): minor reformatting
Goffi <goffi@goffi.org>
parents: 1536
diff changeset
520 img_elts = parent_elt.select(".message-attachment img")
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
521 for img_elt in img_elts:
1540
b4342176fa0a browser (chat): minor reformatting
Goffi <goffi@goffi.org>
parents: 1536
diff changeset
522 img_elt.bind("click", self.open_modal)
b4342176fa0a browser (chat): minor reformatting
Goffi <goffi@goffi.org>
parents: 1536
diff changeset
523 img_elt.style.cursor = "pointer"
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
524
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
525 ## reaction button
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
526 for reaction_btn in parent_elt.select(".reaction-button"):
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
527 message_elt = reaction_btn.closest("div.is-chat-message")
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
528 tippy(
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
529 reaction_btn,
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
530 {
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
531 "trigger": "click",
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
532 "content": self.get_reaction_panel,
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
533 "appendTo": document.body,
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
534 "placement": "bottom",
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
535 "interactive": True,
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
536 "theme": "light",
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
537 "onShow": lambda __, message_elt=message_elt: (
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
538 message_elt.classList.add("has-popup-focus")
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
539 ),
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
540 "onHide": lambda __, message_elt=message_elt: (
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
541 message_elt.classList.remove("has-popup-focus")
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
542 ),
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
543 },
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
544 )
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
545
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
546 ## extra button
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
547 for extra_btn in parent_elt.select(".extra-button"):
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
548 extra_btn.bind("click", self.on_extra_btn_click)
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
549
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
550 ## editions
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
551 for edition_icon_elt in parent_elt.select(".message-editions"):
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
552 message_elt = edition_icon_elt.closest("div.is-chat-message")
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
553 dataset = message_elt.dataset.to_dict()
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
554 try:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
555 editions = json.loads(dataset["editions"])
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
556 except (ValueError, KeyError):
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
557 log.error(
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
558 f"Internal Error: invalid or missing editions data: {message_elt['id']}"
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
559 )
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
560 else:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
561 for edition in editions:
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
562 edition["text"] = (
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
563 edition["message"].get("")
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
564 or next(iter(edition["message"].values()), "")
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
565 )
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
566 editions_elt = self.editions_tpl.get_elt({"editions": editions})
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
567 tippy(
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
568 edition_icon_elt,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
569 {
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
570 "content": editions_elt,
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
571 "theme": "light",
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
572 "appendTo": document.body
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
573 }
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
574
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
575 )
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
576
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
577 def add_reactions_listeners(self, parent_elt=None) -> None:
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
578 """Add listener on reactions to handle details and reaction toggle"""
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
579 if parent_elt is None:
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
580 parent_elt = document
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
581
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
582 is_touch = is_touch_device()
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
583
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
584 for reaction_elt in parent_elt.select(".reaction"):
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
585 # Reaction details
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
586 dataset = reaction_elt.dataset.to_dict()
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
587 reacting_jids = sorted(json.loads(dataset.get("jids", "[]")))
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
588 reaction_details_elt = self.reactions_details_tpl.get_elt(
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
589 {"reacting_jids": reacting_jids, "identities": identities}
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
590 )
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
591
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
592 # Configure tippy based on device type
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
593 tippy_config = {
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
594 "content": reaction_details_elt,
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
595 "placement": "bottom",
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
596 "theme": "light",
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
597 "touch": ["hold", 500] if is_touch else True,
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
598 "trigger": "click" if is_touch else "mouseenter focus",
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
599 "delay": [0, 800] if is_touch else 0,
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
600 }
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
601 tippy(reaction_elt, tippy_config)
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
602
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
603 # Toggle reaction when clicked/touched
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
604 emoji_elt = reaction_elt.select_one(".emoji")
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
605 emoji = emoji_elt.html.strip()
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
606 message_elt = reaction_elt.closest("div.is-chat-message")
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
607 msg_id = message_elt["id"]
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
608
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
609 def toggle_reaction(event, msg_id=msg_id, emoji=emoji):
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
610 # Prevent default if it's a touch device to distinguish from long press
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
611 if is_touch:
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
612 event.preventDefault()
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
613 aio.run(bridge.message_reactions_set(msg_id, [emoji], "toggle"))
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
614
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
615 reaction_elt.bind("click", toggle_reaction)
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
616
1541
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
617 def find_links(self, message_elt):
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
618 """Find all http and https links within the body of a message."""
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
619 msg_body_elt = message_elt.select_one(".msg_body")
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
620 if not msg_body_elt:
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
621 return
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
622
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
623 # Extracting links from text content
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
624 text = msg_body_elt.text
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
625 raw_urls = re.findall(
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
626 r"http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F])|#)+",
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
627 text,
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
628 )
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
629
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
630 # Extracting links from <a> elements
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
631 a_elements = msg_body_elt.select("a")
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
632 for a_elt in a_elements:
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
633 href = a_elt.attrs.get("href", "")
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
634 if href.startswith("http://") or href.startswith("https://"):
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
635 raw_urls.append(href)
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
636
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
637 # we remove duplicates
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
638 urls = list(dict.fromkeys(raw_urls))
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
639
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
640 return urls
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
641
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
642 async def add_url_previews(self, url_previews_elt, urls) -> None:
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
643 """Add URL previews to the .url-previews element of a message."""
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
644 url_previews_elt.clear()
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
645 for url in urls:
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
646 try:
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
647 url_preview_data_s = await bridge.url_preview_get(url, "")
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
648 except Exception as e:
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
649 log.warning(f"Couldn't get URL preview for {url}: {e}")
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
650 continue
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
651
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
652 if not url_preview_data_s:
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
653 log.warning(f"No preview could be found for URL: {url}")
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
654 continue
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
655
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
656 url_preview_data = json.loads(url_preview_data_s)
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
657
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
658 url_preview_elt = self.url_preview_tpl.get_elt(
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
659 {"url_preview": url_preview_data}
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
660 )
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
661 url_previews_elt <= url_preview_elt
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
662
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
663 def handle_url_previews(self, parent_elt=None):
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
664 """Check if URL are presents in a message and show appropriate element
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
665
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
666 According to settings, either a preview control panel will be shown to wait for
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
667 user click, or directly the previews, or nothing at all.
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
668 """
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
669
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
670 if parent_elt is None:
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
671 parent_elt = document
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
672 chat_message_elts = parent_elt.select(".is-chat-message")
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
673 else:
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
674 chat_message_elts = [parent_elt]
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
675 for message_elt in chat_message_elts:
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
676 urls = self.find_links(message_elt)
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
677 if urls:
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
678 url_previews_elt = message_elt.select_one(".url-previews")
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
679 url_previews_elt.classList.remove("is-hidden")
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
680 preview_control_elt = self.url_preview_control_tpl.get_elt()
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
681 fetch_preview_btn = preview_control_elt.select_one(
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
682 ".action_fetch_preview"
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
683 )
1541
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
684 fetch_preview_btn.bind(
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
685 "click",
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
686 lambda __, previews_elt=url_previews_elt, preview_urls=urls: aio.run(
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
687 self.add_url_previews(previews_elt, preview_urls)
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
688 ),
1541
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
689 )
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
690 url_previews_elt <= preview_control_elt
3c384b51b2a1 browser (chat): URL previews implementation
Goffi <goffi@goffi.org>
parents: 1540
diff changeset
691
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
692 def open_modal(self, evt):
1540
b4342176fa0a browser (chat): minor reformatting
Goffi <goffi@goffi.org>
parents: 1536
diff changeset
693 modal_image = document.select_one("#modal-image")
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
694 modal_image.src = evt.target.src
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
695 modal_image.alt = evt.target.alt
1540
b4342176fa0a browser (chat): minor reformatting
Goffi <goffi@goffi.org>
parents: 1536
diff changeset
696 modal = document.select_one("#modal")
b4342176fa0a browser (chat): minor reformatting
Goffi <goffi@goffi.org>
parents: 1536
diff changeset
697 modal.classList.add("is-active")
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
698
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
699 def close_modal(self, evt):
1540
b4342176fa0a browser (chat): minor reformatting
Goffi <goffi@goffi.org>
parents: 1536
diff changeset
700 modal = document.select_one("#modal")
b4342176fa0a browser (chat): minor reformatting
Goffi <goffi@goffi.org>
parents: 1536
diff changeset
701 modal.classList.remove("is-active")
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
702
1542
fb31d3dba0c3 browser (chat): add marker for new messages when page is not visible
Goffi <goffi@goffi.org>
parents: 1541
diff changeset
703 def handle_visibility_change(self, evt):
fb31d3dba0c3 browser (chat): add marker for new messages when page is not visible
Goffi <goffi@goffi.org>
parents: 1541
diff changeset
704 if (
fb31d3dba0c3 browser (chat): add marker for new messages when page is not visible
Goffi <goffi@goffi.org>
parents: 1541
diff changeset
705 document.visibilityState == "hidden"
fb31d3dba0c3 browser (chat): add marker for new messages when page is not visible
Goffi <goffi@goffi.org>
parents: 1541
diff changeset
706 and self.new_messages_marker_elt.parent is not None
fb31d3dba0c3 browser (chat): add marker for new messages when page is not visible
Goffi <goffi@goffi.org>
parents: 1541
diff changeset
707 ):
fb31d3dba0c3 browser (chat): add marker for new messages when page is not visible
Goffi <goffi@goffi.org>
parents: 1541
diff changeset
708 # if there is a new messages marker, we remove it
fb31d3dba0c3 browser (chat): add marker for new messages when page is not visible
Goffi <goffi@goffi.org>
parents: 1541
diff changeset
709 self.new_messages_marker_elt.remove()
fb31d3dba0c3 browser (chat): add marker for new messages when page is not visible
Goffi <goffi@goffi.org>
parents: 1541
diff changeset
710
fb31d3dba0c3 browser (chat): add marker for new messages when page is not visible
Goffi <goffi@goffi.org>
parents: 1541
diff changeset
711
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
712 libervia_web_chat = LiberviaWebChat()
1540
b4342176fa0a browser (chat): minor reformatting
Goffi <goffi@goffi.org>
parents: 1536
diff changeset
713
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
714 document["message_input"].bind(
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
715 "input", lambda __: libervia_web_chat.auto_resize_message_input()
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
716 )
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
717 document["message_input"].bind("keydown", libervia_web_chat.on_message_keydown)
1584
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
718 document["send_button"].bind(
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
719 "click",
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
720 lambda __: aio.run(libervia_web_chat.send_message())
eab815e48795 browser (chat): message edition + extra menu:
Goffi <goffi@goffi.org>
parents: 1577
diff changeset
721 )
1540
b4342176fa0a browser (chat): minor reformatting
Goffi <goffi@goffi.org>
parents: 1536
diff changeset
722 document["attach_button"].bind("click", libervia_web_chat.on_attach_button_click)
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
723 document["file_input"].bind("change", libervia_web_chat.on_file_selected)
1542
fb31d3dba0c3 browser (chat): add marker for new messages when page is not visible
Goffi <goffi@goffi.org>
parents: 1541
diff changeset
724
fb31d3dba0c3 browser (chat): add marker for new messages when page is not visible
Goffi <goffi@goffi.org>
parents: 1541
diff changeset
725 document.bind("visibilitychange", libervia_web_chat.handle_visibility_change)
fb31d3dba0c3 browser (chat): add marker for new messages when page is not visible
Goffi <goffi@goffi.org>
parents: 1541
diff changeset
726
1536
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
727 bridge.register_signal("message_new", libervia_web_chat._on_message_new)
1577
9ba532041a8e browser (chat): implement message reactions.
Goffi <goffi@goffi.org>
parents: 1542
diff changeset
728 bridge.register_signal("message_update", libervia_web_chat._on_message_update)