2021-05-04 14:53:03 -04:00
import RNS
2021-09-05 14:38:10 -04:00
import os
2021-05-04 14:53:03 -04:00
import time
import nomadnet
2021-05-13 10:39:31 -04:00
import LXMF
2021-05-04 14:53:03 -04:00
2021-05-12 08:02:44 -04:00
import urwid
2021-05-13 10:39:31 -04:00
from datetime import datetime
from nomadnet . Directory import DirectoryEntry
2021-05-14 11:36:35 -04:00
from nomadnet . vendor . additional_urwid_widgets import IndicativeListBox
2021-05-12 08:02:44 -04:00
class ConversationListDisplayShortcuts ( ) :
def __init__ ( self , app ) :
self . app = app
2022-11-22 13:55:17 -05:00
self . widget = urwid . AttrMap ( urwid . Text ( " [C-e] Peer Info [C-x] Delete [C-r] Sync [C-n] New [C-u] Ingest URI [C-g] Fullscreen " ) , " shortcutbar " )
2021-05-12 08:02:44 -04:00
class ConversationDisplayShortcuts ( ) :
2021-05-04 05:08:16 -04:00
def __init__ ( self , app ) :
self . app = app
2022-11-19 14:04:01 -05:00
self . widget = urwid . AttrMap ( urwid . Text ( " [C-d] Send [C-p] Paper Msg [C-t] Title [C-k] Clear [C-w] Close [C-u] Purge [C-x] Clear History [C-o] Sort " ) , " shortcutbar " )
2021-05-13 10:39:31 -04:00
class ConversationsArea ( urwid . LineBox ) :
def keypress ( self , size , key ) :
2021-05-14 08:45:20 -04:00
if key == " ctrl e " :
self . delegate . edit_selected_in_directory ( )
2021-05-13 10:39:31 -04:00
elif key == " ctrl x " :
self . delegate . delete_selected_conversation ( )
elif key == " ctrl n " :
self . delegate . new_conversation ( )
2022-11-19 14:04:01 -05:00
elif key == " ctrl u " :
2022-11-22 13:55:17 -05:00
self . delegate . ingest_lxm_uri ( )
2021-10-07 12:14:06 -04:00
elif key == " ctrl r " :
self . delegate . sync_conversations ( )
2022-07-04 11:34:12 -04:00
elif key == " ctrl g " :
self . delegate . toggle_fullscreen ( )
2021-05-14 11:36:35 -04:00
elif key == " tab " :
2024-01-18 05:58:22 -05:00
self . delegate . app . ui . main_display . frame . focus_position = " header "
2021-05-19 03:26:12 -04:00
elif key == " up " and ( self . delegate . ilb . first_item_is_selected ( ) or self . delegate . ilb . body_is_empty ( ) ) :
2024-01-18 05:58:22 -05:00
self . delegate . app . ui . main_display . frame . focus_position = " header "
2021-05-13 10:39:31 -04:00
else :
return super ( ConversationsArea , self ) . keypress ( size , key )
2021-05-04 05:08:16 -04:00
2021-05-14 16:12:42 -04:00
class DialogLineBox ( urwid . LineBox ) :
def keypress ( self , size , key ) :
if key == " esc " :
self . delegate . update_conversation_list ( )
else :
return super ( DialogLineBox , self ) . keypress ( size , key )
2021-05-04 05:08:16 -04:00
class ConversationsDisplay ( ) :
2021-05-04 14:53:03 -04:00
list_width = 0.33
2022-07-04 11:07:54 -04:00
given_list_width = 52
2021-05-04 14:53:03 -04:00
cached_conversation_widgets = { }
2021-05-04 05:08:16 -04:00
def __init__ ( self , app ) :
self . app = app
2021-05-13 10:39:31 -04:00
self . dialog_open = False
2021-10-07 12:14:06 -04:00
self . sync_dialog = None
2021-05-15 15:08:30 -04:00
self . currently_displayed_conversation = None
2021-05-04 09:10:21 -04:00
2021-05-12 08:02:44 -04:00
def disp_list_shortcuts ( sender , arg1 , arg2 ) :
self . shortcuts_display = self . list_shortcuts
self . app . ui . main_display . update_active_shortcuts ( )
2021-05-13 10:39:31 -04:00
self . update_listbox ( )
2021-05-04 09:10:21 -04:00
2021-05-15 15:08:30 -04:00
self . columns_widget = urwid . Columns (
[
2024-01-18 05:58:22 -05:00
# (urwid.WEIGHT, ConversationsDisplay.list_width, self.listbox),
# (urwid.WEIGHT, 1-ConversationsDisplay.list_width, self.make_conversation_widget(None))
2022-07-04 11:07:54 -04:00
( ConversationsDisplay . given_list_width , self . listbox ) ,
2024-01-18 05:58:22 -05:00
( urwid . WEIGHT , 1 , self . make_conversation_widget ( None ) )
2021-05-15 15:08:30 -04:00
] ,
dividechars = 0 , focus_column = 0 , box_columns = [ 0 ]
)
2021-05-04 05:08:16 -04:00
2021-05-12 08:02:44 -04:00
self . list_shortcuts = ConversationListDisplayShortcuts ( self . app )
self . editor_shortcuts = ConversationDisplayShortcuts ( self . app )
self . shortcuts_display = self . list_shortcuts
2021-05-13 10:39:31 -04:00
self . widget = self . columns_widget
nomadnet . Conversation . created_callback = self . update_conversation_list
def focus_change_event ( self ) :
# This hack corrects buggy styling behaviour in IndicativeListBox
if not self . dialog_open :
ilb_position = self . ilb . get_selected_position ( )
self . update_conversation_list ( )
2021-05-13 14:25:04 -04:00
if ilb_position != None :
self . ilb . select_item ( ilb_position )
2021-05-13 10:39:31 -04:00
def update_listbox ( self ) :
conversation_list_widgets = [ ]
for conversation in self . app . conversations ( ) :
conversation_list_widgets . append ( self . conversation_list_widget ( conversation ) )
self . list_widgets = conversation_list_widgets
self . ilb = IndicativeListBox (
self . list_widgets ,
on_selection_change = self . conversation_list_selection ,
initialization_is_selection_change = False ,
highlight_offFocus = " list_off_focus "
)
2024-01-18 05:58:22 -05:00
self . listbox = ConversationsArea ( urwid . Filler ( self . ilb , height = urwid . RELATIVE_100 ) , title = " Conversations " )
2021-05-13 10:39:31 -04:00
self . listbox . delegate = self
def delete_selected_conversation ( self ) :
self . dialog_open = True
2023-02-09 06:45:37 -05:00
item = self . ilb . get_selected_item ( )
if item == None :
return
source_hash = item . source_hash
2021-05-13 10:39:31 -04:00
def dismiss_dialog ( sender ) :
self . update_conversation_list ( )
self . dialog_open = False
def confirmed ( sender ) :
self . dialog_open = False
self . delete_conversation ( source_hash )
nomadnet . Conversation . delete_conversation ( source_hash , self . app )
self . update_conversation_list ( )
2021-05-14 16:12:42 -04:00
dialog = DialogLineBox (
2021-05-13 10:39:31 -04:00
urwid . Pile ( [
2024-01-18 05:58:22 -05:00
urwid . Text (
" Delete conversation with \n " + self . app . directory . simplest_display_str ( bytes . fromhex ( source_hash ) ) + " \n " ,
align = urwid . CENTER ,
) ,
urwid . Columns ( [
( urwid . WEIGHT , 0.45 , urwid . Button ( " Yes " , on_press = confirmed ) ) ,
( urwid . WEIGHT , 0.1 , urwid . Text ( " " ) ) ,
( urwid . WEIGHT , 0.45 , urwid . Button ( " No " , on_press = dismiss_dialog ) ) ,
] )
2021-05-13 10:39:31 -04:00
] ) , title = " ? "
)
2021-05-14 16:12:42 -04:00
dialog . delegate = self
2021-05-13 10:39:31 -04:00
bottom = self . listbox
2024-01-18 05:58:22 -05:00
overlay = urwid . Overlay (
dialog ,
bottom ,
align = urwid . CENTER ,
width = urwid . RELATIVE_100 ,
valign = urwid . MIDDLE ,
height = urwid . PACK ,
left = 2 ,
right = 2 ,
)
2021-05-13 10:39:31 -04:00
2024-01-18 05:58:22 -05:00
# options = self.columns_widget.options(urwid.WEIGHT, ConversationsDisplay.list_width)
options = self . columns_widget . options ( urwid . GIVEN , ConversationsDisplay . given_list_width )
2021-05-13 10:39:31 -04:00
self . columns_widget . contents [ 0 ] = ( overlay , options )
2021-05-14 08:45:20 -04:00
def edit_selected_in_directory ( self ) :
2021-07-02 07:35:10 -04:00
g = self . app . ui . glyphs
2021-05-13 10:39:31 -04:00
self . dialog_open = True
2023-02-09 06:45:37 -05:00
item = self . ilb . get_selected_item ( )
if item == None :
return
source_hash_text = item . source_hash
2021-05-13 10:39:31 -04:00
display_name = self . ilb . get_selected_item ( ) . display_name
2021-05-14 16:12:42 -04:00
if display_name == None :
display_name = " "
2021-05-13 10:39:31 -04:00
2021-05-15 15:08:30 -04:00
e_id = urwid . Edit ( caption = " Addr : " , edit_text = source_hash_text )
t_id = urwid . Text ( " Addr : " + source_hash_text )
2021-05-13 10:39:31 -04:00
e_name = urwid . Edit ( caption = " Name : " , edit_text = display_name )
2021-05-14 08:45:20 -04:00
selected_id_widget = t_id
2021-10-03 12:44:00 -04:00
untrusted_selected = False
unknown_selected = True
trusted_selected = False
direct_selected = True
propagated_selected = False
2021-05-14 08:45:20 -04:00
try :
if self . app . directory . find ( bytes . fromhex ( source_hash_text ) ) :
trust_level = self . app . directory . trust_level ( bytes . fromhex ( source_hash_text ) )
if trust_level == DirectoryEntry . UNTRUSTED :
untrusted_selected = True
unknown_selected = False
trusted_selected = False
elif trust_level == DirectoryEntry . UNKNOWN :
untrusted_selected = False
unknown_selected = True
trusted_selected = False
elif trust_level == DirectoryEntry . TRUSTED :
untrusted_selected = False
unknown_selected = False
trusted_selected = True
2021-10-03 12:44:00 -04:00
if self . app . directory . preferred_delivery ( bytes . fromhex ( source_hash_text ) ) == DirectoryEntry . PROPAGATED :
direct_selected = False
propagated_selected = True
2021-05-14 08:45:20 -04:00
except Exception as e :
2021-05-14 11:36:35 -04:00
pass
2021-05-14 08:45:20 -04:00
2021-05-13 10:39:31 -04:00
trust_button_group = [ ]
2021-05-14 08:45:20 -04:00
r_untrusted = urwid . RadioButton ( trust_button_group , " Untrusted " , state = untrusted_selected )
r_unknown = urwid . RadioButton ( trust_button_group , " Unknown " , state = unknown_selected )
r_trusted = urwid . RadioButton ( trust_button_group , " Trusted " , state = trusted_selected )
2021-05-13 10:39:31 -04:00
2021-10-03 12:44:00 -04:00
method_button_group = [ ]
r_direct = urwid . RadioButton ( method_button_group , " Deliver directly " , state = direct_selected )
r_propagated = urwid . RadioButton ( method_button_group , " Use propagation nodes " , state = propagated_selected )
2021-05-13 10:39:31 -04:00
def dismiss_dialog ( sender ) :
self . update_conversation_list ( )
self . dialog_open = False
def confirmed ( sender ) :
try :
display_name = e_name . get_edit_text ( )
source_hash = bytes . fromhex ( e_id . get_edit_text ( ) )
trust_level = DirectoryEntry . UNTRUSTED
if r_unknown . state == True :
trust_level = DirectoryEntry . UNKNOWN
elif r_trusted . state == True :
trust_level = DirectoryEntry . TRUSTED
2021-10-03 12:44:00 -04:00
delivery = DirectoryEntry . DIRECT
if r_propagated . state == True :
delivery = DirectoryEntry . PROPAGATED
entry = DirectoryEntry ( source_hash , display_name , trust_level , preferred_delivery = delivery )
2021-05-13 10:39:31 -04:00
self . app . directory . remember ( entry )
self . update_conversation_list ( )
self . dialog_open = False
2021-05-15 15:08:30 -04:00
self . app . ui . main_display . sub_displays . network_display . directory_change_callback ( )
2021-05-13 10:39:31 -04:00
except Exception as e :
RNS . log ( " Could not save directory entry. The contained exception was: " + str ( e ) , RNS . LOG_VERBOSE )
if not dialog_pile . error_display :
dialog_pile . error_display = True
2024-01-18 05:58:22 -05:00
options = dialog_pile . options ( height_type = urwid . PACK )
2021-05-13 10:39:31 -04:00
dialog_pile . contents . append ( ( urwid . Text ( " " ) , options ) )
2024-01-18 05:58:22 -05:00
dialog_pile . contents . append ( (
urwid . Text ( ( " error_text " , " Could not save entry. Check your input. " ) , align = urwid . CENTER ) ,
options , )
)
2021-05-13 10:39:31 -04:00
2021-05-14 16:12:42 -04:00
source_is_known = self . app . directory . is_known ( bytes . fromhex ( source_hash_text ) )
if source_is_known :
2021-07-02 07:35:10 -04:00
known_section = urwid . Divider ( g [ " divider1 " ] )
2021-05-14 16:12:42 -04:00
else :
def query_action ( sender , user_data ) :
2021-05-15 15:08:30 -04:00
self . close_conversation_by_hash ( user_data )
2021-05-14 16:12:42 -04:00
nomadnet . Conversation . query_for_peer ( user_data )
2024-01-18 05:58:22 -05:00
options = dialog_pile . options ( height_type = urwid . PACK )
2021-05-14 16:12:42 -04:00
dialog_pile . contents = [
( urwid . Text ( " Query sent " ) , options ) ,
( urwid . Button ( " OK " , on_press = dismiss_dialog ) , options )
]
query_button = urwid . Button ( " Query network for keys " , on_press = query_action , user_data = source_hash_text )
2024-01-18 05:58:22 -05:00
known_section = urwid . Pile ( [
urwid . Divider ( g [ " divider1 " ] ) ,
urwid . Text ( g [ " info " ] + " \n " , align = urwid . CENTER ) ,
urwid . Text (
" The identity of this peer is not known, and you cannot currently send messages to it. "
" You can query the network to obtain the identity. \n " ,
align = urwid . CENTER ,
) ,
query_button ,
urwid . Divider ( g [ " divider1 " ] ) ,
] )
2021-05-14 16:12:42 -04:00
2021-05-13 10:39:31 -04:00
dialog_pile = urwid . Pile ( [
2021-05-14 08:45:20 -04:00
selected_id_widget ,
2021-05-13 10:39:31 -04:00
e_name ,
2021-07-02 07:35:10 -04:00
urwid . Divider ( g [ " divider1 " ] ) ,
2021-05-13 10:39:31 -04:00
r_untrusted ,
r_unknown ,
r_trusted ,
2021-10-03 12:44:00 -04:00
urwid . Divider ( g [ " divider1 " ] ) ,
r_direct ,
r_propagated ,
2021-05-14 16:12:42 -04:00
known_section ,
2024-01-18 05:58:22 -05:00
urwid . Columns ( [
( urwid . WEIGHT , 0.45 , urwid . Button ( " Save " , on_press = confirmed ) ) ,
( urwid . WEIGHT , 0.1 , urwid . Text ( " " ) ) ,
( urwid . WEIGHT , 0.45 , urwid . Button ( " Back " , on_press = dismiss_dialog ) ) ,
] )
2021-05-13 10:39:31 -04:00
] )
dialog_pile . error_display = False
2021-05-15 15:08:30 -04:00
dialog = DialogLineBox ( dialog_pile , title = " Peer Info " )
2021-05-14 16:12:42 -04:00
dialog . delegate = self
2021-05-13 10:39:31 -04:00
bottom = self . listbox
2024-01-18 05:58:22 -05:00
overlay = urwid . Overlay (
dialog ,
bottom ,
align = urwid . CENTER ,
width = urwid . RELATIVE_100 ,
valign = urwid . MIDDLE ,
height = urwid . PACK ,
left = 2 ,
right = 2 ,
)
2021-05-13 10:39:31 -04:00
2024-01-18 05:58:22 -05:00
# options = self.columns_widget.options(urwid.WEIGHT, ConversationsDisplay.list_width)
options = self . columns_widget . options ( urwid . GIVEN , ConversationsDisplay . given_list_width )
2021-05-13 10:39:31 -04:00
self . columns_widget . contents [ 0 ] = ( overlay , options )
def new_conversation ( self ) :
2021-05-14 08:45:20 -04:00
self . dialog_open = True
source_hash = " "
display_name = " "
2021-05-15 15:08:30 -04:00
e_id = urwid . Edit ( caption = " Addr : " , edit_text = source_hash )
2021-05-14 08:45:20 -04:00
e_name = urwid . Edit ( caption = " Name : " , edit_text = display_name )
trust_button_group = [ ]
r_untrusted = urwid . RadioButton ( trust_button_group , " Untrusted " )
r_unknown = urwid . RadioButton ( trust_button_group , " Unknown " , state = True )
r_trusted = urwid . RadioButton ( trust_button_group , " Trusted " )
def dismiss_dialog ( sender ) :
self . update_conversation_list ( )
self . dialog_open = False
def confirmed ( sender ) :
try :
existing_conversations = nomadnet . Conversation . conversation_list ( self . app )
display_name = e_name . get_edit_text ( )
source_hash_text = e_id . get_edit_text ( )
source_hash = bytes . fromhex ( source_hash_text )
trust_level = DirectoryEntry . UNTRUSTED
if r_unknown . state == True :
trust_level = DirectoryEntry . UNKNOWN
elif r_trusted . state == True :
trust_level = DirectoryEntry . TRUSTED
if not source_hash in [ c [ 0 ] for c in existing_conversations ] :
entry = DirectoryEntry ( source_hash , display_name , trust_level )
self . app . directory . remember ( entry )
new_conversation = nomadnet . Conversation ( source_hash_text , nomadnet . NomadNetworkApp . get_shared_instance ( ) , initiator = True )
2022-09-13 15:47:41 -04:00
2021-05-14 08:45:20 -04:00
self . update_conversation_list ( )
self . display_conversation ( source_hash_text )
self . dialog_open = False
except Exception as e :
RNS . log ( " Could not start conversation. The contained exception was: " + str ( e ) , RNS . LOG_VERBOSE )
if not dialog_pile . error_display :
dialog_pile . error_display = True
2024-01-18 05:58:22 -05:00
options = dialog_pile . options ( height_type = urwid . PACK )
2021-05-14 08:45:20 -04:00
dialog_pile . contents . append ( ( urwid . Text ( " " ) , options ) )
2024-01-18 05:58:22 -05:00
dialog_pile . contents . append ( (
urwid . Text (
( " error_text " , " Could not start conversation. Check your input. " ) ,
align = urwid . CENTER ,
) ,
options ,
) )
2021-05-14 08:45:20 -04:00
dialog_pile = urwid . Pile ( [
e_id ,
e_name ,
urwid . Text ( " " ) ,
r_untrusted ,
r_unknown ,
r_trusted ,
urwid . Text ( " " ) ,
2024-01-18 05:58:22 -05:00
urwid . Columns ( [
( urwid . WEIGHT , 0.45 , urwid . Button ( " Create " , on_press = confirmed ) ) ,
( urwid . WEIGHT , 0.1 , urwid . Text ( " " ) ) ,
( urwid . WEIGHT , 0.45 , urwid . Button ( " Back " , on_press = dismiss_dialog ) ) ,
] )
2021-05-14 08:45:20 -04:00
] )
dialog_pile . error_display = False
2021-05-14 16:12:42 -04:00
dialog = DialogLineBox ( dialog_pile , title = " New Conversation " )
dialog . delegate = self
2021-05-14 08:45:20 -04:00
bottom = self . listbox
2024-01-18 05:58:22 -05:00
overlay = urwid . Overlay (
dialog ,
bottom ,
align = urwid . CENTER ,
width = urwid . RELATIVE_100 ,
valign = urwid . MIDDLE ,
height = urwid . PACK ,
left = 2 ,
right = 2 ,
)
2021-05-14 08:45:20 -04:00
2024-01-18 05:58:22 -05:00
# options = self.columns_widget.options(urwid.WEIGHT, ConversationsDisplay.list_width)
options = self . columns_widget . options ( urwid . GIVEN , ConversationsDisplay . given_list_width )
2021-05-14 08:45:20 -04:00
self . columns_widget . contents [ 0 ] = ( overlay , options )
2021-05-13 10:39:31 -04:00
2022-11-22 13:55:17 -05:00
def ingest_lxm_uri ( self ) :
2022-11-19 14:04:01 -05:00
self . dialog_open = True
2022-11-22 13:55:17 -05:00
lxm_uri = " "
e_uri = urwid . Edit ( caption = " URI : " , edit_text = lxm_uri )
2022-11-19 14:04:01 -05:00
def dismiss_dialog ( sender ) :
self . update_conversation_list ( )
self . dialog_open = False
def confirmed ( sender ) :
try :
local_delivery_signal = " local_delivery_occurred "
duplicate_signal = " duplicate_lxm "
2022-11-22 13:55:17 -05:00
lxm_uri = e_uri . get_edit_text ( )
2022-11-19 14:04:01 -05:00
2022-11-22 13:55:17 -05:00
ingest_result = self . app . message_router . ingest_lxm_uri (
lxm_uri ,
2022-11-19 14:04:01 -05:00
signal_local_delivery = local_delivery_signal ,
signal_duplicate = duplicate_signal
)
if ingest_result == False :
2022-11-22 13:55:17 -05:00
raise ValueError ( " The URI contained no decodable messages " )
2022-11-19 14:04:01 -05:00
elif ingest_result == local_delivery_signal :
rdialog_pile = urwid . Pile ( [
urwid . Text ( " Message was decoded, decrypted successfully, and added to your conversation list. " ) ,
urwid . Text ( " " ) ,
2024-01-18 05:58:22 -05:00
urwid . Columns ( [
( urwid . WEIGHT , 0.6 , urwid . Text ( " " ) ) ,
( urwid . WEIGHT , 0.4 , urwid . Button ( " OK " , on_press = dismiss_dialog ) ) ,
] )
2022-11-19 14:04:01 -05:00
] )
rdialog_pile . error_display = False
2022-11-22 13:55:17 -05:00
rdialog = DialogLineBox ( rdialog_pile , title = " Ingest message URI " )
2022-11-19 14:04:01 -05:00
rdialog . delegate = self
bottom = self . listbox
2024-01-18 05:58:22 -05:00
roverlay = urwid . Overlay (
rdialog ,
bottom ,
align = urwid . CENTER ,
width = urwid . RELATIVE_100 ,
valign = urwid . MIDDLE ,
height = urwid . PACK ,
left = 2 ,
right = 2 ,
)
options = self . columns_widget . options ( urwid . GIVEN , ConversationsDisplay . given_list_width )
2022-11-19 14:04:01 -05:00
self . columns_widget . contents [ 0 ] = ( roverlay , options )
elif ingest_result == duplicate_signal :
rdialog_pile = urwid . Pile ( [
urwid . Text ( " The decoded message has already been processed by the LXMF Router, and will not be ingested again. " ) ,
urwid . Text ( " " ) ,
2024-01-18 05:58:22 -05:00
urwid . Columns ( [
( urwid . WEIGHT , 0.6 , urwid . Text ( " " ) ) ,
( urwid . WEIGHT , 0.4 , urwid . Button ( " OK " , on_press = dismiss_dialog ) ) ,
] )
2022-11-19 14:04:01 -05:00
] )
rdialog_pile . error_display = False
2022-11-22 13:55:17 -05:00
rdialog = DialogLineBox ( rdialog_pile , title = " Ingest message URI " )
2022-11-19 14:04:01 -05:00
rdialog . delegate = self
bottom = self . listbox
2024-01-18 05:58:22 -05:00
roverlay = urwid . Overlay (
rdialog ,
bottom ,
align = urwid . CENTER ,
width = urwid . RELATIVE_100 ,
valign = urwid . MIDDLE ,
height = urwid . PACK ,
left = 2 ,
right = 2 ,
)
options = self . columns_widget . options ( urwid . GIVEN , ConversationsDisplay . given_list_width )
2022-11-19 14:04:01 -05:00
self . columns_widget . contents [ 0 ] = ( roverlay , options )
else :
if self . app . enable_node :
propagation_text = " The decoded message was not addressed to this LXMF address, but has been added to the propagation node queues, and will be distributed on the propagation network. "
else :
propagation_text = " The decoded message was not addressed to this LXMF address, and has been discarded. "
rdialog_pile = urwid . Pile ( [
urwid . Text ( propagation_text ) ,
urwid . Text ( " " ) ,
2024-01-18 05:58:22 -05:00
urwid . Columns ( [
( urwid . WEIGHT , 0.6 , urwid . Text ( " " ) ) ,
( urwid . WEIGHT , 0.4 , urwid . Button ( " OK " , on_press = dismiss_dialog ) ) ,
] )
2022-11-19 14:04:01 -05:00
] )
rdialog_pile . error_display = False
2022-11-22 13:55:17 -05:00
rdialog = DialogLineBox ( rdialog_pile , title = " Ingest message URI " )
2022-11-19 14:04:01 -05:00
rdialog . delegate = self
bottom = self . listbox
2024-01-18 05:58:22 -05:00
roverlay = urwid . Overlay (
rdialog ,
bottom ,
align = urwid . CENTER ,
width = urwid . RELATIVE_100 ,
valign = urwid . MIDDLE ,
height = urwid . PACK ,
left = 2 ,
right = 2 ,
)
options = self . columns_widget . options ( urwid . GIVEN , ConversationsDisplay . given_list_width )
2022-11-19 14:04:01 -05:00
self . columns_widget . contents [ 0 ] = ( roverlay , options )
except Exception as e :
2022-11-22 13:55:17 -05:00
RNS . log ( " Could not ingest LXM URI. The contained exception was: " + str ( e ) , RNS . LOG_VERBOSE )
2022-11-19 14:04:01 -05:00
if not dialog_pile . error_display :
dialog_pile . error_display = True
2024-01-18 05:58:22 -05:00
options = dialog_pile . options ( height_type = urwid . PACK )
2022-11-19 14:04:01 -05:00
dialog_pile . contents . append ( ( urwid . Text ( " " ) , options ) )
2024-01-18 05:58:22 -05:00
dialog_pile . contents . append ( ( urwid . Text ( ( " error_text " , " Could ingest LXM from URI data. Check your input. " ) , align = urwid . CENTER ) , options ) )
2022-11-19 14:04:01 -05:00
dialog_pile = urwid . Pile ( [
2022-11-22 13:55:17 -05:00
e_uri ,
2022-11-19 14:04:01 -05:00
urwid . Text ( " " ) ,
2024-01-18 05:58:22 -05:00
urwid . Columns ( [
( urwid . WEIGHT , 0.45 , urwid . Button ( " Ingest " , on_press = confirmed ) ) ,
( urwid . WEIGHT , 0.1 , urwid . Text ( " " ) ) ,
( urwid . WEIGHT , 0.45 , urwid . Button ( " Back " , on_press = dismiss_dialog ) ) ,
] )
2022-11-19 14:04:01 -05:00
] )
dialog_pile . error_display = False
2022-11-22 13:55:17 -05:00
dialog = DialogLineBox ( dialog_pile , title = " Ingest message URI " )
2022-11-19 14:04:01 -05:00
dialog . delegate = self
bottom = self . listbox
2024-01-18 05:58:22 -05:00
overlay = urwid . Overlay (
dialog ,
bottom ,
align = urwid . CENTER ,
width = urwid . RELATIVE_100 ,
valign = urwid . MIDDLE ,
height = urwid . PACK ,
left = 2 ,
right = 2 ,
)
2022-11-19 14:04:01 -05:00
2024-01-18 05:58:22 -05:00
options = self . columns_widget . options ( urwid . GIVEN , ConversationsDisplay . given_list_width )
2022-11-19 14:04:01 -05:00
self . columns_widget . contents [ 0 ] = ( overlay , options )
2021-05-13 10:39:31 -04:00
def delete_conversation ( self , source_hash ) :
if source_hash in ConversationsDisplay . cached_conversation_widgets :
conversation = ConversationsDisplay . cached_conversation_widgets [ source_hash ]
self . close_conversation ( conversation )
2022-07-04 11:34:12 -04:00
def toggle_fullscreen ( self ) :
if ConversationsDisplay . given_list_width != 0 :
self . saved_list_width = ConversationsDisplay . given_list_width
ConversationsDisplay . given_list_width = 0
else :
ConversationsDisplay . given_list_width = self . saved_list_width
self . update_conversation_list ( )
2021-10-07 12:14:06 -04:00
def sync_conversations ( self ) :
2021-10-08 05:58:24 -04:00
g = self . app . ui . glyphs
2021-10-07 12:14:06 -04:00
self . dialog_open = True
def dismiss_dialog ( sender ) :
self . dialog_open = False
self . sync_dialog = None
self . update_conversation_list ( )
2022-06-17 07:43:38 -04:00
if self . app . message_router . propagation_transfer_state > = LXMF . LXMRouter . PR_COMPLETE :
2021-10-07 12:14:06 -04:00
self . app . cancel_lxmf_sync ( )
2021-10-08 05:58:24 -04:00
max_messages_group = [ ]
r_mall = urwid . RadioButton ( max_messages_group , " Download all " , state = True )
r_mlim = urwid . RadioButton ( max_messages_group , " Limit to " , state = False )
ie_lim = urwid . IntEdit ( " " , 5 )
2024-01-18 05:58:22 -05:00
rbs = urwid . GridFlow ( [ r_mlim , ie_lim ] , 12 , 1 , 0 , align = urwid . LEFT )
2021-10-07 12:14:06 -04:00
def sync_now ( sender ) :
2021-10-08 05:58:24 -04:00
limit = None
if r_mlim . get_state ( ) :
limit = ie_lim . value ( )
self . app . request_lxmf_sync ( limit )
2021-10-07 12:14:06 -04:00
self . update_sync_dialog ( )
def cancel_sync ( sender ) :
self . app . cancel_lxmf_sync ( )
2021-10-12 15:12:32 -04:00
self . update_sync_dialog ( )
2021-10-07 12:14:06 -04:00
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 )
real_sync_button = urwid . Button ( " Sync Now " , on_press = sync_now )
hidden_sync_button = urwid . Button ( " Cancel Sync " , on_press = cancel_sync )
2022-06-17 07:43:38 -04:00
if self . app . get_sync_status ( ) == " Idle " or self . app . message_router . propagation_transfer_state > = LXMF . LXMRouter . PR_COMPLETE :
2021-10-07 12:14:06 -04:00
sync_button = real_sync_button
else :
sync_button = hidden_sync_button
2024-01-18 05:58:22 -05:00
button_columns = urwid . Columns ( [
( urwid . WEIGHT , 0.45 , sync_button ) ,
( urwid . WEIGHT , 0.1 , urwid . Text ( " " ) ) ,
( urwid . WEIGHT , 0.45 , cancel_button ) ,
] )
2021-10-07 12:14:06 -04:00
real_sync_button . bc = button_columns
2021-10-08 07:34:04 -04:00
pn_ident = None
2021-10-08 03:12:20 -04:00
if self . app . get_default_propagation_node ( ) != None :
2021-10-08 05:58:24 -04:00
pn_hash = self . app . get_default_propagation_node ( )
pn_ident = RNS . Identity . recall ( pn_hash )
2021-10-08 07:34:04 -04:00
if pn_ident == None :
RNS . log ( " Propagation node identity is unknown, requesting from network... " , RNS . LOG_DEBUG )
RNS . Transport . request_path ( pn_hash )
if pn_ident != None :
2021-10-08 05:58:24 -04:00
node_hash = RNS . Destination . hash_from_name_and_identity ( " nomadnetwork.node " , pn_ident )
pn_entry = self . app . directory . find ( node_hash )
2022-10-25 06:52:02 -04:00
pn_display_str = " "
if pn_entry != None :
pn_display_str + = " " + str ( pn_entry . display_name )
else :
pn_display_str + = " " + RNS . prettyhexrep ( pn_hash )
2021-10-08 05:58:24 -04:00
2021-10-08 03:12:20 -04:00
dialog = DialogLineBox (
urwid . Pile ( [
2024-01-18 05:58:22 -05:00
urwid . Text ( " " + g [ " node " ] + pn_display_str , align = urwid . CENTER ) ,
2021-10-08 05:58:24 -04:00
urwid . Divider ( g [ " divider1 " ] ) ,
2021-10-08 03:12:20 -04:00
sync_progress ,
2021-10-08 05:58:24 -04:00
urwid . Divider ( g [ " divider1 " ] ) ,
r_mall ,
rbs ,
2021-10-08 03:12:20 -04:00
urwid . Text ( " " ) ,
button_columns
] ) , title = " Message Sync "
)
else :
2024-01-18 05:58:22 -05:00
button_columns = urwid . Columns ( [
( urwid . WEIGHT , 0.45 , urwid . Text ( " " ) ) ,
( urwid . WEIGHT , 0.1 , urwid . Text ( " " ) ) ,
( urwid . WEIGHT , 0.45 , cancel_button ) ,
] )
2021-10-08 03:12:20 -04:00
dialog = DialogLineBox (
urwid . Pile ( [
urwid . Text ( " " ) ,
2024-01-18 05:58:22 -05:00
urwid . Text ( " No trusted nodes found, cannot sync! \n " , align = urwid . CENTER ) ,
urwid . Text (
" To synchronise messages from the network, "
" one or more nodes must be marked as trusted in the Known Nodes list, "
" or a node must manually be selected as the default propagation node. "
" Nomad Network will then automatically sync from the nearest trusted node, "
" or the manually selected one. " ,
align = urwid . LEFT ,
) ,
2021-10-08 03:12:20 -04:00
urwid . Text ( " " ) ,
button_columns
] ) , title = " Message Sync "
)
2021-10-07 12:14:06 -04:00
dialog . delegate = self
dialog . sync_progress = sync_progress
dialog . cancel_button = cancel_button
dialog . real_sync_button = real_sync_button
dialog . hidden_sync_button = hidden_sync_button
dialog . bc = button_columns
self . sync_dialog = dialog
bottom = self . listbox
2024-01-18 05:58:22 -05:00
overlay = urwid . Overlay (
dialog ,
bottom ,
align = urwid . CENTER ,
width = urwid . RELATIVE_100 ,
valign = urwid . MIDDLE ,
height = urwid . PACK ,
left = 2 ,
right = 2 ,
)
2021-10-07 12:14:06 -04:00
2024-01-18 05:58:22 -05:00
# options = self.columns_widget.options(urwid.WEIGHT, ConversationsDisplay.list_width)
options = self . columns_widget . options ( urwid . GIVEN , ConversationsDisplay . given_list_width )
2021-10-07 12:14:06 -04:00
self . columns_widget . contents [ 0 ] = ( overlay , options )
def update_sync_dialog ( self , loop = None , sender = None ) :
if self . dialog_open and self . sync_dialog != None :
self . sync_dialog . sync_progress . set_completion ( self . app . get_sync_progress ( ) )
2022-06-17 07:43:38 -04:00
if self . app . get_sync_status ( ) == " Idle " or self . app . message_router . propagation_transfer_state > = LXMF . LXMRouter . PR_COMPLETE :
2024-01-18 05:58:22 -05:00
self . sync_dialog . bc . contents [ 0 ] = ( self . sync_dialog . real_sync_button , self . sync_dialog . bc . options ( urwid . WEIGHT , 0.45 ) )
2021-10-07 12:14:06 -04:00
else :
2024-01-18 05:58:22 -05:00
self . sync_dialog . bc . contents [ 0 ] = ( self . sync_dialog . hidden_sync_button , self . sync_dialog . bc . options ( urwid . WEIGHT , 0.45 ) )
2021-10-07 12:14:06 -04:00
self . app . ui . loop . set_alarm_in ( 0.2 , self . update_sync_dialog )
2021-05-13 10:39:31 -04:00
def conversation_list_selection ( self , arg1 , arg2 ) :
pass
def update_conversation_list ( self ) :
ilb_position = self . ilb . get_selected_position ( )
self . update_listbox ( )
2024-01-18 05:58:22 -05:00
# options = self.columns_widget.options(urwid.WEIGHT, ConversationsDisplay.list_width)
options = self . columns_widget . options ( urwid . GIVEN , ConversationsDisplay . given_list_width )
2021-10-07 12:14:06 -04:00
if not ( self . dialog_open and self . sync_dialog != None ) :
self . columns_widget . contents [ 0 ] = ( self . listbox , options )
else :
bottom = self . listbox
2024-01-18 05:58:22 -05:00
overlay = urwid . Overlay (
self . sync_dialog ,
bottom ,
align = urwid . CENTER ,
width = urwid . RELATIVE_100 ,
valign = urwid . MIDDLE ,
height = urwid . PACK ,
left = 2 ,
right = 2 ,
)
2021-10-07 12:14:06 -04:00
self . columns_widget . contents [ 0 ] = ( overlay , options )
2021-05-13 14:25:04 -04:00
if ilb_position != None :
self . ilb . select_item ( ilb_position )
2021-05-13 10:39:31 -04:00
nomadnet . NomadNetworkApp . get_shared_instance ( ) . ui . loop . draw_screen ( )
2021-09-23 11:20:13 -04:00
if self . app . ui . main_display . sub_displays . active_display == self . app . ui . main_display . sub_displays . conversations_display :
if self . currently_displayed_conversation != None :
if self . app . conversation_is_unread ( self . currently_displayed_conversation ) :
self . app . mark_conversation_read ( self . currently_displayed_conversation )
try :
if os . path . isfile ( self . app . conversationpath + " / " + self . currently_displayed_conversation + " /unread " ) :
os . unlink ( self . app . conversationpath + " / " + self . currently_displayed_conversation + " /unread " )
except Exception as e :
raise e
2021-09-05 14:38:10 -04:00
2021-05-13 10:39:31 -04:00
2021-05-04 05:08:16 -04:00
2021-05-04 14:53:03 -04:00
def display_conversation ( self , sender = None , source_hash = None ) :
2021-09-05 14:38:10 -04:00
if self . currently_displayed_conversation != None :
if self . app . conversation_is_unread ( self . currently_displayed_conversation ) :
self . app . mark_conversation_read ( self . currently_displayed_conversation )
2021-05-13 10:39:31 -04:00
self . currently_displayed_conversation = source_hash
2024-01-18 05:58:22 -05:00
# options = self.widget.options(urwid.WEIGHT, 1-ConversationsDisplay.list_width)
options = self . widget . options ( urwid . WEIGHT , 1 )
2021-05-04 14:53:03 -04:00
self . widget . contents [ 1 ] = ( self . make_conversation_widget ( source_hash ) , options )
2021-06-30 08:49:26 -04:00
if source_hash == None :
2024-01-18 05:58:22 -05:00
self . widget . focus_position = 0
2021-06-30 08:49:26 -04:00
else :
2021-09-05 14:38:10 -04:00
if self . app . conversation_is_unread ( source_hash ) :
self . app . mark_conversation_read ( source_hash )
self . update_conversation_list ( )
2024-01-18 05:58:22 -05:00
self . widget . focus_position = 1
2021-09-05 14:38:10 -04:00
conversation_position = None
index = 0
for widget in self . list_widgets :
if widget . source_hash == source_hash :
conversation_position = index
index + = 1
if conversation_position != None :
self . ilb . select_item ( conversation_position )
2021-05-04 14:53:03 -04:00
def make_conversation_widget ( self , source_hash ) :
2021-05-13 10:39:31 -04:00
if source_hash in ConversationsDisplay . cached_conversation_widgets :
conversation_widget = ConversationsDisplay . cached_conversation_widgets [ source_hash ]
if source_hash != None :
conversation_widget . update_message_widgets ( replace = True )
2021-05-14 16:12:42 -04:00
conversation_widget . check_editor_allowed ( )
2021-05-13 10:39:31 -04:00
return conversation_widget
else :
widget = ConversationWidget ( source_hash )
widget . delegate = self
ConversationsDisplay . cached_conversation_widgets [ source_hash ] = widget
2021-05-14 16:12:42 -04:00
widget . check_editor_allowed ( )
2021-05-13 10:39:31 -04:00
return widget
2021-05-15 15:08:30 -04:00
def close_conversation_by_hash ( self , conversation_hash ) :
if conversation_hash in ConversationsDisplay . cached_conversation_widgets :
ConversationsDisplay . cached_conversation_widgets . pop ( conversation_hash )
if self . currently_displayed_conversation == conversation_hash :
self . display_conversation ( sender = None , source_hash = None )
2021-05-13 10:39:31 -04:00
def close_conversation ( self , conversation ) :
2021-05-15 15:08:30 -04:00
if conversation . source_hash in ConversationsDisplay . cached_conversation_widgets :
ConversationsDisplay . cached_conversation_widgets . pop ( conversation . source_hash )
if self . currently_displayed_conversation == conversation . source_hash :
self . display_conversation ( sender = None , source_hash = None )
2021-05-13 10:39:31 -04:00
def conversation_list_widget ( self , conversation ) :
trust_level = conversation [ 2 ]
display_name = conversation [ 1 ]
source_hash = conversation [ 0 ]
2021-09-05 14:38:10 -04:00
unread = conversation [ 4 ]
2021-05-13 10:39:31 -04:00
2021-07-02 07:35:10 -04:00
g = self . app . ui . glyphs
2021-05-13 10:39:31 -04:00
if trust_level == DirectoryEntry . UNTRUSTED :
2021-07-02 07:35:10 -04:00
symbol = g [ " cross " ]
2021-05-14 08:45:20 -04:00
style = " list_untrusted "
focus_style = " list_focus_untrusted "
2021-05-13 10:39:31 -04:00
elif trust_level == DirectoryEntry . UNKNOWN :
2021-05-14 08:45:20 -04:00
symbol = " ? "
style = " list_unknown "
focus_style = " list_focus "
2021-05-13 10:39:31 -04:00
elif trust_level == DirectoryEntry . TRUSTED :
2021-07-02 07:35:10 -04:00
symbol = g [ " check " ]
2021-05-14 08:45:20 -04:00
style = " list_trusted "
focus_style = " list_focus_trusted "
2021-05-13 10:39:31 -04:00
elif trust_level == DirectoryEntry . WARNING :
2021-07-02 07:35:10 -04:00
symbol = g [ " warning " ]
2021-05-14 08:45:20 -04:00
style = " list_warning "
focus_style = " list_focus "
2021-05-13 10:39:31 -04:00
else :
2021-07-02 07:35:10 -04:00
symbol = g [ " warning " ]
2021-05-14 08:45:20 -04:00
style = " list_untrusted "
focus_style = " list_focus_untrusted "
2021-05-13 10:39:31 -04:00
display_text = symbol
2021-09-05 14:38:10 -04:00
2021-05-14 16:12:42 -04:00
if display_name != None and display_name != " " :
2021-05-13 10:39:31 -04:00
display_text + = " " + display_name
if trust_level != DirectoryEntry . TRUSTED :
display_text + = " < " + source_hash + " > "
2021-09-25 10:57:29 -04:00
if trust_level != DirectoryEntry . UNTRUSTED :
2021-09-05 14:38:10 -04:00
if unread :
if source_hash != self . currently_displayed_conversation :
display_text + = " " + g [ " unread " ]
2021-05-13 10:39:31 -04:00
widget = ListEntry ( display_text )
urwid . connect_signal ( widget , " click " , self . display_conversation , conversation [ 0 ] )
2021-05-14 08:45:20 -04:00
display_widget = urwid . AttrMap ( widget , style , focus_style )
2021-05-13 10:39:31 -04:00
display_widget . source_hash = source_hash
display_widget . display_name = display_name
return display_widget
def shortcuts ( self ) :
focus_path = self . widget . get_focus_path ( )
if focus_path [ 0 ] == 0 :
return self . list_shortcuts
elif focus_path [ 0 ] == 1 :
return self . editor_shortcuts
else :
return self . list_shortcuts
class ListEntry ( urwid . Text ) :
_selectable = True
signals = [ " click " ]
def keypress ( self , size , key ) :
"""
Send ' click ' signal on ' activate ' command .
"""
if self . _command_map [ key ] != urwid . ACTIVATE :
return key
self . _emit ( ' click ' )
def mouse_event ( self , size , event , button , x , y , focus ) :
"""
Send ' click ' signal on button 1 press .
"""
if button != 1 or not urwid . util . is_mouse_press ( event ) :
return False
self . _emit ( ' click ' )
return True
2021-05-04 14:53:03 -04:00
2021-05-13 10:39:31 -04:00
class MessageEdit ( urwid . Edit ) :
def keypress ( self , size , key ) :
if key == " ctrl d " :
self . delegate . send_message ( )
2022-11-19 14:04:01 -05:00
elif key == " ctrl p " :
self . delegate . paper_message ( )
2021-05-13 10:39:31 -04:00
elif key == " ctrl k " :
self . delegate . clear_editor ( )
2021-05-14 11:36:35 -04:00
elif key == " up " :
y = self . get_cursor_coords ( size ) [ 1 ]
if y == 0 :
if self . delegate . full_editor_active and self . name == " title_editor " :
2024-01-18 05:58:22 -05:00
self . delegate . frame . focus_position = " body "
2021-05-14 11:36:35 -04:00
elif not self . delegate . full_editor_active and self . name == " content_editor " :
2024-01-18 05:58:22 -05:00
self . delegate . frame . focus_position = " body "
2021-05-14 11:36:35 -04:00
else :
return super ( MessageEdit , self ) . keypress ( size , key )
else :
return super ( MessageEdit , self ) . keypress ( size , key )
2021-05-13 10:39:31 -04:00
else :
return super ( MessageEdit , self ) . keypress ( size , key )
2021-05-14 11:36:35 -04:00
class ConversationFrame ( urwid . Frame ) :
def keypress ( self , size , key ) :
2024-01-18 05:58:22 -05:00
if self . focus_position == " body " :
2021-05-14 11:36:35 -04:00
if key == " up " and self . delegate . messagelist . top_is_visible :
2024-01-18 05:58:22 -05:00
nomadnet . NomadNetworkApp . get_shared_instance ( ) . ui . main_display . frame . focus_position = " header "
2021-05-14 11:36:35 -04:00
elif key == " down " and self . delegate . messagelist . bottom_is_visible :
2024-01-18 05:58:22 -05:00
self . focus_position = " footer "
2021-05-14 11:36:35 -04:00
else :
return super ( ConversationFrame , self ) . keypress ( size , key )
elif key == " ctrl k " :
self . delegate . clear_editor ( )
else :
return super ( ConversationFrame , self ) . keypress ( size , key )
2021-05-13 10:39:31 -04:00
class ConversationWidget ( urwid . WidgetWrap ) :
def __init__ ( self , source_hash ) :
2021-07-02 07:35:10 -04:00
self . app = nomadnet . NomadNetworkApp . get_shared_instance ( )
g = self . app . ui . glyphs
2021-05-04 14:53:03 -04:00
if source_hash == None :
2021-05-14 16:12:42 -04:00
self . frame = None
2021-05-15 15:08:30 -04:00
display_widget = urwid . LineBox ( urwid . Filler ( urwid . Text ( " \n No conversation selected " ) , " top " ) )
2024-01-18 04:22:38 -05:00
super ( ) . __init__ ( display_widget )
2021-05-04 14:53:03 -04:00
else :
if source_hash in ConversationsDisplay . cached_conversation_widgets :
return ConversationsDisplay . cached_conversation_widgets [ source_hash ]
else :
2021-05-13 10:39:31 -04:00
self . source_hash = source_hash
self . conversation = nomadnet . Conversation ( source_hash , nomadnet . NomadNetworkApp . get_shared_instance ( ) )
self . message_widgets = [ ]
2021-10-08 08:46:20 -04:00
self . sort_by_timestamp = False
2021-05-13 10:39:31 -04:00
self . updating_message_widgets = False
2021-05-04 14:53:03 -04:00
2021-05-13 10:39:31 -04:00
self . update_message_widgets ( )
2021-05-04 14:53:03 -04:00
2021-05-13 10:39:31 -04:00
self . conversation . register_changed_callback ( self . conversation_changed )
2021-05-04 14:53:03 -04:00
2021-05-14 09:13:17 -04:00
#title_editor = MessageEdit(caption="\u270E", edit_text="", multiline=False)
title_editor = MessageEdit ( caption = " " , edit_text = " " , multiline = False )
title_editor . delegate = self
2021-05-14 11:36:35 -04:00
title_editor . name = " title_editor "
2021-05-14 09:13:17 -04:00
#msg_editor = MessageEdit(caption="\u270E", edit_text="", multiline=True)
msg_editor = MessageEdit ( caption = " " , edit_text = " " , multiline = True )
2021-05-13 10:39:31 -04:00
msg_editor . delegate = self
2021-05-14 11:36:35 -04:00
msg_editor . name = " content_editor "
2021-05-12 08:02:44 -04:00
2021-05-13 10:39:31 -04:00
header = None
if self . conversation . trust_level == DirectoryEntry . UNTRUSTED :
2024-01-18 05:58:22 -05:00
header = urwid . AttrMap (
urwid . Padding (
urwid . Text ( g [ " warning " ] + " Warning: Conversation with untrusted peer " + g [ " warning " ] , align = urwid . CENTER ) ) ,
" msg_warning_untrusted " ,
)
2021-05-13 10:39:31 -04:00
2021-05-14 09:13:17 -04:00
self . minimal_editor = urwid . AttrMap ( msg_editor , " msg_editor " )
2021-05-14 11:36:35 -04:00
self . minimal_editor . name = " minimal_editor "
2021-05-14 09:13:17 -04:00
title_columns = urwid . Columns ( [
( 8 , urwid . Text ( " Title " ) ) ,
urwid . AttrMap ( title_editor , " msg_editor " ) ,
] )
content_columns = urwid . Columns ( [
( 8 , urwid . Text ( " Content " ) ) ,
urwid . AttrMap ( msg_editor , " msg_editor " )
] )
self . full_editor = urwid . Pile ( [
title_columns ,
content_columns
] )
2021-05-14 11:36:35 -04:00
self . full_editor . name = " full_editor "
2021-05-14 09:13:17 -04:00
self . content_editor = msg_editor
self . title_editor = title_editor
self . full_editor_active = False
2021-05-04 14:53:03 -04:00
2021-05-14 11:36:35 -04:00
self . frame = ConversationFrame (
2021-05-13 10:39:31 -04:00
self . messagelist ,
header = header ,
2021-05-15 15:08:30 -04:00
footer = self . minimal_editor ,
focus_part = " footer "
2021-05-13 10:39:31 -04:00
)
2021-05-14 11:36:35 -04:00
self . frame . delegate = self
2021-05-12 08:02:44 -04:00
2021-05-13 10:39:31 -04:00
self . display_widget = urwid . LineBox (
self . frame
)
2021-05-12 08:02:44 -04:00
2024-01-18 04:22:38 -05:00
super ( ) . __init__ ( self . display_widget )
2021-05-13 10:39:31 -04:00
2021-09-11 05:33:20 -04:00
def clear_history_dialog ( self ) :
def dismiss_dialog ( sender ) :
self . dialog_open = False
self . conversation_changed ( None )
def confirmed ( sender ) :
self . dialog_open = False
self . conversation . clear_history ( )
self . conversation_changed ( None )
dialog = DialogLineBox (
urwid . Pile ( [
2024-01-18 05:58:22 -05:00
urwid . Text ( " Clear conversation history \n " , align = urwid . CENTER ) ,
urwid . Columns ( [
( urwid . WEIGHT , 0.45 , urwid . Button ( " Yes " , on_press = confirmed ) ) ,
( urwid . WEIGHT , 0.1 , urwid . Text ( " " ) ) ,
( urwid . WEIGHT , 0.45 , urwid . Button ( " No " , on_press = dismiss_dialog ) ) ,
] )
2021-09-11 05:33:20 -04:00
] ) , title = " ? "
)
dialog . delegate = self
bottom = self . messagelist
2024-01-18 05:58:22 -05:00
overlay = urwid . Overlay (
dialog ,
bottom ,
align = urwid . CENTER ,
width = 34 ,
valign = urwid . MIDDLE ,
height = urwid . PACK ,
left = 2 ,
right = 2 ,
)
2021-09-11 05:33:20 -04:00
self . frame . contents [ " body " ] = ( overlay , self . frame . options ( ) )
2024-01-18 05:58:22 -05:00
self . frame . focus_position = " body "
2021-09-11 05:33:20 -04:00
2021-05-14 09:13:17 -04:00
def toggle_editor ( self ) :
if self . full_editor_active :
self . frame . contents [ " footer " ] = ( self . minimal_editor , None )
self . full_editor_active = False
else :
self . frame . contents [ " footer " ] = ( self . full_editor , None )
self . full_editor_active = True
2021-05-14 16:12:42 -04:00
def check_editor_allowed ( self ) :
2021-07-02 07:35:10 -04:00
g = self . app . ui . glyphs
2021-05-14 16:12:42 -04:00
if self . frame :
allowed = nomadnet . NomadNetworkApp . get_shared_instance ( ) . directory . is_known ( bytes . fromhex ( self . source_hash ) )
if allowed :
self . frame . contents [ " footer " ] = ( self . minimal_editor , None )
else :
2024-01-18 05:58:22 -05:00
warning = urwid . AttrMap (
urwid . Padding ( urwid . Text (
" \n " + g [ " info " ] + " \n \n You cannot currently message this peer, since it ' s identity keys are not known. "
" The keys have been requested from the network and should arrive shortly, if available. "
" Close this conversation and reopen it to try again. \n \n "
" To query the network manually, select this conversation in the conversation list, "
" press Ctrl-E, and use the query button. \n " ,
align = urwid . CENTER ,
) ) ,
" msg_header_caution " ,
)
2021-05-14 16:12:42 -04:00
self . frame . contents [ " footer " ] = ( warning , None )
2021-05-14 11:36:35 -04:00
def toggle_focus_area ( self ) :
name = " "
try :
name = self . frame . get_focus_widgets ( ) [ 0 ] . name
except Exception as e :
pass
if name == " messagelist " :
2024-01-18 05:58:22 -05:00
self . frame . focus_position = " footer "
2021-05-14 11:36:35 -04:00
elif name == " minimal_editor " or name == " full_editor " :
2024-01-18 05:58:22 -05:00
self . frame . focus_position = " body "
2021-05-14 11:36:35 -04:00
2021-05-14 08:45:20 -04:00
def keypress ( self , size , key ) :
2021-05-14 11:36:35 -04:00
if key == " tab " :
self . toggle_focus_area ( )
elif key == " ctrl w " :
2021-05-14 08:45:20 -04:00
self . close ( )
2022-11-19 14:04:01 -05:00
elif key == " ctrl u " :
2021-05-14 08:45:20 -04:00
self . conversation . purge_failed ( )
self . conversation_changed ( None )
2021-05-14 09:13:17 -04:00
elif key == " ctrl t " :
self . toggle_editor ( )
2021-09-11 05:33:20 -04:00
elif key == " ctrl x " :
self . clear_history_dialog ( )
2022-07-04 11:34:12 -04:00
elif key == " ctrl g " :
nomadnet . NomadNetworkApp . get_shared_instance ( ) . ui . main_display . sub_displays . conversations_display . toggle_fullscreen ( )
2021-10-08 08:46:20 -04:00
elif key == " ctrl o " :
self . sort_by_timestamp ^ = True
self . conversation_changed ( None )
2021-05-14 08:45:20 -04:00
else :
return super ( ConversationWidget , self ) . keypress ( size , key )
2021-05-13 10:39:31 -04:00
def conversation_changed ( self , conversation ) :
self . update_message_widgets ( replace = True )
def update_message_widgets ( self , replace = False ) :
while self . updating_message_widgets :
time . sleep ( 0.5 )
self . updating_message_widgets = True
self . message_widgets = [ ]
added_hashes = [ ]
for message in self . conversation . messages :
message_hash = message . get_hash ( )
if not message_hash in added_hashes :
added_hashes . append ( message_hash )
message_widget = LXMessageWidget ( message )
self . message_widgets . append ( message_widget )
2021-10-08 08:46:20 -04:00
if self . sort_by_timestamp :
self . message_widgets . sort ( key = lambda m : m . timestamp , reverse = False )
else :
self . message_widgets . sort ( key = lambda m : m . sort_timestamp , reverse = False )
2021-05-04 14:53:03 -04:00
2021-05-13 10:39:31 -04:00
from nomadnet . vendor . additional_urwid_widgets import IndicativeListBox
self . messagelist = IndicativeListBox ( self . message_widgets , position = len ( self . message_widgets ) - 1 )
2021-05-14 11:36:35 -04:00
self . messagelist . name = " messagelist "
2021-05-13 10:39:31 -04:00
if replace :
self . frame . contents [ " body " ] = ( self . messagelist , None )
nomadnet . NomadNetworkApp . get_shared_instance ( ) . ui . loop . draw_screen ( )
2021-05-04 14:53:03 -04:00
2021-05-13 10:39:31 -04:00
self . updating_message_widgets = False
2021-05-04 14:53:03 -04:00
2021-05-13 10:39:31 -04:00
def clear_editor ( self ) :
2021-05-14 09:13:17 -04:00
self . content_editor . set_edit_text ( " " )
self . title_editor . set_edit_text ( " " )
2021-05-13 10:39:31 -04:00
def send_message ( self ) :
2021-05-14 09:13:17 -04:00
content = self . content_editor . get_edit_text ( )
title = self . title_editor . get_edit_text ( )
2021-05-13 10:39:31 -04:00
if not content == " " :
2021-05-14 16:12:42 -04:00
if self . conversation . send ( content , title ) :
self . clear_editor ( )
else :
pass
2021-05-13 10:39:31 -04:00
2023-10-15 14:35:21 -04:00
def paper_message_saved ( self , path ) :
g = self . app . ui . glyphs
def dismiss_dialog ( sender ) :
self . dialog_open = False
self . conversation_changed ( None )
dialog = DialogLineBox (
urwid . Pile ( [
2024-01-18 05:58:22 -05:00
urwid . Text ( " The paper message was saved to: \n \n " + str ( path ) + " \n " , align = urwid . CENTER ) ,
urwid . Columns ( [
( urwid . WEIGHT , 0.6 , urwid . Text ( " " ) ) ,
( urwid . WEIGHT , 0.4 , urwid . Button ( " OK " , on_press = dismiss_dialog ) ) ,
] )
2023-10-15 18:16:04 -04:00
] ) , title = g [ " papermsg " ] . replace ( " " , " " )
2023-10-15 14:35:21 -04:00
)
dialog . delegate = self
bottom = self . messagelist
2024-01-18 05:58:22 -05:00
overlay = urwid . Overlay ( dialog , bottom , align = urwid . CENTER , width = 60 , valign = urwid . MIDDLE , height = urwid . PACK , left = 2 , right = 2 )
2023-10-15 14:35:21 -04:00
self . frame . contents [ " body " ] = ( overlay , self . frame . options ( ) )
2024-01-18 05:58:22 -05:00
self . frame . focus_position = " body "
2023-10-15 14:35:21 -04:00
def print_paper_message_qr ( self ) :
2022-11-19 14:04:01 -05:00
content = self . content_editor . get_edit_text ( )
title = self . title_editor . get_edit_text ( )
if not content == " " :
if self . conversation . paper_output ( content , title ) :
self . clear_editor ( )
else :
self . paper_message_failed ( )
2023-10-15 14:35:21 -04:00
def save_paper_message_qr ( self ) :
content = self . content_editor . get_edit_text ( )
title = self . title_editor . get_edit_text ( )
if not content == " " :
output_result = self . conversation . paper_output ( content , title , mode = " save_qr " )
if output_result != False :
self . clear_editor ( )
self . paper_message_saved ( output_result )
else :
self . paper_message_failed ( )
def save_paper_message_uri ( self ) :
content = self . content_editor . get_edit_text ( )
title = self . title_editor . get_edit_text ( )
if not content == " " :
output_result = self . conversation . paper_output ( content , title , mode = " save_uri " )
if output_result != False :
self . clear_editor ( )
self . paper_message_saved ( output_result )
else :
self . paper_message_failed ( )
def paper_message ( self ) :
def dismiss_dialog ( sender ) :
self . dialog_open = False
self . conversation_changed ( None )
def print_qr ( sender ) :
dismiss_dialog ( self )
self . print_paper_message_qr ( )
def save_qr ( sender ) :
dismiss_dialog ( self )
self . save_paper_message_qr ( )
def save_uri ( sender ) :
dismiss_dialog ( self )
self . save_paper_message_uri ( )
dialog = DialogLineBox (
urwid . Pile ( [
2024-01-18 05:58:22 -05:00
urwid . Text (
" Select the desired paper message output method. \n Saved files will be written to: \n \n " + str ( self . app . downloads_path ) + " \n " ,
align = urwid . CENTER ,
) ,
2023-10-15 14:35:21 -04:00
urwid . Columns ( [
2024-01-18 05:58:22 -05:00
( urwid . WEIGHT , 0.5 , urwid . Button ( " Print QR " , on_press = print_qr ) ) ,
( urwid . WEIGHT , 0.1 , urwid . Text ( " " ) ) ,
( urwid . WEIGHT , 0.5 , urwid . Button ( " Save QR " , on_press = save_qr ) ) ,
( urwid . WEIGHT , 0.1 , urwid . Text ( " " ) ) ,
( urwid . WEIGHT , 0.5 , urwid . Button ( " Save URI " , on_press = save_uri ) ) ,
( urwid . WEIGHT , 0.1 , urwid . Text ( " " ) ) ,
( urwid . WEIGHT , 0.5 , urwid . Button ( " Cancel " , on_press = dismiss_dialog ) )
2023-10-15 14:35:21 -04:00
] )
] ) , title = " Create Paper Message "
)
dialog . delegate = self
bottom = self . messagelist
2024-01-18 05:58:22 -05:00
overlay = urwid . Overlay ( dialog , bottom , align = urwid . CENTER , width = 60 , valign = urwid . MIDDLE , height = urwid . PACK , left = 2 , right = 2 )
2023-10-15 14:35:21 -04:00
self . frame . contents [ " body " ] = ( overlay , self . frame . options ( ) )
2024-01-18 05:58:22 -05:00
self . frame . focus_position = " body "
2023-10-15 14:35:21 -04:00
2022-11-19 14:04:01 -05:00
def paper_message_failed ( self ) :
def dismiss_dialog ( sender ) :
self . dialog_open = False
self . conversation_changed ( None )
dialog = DialogLineBox (
urwid . Pile ( [
2024-01-18 05:58:22 -05:00
urwid . Text (
" Could not output paper message, \n check your settings. See the log \n file for any error messages. \n " ,
align = urwid . CENTER ,
) ,
urwid . Columns ( [
( urwid . WEIGHT , 0.6 , urwid . Text ( " " ) ) ,
( urwid . WEIGHT , 0.4 , urwid . Button ( " OK " , on_press = dismiss_dialog ) ) ,
] )
2022-11-19 14:04:01 -05:00
] ) , title = " ! "
)
dialog . delegate = self
bottom = self . messagelist
2024-01-18 05:58:22 -05:00
overlay = urwid . Overlay ( dialog , bottom , align = urwid . CENTER , width = 34 , valign = urwid . MIDDLE , height = urwid . PACK , left = 2 , right = 2 )
2022-11-19 14:04:01 -05:00
self . frame . contents [ " body " ] = ( overlay , self . frame . options ( ) )
2024-01-18 05:58:22 -05:00
self . frame . focus_position = " body "
2022-11-19 14:04:01 -05:00
2021-05-13 10:39:31 -04:00
def close ( self ) :
self . delegate . close_conversation ( self )
class LXMessageWidget ( urwid . WidgetWrap ) :
def __init__ ( self , message ) :
app = nomadnet . NomadNetworkApp . get_shared_instance ( )
2021-07-02 07:35:10 -04:00
g = app . ui . glyphs
2021-05-13 10:39:31 -04:00
self . timestamp = message . get_timestamp ( )
2021-09-23 11:45:01 -04:00
self . sort_timestamp = message . sort_timestamp
2021-05-13 10:39:31 -04:00
time_format = app . time_format
message_time = datetime . fromtimestamp ( self . timestamp )
2021-05-14 13:38:21 -04:00
encryption_string = " "
if message . get_transport_encrypted ( ) :
2021-09-16 13:54:32 -04:00
encryption_string = " [ " + g [ " encrypted " ] + " " + str ( message . get_transport_encryption ( ) ) + " ] "
2021-05-14 13:38:21 -04:00
else :
2021-09-16 13:54:32 -04:00
encryption_string = " [ " + g [ " plaintext " ] + " " + str ( message . get_transport_encryption ( ) ) + " ] "
2021-05-14 13:38:21 -04:00
title_string = message_time . strftime ( time_format ) + encryption_string
2021-05-13 10:39:31 -04:00
if app . lxmf_destination . hash == message . lxm . source_hash :
if message . lxm . state == LXMF . LXMessage . DELIVERED :
header_style = " msg_header_delivered "
2021-07-02 07:35:10 -04:00
title_string = g [ " check " ] + " " + title_string
2021-05-14 08:45:20 -04:00
elif message . lxm . state == LXMF . LXMessage . FAILED :
header_style = " msg_header_failed "
2021-07-02 07:35:10 -04:00
title_string = g [ " cross " ] + " " + title_string
2021-10-07 15:04:11 -04:00
elif message . lxm . method == LXMF . LXMessage . PROPAGATED and message . lxm . state == LXMF . LXMessage . SENT :
header_style = " msg_header_propagated "
title_string = g [ " sent " ] + " " + title_string
2022-11-19 14:04:01 -05:00
elif message . lxm . method == LXMF . LXMessage . PAPER and message . lxm . state == LXMF . LXMessage . PAPER :
header_style = " msg_header_propagated "
title_string = g [ " papermsg " ] + " " + title_string
2021-10-03 12:44:00 -04:00
elif message . lxm . state == LXMF . LXMessage . SENT :
header_style = " msg_header_sent "
title_string = g [ " sent " ] + " " + title_string
2021-05-13 10:39:31 -04:00
else :
header_style = " msg_header_sent "
2021-07-02 07:35:10 -04:00
title_string = g [ " arrow_r " ] + " " + title_string
2021-05-12 08:02:44 -04:00
else :
2021-05-13 10:39:31 -04:00
if message . signature_validated ( ) :
header_style = " msg_header_ok "
2021-07-02 07:35:10 -04:00
title_string = g [ " check " ] + " " + title_string
2021-05-13 10:39:31 -04:00
else :
header_style = " msg_header_caution "
2021-07-02 07:35:10 -04:00
title_string = g [ " warning " ] + " " + message . get_signature_description ( ) + " \n " + title_string
2021-05-13 10:39:31 -04:00
if message . get_title ( ) != " " :
title_string + = " | " + message . get_title ( )
title = urwid . AttrMap ( urwid . Text ( title_string ) , header_style )
display_widget = urwid . Pile ( [
title ,
urwid . Text ( message . get_content ( ) ) ,
urwid . Text ( " " )
] )
2024-01-18 04:22:38 -05:00
super ( ) . __init__ ( display_widget )
2021-10-07 12:14:06 -04:00
class SyncProgressBar ( urwid . ProgressBar ) :
def get_text ( self ) :
status = nomadnet . NomadNetworkApp . get_shared_instance ( ) . get_sync_status ( )
show_percent = nomadnet . NomadNetworkApp . get_shared_instance ( ) . sync_status_show_percent ( )
if show_percent :
return status + " " + super ( ) . get_text ( )
else :
return status