mirror of
https://github.com/markqvist/NomadNet.git
synced 2025-12-17 14:54:26 +01:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f8775adbab | ||
|
|
c0dac0eadb | ||
|
|
c198d516da | ||
|
|
d9886980fa | ||
|
|
7ced4c3659 | ||
|
|
c3c8f99131 | ||
|
|
9f00ffbae6 | ||
|
|
a26edd21db | ||
|
|
46f3a4127c | ||
|
|
eeb15dcb43 | ||
|
|
9ef34fc774 | ||
|
|
704a4ea828 | ||
|
|
5f31aeb3c1 |
2
.github/ISSUE_TEMPLATE/🐛-bug-report.md
vendored
2
.github/ISSUE_TEMPLATE/🐛-bug-report.md
vendored
@@ -12,7 +12,7 @@ Before creating a bug report on this issue tracker, you **must** read the [Contr
|
|||||||
|
|
||||||
- The issue tracker is used by developers of this project. **Do not use it to ask general questions, or for support requests**.
|
- The issue tracker is used by developers of this project. **Do not use it to ask general questions, or for support requests**.
|
||||||
- Ideas and feature requests can be made on the [Discussions](https://github.com/markqvist/Reticulum/discussions). **Only** feature requests accepted by maintainers and developers are tracked and included on the issue tracker. **Do not post feature requests here**.
|
- Ideas and feature requests can be made on the [Discussions](https://github.com/markqvist/Reticulum/discussions). **Only** feature requests accepted by maintainers and developers are tracked and included on the issue tracker. **Do not post feature requests here**.
|
||||||
- After reading the [Contribution Guidelines](https://github.com/markqvist/Reticulum/blob/master/Contributing.md), delete this section from your bug report.
|
- After reading the [Contribution Guidelines](https://github.com/markqvist/Reticulum/blob/master/Contributing.md), **delete this section only** (*"Read the Contribution Guidelines"*) from your bug report, **and fill in all the other sections**.
|
||||||
|
|
||||||
**Describe the Bug**
|
**Describe the Bug**
|
||||||
A clear and concise description of what the bug is.
|
A clear and concise description of what the bug is.
|
||||||
|
|||||||
@@ -16,10 +16,6 @@ ENV PATH="/home/myuser/.local/bin:${PATH}"
|
|||||||
|
|
||||||
################### BEGIN NomadNet ###########################################
|
################### BEGIN NomadNet ###########################################
|
||||||
|
|
||||||
COPY --chown=myuser:myuser requirements.txt requirements.txt
|
|
||||||
|
|
||||||
RUN pip install --user -r requirements.txt
|
|
||||||
|
|
||||||
|
|
||||||
COPY --chown=myuser:myuser . .
|
COPY --chown=myuser:myuser . .
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import RNS
|
|||||||
import LXMF
|
import LXMF
|
||||||
import time
|
import time
|
||||||
import nomadnet
|
import nomadnet
|
||||||
|
import threading
|
||||||
import RNS.vendor.umsgpack as msgpack
|
import RNS.vendor.umsgpack as msgpack
|
||||||
|
|
||||||
class PNAnnounceHandler:
|
class PNAnnounceHandler:
|
||||||
@@ -29,7 +30,7 @@ class PNAnnounceHandler:
|
|||||||
RNS.log("The contained exception was: "+str(e), RNS.LOG_DEBUG)
|
RNS.log("The contained exception was: "+str(e), RNS.LOG_DEBUG)
|
||||||
|
|
||||||
class Directory:
|
class Directory:
|
||||||
ANNOUNCE_STREAM_MAXLENGTH = 64
|
ANNOUNCE_STREAM_MAXLENGTH = 256
|
||||||
|
|
||||||
aspect_filter = "nomadnetwork.node"
|
aspect_filter = "nomadnetwork.node"
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -55,6 +56,7 @@ class Directory:
|
|||||||
self.directory_entries = {}
|
self.directory_entries = {}
|
||||||
self.announce_stream = []
|
self.announce_stream = []
|
||||||
self.app = app
|
self.app = app
|
||||||
|
self.announce_lock = threading.Lock()
|
||||||
self.load_from_disk()
|
self.load_from_disk()
|
||||||
|
|
||||||
self.pn_announce_handler = PNAnnounceHandler(self)
|
self.pn_announce_handler = PNAnnounceHandler(self)
|
||||||
@@ -124,90 +126,94 @@ class Directory:
|
|||||||
RNS.log("Could not load directory from disk. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
RNS.log("Could not load directory from disk. The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
|
|
||||||
def lxmf_announce_received(self, source_hash, app_data):
|
def lxmf_announce_received(self, source_hash, app_data):
|
||||||
if app_data != None:
|
with self.announce_lock:
|
||||||
if self.app.compact_stream:
|
if app_data != None:
|
||||||
try:
|
if self.app.compact_stream:
|
||||||
remove_announces = []
|
try:
|
||||||
for announce in self.announce_stream:
|
remove_announces = []
|
||||||
if announce[1] == source_hash:
|
for announce in self.announce_stream:
|
||||||
remove_announces.append(announce)
|
if announce[1] == source_hash:
|
||||||
|
remove_announces.append(announce)
|
||||||
|
|
||||||
for a in remove_announces:
|
for a in remove_announces:
|
||||||
self.announce_stream.remove(a)
|
self.announce_stream.remove(a)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("An error occurred while compacting the announce stream. The contained exception was:"+str(e), RNS.LOG_ERROR)
|
RNS.log("An error occurred while compacting the announce stream. The contained exception was:"+str(e), RNS.LOG_ERROR)
|
||||||
|
|
||||||
timestamp = time.time()
|
timestamp = time.time()
|
||||||
self.announce_stream.insert(0, (timestamp, source_hash, app_data, "peer"))
|
self.announce_stream.insert(0, (timestamp, source_hash, app_data, "peer"))
|
||||||
while len(self.announce_stream) > Directory.ANNOUNCE_STREAM_MAXLENGTH:
|
while len(self.announce_stream) > Directory.ANNOUNCE_STREAM_MAXLENGTH:
|
||||||
self.announce_stream.pop()
|
self.announce_stream.pop()
|
||||||
|
|
||||||
if hasattr(self.app.ui, "main_display"):
|
if hasattr(self.app, "ui") and self.app.ui != None:
|
||||||
self.app.ui.main_display.sub_displays.network_display.directory_change_callback()
|
if hasattr(self.app.ui, "main_display"):
|
||||||
|
self.app.ui.main_display.sub_displays.network_display.directory_change_callback()
|
||||||
|
|
||||||
def node_announce_received(self, source_hash, app_data, associated_peer):
|
def node_announce_received(self, source_hash, app_data, associated_peer):
|
||||||
if app_data != None:
|
with self.announce_lock:
|
||||||
if self.app.compact_stream:
|
if app_data != None:
|
||||||
try:
|
if self.app.compact_stream:
|
||||||
remove_announces = []
|
try:
|
||||||
for announce in self.announce_stream:
|
remove_announces = []
|
||||||
if announce[1] == source_hash:
|
for announce in self.announce_stream:
|
||||||
remove_announces.append(announce)
|
if announce[1] == source_hash:
|
||||||
|
remove_announces.append(announce)
|
||||||
|
|
||||||
for a in remove_announces:
|
for a in remove_announces:
|
||||||
self.announce_stream.remove(a)
|
self.announce_stream.remove(a)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
RNS.log("An error occurred while compacting the announce stream. The contained exception was:"+str(e), RNS.LOG_ERROR)
|
||||||
|
|
||||||
|
timestamp = time.time()
|
||||||
|
self.announce_stream.insert(0, (timestamp, source_hash, app_data, "node"))
|
||||||
|
while len(self.announce_stream) > Directory.ANNOUNCE_STREAM_MAXLENGTH:
|
||||||
|
self.announce_stream.pop()
|
||||||
|
|
||||||
|
if self.trust_level(associated_peer) == DirectoryEntry.TRUSTED:
|
||||||
|
existing_entry = self.find(source_hash)
|
||||||
|
if not existing_entry:
|
||||||
|
node_entry = DirectoryEntry(source_hash, display_name=app_data.decode("utf-8"), trust_level=DirectoryEntry.TRUSTED, hosts_node=True)
|
||||||
|
self.remember(node_entry)
|
||||||
|
|
||||||
except Exception as e:
|
if hasattr(self.app.ui, "main_display"):
|
||||||
RNS.log("An error occurred while compacting the announce stream. The contained exception was:"+str(e), RNS.LOG_ERROR)
|
self.app.ui.main_display.sub_displays.network_display.directory_change_callback()
|
||||||
|
|
||||||
timestamp = time.time()
|
|
||||||
self.announce_stream.insert(0, (timestamp, source_hash, app_data, "node"))
|
|
||||||
while len(self.announce_stream) > Directory.ANNOUNCE_STREAM_MAXLENGTH:
|
|
||||||
self.announce_stream.pop()
|
|
||||||
|
|
||||||
if self.trust_level(associated_peer) == DirectoryEntry.TRUSTED:
|
|
||||||
existing_entry = self.find(source_hash)
|
|
||||||
if not existing_entry:
|
|
||||||
node_entry = DirectoryEntry(source_hash, display_name=app_data.decode("utf-8"), trust_level=DirectoryEntry.TRUSTED, hosts_node=True)
|
|
||||||
self.remember(node_entry)
|
|
||||||
|
|
||||||
if hasattr(self.app.ui, "main_display"):
|
|
||||||
self.app.ui.main_display.sub_displays.network_display.directory_change_callback()
|
|
||||||
|
|
||||||
def pn_announce_received(self, source_hash, app_data, associated_peer, associated_node):
|
def pn_announce_received(self, source_hash, app_data, associated_peer, associated_node):
|
||||||
found_node = None
|
with self.announce_lock:
|
||||||
for sh in self.directory_entries:
|
found_node = None
|
||||||
if sh == associated_node:
|
for sh in self.directory_entries:
|
||||||
found_node = True
|
if sh == associated_node:
|
||||||
break
|
found_node = True
|
||||||
|
break
|
||||||
|
|
||||||
for e in self.announce_stream:
|
for e in self.announce_stream:
|
||||||
if e[1] == associated_node:
|
if e[1] == associated_node:
|
||||||
found_node = True
|
found_node = True
|
||||||
break
|
break
|
||||||
|
|
||||||
if not found_node:
|
if not found_node:
|
||||||
if self.app.compact_stream:
|
if self.app.compact_stream:
|
||||||
try:
|
try:
|
||||||
remove_announces = []
|
remove_announces = []
|
||||||
for announce in self.announce_stream:
|
for announce in self.announce_stream:
|
||||||
if announce[1] == source_hash:
|
if announce[1] == source_hash:
|
||||||
remove_announces.append(announce)
|
remove_announces.append(announce)
|
||||||
|
|
||||||
for a in remove_announces:
|
for a in remove_announces:
|
||||||
self.announce_stream.remove(a)
|
self.announce_stream.remove(a)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
RNS.log("An error occurred while compacting the announce stream. The contained exception was:"+str(e), RNS.LOG_ERROR)
|
||||||
|
|
||||||
|
timestamp = time.time()
|
||||||
|
self.announce_stream.insert(0, (timestamp, source_hash, app_data, "pn"))
|
||||||
|
while len(self.announce_stream) > Directory.ANNOUNCE_STREAM_MAXLENGTH:
|
||||||
|
self.announce_stream.pop()
|
||||||
|
|
||||||
except Exception as e:
|
if hasattr(self.app, "ui") and hasattr(self.app.ui, "main_display"):
|
||||||
RNS.log("An error occurred while compacting the announce stream. The contained exception was:"+str(e), RNS.LOG_ERROR)
|
self.app.ui.main_display.sub_displays.network_display.directory_change_callback()
|
||||||
|
|
||||||
timestamp = time.time()
|
|
||||||
self.announce_stream.insert(0, (timestamp, source_hash, app_data, "pn"))
|
|
||||||
while len(self.announce_stream) > Directory.ANNOUNCE_STREAM_MAXLENGTH:
|
|
||||||
self.announce_stream.pop()
|
|
||||||
|
|
||||||
if hasattr(self.app.ui, "main_display"):
|
|
||||||
self.app.ui.main_display.sub_displays.network_display.directory_change_callback()
|
|
||||||
|
|
||||||
def remove_announce_with_timestamp(self, timestamp):
|
def remove_announce_with_timestamp(self, timestamp):
|
||||||
selected_announce = None
|
selected_announce = None
|
||||||
|
|||||||
@@ -537,7 +537,7 @@ class NomadNetworkApp:
|
|||||||
RNS.log("Could not autoselect a propagation node! LXMF propagation will not be available until a trusted node announces on the network, or a propagation node is manually selected.", RNS.LOG_WARNING)
|
RNS.log("Could not autoselect a propagation node! LXMF propagation will not be available until a trusted node announces on the network, or a propagation node is manually selected.", RNS.LOG_WARNING)
|
||||||
else:
|
else:
|
||||||
pn_name_str = ""
|
pn_name_str = ""
|
||||||
RNS.log("Selecting "+RNS.prettyhexrep(selected_node)+pn_name_str+" as default LXMF propagation node", RNS.LOG_INFO)
|
RNS.log("Selecting "+RNS.prettyhexrep(selected_node)+pn_name_str+" as default LXMF propagation node", RNS.LOG_DEBUG)
|
||||||
self.message_router.set_outbound_propagation_node(selected_node)
|
self.message_router.set_outbound_propagation_node(selected_node)
|
||||||
|
|
||||||
def get_user_selected_propagation_node(self):
|
def get_user_selected_propagation_node(self):
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
__version__ = "0.6.0"
|
__version__ = "0.6.1"
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ class AnnounceInfo(urwid.WidgetWrap):
|
|||||||
if is_node:
|
if is_node:
|
||||||
try:
|
try:
|
||||||
existing_conversations = nomadnet.Conversation.conversation_list(self.app)
|
existing_conversations = nomadnet.Conversation.conversation_list(self.app)
|
||||||
|
|
||||||
source_hash_text = RNS.hexrep(op_hash, delimit=False)
|
source_hash_text = RNS.hexrep(op_hash, delimit=False)
|
||||||
display_name = op_str
|
display_name = op_str
|
||||||
|
|
||||||
@@ -162,7 +162,7 @@ class AnnounceInfo(urwid.WidgetWrap):
|
|||||||
show_announce_stream(None)
|
show_announce_stream(None)
|
||||||
try:
|
try:
|
||||||
existing_conversations = nomadnet.Conversation.conversation_list(self.app)
|
existing_conversations = nomadnet.Conversation.conversation_list(self.app)
|
||||||
|
|
||||||
source_hash_text = RNS.hexrep(source_hash, delimit=False)
|
source_hash_text = RNS.hexrep(source_hash, delimit=False)
|
||||||
display_name = data_str
|
display_name = data_str
|
||||||
|
|
||||||
@@ -316,7 +316,7 @@ class AnnounceStreamEntry(urwid.WidgetWrap):
|
|||||||
info_widget = AnnounceInfo(announce, parent, self.app)
|
info_widget = AnnounceInfo(announce, parent, self.app)
|
||||||
options = parent.left_pile.options(height_type=urwid.WEIGHT, height_amount=1)
|
options = parent.left_pile.options(height_type=urwid.WEIGHT, height_amount=1)
|
||||||
parent.left_pile.contents[0] = (info_widget, options)
|
parent.left_pile.contents[0] = (info_widget, options)
|
||||||
|
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
def dismiss_dialog(sender):
|
def dismiss_dialog(sender):
|
||||||
self.delegate.parent.close_list_dialogs()
|
self.delegate.parent.close_list_dialogs()
|
||||||
@@ -368,6 +368,10 @@ class AnnounceStreamEntry(urwid.WidgetWrap):
|
|||||||
def timestamp(self):
|
def timestamp(self):
|
||||||
return self.timestamp
|
return self.timestamp
|
||||||
|
|
||||||
|
class TabButton(urwid.Button):
|
||||||
|
button_left = urwid.Text("[")
|
||||||
|
button_right = urwid.Text("]")
|
||||||
|
|
||||||
class AnnounceStream(urwid.WidgetWrap):
|
class AnnounceStream(urwid.WidgetWrap):
|
||||||
def __init__(self, app, parent):
|
def __init__(self, app, parent):
|
||||||
self.app = app
|
self.app = app
|
||||||
@@ -376,11 +380,24 @@ class AnnounceStream(urwid.WidgetWrap):
|
|||||||
self.timeout = self.app.config["textui"]["animation_interval"]*2
|
self.timeout = self.app.config["textui"]["animation_interval"]*2
|
||||||
self.ilb = None
|
self.ilb = None
|
||||||
self.no_content = True
|
self.no_content = True
|
||||||
|
self.current_tab = "nodes"
|
||||||
|
|
||||||
self.added_entries = []
|
self.added_entries = []
|
||||||
self.widget_list = []
|
self.widget_list = []
|
||||||
self.update_widget_list()
|
self.update_widget_list()
|
||||||
|
|
||||||
|
# Create tab buttons
|
||||||
|
self.tab_nodes = TabButton("Nodes", on_press=self.show_nodes_tab)
|
||||||
|
self.tab_peers = TabButton("Peers", on_press=self.show_peers_tab)
|
||||||
|
self.tab_pn = TabButton("Propagation Nodes", on_press=self.show_pn_tab)
|
||||||
|
|
||||||
|
# Create tab bar with proportional widths
|
||||||
|
self.tab_bar = urwid.Columns([
|
||||||
|
('weight', 1, self.tab_nodes),
|
||||||
|
('weight', 1, self.tab_peers),
|
||||||
|
('weight', 3, self.tab_pn),
|
||||||
|
], dividechars=1) # Add 1 character spacing between tabs
|
||||||
|
|
||||||
self.ilb = ExceptionHandlingListBox(
|
self.ilb = ExceptionHandlingListBox(
|
||||||
self.widget_list,
|
self.widget_list,
|
||||||
on_selection_change=self.list_selection,
|
on_selection_change=self.list_selection,
|
||||||
@@ -389,7 +406,13 @@ class AnnounceStream(urwid.WidgetWrap):
|
|||||||
#highlight_offFocus="list_off_focus"
|
#highlight_offFocus="list_off_focus"
|
||||||
)
|
)
|
||||||
|
|
||||||
self.display_widget = self.ilb
|
# Combine tab bar and list box
|
||||||
|
self.pile = urwid.Pile([
|
||||||
|
('pack', self.tab_bar),
|
||||||
|
('weight', 1, self.ilb),
|
||||||
|
])
|
||||||
|
|
||||||
|
self.display_widget = self.pile
|
||||||
super().__init__(urwid.LineBox(self.display_widget, title="Announce Stream"))
|
super().__init__(urwid.LineBox(self.display_widget, title="Announce Stream"))
|
||||||
|
|
||||||
def keypress(self, size, key):
|
def keypress(self, size, key):
|
||||||
@@ -397,7 +420,7 @@ class AnnounceStream(urwid.WidgetWrap):
|
|||||||
nomadnet.NomadNetworkApp.get_shared_instance().ui.main_display.frame.focus_position = "header"
|
nomadnet.NomadNetworkApp.get_shared_instance().ui.main_display.frame.focus_position = "header"
|
||||||
elif key == "ctrl x":
|
elif key == "ctrl x":
|
||||||
self.delete_selected_entry()
|
self.delete_selected_entry()
|
||||||
|
|
||||||
return super(AnnounceStream, self).keypress(size, key)
|
return super(AnnounceStream, self).keypress(size, key)
|
||||||
|
|
||||||
def delete_selected_entry(self):
|
def delete_selected_entry(self):
|
||||||
@@ -412,28 +435,45 @@ class AnnounceStream(urwid.WidgetWrap):
|
|||||||
self.update_widget_list()
|
self.update_widget_list()
|
||||||
|
|
||||||
def update_widget_list(self):
|
def update_widget_list(self):
|
||||||
|
self.widget_list = []
|
||||||
new_entries = []
|
new_entries = []
|
||||||
|
|
||||||
for e in self.app.directory.announce_stream:
|
for e in self.app.directory.announce_stream:
|
||||||
if not e[0] in self.added_entries:
|
announce_type = e[3]
|
||||||
self.added_entries.insert(0, e[0])
|
|
||||||
new_entries.insert(0, e)
|
# Filter based on current tab
|
||||||
|
if self.current_tab == "nodes" and (announce_type == "node" or announce_type == True):
|
||||||
|
new_entries.append(e)
|
||||||
|
elif self.current_tab == "peers" and (announce_type == "peer" or announce_type == False):
|
||||||
|
new_entries.append(e)
|
||||||
|
elif self.current_tab == "pn" and announce_type == "pn":
|
||||||
|
new_entries.append(e)
|
||||||
|
|
||||||
for e in new_entries:
|
for e in new_entries:
|
||||||
nw = AnnounceStreamEntry(self.app, e, self)
|
nw = AnnounceStreamEntry(self.app, e, self)
|
||||||
nw.timestamp = e[0]
|
nw.timestamp = e[0]
|
||||||
self.widget_list.insert(0, nw)
|
self.widget_list.append(nw)
|
||||||
|
|
||||||
if len(new_entries) > 0:
|
if len(new_entries) > 0:
|
||||||
self.no_content = False
|
self.no_content = False
|
||||||
if self.ilb != None:
|
|
||||||
self.ilb.set_body(self.widget_list)
|
|
||||||
else:
|
else:
|
||||||
if len(self.widget_list) == 0:
|
self.no_content = True
|
||||||
self.no_content = True
|
self.widget_list = [urwid.Text(f"No {self.current_tab} announces", align='center')]
|
||||||
|
|
||||||
if self.ilb != None:
|
|
||||||
self.ilb.set_body(self.widget_list)
|
|
||||||
|
|
||||||
|
if self.ilb:
|
||||||
|
self.ilb.set_body(self.widget_list)
|
||||||
|
|
||||||
|
def show_nodes_tab(self, button):
|
||||||
|
self.current_tab = "nodes"
|
||||||
|
self.update_widget_list()
|
||||||
|
|
||||||
|
def show_peers_tab(self, button):
|
||||||
|
self.current_tab = "peers"
|
||||||
|
self.update_widget_list()
|
||||||
|
|
||||||
|
def show_pn_tab(self, button):
|
||||||
|
self.current_tab = "pn"
|
||||||
|
self.update_widget_list()
|
||||||
|
|
||||||
def list_selection(self, arg1, arg2):
|
def list_selection(self, arg1, arg2):
|
||||||
pass
|
pass
|
||||||
@@ -596,7 +636,7 @@ class KnownNodeInfo(urwid.WidgetWrap):
|
|||||||
if node_ident != None:
|
if node_ident != None:
|
||||||
try:
|
try:
|
||||||
existing_conversations = nomadnet.Conversation.conversation_list(self.app)
|
existing_conversations = nomadnet.Conversation.conversation_list(self.app)
|
||||||
|
|
||||||
source_hash_text = RNS.hexrep(op_hash, delimit=False)
|
source_hash_text = RNS.hexrep(op_hash, delimit=False)
|
||||||
display_name = op_str
|
display_name = op_str
|
||||||
|
|
||||||
@@ -632,7 +672,7 @@ class KnownNodeInfo(urwid.WidgetWrap):
|
|||||||
trust_level = DirectoryEntry.UNTRUSTED
|
trust_level = DirectoryEntry.UNTRUSTED
|
||||||
if r_unknown.get_state() == True:
|
if r_unknown.get_state() == True:
|
||||||
trust_level = DirectoryEntry.UNKNOWN
|
trust_level = DirectoryEntry.UNKNOWN
|
||||||
|
|
||||||
if r_trusted.get_state() == True:
|
if r_trusted.get_state() == True:
|
||||||
trust_level = DirectoryEntry.TRUSTED
|
trust_level = DirectoryEntry.TRUSTED
|
||||||
|
|
||||||
@@ -699,7 +739,7 @@ class KnownNodeInfo(urwid.WidgetWrap):
|
|||||||
pile_widgets.insert(4, operator_entry)
|
pile_widgets.insert(4, operator_entry)
|
||||||
|
|
||||||
pile = urwid.Pile(pile_widgets)
|
pile = urwid.Pile(pile_widgets)
|
||||||
|
|
||||||
pile.focus_position = len(pile.contents)-1
|
pile.focus_position = len(pile.contents)-1
|
||||||
button_columns.focus_position = 0
|
button_columns.focus_position = 0
|
||||||
|
|
||||||
@@ -733,7 +773,7 @@ class KnownNodes(urwid.WidgetWrap):
|
|||||||
g = self.app.ui.glyphs
|
g = self.app.ui.glyphs
|
||||||
|
|
||||||
self.widget_list = self.make_node_widgets()
|
self.widget_list = self.make_node_widgets()
|
||||||
|
|
||||||
self.ilb = ExceptionHandlingListBox(
|
self.ilb = ExceptionHandlingListBox(
|
||||||
self.widget_list,
|
self.widget_list,
|
||||||
on_selection_change=self.node_list_selection,
|
on_selection_change=self.node_list_selection,
|
||||||
@@ -767,7 +807,7 @@ class KnownNodes(urwid.WidgetWrap):
|
|||||||
nomadnet.NomadNetworkApp.get_shared_instance().ui.main_display.frame.focus_position = "header"
|
nomadnet.NomadNetworkApp.get_shared_instance().ui.main_display.frame.focus_position = "header"
|
||||||
elif key == "ctrl x":
|
elif key == "ctrl x":
|
||||||
self.delete_selected_entry()
|
self.delete_selected_entry()
|
||||||
|
|
||||||
return super(KnownNodes, self).keypress(size, key)
|
return super(KnownNodes, self).keypress(size, key)
|
||||||
|
|
||||||
|
|
||||||
@@ -910,7 +950,7 @@ class NodeEntry(urwid.WidgetWrap):
|
|||||||
focus_style = "list_focus_untrusted"
|
focus_style = "list_focus_untrusted"
|
||||||
|
|
||||||
type_symbol = g["node"]
|
type_symbol = g["node"]
|
||||||
|
|
||||||
widget = ListEntry(type_symbol+" "+display_str)
|
widget = ListEntry(type_symbol+" "+display_str)
|
||||||
urwid.connect_signal(widget, "click", delegate.connect_node, node)
|
urwid.connect_signal(widget, "click", delegate.connect_node, node)
|
||||||
|
|
||||||
@@ -1209,7 +1249,7 @@ class LocalPeer(urwid.WidgetWrap):
|
|||||||
|
|
||||||
#overlay = urwid.Overlay(dialog, bottom, align=urwid.CENTER, width=urwid.RELATIVE_100, valign=urwid.MIDDLE, height=urwid.PACK, left=4, right=4)
|
#overlay = urwid.Overlay(dialog, bottom, align=urwid.CENTER, width=urwid.RELATIVE_100, valign=urwid.MIDDLE, height=urwid.PACK, left=4, right=4)
|
||||||
overlay = dialog
|
overlay = dialog
|
||||||
|
|
||||||
self.dialog_open = True
|
self.dialog_open = True
|
||||||
options = self.parent.left_pile.options(height_type=urwid.PACK, height_amount=None)
|
options = self.parent.left_pile.options(height_type=urwid.PACK, height_amount=None)
|
||||||
self.parent.left_pile.contents[1] = (overlay, options)
|
self.parent.left_pile.contents[1] = (overlay, options)
|
||||||
@@ -1226,7 +1266,7 @@ class LocalPeer(urwid.WidgetWrap):
|
|||||||
self.t_last_announce.update_time()
|
self.t_last_announce.update_time()
|
||||||
|
|
||||||
announce_button = urwid.Button("Announce Now", on_press=announce_query)
|
announce_button = urwid.Button("Announce Now", on_press=announce_query)
|
||||||
|
|
||||||
self.display_widget = urwid.Pile(
|
self.display_widget = urwid.Pile(
|
||||||
[
|
[
|
||||||
t_id,
|
t_id,
|
||||||
@@ -1270,13 +1310,13 @@ class NodeInfo(urwid.WidgetWrap):
|
|||||||
def show_peer_info(sender):
|
def show_peer_info(sender):
|
||||||
options = self.parent.left_pile.options(height_type=urwid.PACK, height_amount=None)
|
options = self.parent.left_pile.options(height_type=urwid.PACK, height_amount=None)
|
||||||
self.parent.left_pile.contents[1] = (LocalPeer(self.app, self.parent), options)
|
self.parent.left_pile.contents[1] = (LocalPeer(self.app, self.parent), options)
|
||||||
|
|
||||||
if self.app.enable_node:
|
if self.app.enable_node:
|
||||||
if self.app.node != None:
|
if self.app.node != None:
|
||||||
display_name = self.app.node.name
|
display_name = self.app.node.name
|
||||||
else:
|
else:
|
||||||
display_name = None
|
display_name = None
|
||||||
|
|
||||||
if display_name == None:
|
if display_name == None:
|
||||||
display_name = ""
|
display_name = ""
|
||||||
|
|
||||||
@@ -1308,7 +1348,7 @@ class NodeInfo(urwid.WidgetWrap):
|
|||||||
|
|
||||||
#overlay = urwid.Overlay(dialog, bottom, align=urwid.CENTER, width=urwid.RELATIVE_100, valign=urwid.MIDDLE, height=urwid.PACK, left=4, right=4)
|
#overlay = urwid.Overlay(dialog, bottom, align=urwid.CENTER, width=urwid.RELATIVE_100, valign=urwid.MIDDLE, height=urwid.PACK, left=4, right=4)
|
||||||
overlay = dialog
|
overlay = dialog
|
||||||
|
|
||||||
self.dialog_open = True
|
self.dialog_open = True
|
||||||
options = self.parent.left_pile.options(height_type=urwid.PACK, height_amount=None)
|
options = self.parent.left_pile.options(height_type=urwid.PACK, height_amount=None)
|
||||||
self.parent.left_pile.contents[1] = (overlay, options)
|
self.parent.left_pile.contents[1] = (overlay, options)
|
||||||
@@ -1596,12 +1636,12 @@ class NetworkDisplay():
|
|||||||
selected_node_entry = parent.known_nodes_display.ilb.get_selected_item()
|
selected_node_entry = parent.known_nodes_display.ilb.get_selected_item()
|
||||||
if selected_node_entry is not None:
|
if selected_node_entry is not None:
|
||||||
selected_node_hash = selected_node_entry.base_widget.display_widget.source_hash
|
selected_node_hash = selected_node_entry.base_widget.display_widget.source_hash
|
||||||
|
|
||||||
if selected_node_hash is not None:
|
if selected_node_hash is not None:
|
||||||
info_widget = KnownNodeInfo(selected_node_hash)
|
info_widget = KnownNodeInfo(selected_node_hash)
|
||||||
options = parent.left_pile.options(height_type=urwid.WEIGHT, height_amount=1)
|
options = parent.left_pile.options(height_type=urwid.WEIGHT, height_amount=1)
|
||||||
parent.left_pile.contents[0] = (info_widget, options)
|
parent.left_pile.contents[0] = (info_widget, options)
|
||||||
|
|
||||||
def focus_lists(self):
|
def focus_lists(self):
|
||||||
self.columns.focus_position = 0
|
self.columns.focus_position = 0
|
||||||
|
|
||||||
@@ -1612,9 +1652,15 @@ class NetworkDisplay():
|
|||||||
self.announce_stream_display.rebuild_widget_list()
|
self.announce_stream_display.rebuild_widget_list()
|
||||||
|
|
||||||
def reinit_lxmf_peers(self):
|
def reinit_lxmf_peers(self):
|
||||||
|
if self.lxmf_peers_display:
|
||||||
|
si = self.lxmf_peers_display.ilb.get_selected_position()
|
||||||
|
else:
|
||||||
|
si = None
|
||||||
self.lxmf_peers_display = LXMFPeers(self.app)
|
self.lxmf_peers_display = LXMFPeers(self.app)
|
||||||
self.lxmf_peers_display.delegate = self
|
self.lxmf_peers_display.delegate = self
|
||||||
self.close_list_dialogs()
|
self.close_list_dialogs()
|
||||||
|
if si != None:
|
||||||
|
self.lxmf_peers_display.ilb.select_item(si)
|
||||||
|
|
||||||
def close_list_dialogs(self):
|
def close_list_dialogs(self):
|
||||||
if self.list_display == 0:
|
if self.list_display == 0:
|
||||||
@@ -1683,7 +1729,7 @@ class LXMFPeers(urwid.WidgetWrap):
|
|||||||
self.delete_selected_entry()
|
self.delete_selected_entry()
|
||||||
elif key == "ctrl r":
|
elif key == "ctrl r":
|
||||||
self.sync_selected_entry()
|
self.sync_selected_entry()
|
||||||
|
|
||||||
return super(LXMFPeers, self).keypress(size, key)
|
return super(LXMFPeers, self).keypress(size, key)
|
||||||
|
|
||||||
|
|
||||||
@@ -1707,7 +1753,7 @@ class LXMFPeers(urwid.WidgetWrap):
|
|||||||
peer = self.app.message_router.peers[destination_hash]
|
peer = self.app.message_router.peers[destination_hash]
|
||||||
if time.time() > peer.last_sync_attempt+sync_grace:
|
if time.time() > peer.last_sync_attempt+sync_grace:
|
||||||
peer.next_sync_attempt = time.time()-1
|
peer.next_sync_attempt = time.time()-1
|
||||||
|
|
||||||
def job():
|
def job():
|
||||||
peer.sync()
|
peer.sync()
|
||||||
threading.Thread(target=job, daemon=True).start()
|
threading.Thread(target=job, daemon=True).start()
|
||||||
@@ -1772,7 +1818,7 @@ class LXMFPeerEntry(urwid.WidgetWrap):
|
|||||||
|
|
||||||
node_identity = RNS.Identity.recall(destination_hash)
|
node_identity = RNS.Identity.recall(destination_hash)
|
||||||
display_str = RNS.prettyhexrep(destination_hash)
|
display_str = RNS.prettyhexrep(destination_hash)
|
||||||
if node_identity != None:
|
if node_identity != None:
|
||||||
node_hash = RNS.Destination.hash_from_name_and_identity("nomadnetwork.node", node_identity)
|
node_hash = RNS.Destination.hash_from_name_and_identity("nomadnetwork.node", node_identity)
|
||||||
display_name = self.app.directory.alleged_display_str(node_hash)
|
display_name = self.app.directory.alleged_display_str(node_hash)
|
||||||
if display_name != None:
|
if display_name != None:
|
||||||
@@ -1801,10 +1847,11 @@ class LXMFPeerEntry(urwid.WidgetWrap):
|
|||||||
txfer_limit = RNS.prettysize(peer.propagation_transfer_limit*1000)
|
txfer_limit = RNS.prettysize(peer.propagation_transfer_limit*1000)
|
||||||
else:
|
else:
|
||||||
txfer_limit = "No"
|
txfer_limit = "No"
|
||||||
|
ar = round(peer.acceptance_rate*100, 2)
|
||||||
peer_info_str = sym+" "+display_str+"\n "+alive_string+", last heard "+pretty_date(int(peer.last_heard))
|
peer_info_str = sym+" "+display_str+"\n "+alive_string+", last heard "+pretty_date(int(peer.last_heard))
|
||||||
peer_info_str += "\n "+str(peer.unhandled_message_count)+f" unhandled LXMs, {txfer_limit} sync limit\n"
|
peer_info_str += "\n "+str(peer.unhandled_message_count)+f" unhandled LXMs, {txfer_limit} sync limit\n"
|
||||||
peer_info_str += f" {RNS.prettyspeed(peer.sync_transfer_rate)} STR, "
|
peer_info_str += f" {RNS.prettyspeed(peer.sync_transfer_rate)} STR, "
|
||||||
peer_info_str += f"{RNS.prettyspeed(peer.link_establishment_rate)} LER\n"
|
peer_info_str += f"{RNS.prettyspeed(peer.link_establishment_rate)} LER, {ar}% AR\n"
|
||||||
widget = ListEntry(peer_info_str)
|
widget = ListEntry(peer_info_str)
|
||||||
self.display_widget = urwid.AttrMap(widget, style, focus_style)
|
self.display_widget = urwid.AttrMap(widget, style, focus_style)
|
||||||
self.display_widget.destination_hash = destination_hash
|
self.display_widget.destination_hash = destination_hash
|
||||||
|
|||||||
2
setup.py
2
setup.py
@@ -30,6 +30,6 @@ setuptools.setup(
|
|||||||
entry_points= {
|
entry_points= {
|
||||||
'console_scripts': ['nomadnet=nomadnet.nomadnet:main']
|
'console_scripts': ['nomadnet=nomadnet.nomadnet:main']
|
||||||
},
|
},
|
||||||
install_requires=["rns>=0.9.1", "lxmf>=0.6.1", "urwid>=2.6.16", "qrcode"],
|
install_requires=["rns>=0.9.1", "lxmf>=0.6.2", "urwid>=2.6.16", "qrcode"],
|
||||||
python_requires=">=3.7",
|
python_requires=">=3.7",
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user