mirror of
				https://github.com/liberatedsystems/Sideband_CE.git
				synced 2024-09-03 04:13:27 +02:00 
			
		
		
		
	Map marker drawing
This commit is contained in:
		
							parent
							
								
									8dad802f53
								
							
						
					
					
						commit
						179ebe7cec
					
				@ -1,4 +1,4 @@
 | 
				
			|||||||
__debug_build__ = False
 | 
					__debug_build__ = True
 | 
				
			||||||
__disable_shaders__ = False
 | 
					__disable_shaders__ = False
 | 
				
			||||||
__version__ = "0.6.3"
 | 
					__version__ = "0.6.3"
 | 
				
			||||||
__variant__ = "beta"
 | 
					__variant__ = "beta"
 | 
				
			||||||
@ -44,6 +44,8 @@ from kivy.uix.screenmanager import FadeTransition, NoTransition
 | 
				
			|||||||
from kivymd.uix.list import OneLineIconListItem
 | 
					from kivymd.uix.list import OneLineIconListItem
 | 
				
			||||||
from kivy.properties import StringProperty
 | 
					from kivy.properties import StringProperty
 | 
				
			||||||
from kivymd.uix.pickers import MDColorPicker
 | 
					from kivymd.uix.pickers import MDColorPicker
 | 
				
			||||||
 | 
					from sideband.sense import Telemeter
 | 
				
			||||||
 | 
					from mapview import MapMarker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if RNS.vendor.platformutils.get_platform() == "android":
 | 
					if RNS.vendor.platformutils.get_platform() == "android":
 | 
				
			||||||
    from sideband.core import SidebandCore
 | 
					    from sideband.core import SidebandCore
 | 
				
			||||||
@ -132,6 +134,8 @@ class SidebandApp(MDApp):
 | 
				
			|||||||
        self.notification_icon = self.sideband.asset_dir+"/notification_icon.png"
 | 
					        self.notification_icon = self.sideband.asset_dir+"/notification_icon.png"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.connectivity_updater = None
 | 
					        self.connectivity_updater = None
 | 
				
			||||||
 | 
					        self.last_map_update = 0
 | 
				
			||||||
 | 
					        self.last_telemetry_received = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #################################################
 | 
					    #################################################
 | 
				
			||||||
@ -601,6 +605,16 @@ class SidebandApp(MDApp):
 | 
				
			|||||||
                if self.announces_view != None:
 | 
					                if self.announces_view != None:
 | 
				
			||||||
                    self.announces_view.update()
 | 
					                    self.announces_view.update()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        elif self.root.ids.screen_manager.current == "map_screen":
 | 
				
			||||||
 | 
					            if hasattr(self.root.ids.map_layout, "map") and self.root.ids.map_layout.map != None:
 | 
				
			||||||
 | 
					                self.sideband.config["map_lat"] = self.root.ids.map_layout.map.lat
 | 
				
			||||||
 | 
					                self.sideband.config["map_lon"] = self.root.ids.map_layout.map.lon
 | 
				
			||||||
 | 
					                self.sideband.config["map_zoom"] = self.root.ids.map_layout.map.zoom
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.last_telemetry_received = self.sideband.getstate("app.flags.last_telemetry", allow_cache=True) or 0
 | 
				
			||||||
 | 
					            if self.last_telemetry_received > self.last_map_update:
 | 
				
			||||||
 | 
					                self.map_update_markers()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.sideband.getstate("app.flags.new_conversations", allow_cache=True):
 | 
					        if self.sideband.getstate("app.flags.new_conversations", allow_cache=True):
 | 
				
			||||||
            if self.conversations_view != None:
 | 
					            if self.conversations_view != None:
 | 
				
			||||||
                self.conversations_view.update()
 | 
					                self.conversations_view.update()
 | 
				
			||||||
@ -695,6 +709,10 @@ class SidebandApp(MDApp):
 | 
				
			|||||||
                self.message_send_action()
 | 
					                self.message_send_action()
 | 
				
			||||||
        if len(modifiers) > 0 and modifiers[0] == 'ctrl' and (text == "l"):
 | 
					        if len(modifiers) > 0 and modifiers[0] == 'ctrl' and (text == "l"):
 | 
				
			||||||
            self.announces_action(self)
 | 
					            self.announces_action(self)
 | 
				
			||||||
 | 
					        if len(modifiers) > 0 and modifiers[0] == 'ctrl' and (text == "m"):
 | 
				
			||||||
 | 
					            self.map_action(self)
 | 
				
			||||||
 | 
					        if len(modifiers) > 0 and modifiers[0] == 'ctrl' and (text == "t"):
 | 
				
			||||||
 | 
					            self.telemetry_action(self)
 | 
				
			||||||
        if len(modifiers) > 0 and modifiers[0] == 'ctrl' and (text == "r"):
 | 
					        if len(modifiers) > 0 and modifiers[0] == 'ctrl' and (text == "r"):
 | 
				
			||||||
            self.conversations_action(self)
 | 
					            self.conversations_action(self)
 | 
				
			||||||
        if len(modifiers) > 0 and modifiers[0] == 'ctrl' and (text == "g"):
 | 
					        if len(modifiers) > 0 and modifiers[0] == 'ctrl' and (text == "g"):
 | 
				
			||||||
