11import lvgl as lv
22
3- from mpos import Activity , Intent , ConnectivityManager , MposKeyboard , pct_of_display_width , pct_of_display_height , SharedPreferences , SettingsActivity
4- from mpos .ui .anim import WidgetAnimator
5-
6- from fullscreen_qr import FullscreenQR
3+ from mpos import Activity , Intent , ConnectivityManager , pct_of_display_width , pct_of_display_height , SharedPreferences , SettingsActivity
74
85class NostrApp (Activity ):
96
107 wallet = None
11- receive_qr_data = None
12- destination = None
13- balance_mode = 0 # 0=sats, 1=bits, 2=μBTC, 3=mBTC, 4=BTC
14- payments_label_current_font = 2
15- payments_label_fonts = [ lv .font_montserrat_10 , lv .font_unscii_8 , lv .font_montserrat_16 , lv .font_montserrat_24 , lv .font_unscii_16 , lv .font_montserrat_28_compressed , lv .font_montserrat_40 ]
8+ events_label_current_font = 2
9+ events_label_fonts = [ lv .font_montserrat_10 , lv .font_unscii_8 , lv .font_montserrat_16 , lv .font_montserrat_24 , lv .font_unscii_16 , lv .font_montserrat_28_compressed , lv .font_montserrat_40 ]
1610
1711 # screens:
1812 main_screen = None
1913
2014 # widgets
2115 balance_label = None
22- receive_qr = None
23- payments_label = None
24-
25- # activities
26- fullscreenqr = FullscreenQR () # need a reference to be able to finish() it
16+ events_label = None
2717
2818 def onCreate (self ):
2919 self .prefs = SharedPreferences ("com.micropythonos.nostr" )
3020 self .main_screen = lv .obj ()
3121 self .main_screen .set_style_pad_all (10 , 0 )
32- # This line needs to be drawn first, otherwise it's over the balance label and steals all the clicks!
33- balance_line = lv .line (self .main_screen )
34- balance_line .set_points ([{'x' :0 ,'y' :35 },{'x' :200 ,'y' :35 }],2 )
35- balance_line .add_flag (lv .obj .FLAG .CLICKABLE )
22+ # Header line
23+ header_line = lv .line (self .main_screen )
24+ header_line .set_points ([{'x' :0 ,'y' :35 },{'x' :200 ,'y' :35 }],2 )
25+ header_line .add_flag (lv .obj .FLAG .CLICKABLE )
26+ # Header label showing which npub we're following
3627 self .balance_label = lv .label (self .main_screen )
3728 self .balance_label .set_text ("" )
3829 self .balance_label .align (lv .ALIGN .TOP_LEFT , 0 , 0 )
3930 self .balance_label .set_style_text_font (lv .font_montserrat_24 , 0 )
4031 self .balance_label .add_flag (lv .obj .FLAG .CLICKABLE )
41- self .balance_label .set_width (pct_of_display_width (75 )) # 100 - receive_qr
42- self .balance_label .add_event_cb (self .balance_label_clicked_cb ,lv .EVENT .CLICKED ,None )
43- self .receive_qr = lv .qrcode (self .main_screen )
44- self .receive_qr .set_size (pct_of_display_width (20 )) # bigger QR results in simpler code (less error correction?)
45- self .receive_qr .set_dark_color (lv .color_black ())
46- self .receive_qr .set_light_color (lv .color_white ())
47- self .receive_qr .align (lv .ALIGN .TOP_RIGHT ,0 ,0 )
48- self .receive_qr .set_style_border_color (lv .color_white (), 0 )
49- self .receive_qr .set_style_border_width (1 , 0 );
50- self .receive_qr .add_flag (lv .obj .FLAG .CLICKABLE )
51- self .receive_qr .add_event_cb (self .qr_clicked_cb ,lv .EVENT .CLICKED ,None )
52- self .payments_label = lv .label (self .main_screen )
53- self .payments_label .set_text ("" )
54- self .payments_label .align_to (balance_line ,lv .ALIGN .OUT_BOTTOM_LEFT ,0 ,10 )
55- self .update_payments_label_font ()
56- self .payments_label .set_width (pct_of_display_width (75 )) # 100 - receive_qr
57- self .payments_label .add_flag (lv .obj .FLAG .CLICKABLE )
58- self .payments_label .add_event_cb (self .payments_label_clicked ,lv .EVENT .CLICKED ,None )
32+ self .balance_label .set_width (pct_of_display_width (100 ))
33+ # Events label
34+ self .events_label = lv .label (self .main_screen )
35+ self .events_label .set_text ("" )
36+ self .events_label .align_to (header_line ,lv .ALIGN .OUT_BOTTOM_LEFT ,0 ,10 )
37+ self .update_events_label_font ()
38+ self .events_label .set_width (pct_of_display_width (100 ))
39+ self .events_label .add_flag (lv .obj .FLAG .CLICKABLE )
40+ self .events_label .add_event_cb (self .events_label_clicked ,lv .EVENT .CLICKED ,None )
5941 settings_button = lv .button (self .main_screen )
6042 settings_button .set_size (lv .pct (20 ), lv .pct (25 ))
6143 settings_button .align (lv .ALIGN .BOTTOM_RIGHT , 0 , 0 )
@@ -64,15 +46,6 @@ def onCreate(self):
6446 settings_label .set_text (lv .SYMBOL .SETTINGS )
6547 settings_label .set_style_text_font (lv .font_montserrat_24 , 0 )
6648 settings_label .center ()
67- if False : # send button disabled for now, not implemented
68- send_button = lv .button (self .main_screen )
69- send_button .set_size (lv .pct (20 ), lv .pct (25 ))
70- send_button .align_to (settings_button , lv .ALIGN .OUT_TOP_MID , 0 , - pct_of_display_height (2 ))
71- send_button .add_event_cb (self .send_button_tap ,lv .EVENT .CLICKED ,None )
72- send_label = lv .label (send_button )
73- send_label .set_text (lv .SYMBOL .UPLOAD )
74- send_label .set_style_text_font (lv .font_montserrat_24 , 0 )
75- send_label .center ()
7649 self .setContentView (self .main_screen )
7750
7851 def onStart (self , main_screen ):
@@ -85,9 +58,8 @@ def onResume(self, main_screen):
8558 self .network_changed (cm .is_online ())
8659
8760 def onPause (self , main_screen ):
88- if self .wallet and self .destination != FullscreenQR :
89- self .wallet .stop () # don't stop the wallet for the fullscreen QR activity
90- self .destination = None
61+ if self .wallet :
62+ self .wallet .stop ()
9163 cm = ConnectivityManager .get ()
9264 cm .unregister_callback (self .network_changed )
9365
@@ -104,88 +76,52 @@ def went_online(self):
10476 return
10577 try :
10678 from nostr_client import NostrClient
107- self .wallet = NostrClient (self .prefs .get_string ("nostr_nsec" ))
108- self .wallet .follow_npub = self .prefs .get_string ("nostr_follow_npub" )
109- self .redraw_static_receive_code_cb ()
79+ nsec = self .prefs .get_string ("nostr_nsec" )
80+ # Generate a random nsec if not configured
81+ if not nsec :
82+ from nostr .key import PrivateKey
83+ random_key = PrivateKey ()
84+ nsec = random_key .bech32 ()
85+ self .prefs .edit ().put_string ("nostr_nsec" , nsec ).commit ()
86+ print (f"Generated random nsec: { nsec } " )
87+ follow_npub = self .prefs .get_string ("nostr_follow_npub" )
88+ relay = self .prefs .get_string ("nostr_relay" )
89+ self .wallet = NostrClient (nsec , follow_npub , relay )
11090 except Exception as e :
11191 self .error_cb (f"Couldn't initialize Nostr client because: { e } " )
11292 import sys
11393 sys .print_exception (e )
11494 return
115- self .balance_label .set_text (lv . SYMBOL . REFRESH )
116- self .payments_label .set_text (f"\n Connecting to backend .\n \n If this takes too long, it might be down or something's wrong with the settings." )
95+ self .balance_label .set_text ("Events from " + self . prefs . get_string ( "nostr_follow_npub" )[: 16 ] + "..." )
96+ self .events_label .set_text (f"\n Connecting to relay .\n \n If this takes too long, the relay might be down or something's wrong with the settings." )
11797 # by now, self.wallet can be assumed
118- self .wallet .start (self .balance_updated_cb , self . redraw_payments_cb , self . redraw_static_receive_code_cb , self .error_cb )
98+ self .wallet .start (self .redraw_events_cb , self .error_cb )
11999
120100 def went_offline (self ):
121101 if self .wallet :
122102 self .wallet .stop () # don't stop the wallet for the fullscreen QR activity
123- self .payments_label .set_text (f"WiFi is not connected, can't talk to wallet..." )
124-
125- def update_payments_label_font (self ):
126- self .payments_label .set_style_text_font (self .payments_label_fonts [self .payments_label_current_font ], 0 )
127-
128- def payments_label_clicked (self , event ):
129- self .payments_label_current_font = (self .payments_label_current_font + 1 ) % len (self .payments_label_fonts )
130- self .update_payments_label_font ()
131-
132- def float_to_string (self , value ):
133- # Format float to string with fixed-point notation, up to 6 decimal places
134- s = "{:.8f}" .format (value )
135- # Remove trailing zeros and decimal point if no decimals remain
136- return s .rstrip ("0" ).rstrip ("." )
137-
138- def display_balance (self , balance ):
139- #print(f"displaying balance {balance}")
140- if self .balance_mode == 0 : # sats
141- #balance_text = "丰 " + str(balance) # font doesnt support it
142- balance_text = str (balance ) + " sat"
143- if balance > 1 :
144- balance_text += "s"
145- elif self .balance_mode == 1 : # bits (1 bit = 100 sats)
146- balance_bits = balance / 100
147- balance_text = self .float_to_string (balance_bits ) + " bit"
148- if balance_bits != 1 :
149- balance_text += "s"
150- elif self .balance_mode == 2 : # micro-BTC (1 μBTC = 100 sats)
151- balance_ubtc = balance / 100
152- balance_text = self .float_to_string (balance_ubtc ) + " micro-BTC"
153- elif self .balance_mode == 3 : # milli-BTC (1 mBTC = 100000 sats)
154- balance_mbtc = balance / 100000
155- balance_text = self .float_to_string (balance_mbtc ) + " milli-BTC"
156- elif self .balance_mode == 4 : # BTC (1 BTC = 100000000 sats)
157- balance_btc = balance / 100000000
158- #balance_text = "₿ " + str(balance) # font doesnt support it - although it should https://fonts.google.com/specimen/Montserrat
159- balance_text = self .float_to_string (balance_btc ) + " BTC"
160- self .balance_label .set_text (balance_text )
161- #print("done displaying balance")
162-
163- def balance_updated_cb (self , sats_added = 0 ):
164- print (f"balance_updated_cb(sats_added={ sats_added } )" )
165- if self .fullscreenqr .has_foreground ():
166- self .fullscreenqr .finish ()
167- balance = self .wallet .last_known_balance
168- print (f"balance: { balance } " )
169- if balance is not None :
170- WidgetAnimator .change_widget (self .balance_label , anim_type = "interpolate" , duration = 5000 , delay = 0 , begin_value = balance - sats_added , end_value = balance , display_change = self .display_balance )
171- else :
172- print ("Not drawing balance because it's None" )
173-
174- def redraw_payments_cb (self ):
175- # this gets called from another thread (the wallet) so make sure it happens in the LVGL thread using lv.async_call():
176- self .payments_label .set_text (str (self .wallet .payment_list ))
103+ self .events_label .set_text (f"WiFi is not connected, can't talk to relay..." )
177104
178- def redraw_static_receive_code_cb (self ):
105+ def update_events_label_font (self ):
106+ self .events_label .set_style_text_font (self .events_label_fonts [self .events_label_current_font ], 0 )
107+
108+ def events_label_clicked (self , event ):
109+ self .events_label_current_font = (self .events_label_current_font + 1 ) % len (self .events_label_fonts )
110+ self .update_events_label_font ()
111+
112+ def redraw_events_cb (self ):
179113 # this gets called from another thread (the wallet) so make sure it happens in the LVGL thread using lv.async_call():
180- self .receive_qr_data = self .wallet .static_receive_code
181- if self .receive_qr_data :
182- self .receive_qr .update (self .receive_qr_data , len (self .receive_qr_data ))
114+ events_text = ""
115+ if self .wallet .event_list :
116+ for event in self .wallet .event_list :
117+ events_text += f"{ event .content } \n \n "
183118 else :
184- print ("Warning: redraw_static_receive_code_cb() was called while self.wallet.static_receive_code is None..." )
119+ events_text = "No events yet..."
120+ self .events_label .set_text (events_text )
185121
186122 def error_cb (self , error ):
187123 if self .wallet and self .wallet .is_running ():
188- self .payments_label .set_text (str (error ))
124+ self .events_label .set_text (str (error ))
189125
190126 def should_show_setting (self , setting ):
191127 return True
@@ -202,16 +138,4 @@ def settings_button_tap(self, event):
202138
203139 def main_ui_set_defaults (self ):
204140 self .balance_label .set_text ("Welcome!" )
205- self .payments_label .set_text (lv .SYMBOL .REFRESH )
206-
207- def balance_label_clicked_cb (self , event ):
208- print ("Balance clicked" )
209- self .balance_mode = (self .balance_mode + 1 ) % 5
210- self .display_balance (self .wallet .last_known_balance )
211-
212- def qr_clicked_cb (self , event ):
213- print ("QR clicked" )
214- if not self .receive_qr_data :
215- return
216- self .destination = FullscreenQR
217- self .startActivity (Intent (activity_class = self .fullscreenqr ).putExtra ("receive_qr_data" , self .receive_qr_data ))
141+ self .events_label .set_text (lv .SYMBOL .REFRESH )
0 commit comments