1
1
use std:: borrow:: Cow ;
2
+ use std:: sync:: Arc ;
2
3
use argon2:: { Argon2 , Params , Version } ;
3
4
use lazy_static:: lazy_static;
4
5
use nostr_sdk:: prelude:: * ;
@@ -26,6 +27,9 @@ use voice::AudioRecorder;
26
27
27
28
mod net;
28
29
30
+ mod upload;
31
+ use upload:: { upload_data_with_progress, ProgressCallback } ;
32
+
29
33
mod util;
30
34
use util:: { extract_https_urls, get_file_type_description} ;
31
35
@@ -772,9 +776,10 @@ async fn message(receiver: String, content: String, replied_to: String, file: Op
772
776
. iter ( )
773
777
. filter ( |m| m. pending )
774
778
. count ( ) ;
775
- let pending_id = String :: from ( "pending-" ) + & pending_count. to_string ( ) ;
779
+ // Create persistent pending_id that will live for the entire function
780
+ let pending_id = Arc :: new ( String :: from ( "pending-" ) + & pending_count. to_string ( ) ) ;
776
781
let msg = Message {
777
- id : pending_id. clone ( ) ,
782
+ id : pending_id. as_ref ( ) . clone ( ) ,
778
783
content,
779
784
replied_to,
780
785
preview_metadata : None ,
@@ -790,13 +795,6 @@ async fn message(receiver: String, content: String, replied_to: String, file: Op
790
795
} ;
791
796
STATE . lock ( ) . await . add_message ( & receiver, msg. clone ( ) ) ;
792
797
793
- // Send the pending message to our frontend
794
- let handle = TAURI_APP . get ( ) . unwrap ( ) ;
795
- handle. emit ( "message_new" , serde_json:: json!( {
796
- "message" : & msg,
797
- "chat_id" : & receiver
798
- } ) ) . unwrap ( ) ;
799
-
800
798
// Grab our pubkey
801
799
let client = NOSTR_CLIENT . get ( ) . expect ( "Nostr client not initialized" ) ;
802
800
let signer = client. signer ( ) . await . unwrap ( ) ;
@@ -806,7 +804,14 @@ async fn message(receiver: String, content: String, replied_to: String, file: Op
806
804
let receiver_pubkey = PublicKey :: from_bech32 ( receiver. clone ( ) . as_str ( ) ) . unwrap ( ) ;
807
805
808
806
// Prepare the NIP-17 rumor
807
+ let handle = TAURI_APP . get ( ) . unwrap ( ) ;
809
808
let mut rumor = if file. is_none ( ) {
809
+ // Send the text message to our frontend
810
+ handle. emit ( "message_new" , serde_json:: json!( {
811
+ "message" : & msg,
812
+ "chat_id" : & receiver
813
+ } ) ) . unwrap ( ) ;
814
+
810
815
// Text Message
811
816
EventBuilder :: private_msg_rumor ( receiver_pubkey, msg. content )
812
817
} else {
@@ -818,10 +823,13 @@ async fn message(receiver: String, content: String, replied_to: String, file: Op
818
823
819
824
// Update the attachment in-state
820
825
{
826
+ // Use a clone of the Arc for this block
827
+ let pending_id_clone = Arc :: clone ( & pending_id) ;
828
+
821
829
// Retrieve the Pending Message
822
830
let mut state = STATE . lock ( ) . await ;
823
831
let chat = state. get_profile_mut ( & receiver) . unwrap ( ) ;
824
- let message = chat. get_message_mut ( & pending_id ) . unwrap ( ) ;
832
+ let message = chat. get_message_mut ( pending_id_clone . as_ref ( ) ) . unwrap ( ) ;
825
833
826
834
// Choose the appropriate base directory based on platform
827
835
let base_directory = if cfg ! ( target_os = "ios" ) {
@@ -856,9 +864,8 @@ async fn message(receiver: String, content: String, replied_to: String, file: Op
856
864
downloaded : true
857
865
} ) ;
858
866
859
- // Update the frontend
860
- handle. emit ( "message_update" , serde_json:: json!( {
861
- "old_id" : & pending_id,
867
+ // Send the pending file upload to our frontend
868
+ handle. emit ( "message_new" , serde_json:: json!( {
862
869
"message" : & message,
863
870
"chat_id" : & receiver
864
871
} ) ) . unwrap ( ) ;
@@ -889,7 +896,21 @@ async fn message(receiver: String, content: String, replied_to: String, file: Op
889
896
let signer = client. signer ( ) . await . unwrap ( ) ;
890
897
let conf = PRIVATE_NIP96_CONFIG . wait ( ) ;
891
898
let file_size = enc_file. len ( ) ;
892
- match upload_data ( & signer, & conf, enc_file, Some ( mime_type) , None ) . await {
899
+ // Clone the Arc outside the closure for use inside a seperate-threaded progress callback
900
+ let pending_id_for_callback = Arc :: clone ( & pending_id) ;
901
+ // Create a progress callback for file uploads
902
+ let progress_callback: ProgressCallback = Box :: new ( move |percentage, _| {
903
+ // This is a simple callback that logs progress but could be enhanced to emit events
904
+ if let Some ( pct) = percentage {
905
+ handle. emit ( "attachment_upload_progress" , serde_json:: json!( {
906
+ "id" : pending_id_for_callback. as_ref( ) ,
907
+ "progress" : pct
908
+ } ) ) . unwrap ( ) ;
909
+ }
910
+ Ok ( ( ) )
911
+ } ) ;
912
+
913
+ match upload_data_with_progress ( & signer, & conf, enc_file, Some ( mime_type) , None , progress_callback) . await {
893
914
Ok ( url) => {
894
915
// Create the attachment rumor
895
916
let attachment_rumor = EventBuilder :: new ( Kind :: from_u16 ( 15 ) , url. to_string ( ) ) ;
@@ -905,14 +926,15 @@ async fn message(receiver: String, content: String, replied_to: String, file: Op
905
926
} ,
906
927
Err ( _) => {
907
928
// The file upload failed: so we mark the message as failed and notify of an error
929
+ let pending_id_for_failure = Arc :: clone ( & pending_id) ;
908
930
let mut state = STATE . lock ( ) . await ;
909
931
let chat = state. get_profile_mut ( & receiver) . unwrap ( ) ;
910
- let failed_msg = chat. get_message_mut ( & pending_id ) . unwrap ( ) ;
932
+ let failed_msg = chat. get_message_mut ( pending_id_for_failure . as_ref ( ) ) . unwrap ( ) ;
911
933
failed_msg. failed = true ;
912
934
913
935
// Update the frontend
914
936
handle. emit ( "message_update" , serde_json:: json!( {
915
- "old_id" : & pending_id ,
937
+ "old_id" : pending_id_for_failure . as_ref ( ) ,
916
938
"message" : & failed_msg,
917
939
"chat_id" : & receiver
918
940
} ) ) . unwrap ( ) ;
@@ -948,15 +970,16 @@ async fn message(receiver: String, content: String, replied_to: String, file: Op
948
970
{
949
971
Ok ( _) => {
950
972
// Mark the message as a success
973
+ let pending_id_for_success = Arc :: clone ( & pending_id) ;
951
974
let mut state = STATE . lock ( ) . await ;
952
975
let chat = state. get_profile_mut ( & receiver) . unwrap ( ) ;
953
- let sent_msg = chat. get_message_mut ( & pending_id ) . unwrap ( ) ;
976
+ let sent_msg = chat. get_message_mut ( pending_id_for_success . as_ref ( ) ) . unwrap ( ) ;
954
977
sent_msg. id = rumor_id. to_hex ( ) ;
955
978
sent_msg. pending = false ;
956
979
957
980
// Update the frontend
958
981
handle. emit ( "message_update" , serde_json:: json!( {
959
- "old_id" : & pending_id ,
982
+ "old_id" : pending_id_for_success . as_ref ( ) ,
960
983
"message" : & sent_msg,
961
984
"chat_id" : & receiver
962
985
} ) ) . unwrap ( ) ;
@@ -969,15 +992,16 @@ async fn message(receiver: String, content: String, replied_to: String, file: Op
969
992
Err ( _) => {
970
993
// This is an odd case; the message was sent to the receiver, but NOT ourselves
971
994
// We'll class it as sent, for now...
995
+ let pending_id_for_partial = Arc :: clone ( & pending_id) ;
972
996
let mut state = STATE . lock ( ) . await ;
973
997
let chat = state. get_profile_mut ( & receiver) . unwrap ( ) ;
974
- let sent_ish_msg = chat. get_message_mut ( & pending_id ) . unwrap ( ) ;
998
+ let sent_ish_msg = chat. get_message_mut ( pending_id_for_partial . as_ref ( ) ) . unwrap ( ) ;
975
999
sent_ish_msg. id = rumor_id. to_hex ( ) ;
976
1000
sent_ish_msg. pending = false ;
977
1001
978
1002
// Update the frontend
979
1003
handle. emit ( "message_update" , serde_json:: json!( {
980
- "old_id" : & pending_id ,
1004
+ "old_id" : pending_id_for_partial . as_ref ( ) ,
981
1005
"message" : & sent_ish_msg,
982
1006
"chat_id" : & receiver
983
1007
} ) ) . unwrap ( ) ;
@@ -991,9 +1015,10 @@ async fn message(receiver: String, content: String, replied_to: String, file: Op
991
1015
}
992
1016
Err ( _) => {
993
1017
// Mark the message as a failure, bad message, bad!
1018
+ let pending_id_for_final = Arc :: clone ( & pending_id) ;
994
1019
let mut state = STATE . lock ( ) . await ;
995
1020
let chat = state. get_profile_mut ( & receiver) . unwrap ( ) ;
996
- let failed_msg = chat. get_message_mut ( & pending_id ) . unwrap ( ) ;
1021
+ let failed_msg = chat. get_message_mut ( pending_id_for_final . as_ref ( ) ) . unwrap ( ) ;
997
1022
failed_msg. failed = true ;
998
1023
return Ok ( false ) ;
999
1024
}
0 commit comments