annotate libervia/web/pages/chat/_browser/__init__.py @ 1536:dc81403a5b2f

browser: chat page: since the move to Brython, the chat was really basic and not really usable. Now that dynamism has been re-implemented correctly in the new frontend, a real advanced chat page can be done. This is the first draft in this direction.
author Goffi <goffi@goffi.org>
date Wed, 28 Jun 2023 10:05:13 +0200
parents
children b4342176fa0a
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
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
2
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
3 import dialog
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
4 import jid
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
5 from bridge import AsyncBridge as Bridge
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
6 from browser import aio, console as log, document, DOMNode, window, bind
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
7 from template import Template, safe
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
8 from file_uploader import FileUploader
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
9 from cache import cache, identities
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
10
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
11 log.warning = log.warn
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
12 profile = window.profile or ""
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
13 own_jid = jid.JID(window.own_jid)
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
14 target_jid = jid.JID(window.target_jid)
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
15 bridge = Bridge()
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
16
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
17 # Sensible value to consider that user is at the bottom
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
18 SCROLL_SENSITIVITY = 200
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
19
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
20
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
21 class LiberviaWebChat:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
22
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
23 def __init__(self):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
24 self.message_tpl = Template("chat/message.html")
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
25 self.messages_elt = document["messages"]
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
26
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
27 # attachments
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
28 self.file_uploader = FileUploader(
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
29 "", "chat/attachment_preview.html", on_delete_cb=self.on_attachment_delete
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
30 )
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
31 self.attachments_elt = document["attachments"]
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
32 self.message_input = document["message_input"]
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
33
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
34 # hide/show attachments
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
35 MutationObserver = window.MutationObserver
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
36 observer = MutationObserver.new(lambda *__: self.update_attachments_visibility())
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
37 observer.observe(self.attachments_elt, {"childList": True})
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
38
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
39 # we want the message scroll to be initially at the bottom
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
40 self.messages_elt.scrollTop = self.messages_elt.scrollHeight
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
41
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
42 @property
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
43 def is_at_bottom(self):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
44 return (
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
45 self.messages_elt.scrollHeight
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
46 - self.messages_elt.scrollTop
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
47 - self.messages_elt.clientHeight
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
48 <= SCROLL_SENSITIVITY
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
49 )
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
50
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
51
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
52 def send_message(self):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
53 """Send message currently in input area
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
54
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
55 The message and corresponding attachment will be sent
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
56 """
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
57 message = self.message_input.value.rstrip()
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
58 log.info(f"{message=}")
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
59
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
60 # attachments
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
61 attachments = []
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
62 for attachment_elt in self.attachments_elt.children:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
63 file_data = json.loads(attachment_elt.getAttribute("data-file"))
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
64 attachments.append(file_data)
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
65
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
66 if message or attachments:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
67 extra = {}
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
68
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
69 if attachments:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
70 extra["attachments"] = attachments
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
71
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
72 # now we send the message
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
73 try:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
74 aio.run(
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
75 bridge.message_send(
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
76 str(target_jid), {"": message}, {}, "auto", json.dumps(extra)
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
77 )
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
78 )
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
79 except Exception as e:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
80 dialog.notification.show(f"Can't send message: {e}", "error")
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
81 else:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
82 self.message_input.value = ""
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
83 self.attachments_elt.clear()
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
84
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
85 def _on_message_new(
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
86 self,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
87 uid: str,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
88 timestamp: float,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
89 from_jid: str,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
90 to_jid: str,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
91 message: dict,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
92 subject: dict,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
93 mess_type: str,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
94 extra_s: str,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
95 profile: str,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
96 ) -> None:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
97 if (
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
98 jid.JID(from_jid).bare == window.target_jid
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
99 or jid.JID(to_jid).bare == window.target_jid
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
100 ):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
101 aio.run(
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
102 self.on_message_new(
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
103 uid,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
104 timestamp,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
105 from_jid,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
106 to_jid,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
107 message,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
108 subject,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
109 mess_type,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
110 json.loads(extra_s),
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
111 profile,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
112 )
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
113 )
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
114
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
115 async def on_message_new(
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
116 self,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
117 uid: str,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
118 timestamp: float,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
119 from_jid: str,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
120 to_jid: str,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
121 message_data: dict,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
122 subject_data: dict,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
123 mess_type: str,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
124 extra: dict,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
125 profile: str,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
126 ) -> None:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
127 log.info(f"on_message_new: [{from_jid} -> {to_jid}] {message_data}, {extra=}")
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
128 xhtml_data = extra.get("xhtml")
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
129 if not xhtml_data:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
130 xhtml = None
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
131 else:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
132 try:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
133 xhtml = xhtml_data[""]
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
134 except KeyError:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
135 xhtml = next(iter(xhtml_data.values()))
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
136
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
137 await cache.fill_identities([from_jid])
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
138
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
139 msg_data = {
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
140 "id": uid,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
141 "timestamp": timestamp,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
142 "type": mess_type,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
143 "from_": from_jid,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
144 "text": message_data.get("") or next(iter(message_data.values()), ""),
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
145 "subject": subject_data.get("") or next(iter(subject_data.values()), ""),
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
146 "type": mess_type,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
147 "thread": extra.get("thread"),
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
148 "thread_parent": extra.get("thread_parent"),
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
149 "reeceived": extra.get("received_timestamp") or timestamp,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
150 "delay_sender": extra.get("delay_sender"),
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
151 "info_type": extra.get("info_type"),
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
152 "html": safe(xhtml) if xhtml else None,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
153 "encrypted": extra.get("encrypted", False),
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
154 "received": extra.get("received", False),
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
155 "edited": extra.get("edited", False),
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
156 "attachments": extra.get("attachments", []),
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
157 }
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
158 message_elt = self.message_tpl.get_elt(
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
159 {
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
160 "own_jid": own_jid,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
161 "msg": msg_data,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
162 "identities": identities,
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
163 }
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
164 )
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
165
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
166 # Check if user is viewing older messages or is at the bottom
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
167 is_at_bottom = self.is_at_bottom
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
168
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
169 self.messages_elt <= message_elt
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
170 self.make_attachments_dynamic(message_elt)
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
171
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
172 # If user was at the bottom, keep the scroll at the bottom
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
173 if is_at_bottom:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
174 self.messages_elt.scrollTop = self.messages_elt.scrollHeight
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
175
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
176 def auto_resize_message_input(self):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
177 """Resize the message input field according to content."""
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
178
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
179 is_at_bottom = self.is_at_bottom
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
180
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
181 # 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
182 # the previous content.
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
183 self.message_input.style.height = "auto"
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
184
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
185 # 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
186 # 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
187 # more lines of text are added.
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
188 self.message_input.style.height = f"{self.message_input.scrollHeight + 2}px"
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
189
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
190 if is_at_bottom:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
191 # we want the message are to still display the last message
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
192 self.messages_elt.scrollTop = self.messages_elt.scrollHeight
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
193
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
194 def on_message_keydown(self, evt):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
195 """Handle the 'keydown' event of the message input field
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
196
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
197 @param evt: The event object. 'target' refers to the textarea element.
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
198 """
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
199 if evt.keyCode == 13: # <Enter> key
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
200 if not window.navigator.maxTouchPoints:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
201 # we have a non touch device, we send message on <Enter>
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
202 if not evt.shiftKey:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
203 evt.preventDefault() # Prevents line break
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
204 self.send_message()
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
205
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
206 def update_attachments_visibility(self):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
207 if len(self.attachments_elt.children):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
208 self.attachments_elt.classList.remove("is-contracted")
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
209 else:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
210 self.attachments_elt.classList.add("is-contracted")
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
211
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
212 def on_file_selected(self, evt):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
213 """Handle file selection"""
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
214 log.info("file selected")
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
215 files = evt.currentTarget.files
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
216 self.file_uploader.upload_files(files, self.attachments_elt)
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
217 self.message_input.focus()
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
218
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
219 def on_attachment_delete(self, evt):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
220 evt.stopPropagation()
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
221 target = evt.currentTarget
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
222 item_elt = DOMNode(target.closest('.attachment-preview'))
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
223 item_elt.remove()
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
224
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
225 def on_attach_button_click(self, evt):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
226 document["file_input"].click()
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
227
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
228 @bind(document["attachments"], 'wheel')
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
229 def wheel_event(evt):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
230 """Make the mouse wheel to act on horizontal scrolling for attachments
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
231
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
232 Attachments don't have vertical scrolling, thus is makes sense to use the wheel
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
233 for horizontal scrolling
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
234 """
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
235 if evt.deltaY != 0:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
236 document['attachments'].scrollLeft += evt.deltaY * 0.8
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
237 evt.preventDefault()
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
238
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
239 def make_attachments_dynamic(self, parent_elt = None):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
240 """Make attachments dynamically clickable"""
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
241 # FIXME: only handle images for now, and display them in a modal
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
242 if parent_elt is None:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
243 parent_elt = document
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
244 img_elts = parent_elt.select('.message-attachment img')
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
245 for img_elt in img_elts:
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
246 img_elt.bind('click', self.open_modal)
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
247 img_elt.style.cursor = 'pointer'
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
248
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
249 close_button = document.select_one('.modal-close')
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
250 close_button.bind('click', self.close_modal)
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
251
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
252 def open_modal(self, evt):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
253 modal_image = document.select_one('#modal-image')
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
254 modal_image.src = evt.target.src
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
255 modal_image.alt = evt.target.alt
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
256 modal = document.select_one('#modal')
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
257 modal.classList.add('is-active')
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
258
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
259 def close_modal(self, evt):
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
260 modal = document.select_one('#modal')
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
261 modal.classList.remove('is-active')
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
262
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
263
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
264 libervia_web_chat = LiberviaWebChat()
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
265 document["message_input"].bind(
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
266 "input", lambda __: libervia_web_chat.auto_resize_message_input()
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
267 )
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
268 document["message_input"].bind("keydown", libervia_web_chat.on_message_keydown)
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
269 document["send_button"].bind("click", lambda __: libervia_web_chat.send_message())
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
270 document["attach_button"].bind(
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
271 "click", libervia_web_chat.on_attach_button_click
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
272 )
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
273 document["file_input"].bind("change", libervia_web_chat.on_file_selected)
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
274 bridge.register_signal("message_new", libervia_web_chat._on_message_new)
dc81403a5b2f browser: chat page:
Goffi <goffi@goffi.org>
parents:
diff changeset
275 libervia_web_chat.make_attachments_dynamic()