@@ -442,18 +442,17 @@ impl App {
442
442
cmd : UICommand ,
443
443
) {
444
444
match cmd {
445
- #[ cfg( not( target_arch = "wasm32" ) ) ]
446
- UICommand :: Save => {
445
+ UICommand :: SaveRecording => {
447
446
save ( self , store_context, None ) ;
448
447
}
449
- #[ cfg( not( target_arch = "wasm32" ) ) ]
450
- UICommand :: SaveSelection => {
448
+ UICommand :: SaveRecordingSelection => {
451
449
save (
452
450
self ,
453
451
store_context,
454
452
self . state . loop_selection ( store_context) ,
455
453
) ;
456
454
}
455
+
457
456
#[ cfg( not( target_arch = "wasm32" ) ) ]
458
457
UICommand :: Open => {
459
458
for file_path in open_file_dialog_native ( ) {
@@ -1501,41 +1500,96 @@ async fn async_open_rrd_dialog() -> Vec<re_data_source::FileContents> {
1501
1500
file_contents
1502
1501
}
1503
1502
1504
- #[ cfg ( not ( target_arch = "wasm32" ) ) ]
1503
+ #[ allow ( clippy :: needless_pass_by_ref_mut ) ]
1505
1504
fn save (
1506
- app : & mut App ,
1505
+ # [ allow ( unused_variables ) ] app : & mut App , // only used on native
1507
1506
store_context : Option < & StoreContext < ' _ > > ,
1508
1507
loop_selection : Option < ( re_entity_db:: Timeline , re_log_types:: TimeRangeF ) > ,
1509
1508
) {
1510
- use crate :: saving :: save_database_to_file ;
1509
+ re_tracing :: profile_function! ( ) ;
1511
1510
1512
1511
let Some ( entity_db) = store_context. as_ref ( ) . and_then ( |view| view. recording ) else {
1513
1512
// NOTE: Can only happen if saving through the command palette.
1514
1513
re_log:: error!( "No data to save!" ) ;
1515
1514
return ;
1516
1515
} ;
1517
1516
1517
+ let file_name = "data.rrd" ;
1518
+
1518
1519
let title = if loop_selection. is_some ( ) {
1519
1520
"Save loop selection"
1520
1521
} else {
1521
1522
"Save"
1522
1523
} ;
1523
1524
1524
- if let Some ( path) = rfd:: FileDialog :: new ( )
1525
- . set_file_name ( "data.rrd" )
1526
- . set_title ( title)
1527
- . save_file ( )
1525
+ // Web
1526
+ #[ cfg( target_arch = "wasm32" ) ]
1528
1527
{
1529
- let f = match save_database_to_file ( entity_db, path , loop_selection) {
1530
- Ok ( f ) => f ,
1528
+ let messages = match entity_db. to_messages ( loop_selection) {
1529
+ Ok ( messages ) => messages ,
1531
1530
Err ( err) => {
1532
1531
re_log:: error!( "File saving failed: {err}" ) ;
1533
1532
return ;
1534
1533
}
1535
1534
} ;
1536
- if let Err ( err) = app. background_tasks . spawn_file_saver ( f) {
1537
- // NOTE: Can only happen if saving through the command palette.
1538
- re_log:: error!( "File saving failed: {err}" ) ;
1535
+
1536
+ wasm_bindgen_futures:: spawn_local ( async move {
1537
+ if let Err ( err) = async_save_dialog ( file_name, title, & messages) . await {
1538
+ re_log:: error!( "File saving failed: {err}" ) ;
1539
+ }
1540
+ } ) ;
1541
+ }
1542
+
1543
+ // Native
1544
+ #[ cfg( not( target_arch = "wasm32" ) ) ]
1545
+ {
1546
+ let path = {
1547
+ re_tracing:: profile_scope!( "file_dialog" ) ;
1548
+ rfd:: FileDialog :: new ( )
1549
+ . set_file_name ( file_name)
1550
+ . set_title ( title)
1551
+ . save_file ( )
1552
+ } ;
1553
+ if let Some ( path) = path {
1554
+ let messages = match entity_db. to_messages ( loop_selection) {
1555
+ Ok ( messages) => messages,
1556
+ Err ( err) => {
1557
+ re_log:: error!( "File saving failed: {err}" ) ;
1558
+ return ;
1559
+ }
1560
+ } ;
1561
+ if let Err ( err) = app
1562
+ . background_tasks
1563
+ . spawn_file_saver ( move || crate :: saving:: encode_to_file ( & path, messages. iter ( ) ) )
1564
+ {
1565
+ // NOTE: Can only happen if saving through the command palette.
1566
+ re_log:: error!( "File saving failed: {err}" ) ;
1567
+ }
1539
1568
}
1540
1569
}
1541
1570
}
1571
+
1572
+ #[ cfg( target_arch = "wasm32" ) ]
1573
+ async fn async_save_dialog (
1574
+ file_name : & str ,
1575
+ title : & str ,
1576
+ messages : & [ LogMsg ] ,
1577
+ ) -> anyhow:: Result < ( ) > {
1578
+ use anyhow:: Context as _;
1579
+
1580
+ let file_handle = rfd:: AsyncFileDialog :: new ( )
1581
+ . set_file_name ( file_name)
1582
+ . set_title ( title)
1583
+ . save_file ( )
1584
+ . await ;
1585
+
1586
+ let Some ( file_handle) = file_handle else {
1587
+ return Ok ( ( ) ) ; // aborted
1588
+ } ;
1589
+
1590
+ let bytes = re_log_encoding:: encoder:: encode_as_bytes (
1591
+ re_log_encoding:: EncodingOptions :: COMPRESSED ,
1592
+ messages. iter ( ) ,
1593
+ ) ?;
1594
+ file_handle. write ( & bytes) . await . context ( "Failed to save" )
1595
+ }
0 commit comments