@ -897,7 +915,6 @@ class SidebandApp(MDApp):
 | 
				
			|||||||
                                on_release=self.messages_view.close_send_error_dialog
 | 
					                                on_release=self.messages_view.close_send_error_dialog
 | 
				
			||||||
                            )
 | 
					                            )
 | 
				
			||||||
                        ],
 | 
					                        ],
 | 
				
			||||||
                        # elevation=0,
 | 
					 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
                    self.messages_view.send_error_dialog.open()
 | 
					                    self.messages_view.send_error_dialog.open()
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
@ -1198,7 +1215,7 @@ class SidebandApp(MDApp):
 | 
				
			|||||||
        self.root.ids.information_scrollview.effect_cls = ScrollEffect
 | 
					        self.root.ids.information_scrollview.effect_cls = ScrollEffect
 | 
				
			||||||
        self.root.ids.information_logo.icon = self.sideband.asset_dir+"/rns_256.png"
 | 
					        self.root.ids.information_logo.icon = self.sideband.asset_dir+"/rns_256.png"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        info = "This is Sideband v"+__version__+" "+__variant__+", on RNS v"+RNS.__version__+" and LXMF v"+LXMF.__version__+".\n\nHumbly build using the following open components:\n\n - [b]Reticulum[/b] (MIT License)\n - [b]LXMF[/b] (MIT License)\n - [b]KivyMD[/b] (MIT License)\n - [b]Kivy[/b] (MIT License)\n - [b]Python[/b] (PSF License)"+"\n\nGo to [u][ref=link]https://unsigned.io/donate[/ref][/u] to support the project.\n\nThe Sideband app is Copyright (c) 2022 Mark Qvist / unsigned.io\n\nPermission is granted to freely share and distribute binary copies of Sideband v"+__version__+" "+__variant__+", so long as no payment or compensation is charged for said distribution or sharing.\n\nIf you were charged or paid anything for this copy of Sideband, please report it to [b]license@unsigned.io[/b].\n\nTHIS IS EXPERIMENTAL SOFTWARE - USE AT YOUR OWN RISK AND RESPONSIBILITY"
 | 
					        info = "This is Sideband v"+__version__+" "+__variant__+", on RNS v"+RNS.__version__+" and LXMF v"+LXMF.__version__+".\n\nHumbly build using the following open components:\n\n - [b]Reticulum[/b] (MIT License)\n - [b]LXMF[/b] (MIT License)\n - [b]KivyMD[/b] (MIT License)\n - [b]Kivy[/b] (MIT License)\n - [b]Python[/b] (PSF License)"+"\n\nGo to [u][ref=link]https://unsigned.io/donate[/ref][/u] to support the project.\n\nThe Sideband app is Copyright (c) 2022 Mark Qvist / unsigned.io\n\nPermission is granted to freely share and distribute binary copies of Sideband v"+__version__+" "+__variant__+", so long as no payment or compensation is charged for said distribution or sharing.\n\nIf you were charged or paid anything for this copy of Sideband, please report it to [b]license@unsigned.io[/b].\n\nTHIS IS EXPERIMENTAL SOFTWARE - SIDEBAND COMES WITH ABSOLUTELY NO WARRANTY - USE AT YOUR OWN RISK AND RESPONSIBILITY"
 | 
				
			||||||
        self.root.ids.information_info.text = info
 | 
					        self.root.ids.information_info.text = info
 | 
				
			||||||
        self.root.ids.information_info.bind(on_ref_press=link_exec)
 | 
					        self.root.ids.information_info.bind(on_ref_press=link_exec)
 | 
				
			||||||
        self.root.ids.screen_manager.transition.direction = "left"
 | 
					        self.root.ids.screen_manager.transition.direction = "left"
 | 
				
			||||||
@ -2832,6 +2849,9 @@ class SidebandApp(MDApp):
 | 
				
			|||||||
            self.root.ids.telemetry_send_to_trusted.active = self.sideband.config["telemetry_send_to_trusted"]
 | 
					            self.root.ids.telemetry_send_to_trusted.active = self.sideband.config["telemetry_send_to_trusted"]
 | 
				
			||||||
            self.root.ids.telemetry_send_to_trusted.bind(active=self.telemetry_save)
 | 
					            self.root.ids.telemetry_send_to_trusted.bind(active=self.telemetry_save)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.root.ids.telemetry_send_appearance.active = self.sideband.config["telemetry_send_appearance"]
 | 
				
			||||||
 | 
					            self.root.ids.telemetry_send_appearance.bind(active=self.telemetry_save)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self.root.ids.telemetry_s_location.active = self.sideband.config["telemetry_s_location"]
 | 
					            self.root.ids.telemetry_s_location.active = self.sideband.config["telemetry_s_location"]
 | 
				
			||||||
            self.root.ids.telemetry_s_location.bind(active=self.telemetry_location_toggle)
 | 
					            self.root.ids.telemetry_s_location.bind(active=self.telemetry_location_toggle)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2909,6 +2929,7 @@ class SidebandApp(MDApp):
 | 
				
			|||||||
        self.sideband.config["telemetry_enabled"] = self.root.ids.telemetry_enabled.active
 | 
					        self.sideband.config["telemetry_enabled"] = self.root.ids.telemetry_enabled.active
 | 
				
			||||||
        self.sideband.config["telemetry_send_to_collector"] = self.root.ids.telemetry_send_to_collector.active
 | 
					        self.sideband.config["telemetry_send_to_collector"] = self.root.ids.telemetry_send_to_collector.active
 | 
				
			||||||
        self.sideband.config["telemetry_send_to_trusted"] = self.root.ids.telemetry_send_to_trusted.active
 | 
					        self.sideband.config["telemetry_send_to_trusted"] = self.root.ids.telemetry_send_to_trusted.active
 | 
				
			||||||
 | 
					        self.sideband.config["telemetry_send_appearance"] = self.root.ids.telemetry_send_appearance.active
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        self.sideband.config["telemetry_s_location"] = self.root.ids.telemetry_s_location.active
 | 
					        self.sideband.config["telemetry_s_location"] = self.root.ids.telemetry_s_location.active
 | 
				
			||||||
        self.sideband.config["telemetry_s_orientation"] = self.root.ids.telemetry_s_orientation.active
 | 
					        self.sideband.config["telemetry_s_orientation"] = self.root.ids.telemetry_s_orientation.active
 | 
				
			||||||
@ -3034,7 +3055,7 @@ class SidebandApp(MDApp):
 | 
				
			|||||||
    def map_action(self, sender=None):
 | 
					    def map_action(self, sender=None):
 | 
				
			||||||
        if not hasattr(self.root.ids.map_layout, "map") or self.root.ids.map_layout.map == None:
 | 
					        if not hasattr(self.root.ids.map_layout, "map") or self.root.ids.map_layout.map == None:
 | 
				
			||||||
            from mapview import MapView
 | 
					            from mapview import MapView
 | 
				
			||||||
            mapview = MapView(zoom=11, lat=50.6394, lon=3.057)
 | 
					            mapview = MapView(zoom=self.sideband.config["map_zoom"], lat=self.sideband.config["map_lat"], lon=self.sideband.config["map_lon"])
 | 
				
			||||||
            mapview.snap_to_zoom = False
 | 
					            mapview.snap_to_zoom = False
 | 
				
			||||||
            mapview.double_tap_zoom = False
 | 
					            mapview.double_tap_zoom = False
 | 
				
			||||||
            self.root.ids.map_layout.map = mapview
 | 
					            self.root.ids.map_layout.map = mapview
 | 
				
			||||||
