From 11439dcabdebcecf3b64d8adb00de7fd25b8986e Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Fri, 27 Oct 2023 20:28:33 +0200 Subject: [PATCH] Improved LXMF sync feedback --- sbapp/main.py | 108 +++++++++++++++++++----------- sbapp/services/sidebandservice.py | 2 +- sbapp/sideband/core.py | 29 +++++++- sbapp/ui/conversations.py | 1 + 4 files changed, 97 insertions(+), 43 deletions(-) diff --git a/sbapp/main.py b/sbapp/main.py index f3a4d40..a9bbef6 100644 --- a/sbapp/main.py +++ b/sbapp/main.py @@ -648,10 +648,16 @@ class SidebandApp(MDApp): self.conversations_view.update() if self.sideband.getstate("app.flags.lxmf_sync_dialog_open", allow_cache=True) and self.sync_dialog != None: - self.sync_dialog.ids.sync_progress.value = self.sideband.get_sync_progress()*100 - self.sync_dialog.ids.sync_status.text = self.sideband.get_sync_status() - state = self.sideband.message_router.propagation_transfer_state + + dlg_sp = self.sideband.get_sync_progress()*100; dlg_ss = self.sideband.get_sync_status() + if state > LXMF.LXMRouter.PR_IDLE and state <= LXMF.LXMRouter.PR_COMPLETE: + self.sync_dialog.ids.sync_progress.value = dlg_sp + else: + self.sync_dialog.ids.sync_progress.value = 0.1 + + self.sync_dialog.ids.sync_status.text = dlg_ss + if state > LXMF.LXMRouter.PR_IDLE and state < LXMF.LXMRouter.PR_COMPLETE: self.widget_hide(self.sync_dialog.stop_button, False) else: @@ -797,7 +803,10 @@ class SidebandApp(MDApp): self.telemetry_action(self) if len(modifiers) > 0 and modifiers[0] == 'ctrl' and (text == "r"): - self.conversations_action(self) + if self.root.ids.screen_manager.current == "conversations_screen": + self.lxmf_sync_action(self) + else: + self.conversations_action(self) if len(modifiers) > 0 and modifiers[0] == 'ctrl' and (text == "g"): self.guide_action(self) @@ -1112,9 +1121,9 @@ class SidebandApp(MDApp): else: if self.sideband.reticulum.is_connected_to_shared_instance: - connectivity_status = "Sideband is connected via a shared Reticulum instance running on this system. Use the rnstatus utility to obtain full connectivity info." + connectivity_status = "Sideband is connected via a shared Reticulum instance running on this system. Use the [b]rnstatus[/b] utility to obtain full connectivity info." else: - connectivity_status = "Sideband is currently running a standalone or master Reticulum instance on this system. Use the rnstatus utility to obtain full connectivity info." + connectivity_status = "Sideband is currently running a standalone or master Reticulum instance on this system. Use the [b]rnstatus[/b] utility to obtain full connectivity info." return connectivity_status @@ -1216,42 +1225,61 @@ class SidebandApp(MDApp): else: sl = None - self.sideband.setpersistent("lxmf.lastsync", time.time()) - self.sideband.setpersistent("lxmf.syncretrying", False) - self.sideband.request_lxmf_sync(limit=sl) + if not hasattr(self, "message_sync_dialog") or self.message_sync_dialog == None: + close_button = MDRectangleFlatButton(text="Close",font_size=dp(18)) + stop_button = MDRectangleFlatButton(text="Stop",font_size=dp(18), theme_text_color="Custom", line_color=self.color_reject, text_color=self.color_reject) - close_button = MDRectangleFlatButton(text="Close",font_size=dp(18)) - stop_button = MDRectangleFlatButton(text="Stop",font_size=dp(18), theme_text_color="Custom", line_color=self.color_reject, text_color=self.color_reject) - dialog_content = MsgSync() - dialog = MDDialog( - title="LXMF Sync via "+RNS.prettyhexrep(self.sideband.message_router.get_outbound_propagation_node()), - type="custom", - content_cls=dialog_content, - buttons=[ stop_button, close_button ], - # elevation=0, - ) - dialog.d_content = dialog_content - def dl_close(s): - self.sideband.setstate("app.flags.lxmf_sync_dialog_open", False) - dialog.dismiss() - # self.sideband.cancel_lxmf_sync() + dialog_content = MsgSync() + dialog = MDDialog( + title="LXMF Sync via "+RNS.prettyhexrep(self.sideband.message_router.get_outbound_propagation_node()), + type="custom", + content_cls=dialog_content, + buttons=[ stop_button, close_button ], + # elevation=0, + ) + dialog.d_content = dialog_content + def dl_close(s): + self.sideband.setstate("app.flags.lxmf_sync_dialog_open", False) + dialog.dismiss() + self.message_sync_dialog.d_content.ids.sync_progress.value = 0.1 + self.message_sync_dialog.d_content.ids.sync_status.text = "" - def dl_stop(s): - # self.sideband.setstate("app.flags.lxmf_sync_dialog_open", False) - # dialog.dismiss() - self.sideband.cancel_lxmf_sync() - def cb(dt): - self.widget_hide(self.sync_dialog.stop_button, True) - Clock.schedule_once(cb, 0.25) + # self.sideband.cancel_lxmf_sync() + + def dl_stop(s): + # self.sideband.setstate("app.flags.lxmf_sync_dialog_open", False) + # dialog.dismiss() + self.sideband.cancel_lxmf_sync() + def cb(dt): + self.widget_hide(self.sync_dialog.stop_button, True) + Clock.schedule_once(cb, 0.25) + + close_button.bind(on_release=dl_close) + stop_button.bind(on_release=dl_stop) + + self.message_sync_dialog = dialog + self.sync_dialog = dialog_content + self.sync_dialog.stop_button = stop_button + + s_state = self.sideband.message_router.propagation_transfer_state + if s_state > LXMF.LXMRouter.PR_PATH_REQUESTED and s_state <= LXMF.LXMRouter.PR_COMPLETE: + dsp = self.sideband.get_sync_progress()*100 + else: + dsp = 0 - close_button.bind(on_release=dl_close) - stop_button.bind(on_release=dl_stop) self.sideband.setstate("app.flags.lxmf_sync_dialog_open", True) - self.sync_dialog = dialog_content - self.sync_dialog.stop_button = stop_button - dialog.open() - dialog_content.ids.sync_progress.value = self.sideband.get_sync_progress()*100 - dialog_content.ids.sync_status.text = self.sideband.get_sync_status() + self.message_sync_dialog.title = f"LXMF Sync via "+RNS.prettyhexrep(self.sideband.message_router.get_outbound_propagation_node()) + self.message_sync_dialog.d_content.ids.sync_status.text = self.sideband.get_sync_status() + self.message_sync_dialog.d_content.ids.sync_progress.value = dsp + self.message_sync_dialog.d_content.ids.sync_progress.start() + self.sync_dialog.ids.sync_progress.stop() + self.message_sync_dialog.open() + + def sij(dt): + self.sideband.setpersistent("lxmf.lastsync", time.time()) + self.sideband.setpersistent("lxmf.syncretrying", False) + self.sideband.request_lxmf_sync(limit=sl) + Clock.schedule_once(sij, 0.1) def new_conversation_action(self, sender=None): def cb(dt): @@ -1837,12 +1865,12 @@ class SidebandApp(MDApp): if self.sideband.reticulum.is_connected_to_shared_instance: info = "Sideband is connected via a shared Reticulum instance running on this system.\n\n" - info += "To get connectivity status, use the rnstatus utility.\n\n" + info += "To get connectivity status, use the [b]rnstatus[/b] utility.\n\n" info += "To configure connectivity, edit the configuration file located at:\n\n" info += str(RNS.Reticulum.configpath) else: info = "Sideband is currently running a standalone or master Reticulum instance on this system.\n\n" - info += "To get connectivity status, use the rnstatus utility.\n\n" + info += "To get connectivity status, use the [b]rnstatus[/b] utility.\n\n" info += "To configure connectivity, edit the configuration file located at:\n\n" info += str(RNS.Reticulum.configpath) diff --git a/sbapp/services/sidebandservice.py b/sbapp/services/sidebandservice.py index c90e7b8..9df9b92 100644 --- a/sbapp/services/sidebandservice.py +++ b/sbapp/services/sidebandservice.py @@ -1,4 +1,4 @@ -__debug_build__ = False +__debug_build__ = True import time import RNS diff --git a/sbapp/sideband/core.py b/sbapp/sideband/core.py index 2e2f5e8..5e1a7d1 100644 --- a/sbapp/sideband/core.py +++ b/sbapp/sideband/core.py @@ -648,6 +648,8 @@ class SidebandCore(): def log_announce(self, dest, app_data, dest_type): try: + if app_data == None: + app_data = b"" RNS.log("Received "+str(dest_type)+" announce for "+RNS.prettyhexrep(dest)+" with data: "+app_data.decode("utf-8")) self._db_save_announce(dest, app_data, dest_type) self.setstate("app.flags.new_announces", True) @@ -2905,7 +2907,7 @@ class SidebandCore(): threading.Thread(target=webshare_job, daemon=True).start() def request_lxmf_sync(self, limit = None): - if self.message_router.propagation_transfer_state == LXMF.LXMRouter.PR_IDLE or self.message_router.propagation_transfer_state == LXMF.LXMRouter.PR_COMPLETE: + if self.message_router.propagation_transfer_state == LXMF.LXMRouter.PR_IDLE or self.message_router.propagation_transfer_state >= LXMF.LXMRouter.PR_COMPLETE: self.message_router.request_messages_from_propagation_node(self.identity, max_messages = limit) RNS.log("LXMF message sync requested from propagation node "+RNS.prettyhexrep(self.message_router.get_outbound_propagation_node())+" for "+str(self.identity)) return True @@ -2917,7 +2919,18 @@ class SidebandCore(): self.message_router.cancel_propagation_node_requests() def get_sync_progress(self): - return self.message_router.propagation_transfer_progress + state = self.message_router.propagation_transfer_state + if state == LXMF.LXMRouter.PR_PATH_REQUESTED: + state_val = 0.05 + elif state == LXMF.LXMRouter.PR_LINK_ESTABLISHING: + state_val = 0.1 + elif state == LXMF.LXMRouter.PR_LINK_ESTABLISHED: + state_val = 0.15 + elif state >= LXMF.LXMRouter.PR_REQUEST_SENT: + state_val = 0.2 + else: + state_val = 0.0 + return (self.message_router.propagation_transfer_progress*0.8)+state_val def lxmf_delivery(self, message): time_string = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(message.timestamp)) @@ -2961,6 +2974,18 @@ class SidebandCore(): return "Receiving messages" elif self.message_router.propagation_transfer_state == LXMF.LXMRouter.PR_RESPONSE_RECEIVED: return "Messages received" + elif self.message_router.propagation_transfer_state == LXMF.LXMRouter.PR_NO_PATH: + return "No path to propagation node" + elif self.message_router.propagation_transfer_state == LXMF.LXMRouter.PR_LINK_FAILED: + return "Link establisment failed" + elif self.message_router.propagation_transfer_state == LXMF.LXMRouter.PR_TRANSFER_FAILED: + return "Sync request failed" + elif self.message_router.propagation_transfer_state == LXMF.LXMRouter.PR_NO_IDENTITY_RCVD: + return "No identity received by remote" + elif self.message_router.propagation_transfer_state == LXMF.LXMRouter.PR_NO_ACCESS: + return "No access to specified node" + elif self.message_router.propagation_transfer_state == LXMF.LXMRouter.PR_FAILED: + return "Sync failed" elif self.message_router.propagation_transfer_state == LXMF.LXMRouter.PR_COMPLETE: new_msgs = self.message_router.propagation_transfer_last_result if new_msgs == 0: diff --git a/sbapp/ui/conversations.py b/sbapp/ui/conversations.py index 3f1e642..dfd901d 100644 --- a/sbapp/ui/conversations.py +++ b/sbapp/ui/conversations.py @@ -473,6 +473,7 @@ Builder.load_string(""" MDProgressBar: id: sync_progress + type: "determinate" value: 0 MDLabel: