@@ -165,6 +165,11 @@ pub struct StatusUpdateItem {
165
165
#[ serde( skip_serializing_if = "Option::is_none" ) ]
166
166
pub info : Option < String > ,
167
167
168
+ /// Optional link the info message will point to.
169
+ /// Used to set `window.location.href` in JS land.
170
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
171
+ pub href : Option < String > ,
172
+
168
173
/// The new name of the editing document.
169
174
/// This is not needed if the webxdc doesn't edit documents.
170
175
#[ serde( skip_serializing_if = "Option::is_none" ) ]
@@ -353,19 +358,22 @@ impl Context {
353
358
354
359
if can_info_msg {
355
360
if let Some ( ref info) = status_update_item. info {
356
- if let Some ( info_msg_id) = self
361
+ let info_msg_id = self
357
362
. get_overwritable_info_msg_id ( & instance, from_id)
358
- . await ?
359
- {
360
- chat:: update_msg_text_and_timestamp (
361
- self ,
362
- instance. chat_id ,
363
- info_msg_id,
364
- info. as_str ( ) ,
365
- timestamp,
366
- )
367
363
. await ?;
368
- notify_msg_id = info_msg_id;
364
+
365
+ if info_msg_id. is_some ( ) && !status_update_item. href . is_some ( ) {
366
+ if let Some ( info_msg_id) = info_msg_id {
367
+ chat:: update_msg_text_and_timestamp (
368
+ self ,
369
+ instance. chat_id ,
370
+ info_msg_id,
371
+ info. as_str ( ) ,
372
+ timestamp,
373
+ )
374
+ . await ?;
375
+ notify_msg_id = info_msg_id;
376
+ }
369
377
} else {
370
378
notify_msg_id = chat:: add_info_msg_with_cmd (
371
379
self ,
@@ -380,6 +388,12 @@ impl Context {
380
388
. await ?;
381
389
}
382
390
notify_text = info. to_string ( ) ;
391
+
392
+ if let Some ( href) = status_update_item. href {
393
+ let mut notify_msg = Message :: load_from_db ( self , notify_msg_id) . await ?;
394
+ notify_msg. param . set ( Param :: Arg , href) ;
395
+ notify_msg. update_param ( self ) . await ?;
396
+ }
383
397
}
384
398
}
385
399
@@ -944,6 +958,18 @@ impl Message {
944
958
let hash = Sha256 :: digest ( data. as_bytes ( ) ) ;
945
959
Ok ( format ! ( "{:x}" , hash) )
946
960
}
961
+
962
+ /// Get link attached to an info message.
963
+ ///
964
+ /// The info message needs to be of type SystemMessage::WebxdcInfoMessage.
965
+ /// Typically, this is used to start the corresponding
966
+ // with `window.location.href` set in JS land.
967
+ pub fn get_webxdc_href ( & self ) -> Option < String > {
968
+ let Some ( href) = self . param . get ( Param :: Arg ) else {
969
+ return None ;
970
+ } ;
971
+ Some ( href. to_string ( ) )
972
+ }
947
973
}
948
974
949
975
#[ cfg( test) ]
@@ -1457,6 +1483,7 @@ mod tests {
1457
1483
StatusUpdateItem {
1458
1484
payload : json ! ( { "foo" : "bar" } ) ,
1459
1485
info : None ,
1486
+ href : None ,
1460
1487
document : None ,
1461
1488
summary : None ,
1462
1489
uid : Some ( "iecie2Ze" . to_string ( ) ) ,
@@ -1482,6 +1509,7 @@ mod tests {
1482
1509
StatusUpdateItem {
1483
1510
payload : json ! ( { "nothing" : "this should be ignored" } ) ,
1484
1511
info : None ,
1512
+ href : None ,
1485
1513
document : None ,
1486
1514
summary : None ,
1487
1515
uid : Some ( "iecie2Ze" . to_string ( ) ) ,
@@ -1516,6 +1544,7 @@ mod tests {
1516
1544
StatusUpdateItem {
1517
1545
payload : json ! ( { "foo2" : "bar2" } ) ,
1518
1546
info : None ,
1547
+ href : None ,
1519
1548
document : None ,
1520
1549
summary : None ,
1521
1550
uid : None ,
@@ -1536,6 +1565,7 @@ mod tests {
1536
1565
StatusUpdateItem {
1537
1566
payload : Value :: Bool ( true ) ,
1538
1567
info : None ,
1568
+ href : None ,
1539
1569
document : None ,
1540
1570
summary : None ,
1541
1571
uid : None ,
@@ -3069,4 +3099,38 @@ sth_for_the = "future""#
3069
3099
3070
3100
Ok ( ( ) )
3071
3101
}
3102
+
3103
+ #[ tokio:: test( flavor = "multi_thread" , worker_threads = 2 ) ]
3104
+ async fn test_webxdc_href ( ) -> Result < ( ) > {
3105
+ let mut tcm = TestContextManager :: new ( ) ;
3106
+ let alice = tcm. alice ( ) . await ;
3107
+ let bob = tcm. bob ( ) . await ;
3108
+
3109
+ let grp_id = alice
3110
+ . create_group_with_members ( ProtectionStatus :: Unprotected , "grp" , & [ & bob] )
3111
+ . await ;
3112
+ let instance = send_webxdc_instance ( & alice, grp_id) . await ?;
3113
+ let sent1 = alice. pop_sent_msg ( ) . await ;
3114
+
3115
+ alice
3116
+ . send_webxdc_status_update (
3117
+ instance. id ,
3118
+ r##"{"payload": "my deeplink data", "info": "my move!", "href": "#foobar"}"## ,
3119
+ "d" ,
3120
+ )
3121
+ . await ?;
3122
+ alice. flush_status_updates ( ) . await ?;
3123
+ let sent2 = alice. pop_sent_msg ( ) . await ;
3124
+ let info_msg = alice. get_last_msg ( ) . await ;
3125
+ assert ! ( info_msg. is_info( ) ) ;
3126
+ assert_eq ! ( info_msg. get_webxdc_href( ) , Some ( "#foobar" . to_string( ) ) ) ;
3127
+
3128
+ bob. recv_msg ( & sent1) . await ;
3129
+ bob. recv_msg_trash ( & sent2) . await ;
3130
+ let info_msg = bob. get_last_msg ( ) . await ;
3131
+ assert ! ( info_msg. is_info( ) ) ;
3132
+ assert_eq ! ( info_msg. get_webxdc_href( ) , Some ( "#foobar" . to_string( ) ) ) ;
3133
+
3134
+ Ok ( ( ) )
3135
+ }
3072
3136
}
0 commit comments