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()