Mercurial > libervia-web
comparison libervia/web/pages/_browser/jid_search.py @ 1619:a2cd4222c702
browser: Updates for new design:
This patch add code to handle the new design for chat.
New bridge method are used to invite users to MUC or get list of occupants.
A new modules is used for components, with a first one for collapsible cards.
rel 457
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 12 Apr 2025 00:21:45 +0200 |
parents | 4a9679369856 |
children |
comparison
equal
deleted
inserted
replaced
1618:5d9889f14012 | 1619:a2cd4222c702 |
---|---|
1 import json | 1 import json |
2 from typing import Callable | |
2 from urllib.parse import quote, urljoin | 3 from urllib.parse import quote, urljoin |
3 | 4 |
4 from bridge import AsyncBridge as Bridge | 5 from bridge import AsyncBridge as Bridge |
5 from browser import aio, console as log, window | 6 from browser import aio, console as log, window |
6 from cache import cache | 7 from cache import cache |
8 import errors | |
7 from template import Template | 9 from template import Template |
8 import jid | 10 import jid |
9 | 11 |
10 log.warning = log.warn | 12 log.warning = log.warn |
11 profile = window.profile or "" | 13 profile = window.profile or "" |
15 | 17 |
16 def __init__( | 18 def __init__( |
17 self, | 19 self, |
18 search_elt, | 20 search_elt, |
19 container_elt=None, | 21 container_elt=None, |
20 filter_cb=None, | 22 filter_cb: Callable[[list[str]], None]|None = None, |
21 empty_cb=None, | 23 empty_cb=None, |
22 get_url=None, | 24 get_url=None, |
23 click_cb=None, | 25 click_cb=None, |
24 options: dict|None = None, | 26 options: dict|None = None, |
25 submit_filter: bool = True, | 27 submit_filter: bool = True, |
37 @param get_url: The function to get URL for each entity in the search result | 39 @param get_url: The function to get URL for each entity in the search result |
38 @param click_cb: The function to handle the click event on each entity in the | 40 @param click_cb: The function to handle the click event on each entity in the |
39 search result | 41 search result |
40 @param options: extra options. Key can be: | 42 @param options: extra options. Key can be: |
41 no_group(bool) | 43 no_group(bool) |
42 True if groups should not be visible | 44 True if entity groups should not be visible |
45 type (str) | |
46 Can be "group" or "one2one". Default to one2one. | |
43 extra_cb(dict) | 47 extra_cb(dict) |
44 a map from CSS selector to callback, the callback will be binded to the | 48 a map from CSS selector to callback, the callback will be binded to the |
45 "click" event, and will be called with the ``item`` as argument | 49 "click" event, and will be called with the ``item`` as argument |
46 @param submit_filter: if True, only submit when a seemingly valid JID is entered | 50 @param submit_filter: if True, only submit when a seemingly valid JID is entered |
47 @param template: template to use | 51 @param template: template to use |
50 @param selected_item_class: The CSS class to apply when an item is selected. This | 54 @param selected_item_class: The CSS class to apply when an item is selected. This |
51 class should define distinctive styles to highlight selected items. | 55 class should define distinctive styles to highlight selected items. |
52 @param selection_state_callback: A callback function to execute when selection | 56 @param selection_state_callback: A callback function to execute when selection |
53 state changes. Takes one boolean parameter indicating if items are selected. | 57 state changes. Takes one boolean parameter indicating if items are selected. |
54 """ | 58 """ |
59 self.selected = set() | |
60 self.current_items = set() | |
55 self.search_item_tpl = Template(template) | 61 self.search_item_tpl = Template(template) |
56 self.search_elt = search_elt | 62 self.search_elt = search_elt |
57 self.search_elt.bind("input", self.on_search_input) | 63 self.search_elt.bind("input", self.on_search_input) |
58 if submit_filter: | 64 if submit_filter: |
59 try: | 65 try: |
66 self.current_query = None | 72 self.current_query = None |
67 self.container_elt = container_elt | 73 self.container_elt = container_elt |
68 if options is None: | 74 if options is None: |
69 options = {} | 75 options = {} |
70 self.options = options | 76 self.options = options |
77 match options.get("type"): | |
78 case None | "one2one": | |
79 self.group = False | |
80 case "group": | |
81 self.group = True | |
82 case _: | |
83 raise errors.InternalError(f"Invalid type: {options.get('type')!r}.") | |
71 | 84 |
72 if click_cb is not None and get_url is None: | 85 if click_cb is not None and get_url is None: |
73 self.get_url = lambda _: "#" | 86 self.get_url = lambda _: "#" |
74 else: | 87 else: |
75 self.get_url = get_url if get_url is not None else self.default_get_url | 88 self.get_url = get_url if get_url is not None else self.default_get_url |
192 | 205 |
193 async def perform_search(self, query): | 206 async def perform_search(self, query): |
194 if self.current_query is None: | 207 if self.current_query is None: |
195 log.debug(f"performing search: {query=}") | 208 log.debug(f"performing search: {query=}") |
196 self.current_query = query | 209 self.current_query = query |
197 jid_items = json.loads(await bridge.jid_search(query, "")) | 210 if self.group: |
211 options = {"entities": False, "groupchat": True} | |
212 else: | |
213 options = {"entities": True, "groupchat": False} | |
214 jid_items = json.loads(await bridge.jid_search(query, json.dumps(options))) | |
198 await cache.fill_identities(i["entity"] for i in jid_items) | 215 await cache.fill_identities(i["entity"] for i in jid_items) |
199 | 216 |
200 self.last_query = query | 217 self.last_query = query |
201 self.current_query = None | 218 self.current_query = None |
202 current_query = self.search_elt.value.strip() | 219 current_query = self.search_elt.value.strip() |
219 self.filter_cb(filtered_items) | 236 self.filter_cb(filtered_items) |
220 | 237 |
221 async def on_empty_search(self, jid_search): | 238 async def on_empty_search(self, jid_search): |
222 """Handle the situation when the search box is empty""" | 239 """Handle the situation when the search box is empty""" |
223 assert self.container_elt is not None | 240 assert self.container_elt is not None |
224 items = [ | 241 if self.group: |
225 { | 242 items = [] |
226 "entity": jid_, | 243 else: |
227 "groups": data["groups"] | 244 items = [ |
228 } | 245 { |
229 for jid_, data in cache.roster.items() | 246 "entity": jid_, |
230 ] | 247 "groups": data["groups"] |
248 } | |
249 for jid_, data in cache.roster.items() | |
250 ] | |
231 self.show_items(items) | 251 self.show_items(items) |
232 | 252 |
233 def on_checkbox_change(self, evt, item): | 253 def on_checkbox_change(self, evt, item): |
234 log.debug(f"checkbox_change {evt.target=} {item=}") | 254 log.debug(f"checkbox_change {evt.target=} {item=}") |
235 evt.stopPropagation() | 255 evt.stopPropagation() |