Compare commits

..

12 Commits
0.1.2 ... 0.1.4

Author SHA1 Message Date
Mark Qvist
6c16e810e5 Updated dependencies 2021-10-15 19:47:16 +02:00
Mark Qvist
6d4ac49264 Updated version 2021-10-15 19:43:19 +02:00
Mark Qvist
939bc37f86 Mitigate KeyError in urwid 2021-10-15 13:13:48 +02:00
Mark Qvist
14eb35f7de Fixed sync progress bar display 2021-10-12 21:12:32 +02:00
Mark Qvist
19fb70fb3f Fixed sync progress bar display 2021-10-12 21:08:31 +02:00
Mark Qvist
9f9f10d54e Updated shortcuts bar 2021-10-12 20:46:05 +02:00
Mark Qvist
863a6cd2cd Update README.md 2021-10-11 15:25:29 +02:00
Mark Qvist
2ec95df3ec Fixed announce interval interpreted as seconds instead of minutes. 2021-10-10 13:50:57 +02:00
Mark Qvist
313cc108de Added selection check 2021-10-10 00:09:43 +02:00
Mark Qvist
33ccab0907 Added LXMF peers section to network view 2021-10-10 00:04:10 +02:00
Mark Qvist
71125252ee Updated versions 2021-10-09 23:25:10 +02:00
Mark Qvist
2ec674fbf3 Fixed node announce interval 2021-10-09 13:41:48 +02:00
8 changed files with 155 additions and 25 deletions

View File

