Mercurial > libervia-desktop-kivy
diff libervia/desktop_kivy/plugins/plugin_wid_blog.py @ 493:b3cedbee561d
refactoring: rename `cagou` to `libervia.desktop_kivy` + update imports and names following backend changes
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 02 Jun 2023 18:26:16 +0200 |
parents | cagou/plugins/plugin_wid_blog.py@203755bbe0fe |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libervia/desktop_kivy/plugins/plugin_wid_blog.py Fri Jun 02 18:26:16 2023 +0200 @@ -0,0 +1,192 @@ +#!/usr/bin/env python3 + +#desktop/mobile frontend for Libervia XMPP client +# Copyright (C) 2016-2022 Jérôme Poisson (goffi@goffi.org) + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +from functools import partial +import json +from typing import Any, Dict, Optional + +from kivy import properties +from kivy.metrics import sp +from kivy.uix.behaviors import ButtonBehavior +from kivy.uix.boxlayout import BoxLayout +from libervia.backend.core import log as logging +from libervia.backend.core.i18n import _ +from libervia.backend.tools.common import data_format +from libervia.frontends.bridge.bridge_frontend import BridgeException +from libervia.frontends.quick_frontend import quick_widgets +from libervia.frontends.tools import jid + +from libervia.desktop_kivy import G +from libervia.desktop_kivy.core.menu import SideMenu + +from ..core import cagou_widget +from ..core.common import SymbolButton +from ..core.constants import Const as C +from ..core.image import Image + +log = logging.getLogger(__name__) + +PLUGIN_INFO = { + "name": _("blog"), + "main": "Blog", + "description": _("(micro)blog"), + "icon_symbol": "pencil", +} + + +class SearchButton(SymbolButton): + blog = properties.ObjectProperty() + + def on_release(self, *args): + self.blog.header_input.dispatch('on_text_validate') + + +class NewPostButton(SymbolButton): + blog = properties.ObjectProperty() + + def on_release(self, *args): + self.blog.show_new_post_menu() + + +class NewPosttMenu(SideMenu): + blog = properties.ObjectProperty() + size_hint_close = (1, 0) + size_hint_open = (1, 0.9) + + def _publish_cb(self, item_id: str) -> None: + G.host.add_note( + _("blog post published"), + _("your blog post has been published with ID {item_id}").format( + item_id=item_id + ) + ) + self.blog.load_blog() + + def _publish_eb(self, exc: BridgeException) -> None: + G.host.add_note( + _("Problem while publish blog post"), + _("Can't publish blog post at {node!r} from {service}: {problem}").format( + node=self.blog.node or G.host.ns_map.get("microblog"), + service=( + self.blog.service if self.blog.service + else G.host.profiles[self.blog.profile].whoami, + ), + problem=exc + ), + C.XMLUI_DATA_LVL_ERROR + ) + + def publish( + self, + title: str, + content: str, + e2ee: bool = False + ) -> None: + self.hide() + mb_data: Dict[str, Any] = {"content_rich": content} + if e2ee: + mb_data["encrypted"] = True + title = title.strip() + if title: + mb_data["title_rich"] = title + G.host.bridge.mb_send( + self.blog.service, + self.blog.node, + data_format.serialise(mb_data), + self.blog.profile, + callback=self._publish_cb, + errback=self._publish_eb, + ) + + +class BlogPostAvatar(ButtonBehavior, Image): + pass + + +class BlogPostWidget(BoxLayout): + blog_data = properties.DictProperty() + font_size = properties.NumericProperty(sp(12)) + title_font_size = properties.NumericProperty(sp(14)) + + +class Blog(quick_widgets.QuickWidget, cagou_widget.LiberviaDesktopKivyWidget): + posts_widget = properties.ObjectProperty() + service = properties.StringProperty() + node = properties.StringProperty() + use_header_input = True + + def __init__(self, host, target, profiles): + quick_widgets.QuickWidget.__init__(self, G.host, target, profiles) + cagou_widget.LiberviaDesktopKivyWidget.__init__(self) + search_btn = SearchButton(blog=self) + self.header_input_add_extra(search_btn) + new_post_btn = NewPostButton(blog=self) + self.header_input_add_extra(new_post_btn) + self.load_blog() + + def on_kv_post(self, __): + self.bind( + service=lambda __, value: self.load_blog(), + node=lambda __, value: self.load_blog(), + ) + + def on_header_wid_input(self): + text = self.header_input.text.strip() + # for now we only use text as node + self.node = text + + def show_new_post_menu(self): + """Show the "add a contact" menu""" + NewPosttMenu(blog=self).show() + + def _mb_get_cb(self, blog_data_s: str) -> None: + blog_data = json.loads(blog_data_s) + for item in blog_data["items"]: + self.posts_widget.add_widget(BlogPostWidget(blog_data=item)) + + def _mb_get_eb( + self, + exc: BridgeException, + ) -> None: + G.host.add_note( + _("Problem while getting blog data"), + _("Can't get blog for {node!r} at {service}: {problem}").format( + node=self.node or G.host.ns_map.get("microblog"), + service=self.service if self.service else G.host.profiles[self.profile].whoami, + problem=exc + ), + C.XMLUI_DATA_LVL_ERROR + ) + + def load_blog( + self, + ) -> None: + """Retrieve a blog and display it""" + extra = {} + self.posts_widget.clear_widgets() + G.host.bridge.mb_get( + self.service, + self.node, + 20, + [], + data_format.serialise(extra), + self.profile, + callback=self._mb_get_cb, + errback=self._mb_get_eb, + )