@@ -58,7 +58,7 @@ use wayland_client::{protocol::wl_output::WlOutput, Proxy};
58
58
59
59
use crate :: {
60
60
clipboard:: { ClipboardCopy , ClipboardKind , ClipboardPaste } ,
61
- config:: { AppTheme , Config , DesktopConfig , Favorite , IconSizes , TabConfig } ,
61
+ config:: { AppTheme , Config , DesktopConfig , Favorite , IconSizes , SessionConfig , TabConfig } ,
62
62
fl, home_dir,
63
63
key_bind:: key_binds,
64
64
localize:: LANGUAGE_SORTER ,
@@ -69,7 +69,7 @@ use crate::{
69
69
tab:: { self , HeadingOptions , ItemMetadata , Location , Tab , HOVER_DURATION } ,
70
70
} ;
71
71
72
- #[ derive( Clone , Debug ) ]
72
+ #[ derive( Clone , Copy , Debug , PartialEq ) ]
73
73
pub enum Mode {
74
74
App ,
75
75
Desktop ,
@@ -303,9 +303,11 @@ pub enum Message {
303
303
Rename ( Option < Entity > ) ,
304
304
ReplaceResult ( ReplaceResult ) ,
305
305
RestoreFromTrash ( Option < Entity > ) ,
306
+ SaveSession ,
306
307
SearchActivate ,
307
308
SearchClear ,
308
309
SearchInput ( String ) ,
310
+ SessionConfig ( SessionConfig ) ,
309
311
SystemThemeModeChange ( cosmic_theme:: ThemeMode ) ,
310
312
TabActivate ( Entity ) ,
311
313
TabNext ,
@@ -1179,27 +1181,43 @@ impl App {
1179
1181
1180
1182
fn settings ( & self ) -> Element < Message > {
1181
1183
// TODO: Should dialog be updated here too?
1182
- widget:: settings:: view_column ( vec ! [ widget:: settings:: section( )
1183
- . title( fl!( "appearance" ) )
1184
- . add( {
1185
- let app_theme_selected = match self . config. app_theme {
1186
- AppTheme :: Dark => 1 ,
1187
- AppTheme :: Light => 2 ,
1188
- AppTheme :: System => 0 ,
1189
- } ;
1190
- widget:: settings:: item:: builder( fl!( "theme" ) ) . control( widget:: dropdown(
1191
- & self . app_themes,
1192
- Some ( app_theme_selected) ,
1193
- move |index| {
1194
- Message :: AppTheme ( match index {
1195
- 1 => AppTheme :: Dark ,
1196
- 2 => AppTheme :: Light ,
1197
- _ => AppTheme :: System ,
1198
- } )
1199
- } ,
1200
- ) )
1201
- } )
1202
- . into( ) ] )
1184
+ widget:: settings:: view_column ( vec ! [
1185
+ widget:: settings:: section( )
1186
+ . title( fl!( "appearance" ) )
1187
+ . add( {
1188
+ let app_theme_selected = match self . config. app_theme {
1189
+ AppTheme :: Dark => 1 ,
1190
+ AppTheme :: Light => 2 ,
1191
+ AppTheme :: System => 0 ,
1192
+ } ;
1193
+ widget:: settings:: item:: builder( fl!( "theme" ) ) . control( widget:: dropdown(
1194
+ & self . app_themes,
1195
+ Some ( app_theme_selected) ,
1196
+ move |index| {
1197
+ Message :: AppTheme ( match index {
1198
+ 1 => AppTheme :: Dark ,
1199
+ 2 => AppTheme :: Light ,
1200
+ _ => AppTheme :: System ,
1201
+ } )
1202
+ } ,
1203
+ ) )
1204
+ } )
1205
+ . into( ) ,
1206
+ widget:: settings:: section( )
1207
+ . title( fl!( "session" ) )
1208
+ . add(
1209
+ widget:: settings:: item:: builder( fl!( "restore-session" ) ) . toggler(
1210
+ self . config. session. restore,
1211
+ move |restore| {
1212
+ Message :: SessionConfig ( SessionConfig {
1213
+ restore,
1214
+ ..Default :: default ( )
1215
+ } )
1216
+ } ,
1217
+ ) ,
1218
+ )
1219
+ . into( ) ,
1220
+ ] )
1203
1221
. into ( )
1204
1222
}
1205
1223
}
@@ -2355,6 +2373,35 @@ impl Application for App {
2355
2373
self . operation ( Operation :: Restore { paths } ) ;
2356
2374
}
2357
2375
}
2376
+ Message :: SaveSession => {
2377
+ if self . config . session . restore && self . mode == Mode :: App {
2378
+ let session = SessionConfig {
2379
+ tabs : Some (
2380
+ self . tab_model
2381
+ . iter ( )
2382
+ . filter_map ( |entity| {
2383
+ match self
2384
+ . tab_model
2385
+ . data :: < Tab > ( entity)
2386
+ . map ( |tab| & tab. location )
2387
+ {
2388
+ // Location's serialization implementation skips variants
2389
+ // such as mounts
2390
+ // However, we'd still clone all Locations here only for
2391
+ // some to be skipped, so it's best to avoid the clone
2392
+ loc @ Location :: Path ( _)
2393
+ | Location :: Recents
2394
+ | Location :: Trash => Some ( loc. clone ( ) ) ,
2395
+ _ => None ,
2396
+ }
2397
+ } )
2398
+ . collect ( ) ,
2399
+ ) ,
2400
+ ..self . config . session
2401
+ } ;
2402
+ config_set ! ( session, session) ;
2403
+ }
2404
+ }
2358
2405
Message :: SearchActivate => {
2359
2406
return if self . search_get ( ) . is_none ( ) {
2360
2407
self . search_set ( Some ( String :: new ( ) ) )
@@ -2368,6 +2415,9 @@ impl Application for App {
2368
2415
Message :: SearchInput ( input) => {
2369
2416
return self . search_set ( Some ( input) ) ;
2370
2417
}
2418
+ Message :: SessionConfig ( session) => {
2419
+ config_set ! ( session, session) ;
2420
+ }
2371
2421
Message :: SystemThemeModeChange ( _theme_mode) => {
2372
2422
return self . update_config ( ) ;
2373
2423
}
@@ -2435,9 +2485,12 @@ impl Application for App {
2435
2485
// Remove item
2436
2486
self . tab_model . remove ( entity) ;
2437
2487
2438
- // If that was the last tab, close window
2488
+ // If that was the last tab, close window and serialize empty session if necessary
2439
2489
if self . tab_model . iter ( ) . next ( ) . is_none ( ) {
2440
- return window:: close ( window:: Id :: MAIN ) ;
2490
+ return Command :: batch ( [
2491
+ self . update ( Message :: SaveSession ) ,
2492
+ window:: close ( window:: Id :: MAIN ) ,
2493
+ ] ) ;
2441
2494
}
2442
2495
2443
2496
return Command :: batch ( [ self . update_title ( ) , self . update_watcher ( ) ] ) ;
@@ -2698,6 +2751,7 @@ impl Application for App {
2698
2751
if let Some ( window_id) = self . window_id_opt . take ( ) {
2699
2752
return Command :: batch ( [
2700
2753
window:: close ( window_id) ,
2754
+ self . update ( Message :: SaveSession ) ,
2701
2755
Command :: perform ( async move { message:: app ( Message :: MaybeExit ) } , |x| x) ,
2702
2756
] ) ;
2703
2757
}
0 commit comments