@ -3045,6 +3066,73 @@ class SidebandApp(MDApp):
 | 
				
			|||||||
        self.root.ids.nav_drawer.set_state("closed")
 | 
					        self.root.ids.nav_drawer.set_state("closed")
 | 
				
			||||||
        self.sideband.setstate("app.displaying", self.root.ids.screen_manager.current)
 | 
					        self.sideband.setstate("app.displaying", self.root.ids.screen_manager.current)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not hasattr(self, "map_markers") or self.map_markers == None:
 | 
				
			||||||
 | 
					            self.map_markers = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        def am_job(dt):
 | 
				
			||||||
 | 
					            self.map_update_markers()
 | 
				
			||||||
 | 
					        Clock.schedule_once(am_job, 0.6)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def map_update_markers(self, sender=None):
 | 
				
			||||||
 | 
					        # TODO: Remove
 | 
				
			||||||
 | 
					        # time_s = time.time()
 | 
				
			||||||
 | 
					        # RNS.log("Update map markers", RNS.LOG_WARNING)
 | 
				
			||||||
 | 
					        earliest = time.time() - self.sideband.config["map_history_limit"]
 | 
				
			||||||
 | 
					        telemetry_entries = self.sideband.list_telemetry(after=earliest)
 | 
				
			||||||
 | 
					        changes = False
 | 
				
			||||||
 | 
					        for telemetry_source in telemetry_entries:
 | 
				
			||||||
 | 
					            skip = False
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            if telemetry_source in self.map_markers:
 | 
				
			||||||
 | 
					                marker = self.map_markers[telemetry_source]
 | 
				
			||||||
 | 
					                newest_timestamp = telemetry_entries[telemetry_source][0][0]
 | 
				
			||||||
 | 
					                if newest_timestamp <= marker.latest_timestamp:
 | 
				
			||||||
 | 
					                    skip = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            latest_viewable = None
 | 
				
			||||||
 | 
					            if not skip:
 | 
				
			||||||
 | 
					                for telemetry_entry in telemetry_entries[telemetry_source]:
 | 
				
			||||||
 | 
					                    telemetry_timestamp = telemetry_entry[0]
 | 
				
			||||||
 | 
					                    telemetry_data = telemetry_entry[1]
 | 
				
			||||||
 | 
					                    t = Telemeter.from_packed(telemetry_data)
 | 
				
			||||||
 | 
					                    if t != None:
 | 
				
			||||||
 | 
					                        telemetry = t.read_all()
 | 
				
			||||||
 | 
					                        # TODO: Remove
 | 
				
			||||||
 | 
					                        # RNS.log(str(telemetry)+" "+str(t), RNS.LOG_WARNING)
 | 
				
			||||||
 | 
					                        if "location" in telemetry and telemetry["location"]["latitude"] != None and telemetry["location"]["longtitude"] != None:
 | 
				
			||||||
 | 
					                            latest_viewable = telemetry
 | 
				
			||||||
 | 
					                            break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if latest_viewable != None:
 | 
				
			||||||
 | 
					                    l = latest_viewable["location"]
 | 
				
			||||||
 | 
					                    if not telemetry_source in self.map_markers:
 | 
				
			||||||
 | 
					                        marker = MapMarker(lat=l["latitude"], lon=l["longtitude"])
 | 
				
			||||||
 | 
					                        marker.source_dest = telemetry_source
 | 
				
			||||||
 | 
					                        marker.latest_timestamp = latest_viewable["time"]["utc"]
 | 
				
			||||||
 | 
					                        self.map_markers[telemetry_source] = marker
 | 
				
			||||||
 | 
					                        self.root.ids.map_layout.map.add_widget(marker)
 | 
				
			||||||
 | 
					                        changes = True
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        marker = self.map_markers[telemetry_source]
 | 
				
			||||||
 | 
					                        marker.latest_timestamp = latest_viewable["time"]["utc"]
 | 
				
			||||||
 | 
					                        marker.lat = l["latitude"]
 | 
				
			||||||
 | 
					                        marker.lon = l["longtitude"]
 | 
				
			||||||
 | 
					                        changes = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.last_map_update = time.time()
 | 
				
			||||||
 | 
					        if changes:
 | 
				
			||||||
 | 
					            mv = self.root.ids.map_layout.map
 | 
				
			||||||
 | 
					            mv.trigger_update(True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # TODO: Remove
 | 
				
			||||||
 | 
					        # RNS.log("Updated map markers in "+RNS.prettytime(time.time()-time_s), RNS.LOG_WARNING)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def map_add_marker(self, marker):
 | 
				
			||||||
 | 
					        marker = MapMarker(lat=0.0, lon=0.0)
 | 
				
			||||||
 | 
					        self.root.ids.map_layout.map.add_widget(marker)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ### Guide screen
 | 
					    ### Guide screen
 | 
				
			||||||
    ######################################
 | 
					    ######################################
 | 
				
			||||||
    def close_guide_action(self, sender=None):
 | 
					    def close_guide_action(self, sender=None):
 | 
				
			||||||
@ -3090,6 +3178,8 @@ If you use Reticulum and LXMF on hardware that does not carry any identifiers ti
 | 
				
			|||||||
 - Ctrl-D or Ctrl-S Send message
 | 
					 - Ctrl-D or Ctrl-S Send message
 | 
				
			||||||
 - Ctrl-R Show Conversations
 | 
					 - Ctrl-R Show Conversations
 | 
				
			||||||
 - Ctrl-L Show Announce Stream
 | 
					 - Ctrl-L Show Announce Stream
 | 
				
			||||||
 | 
					 - Ctrl-M Show Situation Map
 | 
				
			||||||
 | 
					 - Ctrl-T Show Telemetry Setup
 | 
				
			||||||
 - Ctrl-N New conversation
 | 
					 - Ctrl-N New conversation
 | 
				
			||||||
 - Ctrl-G Show guide"""
 | 
					 - Ctrl-G Show guide"""
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
				
			|||||||
@ -18,6 +18,7 @@ from mapview.constants import CACHE_DIR
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# if "MAPVIEW_DEBUG_DOWNLOADER" in environ:
 | 
					# if "MAPVIEW_DEBUG_DOWNLOADER" in environ:
 | 
				
			||||||
#     Logger.setLevel(LOG_LEVELS['debug'])
 | 
					#     Logger.setLevel(LOG_LEVELS['debug'])
 | 
				
			||||||
 | 
					Logger.setLevel(LOG_LEVELS['error'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# user agent is needed because since may 2019 OSM gives me a 429 or 403 server error
 | 
					# user agent is needed because since may 2019 OSM gives me a 429 or 403 server error
 | 
				
			||||||
# I tried it with a simpler one (just Mozilla/5.0) this also gets rejected
 | 
					# I tried it with a simpler one (just Mozilla/5.0) this also gets rejected
 | 
				
			||||||
@ -56,21 +57,21 @@ class Downloader:
 | 
				
			|||||||
        self._futures.append(future)
 | 
					        self._futures.append(future)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def download_tile(self, tile):
 | 
					    def download_tile(self, tile):
 | 
				
			||||||
        Logger.debug(
 | 
					        # Logger.debug(
 | 
				
			||||||
            "Downloader: queue(tile) zoom={} x={} y={}".format(
 | 
					        #     "Downloader: queue(tile) zoom={} x={} y={}".format(
 | 
				
			||||||
                tile.zoom, tile.tile_x, tile.tile_y
 | 
					        #         tile.zoom, tile.tile_x, tile.tile_y
 | 
				
			||||||
            )
 | 
					        #     )
 | 
				
			||||||
        )
 | 
					        # )
 | 
				
			||||||
        future = self.executor.submit(self._load_tile, tile)
 | 
					        future = self.executor.submit(self._load_tile, tile)
 | 
				
			||||||
        self._futures.append(future)
 | 
					        self._futures.append(future)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def download(self, url, callback, **kwargs):
 | 
					    def download(self, url, callback, **kwargs):
 | 
				
			||||||
        Logger.debug("Downloader: queue(url) {}".format(url))
 | 
					        # Logger.debug("Downloader: queue(url) {}".format(url))
 | 
				
			||||||
        future = self.executor.submit(self._download_url, url, callback, kwargs)
 | 
					        future = self.executor.submit(self._download_url, url, callback, kwargs)
 | 
				
			||||||
        self._futures.append(future)
 | 
					        self._futures.append(future)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _download_url(self, url, callback, kwargs):
 | 
					    def _download_url(self, url, callback, kwargs):
 | 
				
			||||||
        Logger.debug("Downloader: download(url) {}".format(url))
 | 
					        # Logger.debug("Downloader: download(url) {}".format(url))
 | 
				
			||||||
        response = requests.get(url, **kwargs)
 | 
					        response = requests.get(url, **kwargs)
 | 
				
			||||||
        response.raise_for_status()
 | 
					        response.raise_for_status()
 | 
				
			||||||
        return callback, (url, response)
 | 
					        return callback, (url, response)
 | 
				
			||||||
@ -80,20 +81,20 @@ class Downloader:
 | 
				
			|||||||
            return
 | 
					            return
 | 
				
			||||||
        cache_fn = tile.cache_fn
 | 
					        cache_fn = tile.cache_fn
 | 
				
			||||||
        if exists(cache_fn):
 | 
					        if exists(cache_fn):
 | 
				
			||||||
            Logger.debug("Downloader: use cache {}".format(cache_fn))
 | 
					            # Logger.debug("Downloader: use cache {}".format(cache_fn))
 | 
				
			||||||
            return tile.set_source, (cache_fn,)
 | 
					            return tile.set_source, (cache_fn,)
 | 
				
			||||||
        tile_y = tile.map_source.get_row_count(tile.zoom) - tile.tile_y - 1
 | 
					        tile_y = tile.map_source.get_row_count(tile.zoom) - tile.tile_y - 1
 | 
				
			||||||
        uri = tile.map_source.url.format(
 | 
					        uri = tile.map_source.url.format(
 | 
				
			||||||
            z=tile.zoom, x=tile.tile_x, y=tile_y, s=choice(tile.map_source.subdomains)
 | 
					            z=tile.zoom, x=tile.tile_x, y=tile_y, s=choice(tile.map_source.subdomains)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        Logger.debug("Downloader: download(tile) {}".format(uri))
 | 
					        # Logger.debug("Downloader: download(tile) {}".format(uri))
 | 
				
			||||||
        response = requests.get(uri, headers={'User-agent': USER_AGENT}, timeout=5)
 | 
					        response = requests.get(uri, headers={'User-agent': USER_AGENT}, timeout=5)
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            response.raise_for_status()
 | 
					            response.raise_for_status()
 | 
				
			||||||
            data = response.content
 | 
					            data = response.content
 | 
				
			||||||
            with open(cache_fn, "wb") as fd:
 | 
					            with open(cache_fn, "wb") as fd:
 | 
				
			||||||
                fd.write(data)
 | 
					                fd.write(data)
 | 
				
			||||||
            Logger.debug("Downloaded {} bytes: {}".format(len(data), uri))
 | 
					            # Logger.debug("Downloaded {} bytes: {}".format(len(data), uri))
 | 
				
			||||||
            return tile.set_source, (cache_fn,)
 | 
					            return tile.set_source, (cache_fn,)
 | 
				
			||||||
        except Exception as e:
 | 
					        except Exception as e:
 | 
				
			||||||
            print("Downloader error: {!r}".format(e))
 | 
					            print("Downloader error: {!r}".format(e))
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,7 @@ import threading
 | 
				
			|||||||
import plyer
 | 
					import plyer
 | 
				
			||||||
import os.path
 | 
					import os.path
 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
 | 
					import struct
 | 
				
			||||||
import sqlite3
 | 
					import sqlite3
 | 
				
			||||||
import random
 | 
					import random
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -313,6 +314,7 @@ class SidebandCore():
 | 
				
			|||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self._db_initstate()
 | 
					            self._db_initstate()
 | 
				
			||||||
            self._db_initpersistent()
 | 
					            self._db_initpersistent()
 | 
				
			||||||
 | 
					            self._db_inittelemetry()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.__save_config()
 | 
					        self.__save_config()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -457,6 +459,8 @@ class SidebandCore():
 | 
				
			|||||||
            self.config["telemetry_fg"] = [0,0,0,1]
 | 
					            self.config["telemetry_fg"] = [0,0,0,1]
 | 
				
			||||||
        if not "telemetry_bg" in self.config:
 | 
					        if not "telemetry_bg" in self.config:
 | 
				
			||||||
            self.config["telemetry_bg"] = [1,1,1,1]
 | 
					            self.config["telemetry_bg"] = [1,1,1,1]
 | 
				
			||||||
 | 
					        if not "telemetry_send_appearance" in self.config:
 | 
				
			||||||
 | 
					            self.config["telemetry_send_appearance"] = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not "telemetry_s_location" in self.config:
 | 
					        if not "telemetry_s_location" in self.config:
 | 
				
			||||||
            self.config["telemetry_s_location"] = False
 | 
					            self.config["telemetry_s_location"] = False
 | 
				
			||||||
@ -483,12 +487,22 @@ class SidebandCore():
 | 
				
			|||||||
        if not "telemetry_s_proximity" in self.config:
 | 
					        if not "telemetry_s_proximity" in self.config:
 | 
				
			||||||
            self.config["telemetry_s_proximity"] = False
 | 
					            self.config["telemetry_s_proximity"] = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not "map_history_limit" in self.config:
 | 
				
			||||||
 | 
					            self.config["map_history_limit"] = 7*24*60*60
 | 
				
			||||||
 | 
					        if not "map_lat" in self.config:
 | 
				
			||||||
 | 
					            self.config["map_lat"] = 0.0
 | 
				
			||||||
 | 
					        if not "map_lon" in self.config:
 | 
				
			||||||
 | 
					            self.config["map_lon"] = 0.0
 | 
				
			||||||
 | 
					        if not "map_zoom" in self.config:
 | 
				
			||||||
 | 
					            self.config["map_zoom"] = 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Make sure we have a database
 | 
					        # Make sure we have a database
 | 
				
			||||||
        if not os.path.isfile(self.db_path):
 | 
					        if not os.path.isfile(self.db_path):
 | 
				
			||||||
            self.__db_init()
 | 
					            self.__db_init()
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self._db_initstate()
 | 
					            self._db_initstate()
 | 
				
			||||||
            self._db_initpersistent()
 | 
					            self._db_initpersistent()
 | 
				
			||||||
 | 
					            self._db_inittelemetry()
 | 
				
			||||||
            self.__db_indices()
 | 
					            self.__db_indices()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __reload_config(self):
 | 
					    def __reload_config(self):
 | 
				
			||||||
@ -709,6 +723,9 @@ class SidebandCore():
 | 
				
			|||||||
        else:
 | 
					        else:
 | 
				
			||||||
            return None
 | 
					            return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def list_telemetry(self, context_dest = None, after = None, before = None, limit = None):
 | 
				
			||||||
 | 
					        return self._db_telemetry(context_dest = context_dest, after = after, before = before, limit = limit)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def list_messages(self, context_dest, after = None, before = None, limit = None):
 | 
					    def list_messages(self, context_dest, after = None, before = None, limit = None):
 | 
				
			||||||
        result = self._db_messages(context_dest, after, before, limit)
 | 
					        result = self._db_messages(context_dest, after, before, limit)
 | 
				
			||||||
        if result != None:
 | 
					        if result != None:
 | 
				
			||||||
@ -909,6 +926,13 @@ class SidebandCore():
 | 
				
			|||||||
        dbc.execute("CREATE TABLE IF NOT EXISTS persistent (property BLOB PRIMARY KEY, value BLOB)")
 | 
					        dbc.execute("CREATE TABLE IF NOT EXISTS persistent (property BLOB PRIMARY KEY, value BLOB)")
 | 
				
			||||||
        db.commit()
 | 
					        db.commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _db_inittelemetry(self):
 | 
				
			||||||
 | 
					        db = self.__db_connect()
 | 
				
			||||||
 | 
					        dbc = db.cursor()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        dbc.execute("CREATE TABLE IF NOT EXISTS telemetry (id INTEGER PRIMARY KEY, dest_context BLOB, ts INTEGER, data BLOB)")
 | 
				
			||||||
 | 
					        db.commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _db_getpersistent(self, prop):
 | 
					    def _db_getpersistent(self, prop):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            db = self.__db_connect()
 | 
					            db = self.__db_connect()
 | 
				
			||||||
@ -998,6 +1022,110 @@ class SidebandCore():
 | 
				
			|||||||
        result = dbc.fetchall()
 | 
					        result = dbc.fetchall()
 | 
				
			||||||
        db.commit()
 | 
					        db.commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _db_telemetry(self, context_dest = None, after = None, before = None, limit = None):
 | 
				
			||||||
 | 
					        db = self.__db_connect()
 | 
				
			||||||
 | 
					        dbc = db.cursor()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # TODO: Implement limit
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        order_part = " order by ts DESC"
 | 
				
			||||||
 | 
					        if context_dest == None:
 | 
				
			||||||
 | 
					            if after != None and before == None:
 | 
				
			||||||
 | 
					                query = "select * from telemetry where ts>:after_ts"+order_part
 | 
				
			||||||
 | 
					                dbc.execute(query, {"after_ts": after})
 | 
				
			||||||
 | 
					            elif after == None and before != None:
 | 
				
			||||||
 | 
					                query = "select * from telemetry where ts<:before_ts"+order_part
 | 
				
			||||||
 | 
					                dbc.execute(query, {"before_ts": before})
 | 
				
			||||||
 | 
					            elif after != None and before != None:
 | 
				
			||||||
 | 
					                query = "select * from telemetry where ts<:before_ts and ts>:after_ts"+order_part
 | 
				
			||||||
 | 
					                dbc.execute(query, {"before_ts": before, "after_ts": after})
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                query = query = "select * from telemetry"
 | 
				
			||||||
 | 
					                dbc.execute(query, {})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        else:        
 | 
				
			||||||
 | 
					            if after != None and before == None:
 | 
				
			||||||
 | 
					                query = "select * from telemetry where dest_context=:context_dest and ts>:after_ts"+order_part
 | 
				
			||||||
 | 
					                dbc.execute(query, {"context_dest": context_dest, "after_ts": after})
 | 
				
			||||||
 | 
					            elif after == None and before != None:
 | 
				
			||||||
 | 
					                query = "select * from telemetry where dest_context=:context_dest and ts<:before_ts"+order_part
 | 
				
			||||||
 | 
					                dbc.execute(query, {"context_dest": context_dest, "before_ts": before})
 | 
				
			||||||
 | 
					            elif after != None and before != None:
 | 
				
			||||||
 | 
					                query = "select * from telemetry where dest_context=:context_dest and ts<:before_ts and ts>:after_ts"+order_part
 | 
				
			||||||
 | 
					                dbc.execute(query, {"context_dest": context_dest, "before_ts": before, "after_ts": after})
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                query = query = "select * from telemetry where dest_context=:context_dest"+order_part
 | 
				
			||||||
 | 
					                dbc.execute(query, {"context_dest": context_dest})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        result = dbc.fetchall()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if len(result) < 1:
 | 
				
			||||||
 | 
					            return None
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            results = {}
 | 
				
			||||||
 | 
					            for entry in result:
 | 
				
			||||||
 | 
					                telemetry_source = entry[1]
 | 
				
			||||||
 | 
					                telemetry_timestamp = entry[2]
 | 
				
			||||||
 | 
					                telemetry_data = entry[3]
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                if not telemetry_source in results:
 | 
				
			||||||
 | 
					                    results[telemetry_source] = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                results[telemetry_source].append([telemetry_timestamp, telemetry_data])
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            return results
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _db_save_telemetry(self, context_dest, telemetry):
 | 
				
			||||||
 | 
					        # TODO: Remove
 | 
				
			||||||
 | 
					        # RNS.log("Saving telemetry for "+RNS.prettyhexrep(context_dest), RNS.LOG_WARNING)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            remote_telemeter = Telemeter.from_packed(telemetry)
 | 
				
			||||||
 | 
					            telemetry_timestamp = remote_telemeter.read_all()["time"]["utc"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            db = self.__db_connect()
 | 
				
			||||||
 | 
					            dbc = db.cursor()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            query = "select * from telemetry where dest_context=:ctx and ts=:tts"
 | 
				
			||||||
 | 
					            dbc.execute(query, {"ctx": context_dest, "tts": telemetry_timestamp})
 | 
				
			||||||
 | 
					            result = dbc.fetchall()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if len(result) != 0:
 | 
				
			||||||
 | 
					                # TODO: Remove
 | 
				
			||||||
 | 
					                # RNS.log("Telemetry entry already exists, ignoring", RNS.LOG_WARNING)
 | 
				
			||||||
 | 
					                return
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            query = "INSERT INTO telemetry (dest_context, ts, data) values (?, ?, ?)"
 | 
				
			||||||
 | 
					            data = (context_dest, telemetry_timestamp, telemetry)
 | 
				
			||||||
 | 
					            dbc.execute(query, data)
 | 
				
			||||||
 | 
					            db.commit()
 | 
				
			||||||
 | 
					            self.setstate("app.flags.last_telemetry", time.time())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        except Exception as e:
 | 
				
			||||||
 | 
					            RNS.log("An error occurred while saving telemetry to database: "+str(e), RNS.LOG_ERROR)
 | 
				
			||||||
 | 
					            self.db = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _db_update_appearance(self, context_dest, timestamp, appearance):
 | 
				
			||||||
 | 
					        # TODO: Remove
 | 
				
			||||||
 | 
					        # RNS.log("Updating appearance for "+RNS.prettyhexrep(context_dest), RNS.LOG_WARNING)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        conv = self._db_conversation(context_dest)
 | 
				
			||||||
 | 
					        data_dict = conv["data"]
 | 
				
			||||||
 | 
					        if data_dict == None:
 | 
				
			||||||
 | 
					            data_dict = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        data_dict["appearance"] = appearance
 | 
				
			||||||
 | 
					        packed_dict = msgpack.packb(data_dict)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        db = self.__db_connect()
 | 
				
			||||||
 | 
					        dbc = db.cursor()
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        query = "UPDATE conv set data = ? where dest_context = ?"
 | 
				
			||||||
 | 
					        data = (packed_dict, context_dest)
 | 
				
			||||||
 | 
					        dbc.execute(query, data)
 | 
				
			||||||
 | 
					        result = dbc.fetchall()
 | 
				
			||||||
 | 
					        db.commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _db_conversation_set_telemetry(self, context_dest, send_telemetry=False):
 | 
					    def _db_conversation_set_telemetry(self, context_dest, send_telemetry=False):
 | 
				
			||||||
        conv = self._db_conversation(context_dest)
 | 
					        conv = self._db_conversation(context_dest)
 | 
				
			||||||
        data_dict = conv["data"]
 | 
					        data_dict = conv["data"]
 | 
				
			||||||
@ -1346,6 +1474,13 @@ class SidebandCore():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        db.commit()
 | 
					        db.commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if lxm.fields != None:
 | 
				
			||||||
 | 
					            if LXMF.FIELD_ICON_APPEARANCE in lxm.fields:
 | 
				
			||||||
 | 
					                self._db_update_appearance(context_dest, lxm.timestamp, lxm.fields[LXMF.FIELD_ICON_APPEARANCE])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if LXMF.FIELD_TELEMETRY in lxm.fields:
 | 
				
			||||||
 | 
					                self._db_save_telemetry(context_dest, lxm.fields[LXMF.FIELD_TELEMETRY])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.__event_conversation_changed(context_dest)
 | 
					        self.__event_conversation_changed(context_dest)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _db_save_announce(self, destination_hash, app_data, dest_type="lxmf.delivery"):
 | 
					    def _db_save_announce(self, destination_hash, app_data, dest_type="lxmf.delivery"):
 | 
				
			||||||
@ -1442,8 +1577,6 @@ class SidebandCore():
 | 
				
			|||||||
    def get_packed_telemetry(self):
 | 
					    def get_packed_telemetry(self):
 | 
				
			||||||
        self.update_telemeter_config()
 | 
					        self.update_telemeter_config()
 | 
				
			||||||
        packed = self.telemeter.packed()
 | 
					        packed = self.telemeter.packed()
 | 
				
			||||||
        # TODO: Remove
 | 
					 | 
				
			||||||
        RNS.log("Packed telemetry: "+str(packed), RNS.LOG_WARNING)
 | 
					 | 
				
			||||||
        return packed
 | 
					        return packed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def is_known(self, dest_hash):
 | 
					    def is_known(self, dest_hash):
 | 
				
			||||||
@ -2096,6 +2229,34 @@ class SidebandCore():
 | 
				
			|||||||
        else:
 | 
					        else:
 | 
				
			||||||
            self.lxm_ingest(message, originator=True)
 | 
					            self.lxm_ingest(message, originator=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_message_fields(self, context_dest):
 | 
				
			||||||
 | 
					        fields = None
 | 
				
			||||||
 | 
					        send_telemetry = self.should_send_telemetry(context_dest)
 | 
				
			||||||
 | 
					        send_appearance = self.config["telemetry_send_appearance"] or send_telemetry
 | 
				
			||||||
 | 
					        if send_telemetry or send_appearance:
 | 
				
			||||||
 | 
					            fields = {}
 | 
				
			||||||
 | 
					            if send_appearance:
 | 
				
			||||||
 | 
					                # TODO: REMOVE
 | 
				
			||||||
 | 
					                # RNS.log("Sending appearance", RNS.LOG_WARNING)
 | 
				
			||||||
 | 
					                def fth(c):
 | 
				
			||||||
 | 
					                    r = c[0]; g = c[1]; b = c[2]
 | 
				
			||||||
 | 
					                    r = min(max(0, r), 1); g = min(max(0, g), 1); b = min(max(0, b), 1)
 | 
				
			||||||
 | 
					                    d = 1.0/255.0
 | 
				
			||||||
 | 
					                    return struct.pack("!BBB", int(r/d), int(g/d), int(b/d))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                icon = self.config["telemetry_icon"]
 | 
				
			||||||
 | 
					                fg = fth(self.config["telemetry_fg"][:-1])
 | 
				
			||||||
 | 
					                bg = fth(self.config["telemetry_bg"][:-1])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                fields[LXMF.FIELD_ICON_APPEARANCE] = [icon, fg, bg]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if send_telemetry:
 | 
				
			||||||
 | 
					                # TODO: REMOVE
 | 
				
			||||||
 | 
					                # RNS.log("Sending telemetry", RNS.LOG_WARNING)
 | 
				
			||||||
 | 
					                fields[LXMF.FIELD_TELEMETRY] = self.latest_packed_telemetry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return fields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def paper_message(self, content, destination_hash):
 | 
					    def paper_message(self, content, destination_hash):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            if content == "":
 | 
					            if content == "":
 | 
				
			||||||
@ -2106,7 +2267,7 @@ class SidebandCore():
 | 
				
			|||||||
            source = self.lxmf_destination
 | 
					            source = self.lxmf_destination
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            desired_method = LXMF.LXMessage.PAPER
 | 
					            desired_method = LXMF.LXMessage.PAPER
 | 
				
			||||||
            lxm = LXMF.LXMessage(dest, source, content, title="", desired_method=desired_method)
 | 
					            lxm = LXMF.LXMessage(dest, source, content, title="", desired_method=desired_method, fields = self.get_message_fields(destination_hash))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self.lxm_ingest(lxm, originator=True)
 | 
					            self.lxm_ingest(lxm, originator=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2130,7 +2291,7 @@ class SidebandCore():
 | 
				
			|||||||
            else:
 | 
					            else:
 | 
				
			||||||
                desired_method = LXMF.LXMessage.DIRECT
 | 
					                desired_method = LXMF.LXMessage.DIRECT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            lxm = LXMF.LXMessage(dest, source, content, title="", desired_method=desired_method)
 | 
					            lxm = LXMF.LXMessage(dest, source, content, title="", desired_method=desired_method, fields = self.get_message_fields(destination_hash))
 | 
				
			||||||
            lxm.register_delivery_callback(self.message_notification)
 | 
					            lxm.register_delivery_callback(self.message_notification)
 | 
				
			||||||
            lxm.register_failed_callback(self.message_notification)
 | 
					            lxm.register_failed_callback(self.message_notification)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2195,6 +2356,9 @@ class SidebandCore():
 | 
				
			|||||||
        self.setstate("lxm_uri_ingest.result", response)
 | 
					        self.setstate("lxm_uri_ingest.result", response)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def lxm_ingest(self, message, originator = False):
 | 
					    def lxm_ingest(self, message, originator = False):
 | 
				
			||||||
 | 
					        # TODO: Remove
 | 
				
			||||||
 | 
					        RNS.log("MESSAGE FIELDS: "+str(message.fields), RNS.LOG_WARNING)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        should_notify = False
 | 
					        should_notify = False
 | 
				
			||||||
        is_trusted = False
 | 
					        is_trusted = False
 | 
				
			||||||
        unread_reason_tx = False
 | 
					        unread_reason_tx = False
 | 
				
			||||||
 | 
				
			|||||||
@ -964,6 +964,22 @@ MDNavigationLayout:
 | 
				
			|||||||
                                pos_hint: {"center_y": 0.3}
 | 
					                                pos_hint: {"center_y": 0.3}
 | 
				
			||||||
                                active: False
 | 
					                                active: False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        MDBoxLayout:
 | 
				
			||||||
 | 
					                            orientation: "horizontal"
 | 
				
			||||||
 | 
					                            size_hint_y: None
 | 
				
			||||||
 | 
					                            padding: [0,0,dp(24),dp(0)]
 | 
				
			||||||
 | 
					                            height: dp(48)
 | 
				
			||||||
 | 
					                            
 | 
				
			||||||
 | 
					                            MDLabel:
 | 
				
			||||||
 | 
					                                text: "Always send custom display style"
 | 
				
			||||||
 | 
					                                font_style: "H6"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            MDSwitch:
 | 
				
			||||||
 | 
					                                id: telemetry_send_appearance
 | 
				
			||||||
 | 
					                                pos_hint: {"center_y": 0.3}
 | 
				
			||||||
 | 
					                                active: False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        MDLabel:
 | 
					                        MDLabel:
 | 
				
			||||||
                            markup: True
 | 
					                            markup: True
 | 
				
			||||||
                            text: "\\n\\n"
 | 
					                            text: "\\n\\n"
 | 
				
			||||||
 | 
				
			|||||||
@ -22,9 +22,11 @@ import subprocess
 | 
				
			|||||||
import shlex
 | 
					import shlex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if RNS.vendor.platformutils.get_platform() == "android":
 | 
					if RNS.vendor.platformutils.get_platform() == "android":
 | 
				
			||||||
 | 
					    from sideband.sense import Telemeter
 | 
				
			||||||
    from ui.helpers import ts_format, file_ts_format, mdc
 | 
					    from ui.helpers import ts_format, file_ts_format, mdc
 | 
				
			||||||
    from ui.helpers import color_received, color_delivered, color_propagated, color_paper, color_failed, color_unknown, intensity_msgs_dark, intensity_msgs_light
 | 
					    from ui.helpers import color_received, color_delivered, color_propagated, color_paper, color_failed, color_unknown, intensity_msgs_dark, intensity_msgs_light
 | 
				
			||||||
else:
 | 
					else:
 | 
				
			||||||
 | 
					    from sbapp.sideband.sense import Telemeter
 | 
				
			||||||
    from .helpers import ts_format, file_ts_format, mdc
 | 
					    from .helpers import ts_format, file_ts_format, mdc
 | 
				
			||||||
    from .helpers import color_received, color_delivered, color_propagated, color_paper, color_failed, color_unknown, intensity_msgs_dark, intensity_msgs_light
 | 
					    from .helpers import color_received, color_delivered, color_propagated, color_paper, color_failed, color_unknown, intensity_msgs_dark, intensity_msgs_light
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -260,6 +262,18 @@ class Messages():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                    return x
 | 
					                    return x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                def gen_copy_telemetry(packed_telemetry, item):
 | 
				
			||||||
 | 
					                    def x():
 | 
				
			||||||
 | 
					                        try:
 | 
				
			||||||
 | 
					                            telemeter = Telemeter.from_packed(packed_telemetry)
 | 
				
			||||||
 | 
					                            Clipboard.copy(str(telemeter.read_all()))
 | 
				
			||||||
 | 
					                            item.dmenu.dismiss()
 | 
				
			||||||
 | 
					                        except Exception as e:
 | 
				
			||||||
 | 
					                            RNS.log("An error occurred while decoding telemetry. The contained exception was: "+str(e), RNS.LOG_ERROR)
 | 
				
			||||||
 | 
					                            Clipboard.copy("Could not decode telemetry")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    return x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                def gen_copy_lxm_uri(lxm, item):
 | 
					                def gen_copy_lxm_uri(lxm, item):
 | 
				
			||||||
                    def x():
 | 
					                    def x():
 | 
				
			||||||
                        Clipboard.copy(lxm.as_uri())
 | 
					                        Clipboard.copy(lxm.as_uri())
 | 
				
			||||||
@ -446,6 +460,30 @@ class Messages():
 | 
				
			|||||||
                                "on_release": gen_del(m["hash"], item)
 | 
					                                "on_release": gen_del(m["hash"], item)
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        ]
 | 
					                        ]
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        if "lxm" in m and m["lxm"] and m["lxm"].fields != None and LXMF.FIELD_TELEMETRY in m["lxm"].fields:
 | 
				
			||||||
 | 
					                            packed_telemetry = m["lxm"].fields[LXMF.FIELD_TELEMETRY]
 | 
				
			||||||
 | 
					                            dm_items = [
 | 
				
			||||||
 | 
					                                {
 | 
				
			||||||
 | 
					                                    "viewclass": "OneLineListItem",
 | 
				
			||||||
 | 
					                                    "text": "Copy",
 | 
				
			||||||
 | 
					                                    "height": dp(40),
 | 
				
			||||||
 | 
					                                    "on_release": gen_copy(m["content"].decode("utf-8"), item)
 | 
				
			||||||
 | 
					                                },
 | 
				
			||||||
 | 
					                                {
 | 
				
			||||||
 | 
					                                    "viewclass": "OneLineListItem",
 | 
				
			||||||
 | 
					                                    "text": "Copy telemetry",
 | 
				
			||||||
 | 
					                                    "height": dp(40),
 | 
				
			||||||
 | 
					                                    "on_release": gen_copy_telemetry(packed_telemetry, item)
 | 
				
			||||||
 | 
					                                },
 | 
				
			||||||
 | 
					                                {
 | 
				
			||||||
 | 
					                                    "text": "Delete",
 | 
				
			||||||
 | 
					                                    "viewclass": "OneLineListItem",
 | 
				
			||||||
 | 
					                                    "height": dp(40),
 | 
				
			||||||
 | 
					                                    "on_release": gen_del(m["hash"], item)
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                            ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        else:
 | 
					                        else:
 | 
				
			||||||
                            dm_items = [
 | 
					                            dm_items = [
 | 
				
			||||||
                                {
 | 
					                                {
 | 
				
			||||||
@ -460,7 +498,6 @@ class Messages():
 | 
				
			|||||||
                                    "height": dp(40),
 | 
					                                    "height": dp(40),
 | 
				
			||||||
                                    "on_release": gen_del(m["hash"], item)
 | 
					                                    "on_release": gen_del(m["hash"], item)
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                            
 | 
					 | 
				
			||||||
                            ]
 | 
					                            ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                item.dmenu = MDDropdownMenu(
 | 
					                item.dmenu = MDDropdownMenu(
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user