import time import RNS import LXMF from kivy.metrics import dp,sp from kivy.core.clipboard import Clipboard from kivymd.uix.card import MDCard from kivymd.uix.menu import MDDropdownMenu # from kivymd.uix.behaviors import RoundedRectangularElevationBehavior, FakeRectangularElevationBehavior from kivymd.uix.behaviors import CommonElevationBehavior from kivy.properties import StringProperty, BooleanProperty from kivy.uix.gridlayout import GridLayout from kivy.uix.boxlayout import BoxLayout from kivy.clock import Clock from kivymd.uix.button import MDRectangleFlatButton from kivymd.uix.dialog import MDDialog if RNS.vendor.platformutils.get_platform() == "android": from ui.helpers import ts_format, mdc from ui.helpers import color_received, color_delivered, color_propagated, color_failed, color_unknown, intensity_msgs_dark, intensity_msgs_light else: from .helpers import ts_format, mdc from .helpers import color_received, color_delivered, color_propagated, color_failed, color_unknown, intensity_msgs_dark, intensity_msgs_light class ListLXMessageCard(MDCard): # class ListLXMessageCard(MDCard, FakeRectangularElevationBehavior): text = StringProperty() heading = StringProperty() class Messages(): def __init__(self, app, context_dest): self.app = app self.context_dest = context_dest self.messages = [] self.added_item_hashes = [] self.latest_message_timestamp = None self.list = None self.widgets = [] self.send_error_dialog = None self.update() def reload(self): if self.list != None: self.list.clear_widgets() self.messages = [] self.added_item_hashes = [] self.latest_message_timestamp = None self.widgets = [] self.update() def update(self): self.messages = self.app.sideband.list_messages(self.context_dest, self.latest_message_timestamp) if self.list == None: layout = GridLayout(cols=1, spacing=dp(16), padding=dp(16), size_hint_y=None) layout.bind(minimum_height=layout.setter('height')) self.list = layout if len(self.messages) > 0: self.update_widget() if self.app.sideband.config["dark_ui"]: intensity_msgs = intensity_msgs_dark else: intensity_msgs = intensity_msgs_light for w in self.widgets: m = w.m if self.app.sideband.config["dark_ui"]: w.line_color = (1.0, 1.0, 1.0, 0.25) else: w.line_color = (1.0, 1.0, 1.0, 0.5) if m["state"] == LXMF.LXMessage.SENDING or m["state"] == LXMF.LXMessage.OUTBOUND: msg = self.app.sideband.message(m["hash"]) if msg["state"] == LXMF.LXMessage.DELIVERED: w.md_bg_color = msg_color = mdc(color_delivered, intensity_msgs) txstr = time.strftime(ts_format, time.localtime(msg["sent"])) titlestr = "" if msg["title"]: titlestr = "[b]Title[/b] "+msg["title"].decode("utf-8")+"\n" w.heading = titlestr+"[b]Sent[/b] "+txstr+" [b]State[/b] Delivered" m["state"] = msg["state"] if msg["method"] == LXMF.LXMessage.PROPAGATED and msg["state"] == LXMF.LXMessage.SENT: w.md_bg_color = msg_color = mdc(color_propagated, intensity_msgs) txstr = time.strftime(ts_format, time.localtime(msg["sent"])) titlestr = "" if msg["title"]: titlestr = "[b]Title[/b] "+msg["title"].decode("utf-8")+"\n" w.heading = titlestr+"[b]Sent[/b] "+txstr+" [b]State[/b] On Propagation Net" m["state"] = msg["state"] if msg["state"] == LXMF.LXMessage.FAILED: w.md_bg_color = msg_color = mdc(color_failed, intensity_msgs) txstr = time.strftime(ts_format, time.localtime(msg["sent"])) titlestr = "" if msg["title"]: titlestr = "[b]Title[/b] "+msg["title"].decode("utf-8")+"\n" w.heading = titlestr+"[b]Sent[/b] "+txstr+" [b]State[/b] Failed" m["state"] = msg["state"] def update_widget(self): if self.app.sideband.config["dark_ui"]: intensity_msgs = intensity_msgs_dark mt_color = [1.0, 1.0, 1.0, 0.8] else: intensity_msgs = intensity_msgs_light mt_color = [1.0, 1.0, 1.0, 0.95] for m in self.messages: if not m["hash"] in self.added_item_hashes: txstr = time.strftime(ts_format, time.localtime(m["sent"])) rxstr = time.strftime(ts_format, time.localtime(m["received"])) titlestr = "" if m["title"]: titlestr = "[b]Title[/b] "+m["title"].decode("utf-8")+"\n" if m["source"] == self.app.sideband.lxmf_destination.hash: if m["state"] == LXMF.LXMessage.DELIVERED: msg_color = mdc(color_delivered, intensity_msgs) heading_str = titlestr+"[b]Sent[/b] "+txstr+" [b]State[/b] Delivered" elif m["method"] == LXMF.LXMessage.PROPAGATED and m["state"] == LXMF.LXMessage.SENT: msg_color = mdc(color_propagated, intensity_msgs) heading_str = titlestr+"[b]Sent[/b] "+txstr+" [b]State[/b] On Propagation Net" elif m["state"] == LXMF.LXMessage.FAILED: msg_color = mdc(color_failed, intensity_msgs) heading_str = titlestr+"[b]Sent[/b] "+txstr+" [b]State[/b] Failed" elif m["state"] == LXMF.LXMessage.OUTBOUND or m["state"] == LXMF.LXMessage.SENDING: msg_color = mdc(color_unknown, intensity_msgs) heading_str = titlestr+"[b]Sent[/b] "+txstr+" [b]State[/b] Sending " else: msg_color = mdc(color_unknown, intensity_msgs) heading_str = titlestr+"[b]Sent[/b] "+txstr+" [b]State[/b] Unknown" else: msg_color = mdc(color_received, intensity_msgs) heading_str = titlestr+"[b]Sent[/b] "+txstr+"\n[b]Received[/b] "+rxstr item = ListLXMessageCard( text=m["content"].decode("utf-8"), heading=heading_str, md_bg_color=msg_color, ) item.sb_uid = m["hash"] item.m = m item.ids.heading_text.theme_text_color = "Custom" item.ids.heading_text.text_color = mt_color item.ids.content_text.theme_text_color = "Custom" item.ids.content_text.text_color = mt_color item.ids.msg_submenu.theme_text_color = "Custom" item.ids.msg_submenu.text_color = mt_color def gen_del(mhash, item): def x(): yes_button = MDRectangleFlatButton(text="Yes",font_size=dp(18), theme_text_color="Custom", line_color=self.app.color_reject, text_color=self.app.color_reject) no_button = MDRectangleFlatButton(text="No",font_size=dp(18)) dialog = MDDialog( title="Delete message?", buttons=[ yes_button, no_button ], # elevation=0, ) def dl_yes(s): dialog.dismiss() self.app.sideband.delete_message(mhash) def cb(dt): self.reload() Clock.schedule_once(cb, 0.2) def dl_no(s): dialog.dismiss() yes_button.bind(on_release=dl_yes) no_button.bind(on_release=dl_no) item.dmenu.dismiss() dialog.open() return x def gen_copy(msg, item): def x(): Clipboard.copy(msg) RNS.log(str(item)) item.dmenu.dismiss() return x dm_items = [ { "viewclass": "OneLineListItem", "text": "Copy", "height": dp(40), "on_release": gen_copy(m["content"].decode("utf-8"), item) }, { "text": "Delete", "viewclass": "OneLineListItem", "height": dp(40), "on_release": gen_del(m["hash"], item) } ] item.dmenu = MDDropdownMenu( caller=item.ids.msg_submenu, items=dm_items, position="center", width_mult=4, elevation=1, radius=dp(3), opening_transition="linear", opening_time=0.0, ) def callback_factory(ref): def x(sender): ref.dmenu.open() return x # Bind menu open item.ids.msg_submenu.bind(on_release=callback_factory(item)) self.added_item_hashes.append(m["hash"]) self.widgets.append(item) self.list.add_widget(item) if self.latest_message_timestamp == None or m["received"] > self.latest_message_timestamp: self.latest_message_timestamp = m["received"] def get_widget(self): return self.list def close_send_error_dialog(self, sender=None): if self.send_error_dialog: self.send_error_dialog.dismiss()