annotate libervia/web/pages/_browser/dialog.py @ 1635:332822ceae85

browser (chat): Add rich editor, forward and extra recipients: A new "extra" menu is now available next to input field, allowing to toggle to rich editor. Rich editors allows message styling using bold, italic, underline, (un)numbered list and link. Other features will probably follow with time. An extra menu item allows to add recipients, with `to`, `cc` or `bcc` flag like for emails. Messages can now be forwarded to any entity with a new item in the 3 dots menu. rel 461
author Goffi <goffi@goffi.org>
date Fri, 04 Jul 2025 17:47:37 +0200
parents 698eaabfca0e
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1299
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
1 """manage common dialogs"""
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
2
1625
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
3 from typing import Callable, Literal
1504
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
4 from browser import document, window, timer, console as log
1299
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
5 from template import Template
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
6
1504
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
7 log.warning = log.warn
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
8
1299
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
9
1549
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
10 class CancelError(Exception):
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
11 """Dialog is cancelled"""
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
12
1600
0a4433a343a3 browser (calls): implement WebRTC file sharing:
Goffi <goffi@goffi.org>
parents: 1589
diff changeset
13 def __init__(self, reason: str = "", text: str = "") -> None:
0a4433a343a3 browser (calls): implement WebRTC file sharing:
Goffi <goffi@goffi.org>
parents: 1589
diff changeset
14 self.reason = reason
0a4433a343a3 browser (calls): implement WebRTC file sharing:
Goffi <goffi@goffi.org>
parents: 1589
diff changeset
15 self.text = text
0a4433a343a3 browser (calls): implement WebRTC file sharing:
Goffi <goffi@goffi.org>
parents: 1589
diff changeset
16 super().__init__(text)
0a4433a343a3 browser (calls): implement WebRTC file sharing:
Goffi <goffi@goffi.org>
parents: 1589
diff changeset
17
1549
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
18
1299
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
19 class Confirm:
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
20
1343
8729d2708f65 browser (dialog): color of `OK` button can be specified:
Goffi <goffi@goffi.org>
parents: 1328
diff changeset
21 def __init__(self, message, ok_label="", cancel_label="", ok_color="success"):
1299
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
22 self._tpl = Template("dialogs/confirm.html")
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
23 self.message = message
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
24 self.ok_label = ok_label
1343
8729d2708f65 browser (dialog): color of `OK` button can be specified:
Goffi <goffi@goffi.org>
parents: 1328
diff changeset
25 assert ok_color in ("success", "danger")
8729d2708f65 browser (dialog): color of `OK` button can be specified:
Goffi <goffi@goffi.org>
parents: 1328
diff changeset
26 self.ok_color = ok_color
1299
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
27 self.cancel_label = cancel_label
1589
7228fc3c4744 browser (dialog): be sure to remove dialog on `OK` and `Cancel` click + avoid side effects
Goffi <goffi@goffi.org>
parents: 1549
diff changeset
28 self._notif_elt = None
1549
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
29 self.reset()
1299
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
30
1549
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
31 def reset(self):
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
32 """Reset values of callbacks and notif element"""
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
33 self._ok_cb = None
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
34 self._cancel_cb = None
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
35 self._reject_cb = None
1589
7228fc3c4744 browser (dialog): be sure to remove dialog on `OK` and `Cancel` click + avoid side effects
Goffi <goffi@goffi.org>
parents: 1549
diff changeset
36 if self._notif_elt is not None:
7228fc3c4744 browser (dialog): be sure to remove dialog on `OK` and `Cancel` click + avoid side effects
Goffi <goffi@goffi.org>
parents: 1549
diff changeset
37 self._notif_elt.remove()
7228fc3c4744 browser (dialog): be sure to remove dialog on `OK` and `Cancel` click + avoid side effects
Goffi <goffi@goffi.org>
parents: 1549
diff changeset
38 self._notif_elt = None
1549
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
39
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
40 def _default_cancel_cb(self, evt, notif_elt):
1299
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
41 notif_elt.remove()
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
42
1600
0a4433a343a3 browser (calls): implement WebRTC file sharing:
Goffi <goffi@goffi.org>
parents: 1589
diff changeset
43 def cancel(self, reason: str = "", text: str = ""):
1549
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
44 """Cancel the dialog, without calling any callback
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
45
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
46 will raise a CancelError
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
47 """
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
48 if self._notif_elt is None:
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
49 log.warning("calling cancel on an unshown dialog")
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
50 else:
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
51 self._notif_elt.remove()
1589
7228fc3c4744 browser (dialog): be sure to remove dialog on `OK` and `Cancel` click + avoid side effects
Goffi <goffi@goffi.org>
parents: 1549
diff changeset
52 self._notif_elt = None
1549
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
53 if self._reject_cb is not None:
1600
0a4433a343a3 browser (calls): implement WebRTC file sharing:
Goffi <goffi@goffi.org>
parents: 1589
diff changeset
54 self._reject_cb(CancelError(reason, text))
1549
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
55 else:
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
56 log.warning("no reject callback set")
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
57 self.reset()
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
58
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
59 def on_ok_click(self, evt):
1589
7228fc3c4744 browser (dialog): be sure to remove dialog on `OK` and `Cancel` click + avoid side effects
Goffi <goffi@goffi.org>
parents: 1549
diff changeset
60 evt.preventDefault()
7228fc3c4744 browser (dialog): be sure to remove dialog on `OK` and `Cancel` click + avoid side effects
Goffi <goffi@goffi.org>
parents: 1549
diff changeset
61 evt.stopPropagation()
1549
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
62 assert self._ok_cb is not None
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
63 self._ok_cb(evt, self._notif_elt)
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
64 self.reset()
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
65
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
66 def on_cancel_click(self, evt) -> None:
1589
7228fc3c4744 browser (dialog): be sure to remove dialog on `OK` and `Cancel` click + avoid side effects
Goffi <goffi@goffi.org>
parents: 1549
diff changeset
67 evt.preventDefault()
7228fc3c4744 browser (dialog): be sure to remove dialog on `OK` and `Cancel` click + avoid side effects
Goffi <goffi@goffi.org>
parents: 1549
diff changeset
68 evt.stopPropagation()
1549
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
69 assert self._cancel_cb is not None
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
70 self._cancel_cb(evt, self._notif_elt)
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
71 self.reset()
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
72
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
73 def show(self, ok_cb, cancel_cb=None, reject_cb=None):
1299
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
74 if cancel_cb is None:
1549
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
75 cancel_cb = self._default_cancel_cb
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
76 self._ok_cb = ok_cb
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
77 self._cancel_cb = cancel_cb
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
78 self._reject_cb = reject_cb
1299
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
79 notif_elt = self._tpl.get_elt({
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
80 "message": self.message,
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
81 "ok_label": self.ok_label,
1343
8729d2708f65 browser (dialog): color of `OK` button can be specified:
Goffi <goffi@goffi.org>
parents: 1328
diff changeset
82 "ok_color": self.ok_color,
1299
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
83 "cancel_label": self.cancel_label,
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
84 })
1549
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
85 self._notif_elt = notif_elt
1299
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
86
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
87 document['notifs_area'] <= notif_elt
053141849206 browser: module to handle dialogs, first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
88 timer.set_timeout(lambda: notif_elt.classList.add('state_appended'), 0)
1549
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
89 for ok_elt in notif_elt.select(".click_to_ok"):
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
90 ok_elt.bind("click", self.on_ok_click)
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
91 for ok_elt in notif_elt.select(".click_to_cancel"):
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
92 ok_elt.bind("click", self.on_cancel_click)
1328
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
93
1385
4b6f711b09cb browser (dialog): new `ashow` method to use `Confirm` in async methods
Goffi <goffi@goffi.org>
parents: 1343
diff changeset
94 def _ashow_cb(self, evt, notif_elt, resolve_cb, confirmed):
4b6f711b09cb browser (dialog): new `ashow` method to use `Confirm` in async methods
Goffi <goffi@goffi.org>
parents: 1343
diff changeset
95 evt.stopPropagation()
4b6f711b09cb browser (dialog): new `ashow` method to use `Confirm` in async methods
Goffi <goffi@goffi.org>
parents: 1343
diff changeset
96 notif_elt.remove()
4b6f711b09cb browser (dialog): new `ashow` method to use `Confirm` in async methods
Goffi <goffi@goffi.org>
parents: 1343
diff changeset
97 resolve_cb(confirmed)
4b6f711b09cb browser (dialog): new `ashow` method to use `Confirm` in async methods
Goffi <goffi@goffi.org>
parents: 1343
diff changeset
98
1635
332822ceae85 browser (chat): Add rich editor, forward and extra recipients:
Goffi <goffi@goffi.org>
parents: 1625
diff changeset
99 async def ashow(self) -> bool:
332822ceae85 browser (chat): Add rich editor, forward and extra recipients:
Goffi <goffi@goffi.org>
parents: 1625
diff changeset
100 """Return True if the dialog is confirmed."""
1385
4b6f711b09cb browser (dialog): new `ashow` method to use `Confirm` in async methods
Goffi <goffi@goffi.org>
parents: 1343
diff changeset
101 return window.Promise.new(
4b6f711b09cb browser (dialog): new `ashow` method to use `Confirm` in async methods
Goffi <goffi@goffi.org>
parents: 1343
diff changeset
102 lambda resolve_cb, reject_cb:
4b6f711b09cb browser (dialog): new `ashow` method to use `Confirm` in async methods
Goffi <goffi@goffi.org>
parents: 1343
diff changeset
103 self.show(
4b6f711b09cb browser (dialog): new `ashow` method to use `Confirm` in async methods
Goffi <goffi@goffi.org>
parents: 1343
diff changeset
104 lambda evt, notif_elt: self._ashow_cb(evt, notif_elt, resolve_cb, True),
1549
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
105 lambda evt, notif_elt: self._ashow_cb(evt, notif_elt, resolve_cb, False),
e47c24204449 browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents: 1518
diff changeset
106 reject_cb
1385
4b6f711b09cb browser (dialog): new `ashow` method to use `Confirm` in async methods
Goffi <goffi@goffi.org>
parents: 1343
diff changeset
107 )
4b6f711b09cb browser (dialog): new `ashow` method to use `Confirm` in async methods
Goffi <goffi@goffi.org>
parents: 1343
diff changeset
108 )
4b6f711b09cb browser (dialog): new `ashow` method to use `Confirm` in async methods
Goffi <goffi@goffi.org>
parents: 1343
diff changeset
109
1328
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
110
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
111 class Notification:
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
112
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
113 def __init__(self):
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
114 self._tpl = Template("dialogs/notification.html")
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
115
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
116 def close(self, notif_elt):
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
117 notif_elt.classList.remove('state_appended')
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
118 notif_elt.bind("transitionend", lambda __: notif_elt.remove())
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
119
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
120 def show(
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
121 self,
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
122 message: str,
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
123 level: str = "info",
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
124 delay: int = 5
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
125 ) -> None:
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
126 # we log in console error messages, may be useful
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
127 if level in ("warning", "error"):
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
128 print(f"[{level}] {message}")
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
129 notif_elt = self._tpl.get_elt({
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
130 "message": message,
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
131 "level": level,
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
132 })
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
133 document["notifs_area"] <= notif_elt
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
134 timer.set_timeout(lambda: notif_elt.classList.add('state_appended'), 0)
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
135 timer.set_timeout(lambda: self.close(notif_elt), delay * 1000)
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
136 for elt in notif_elt.select('.click_to_close'):
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
137 elt.bind('click', lambda __: self.close(notif_elt))
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
138
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
139
1504
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
140 class RetryNotification:
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
141 def __init__(self, retry_cb):
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
142 self._tpl = Template("dialogs/retry-notification.html")
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
143 self.retry_cb = retry_cb
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
144 self.counter = 0
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
145 self.timer = None
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
146
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
147 def retry(self, notif_elt):
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
148 if self.timer is not None:
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
149 timer.clear_interval(self.timer)
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
150 self.timer = None
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
151 notif_elt.classList.remove('state_appended')
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
152 notif_elt.bind("transitionend", lambda __: notif_elt.remove())
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
153 self.retry_cb()
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
154
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
155 def update_counter(self, notif_elt):
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
156 counter = notif_elt.select_one(".retry_counter")
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
157 counter.text = str(self.counter)
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
158 self.counter -= 1
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
159 if self.counter < 0:
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
160 self.retry(notif_elt)
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
161
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
162 def show(
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
163 self,
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
164 message: str,
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
165 level: str = "warning",
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
166 delay: int = 5
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
167 ) -> None:
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
168 # we log in console error messages, may be useful
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
169 if level == "error":
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
170 log.error(message)
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
171 elif level == "warning":
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
172 log.warning(message)
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
173 self.counter = delay
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
174 notif_elt = self._tpl.get_elt({
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
175 "message": message,
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
176 "level": level,
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
177 })
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
178 self.update_counter(notif_elt)
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
179 document["notifs_area"] <= notif_elt
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
180 timer.set_timeout(lambda: notif_elt.classList.add('state_appended'), 0)
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
181 self.timer = timer.set_interval(self.update_counter, 1000, notif_elt)
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
182 for elt in notif_elt.select('.click_to_retry'):
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
183 elt.bind('click', lambda __: self.retry(notif_elt))
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
184
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
185
1619
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
186 class Modal:
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
187
1625
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
188 def __init__(
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
189 self,
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
190 content_elt,
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
191 is_card: bool = False,
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
192 closable: bool = False,
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
193 close_cb: Callable|None = None,
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
194 position: Literal["center", "left", "right", "top", "bottom"] = "center"
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
195 ) -> None:
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
196 self.position = position
1619
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
197 self.is_card = is_card
1625
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
198 if is_card and position == 'center':
1619
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
199 if not content_elt.classList.contains("modal-card"):
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
200 raise ValueError(
1625
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
201 'Element must have a "modal-card" class when `is_card` is used for center modal'
1619
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
202 )
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
203 self.closable = closable
1620
3a60bf3762ef browser: threads and replies implementation:
Goffi <goffi@goffi.org>
parents: 1619
diff changeset
204 self._close_cb = close_cb
1619
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
205 self._tpl = Template("dialogs/modal.html")
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
206 self.content_elt = content_elt
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
207 self._modal_elt = None
1625
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
208 self._closing = False
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
209 self._is_panel = position != 'center'
1619
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
210
1625
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
211 def _cleanup(self):
1619
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
212 if self._modal_elt is not None:
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
213 self._modal_elt.remove()
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
214 self._modal_elt = None
1625
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
215 self._closing = False
1619
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
216
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
217 def close(self):
1625
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
218 if self._modal_elt is None or self._closing:
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
219 return
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
220
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
221 self._closing = True
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
222
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
223 self._modal_elt.classList.remove('is-active')
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
224
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
225 if self._is_panel:
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
226 self._modal_elt.classList.add('closing')
1619
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
227
1625
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
228 def on_close_finished():
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
229 if self._close_cb:
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
230 self._close_cb()
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
231 self._cleanup()
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
232
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
233 timer.set_timeout(on_close_finished, 300)
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
234
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
235 def on_background_click(self, evt):
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
236 if self.closable and not self._closing:
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
237 evt.preventDefault()
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
238 evt.stopPropagation()
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
239 self.close()
1619
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
240
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
241 def show(self) -> None:
1625
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
242 if self._modal_elt:
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
243 self._cleanup()
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
244
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
245 self._modal_elt = self._tpl.get_elt({
1619
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
246 "closable": self.closable,
1625
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
247 "position": self.position,
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
248 "is_panel": self._is_panel
1619
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
249 })
1625
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
250
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
251 if self.position == 'center':
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
252 container_elt = self._modal_elt.select_one(".modal-content")
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
253 container_elt <= self.content_elt
1619
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
254 else:
1625
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
255 container_elt = self._modal_elt.select_one(".modal-panel-container")
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
256 container_elt <= self.content_elt
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
257 container_elt.classList.add(f"is-{self.position}")
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
258
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
259 document['notifs_area'] <= self._modal_elt
1619
a2cd4222c702 browser: Updates for new design:
Goffi <goffi@goffi.org>
parents: 1600
diff changeset
260
1625
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
261 if self.closable:
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
262 bg = self._modal_elt.select_one(".modal-background, .modal-panel-background")
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
263 if bg:
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
264 bg.bind("click", self.on_background_click)
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
265
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
266 # Add active class after a small delay to trigger animation
698eaabfca0e browser (chat): side/panel and keyword handling:
Goffi <goffi@goffi.org>
parents: 1620
diff changeset
267 timer.set_timeout(lambda: self._modal_elt.classList.add('is-active'), 10)
1504
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
268
409d10211b20 server, browser: dynamic pages refactoring:
Goffi <goffi@goffi.org>
parents: 1385
diff changeset
269
1328
683e50799d6d browser (dialog): new class to handle notifications
Goffi <goffi@goffi.org>
parents: 1299
diff changeset
270 notification = Notification()