Mercurial > libervia-web
changeset 1638:4670dbf49909
browser (blog): Add initial browser implementation.
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 04 Jul 2025 18:22:44 +0200 |
parents | 29dd52585984 |
children | 301fe2f1a34a |
files | libervia/web/pages/blog/_browser/__init__.py |
diffstat | 1 files changed, 144 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libervia/web/pages/blog/_browser/__init__.py Fri Jul 04 18:22:44 2025 +0200 @@ -0,0 +1,144 @@ +#!/usr/bin/env python3 + +import json + +import alt_media_player +from bridge import AsyncBridge as Bridge +from browser import aio, document, console as log, window +from cache import identities, roster +from template import Template +from javascript import pyobj2jsobj +from js_modules.tippy_js import tippy as tippy_ori + + +log.warning = log.warn +bridge = Bridge() +alt_media_player.install_if_needed() + +own_jid = window.own_jid +blog_url = window.blog_url +service = window.service +node = window.node + + +# FIXME: workaround for https://github.com/brython-dev/brython/issues/2542 +def tippy(target, data): + return tippy_ori(target, pyobj2jsobj(data)) + + +class LiberviaWebBlog: + + def __init__(self) -> None: + # Templates + self.reactions_tpl = Template("components/reactions.html") + self.reactions_details_tpl = Template("components/reactions_details.html") + + # panels and their toggle buttons + self.left_panel = document["left_panel"] + self.left_toggle = document["left_panel-toggle"] + self.left_toggle.bind("click", self.on_left_panel_toggle_click) + self.main_panel = document["main_panel"] + self.contacts_links_tpl = Template("components/contacts_links.html") + contacts_links_elt = self.contacts_links_tpl.get_elt( + { + "roster": roster, + "identities": identities, + "base_url": blog_url + } + ) + document["contact-blogs"] <= contacts_links_elt + self.post_init_blog_item() + + def on_left_panel_toggle_click(self, evt) -> None: + """Show/Hide side bar.""" + self.left_panel.classList.toggle("is-collapsed") + # self.main_panel.classList.toggle("is-expanded-left") + + async def on_reaction_click(self, evt, blog_item_elt): + item_id = blog_item_elt["id"] + window.evt = evt + reaction = evt.detail["unicode"] + attachments_data = { + "service": service, + "node": node, + "id": item_id, + "extra": {"reactions": {"add": [reaction]}} + } + await bridge.ps_attachments_set(json.dumps(attachments_data)) + + def get_reaction_panel(self, source_elt): + emoji_picker_elt = document.createElement("emoji-picker") + blog_item_elt = source_elt.closest("article.blog-item") + emoji_picker_elt.bind( + "emoji-click", lambda evt: aio.run(self.on_reaction_click(evt, blog_item_elt)) + ) + + return emoji_picker_elt + + async def add_attachments(self, blog_item_elt) -> None: + try: + attachments_s, metadata_s = await bridge.ps_attachments_get( + service, node, blog_item_elt["id"], [], "" + ) + except Exception as e: + log.warning( + f"Can't find attachments for {blog_item_elt['id']}: {e}" + ) + else: + attachments = json.loads(attachments_s) + metadata = json.loads(metadata_s) + reactions: dict[str, list[str]] = {} + for attachment in attachments: + if "reactions" in attachment: + for reaction in attachment["reactions"]["reactions"]: + reactions.setdefault(reaction, []).append(attachment["from"]) + if reactions: + reactions_elt = self.reactions_tpl.get_elt( + { + "own_jid": str(own_jid), + "reactions": reactions + }) + footer = blog_item_elt.select_one("div.blog-item-footer") + if footer is not None: + footer <= reactions_elt + + + def post_init_blog_item(self, parent_elt = None) -> None: + """Make the dynamic elements clickabled and add attachments to blog item. + + @parent_elt: all ``blog_item`` elements of this element (or ``parent_elt`` itself + if it's a blog_item) well be handled. + If None, all blog items of the whole document will be handled. + """ + if parent_elt is None: + blog_items = document.select(".blog-item") + elif parent_elt.classList.contains(".blog-item"): + blog_items= [parent_elt] + else: + blog_items = parent_elt.select(".blog-item") + + for blog_item_elt in blog_items: + aio.run(self.add_attachments(blog_item_elt)) + reaction_button_elt = blog_item_elt.select_one("button.reaction-button") + if reaction_button_elt: + tippy( + reaction_button_elt, + { + "trigger": "click", + "content": self.get_reaction_panel, + "appendTo": document.body, + "placement": "bottom", + "interactive": True, + "theme": "light", + "onShow": lambda __, blog_item_elt=blog_item_elt: ( + blog_item_elt.classList.add("has-popup-focus") + ), + "onHide": lambda __, blog_item_elt=blog_item_elt: ( + blog_item_elt.classList.remove("has-popup-focus") + ), + } + ) + + + +libervia_web_blog = LiberviaWebBlog()