@@ -49,6 +49,13 @@ The first time the program is running, you will be presented with the guide sect
To use Nomad Network on packet radio or LoRa, you will need to configure your Reticulum installation to use any relevant packet radio TNCs or LoRa devices on your system. See the [Reticulum documentation](https://markqvist.github.io/Reticulum/manual/interfaces.html) for info.
## Support Nomad Network
You can help support the continued development of open, free and private communications systems by donating via one of the following channels:
- Ethereum: 0x81F7B979fEa6134bA9FD5c701b3501A2e61E897a
- Bitcoin: 3CPmacGm34qYvR6XWLVEJmi2aNe3PZqUuq
- Ko-Fi: https://ko-fi.com/markqvist
## Caveat Emptor
Nomad Network is beta software, and should be considered as such. While it has been built with cryptography best-practices very foremost in mind, it _has not_ been externally security audited, and there could very well be privacy-breaking bugs. If you want to help out, or help sponsor an audit, please do get in touch.

View File

@@ -31,6 +31,10 @@ class Node:
if self.app.node_announce_at_start:
self.announce()
job_thread = threading.Thread(target=self.__jobs)
job_thread.setDaemon(True)
job_thread.start()
def register_pages(self):
self.servedpages = []
@@ -134,7 +138,7 @@ class Node:
while self.should_run_jobs:
now = time.time()
if now > self.last_announce + self.announce_interval:
if now > self.last_announce + self.announce_interval*60:
self.announce()
time.sleep(self.job_interval)

View File

@@ -218,6 +218,8 @@ class NomadNetworkApp:
elif self.message_router.propagation_transfer_state == LXMF.LXMRouter.PR_LINK_ESTABLISHED:
return "Link established"
elif self.message_router.propagation_transfer_state == LXMF.LXMRouter.PR_REQUEST_SENT:
return "Sync request sent"
elif self.message_router.propagation_transfer_state == LXMF.LXMRouter.PR_RECEIVING:
return "Receiving messages"
elif self.message_router.propagation_transfer_state == LXMF.LXMRouter.PR_RESPONSE_RECEIVED:
return "Messages received"
@@ -241,6 +243,8 @@ class NomadNetworkApp:
return True
elif self.message_router.propagation_transfer_state == LXMF.LXMRouter.PR_REQUEST_SENT:
return True
elif self.message_router.propagation_transfer_state == LXMF.LXMRouter.PR_RECEIVING:
return True
elif self.message_router.propagation_transfer_state == LXMF.LXMRouter.PR_RESPONSE_RECEIVED:
return True
elif self.message_router.propagation_transfer_state == LXMF.LXMRouter.PR_COMPLETE:

View File

@@ -1 +1 @@
__version__ = "0.1.2"
__version__ = "0.1.4"

View File

@@ -20,7 +20,7 @@ class ConversationDisplayShortcuts():
def __init__(self, app):
self.app = app
self.widget = urwid.AttrMap(urwid.Text("[C-d] Send [C-k] Clear Editor [C-w] Close [C-t] Editor Type [C-p] Purge [C-x] Clear History [C-o] Sort"), "shortcutbar")
self.widget = urwid.AttrMap(urwid.Text("[C-d] Send [C-k] Clear [C-w] Close [C-t] Title [C-p] Purge [C-x] Clear History [C-o] Sort"), "shortcutbar")
class ConversationsArea(urwid.LineBox):
def keypress(self, size, key):
@@ -352,6 +352,7 @@ class ConversationsDisplay():
def cancel_sync(sender):
self.app.cancel_lxmf_sync()
self.update_sync_dialog()
cancel_button = urwid.Button("Close", on_press=dismiss_dialog)
sync_progress = SyncProgressBar("progress_empty" , "progress_full", current=self.app.get_sync_progress(), done=1.0, satt=None)

View File

@@ -129,11 +129,12 @@ class MainDisplay():
def update_active_shortcuts(self):
self.frame.contents["footer"] = (self.sub_displays.active().shortcuts().widget, None)
def request_redraw(self):
self.app.ui.loop.set_alarm_in(0.25, self.redraw_now)
def request_redraw(self, extra_delay=0.0):
self.app.ui.loop.set_alarm_in(0.25+extra_delay, self.redraw_now)
def redraw_now(self, sender=None, data=None):
self.app.ui.loop.draw_screen()
self.app.ui.loop.screen.clear()
#self.app.ui.loop.draw_screen()
def start(self):
self.menu_display.start()

View File

@@ -107,6 +107,7 @@ class AnnounceInfo(urwid.WidgetWrap):
self.parent.left_pile.contents[0] = (self.parent.announce_stream_display, options)
def connect(sender):
self.app.ui.main_display.request_redraw(extra_delay=0.75)
self.parent.browser.retrieve_url(RNS.hexrep(source_hash, delimit=False))
show_announce_stream(None)
@@ -433,6 +434,7 @@ class KnownNodeInfo(urwid.WidgetWrap):
self.parent.left_pile.contents[0] = (self.parent.known_nodes_display, options)
def connect(sender):
self.app.ui.main_display.request_redraw(extra_delay=0.75)
self.parent.browser.retrieve_url(RNS.hexrep(source_hash, delimit=False))
show_known_nodes(None)
@@ -576,7 +578,9 @@ class KnownNodes(urwid.WidgetWrap):
self.delegate.left_pile.contents[0] = (overlay, options)
def delete_selected_entry(self):
source_hash = self.ilb.get_selected_item().original_widget.source_hash
si = self.ilb.get_selected_item()
if si != None:
source_hash = si.original_widget.source_hash
def dismiss_dialog(sender):
self.delegate.close_list_dialogs()
@@ -1022,6 +1026,9 @@ class NetworkLeftPile(urwid.Pile):
def keypress(self, size, key):
if key == "ctrl l":
self.parent.toggle_list()
elif key == "ctrl p":
self.parent.reinit_lxmf_peers()
self.parent.show_peers()
elif key == "ctrl w":
self.parent.browser.disconnect()
elif key == "ctrl u":
@@ -1043,6 +1050,7 @@ class NetworkDisplay():
self.browser.loopback = self.app.node.destination.hash
self.known_nodes_display = KnownNodes(self.app)
self.lxmf_peers_display = LXMFPeers(self.app)
self.network_stats_display = NetworkStats(self.app, self)
self.announce_stream_display = AnnounceStream(self.app, self)
self.local_peer_display = LocalPeer(self.app, self)
@@ -1084,6 +1092,15 @@ class NetworkDisplay():
self.left_pile.contents[0] = (self.known_nodes_display, options)
self.list_display = 1
def show_peers(self):
options = self.left_pile.options(height_type="weight", height_amount=1)
self.left_pile.contents[0] = (self.lxmf_peers_display, options)
if self.list_display != 0:
self.list_display = 0
else:
self.list_display = 1
def focus_lists(self):
self.columns.focus_position = 0
@@ -1093,6 +1110,11 @@ class NetworkDisplay():
self.close_list_dialogs()
self.announce_stream_display.rebuild_widget_list()
def reinit_lxmf_peers(self):
self.lxmf_peers_display = LXMFPeers(self.app)
self.lxmf_peers_display.delegate = self
self.close_list_dialogs()
def close_list_dialogs(self):
if self.list_display == 0:
options = self.left_pile.options(height_type="weight", height_amount=1)
@@ -1121,6 +1143,97 @@ class NetworkDisplay():
self.known_nodes_display.rebuild_widget_list()
class LXMFPeers(urwid.WidgetWrap):
def __init__(self, app):
self.app = app
self.peer_list = app.message_router.peers
# self.peer_list = {}
g = self.app.ui.glyphs
self.widget_list = self.make_peer_widgets()
self.ilb = IndicativeListBox(
self.widget_list,
on_selection_change=self.node_list_selection,
initialization_is_selection_change=False,
highlight_offFocus="list_off_focus"
)
if len(self.peer_list) > 0:
self.display_widget = self.ilb
widget_style = None
self.no_content = False
else:
self.no_content = True
widget_style = "inactive_text"
self.pile = urwid.Pile([urwid.Text(("warning_text", g["info"]+"\n"), align="center"), SelectText(("warning_text", "Currently, no LXMF nodes are peered\n\n"), align="center")])
self.display_widget = urwid.Filler(self.pile, valign="top", height="pack")
urwid.WidgetWrap.__init__(self, urwid.AttrMap(urwid.LineBox(self.display_widget, title="LXMF Peers"), widget_style))
def keypress(self, size, key):
if key == "up" and (self.no_content or self.ilb.first_item_is_selected()):
nomadnet.NomadNetworkApp.get_shared_instance().ui.main_display.frame.set_focus("header")
elif key == "ctrl x":
self.delete_selected_entry()
return super(LXMFPeers, self).keypress(size, key)
def node_list_selection(self, arg1, arg2):
pass
def delete_selected_entry(self):
si = self.ilb.get_selected_item()
if si != None:
destination_hash = si.original_widget.destination_hash
self.app.message_router.unpeer(destination_hash)
self.delegate.reinit_lxmf_peers()
self.delegate.show_peers()
def rebuild_widget_list(self):
self.peer_list = self.app.message_router.peers
self.widget_list = self.make_peer_widgets()
self.ilb.set_body(self.widget_list)
if len(self.widget_list) > 0:
self.no_content = False
else:
self.no_content = True
self.delegate.reinit_lxmf_peers()
def make_peer_widgets(self):
widget_list = []
for peer_id in self.peer_list:
peer = self.peer_list[peer_id]
pe = LXMFPeerEntry(self.app, peer, self)
pe.destination_hash = peer.destination_hash
widget_list.append(pe)
# TODO: Sort list
return widget_list
class LXMFPeerEntry(urwid.WidgetWrap):
def __init__(self, app, peer, delegate):
destination_hash = peer.destination_hash
self.app = app
g = self.app.ui.glyphs
display_str = RNS.prettyhexrep(destination_hash)
sym = g["sent"]
style = "list_unknown"
focus_style = "list_focus"
widget = ListEntry(sym+" "+display_str+"\n Last heard "+pretty_date(int(peer.last_heard))+"\n "+str(len(peer.unhandled_messages))+" unhandled")
# urwid.connect_signal(widget, "click", delegate.connect_node, node)
self.display_widget = urwid.AttrMap(widget, style, focus_style)
self.display_widget.destination_hash = destination_hash
urwid.WidgetWrap.__init__(self, self.display_widget)
def pretty_date(time=False):
"""

View File

@@ -23,6 +23,6 @@ setuptools.setup(
entry_points= {
'console_scripts': ['nomadnet=nomadnet.nomadnet:main']
},
install_requires=['rns>=0.2.7', 'lxmf>=0.1.0', 'urwid>=2.1.2'],
install_requires=['rns>=0.2.9', 'lxmf>=0.1.2', 'urwid>=2.1.2'],
python_requires='>=3.6',
)