@@ -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 ,
@@ -1163,27 +1165,43 @@ impl App {
1163
1165
1164
1166
fn settings ( & self ) -> Element < Message > {
1165
1167
// TODO: Should dialog be updated here too?
1166
- widget:: settings:: view_column ( vec ! [ widget:: settings:: section( )
1167
- . title( fl!( "appearance" ) )
1168
- . add( {
1169
- let app_theme_selected = match self . config. app_theme {
1170
- AppTheme :: Dark => 1 ,
1171
- AppTheme :: Light => 2 ,
1172
- AppTheme :: System => 0 ,
1173
- } ;
1174
- widget:: settings:: item:: builder( fl!( "theme" ) ) . control( widget:: dropdown(
1175
- & self . app_themes,
1176
- Some ( app_theme_selected) ,
1177
- move |index| {
1178
- Message :: AppTheme ( match index {
1179
- 1 => AppTheme :: Dark ,
1180
- 2 => AppTheme :: Light ,
1181
- _ => AppTheme :: System ,
1182
- } )
1183
- } ,
1184
- ) )
1185
- } )
1186
- . into( ) ] )
1168
+ widget:: settings:: view_column ( vec ! [
1169
+ widget:: settings:: section( )
1170
+ . title( fl!( "appearance" ) )
1171
+ . add( {
1172
+ let app_theme_selected = match self . config. app_theme {
1173
+ AppTheme :: Dark => 1 ,
1174
+ AppTheme :: Light => 2 ,
1175
+ AppTheme :: System => 0 ,
1176
+ } ;
1177
+ widget:: settings:: item:: builder( fl!( "theme" ) ) . control( widget:: dropdown(
1178
+ & self . app_themes,
1179
+ Some ( app_theme_selected) ,
1180
+ move |index| {
1181
+ Message :: AppTheme ( match index {
1182
+ 1 => AppTheme :: Dark ,
1183
+ 2 => AppTheme :: Light ,
1184
+ _ => AppTheme :: System ,
1185
+ } )
1186
+ } ,
1187
+ ) )
1188
+ } )
1189
+ . into( ) ,
1190
+ widget:: settings:: section( )
1191
+ . title( fl!( "session" ) )
1192
+ . add(
1193
+ widget:: settings:: item:: builder( fl!( "restore-session" ) ) . toggler(
1194
+ self . config. session. restore,
1195
+ move |restore| {
1196
+ Message :: SessionConfig ( SessionConfig {
1197
+ restore,
1198
+ ..Default :: default ( )
1199
+ } )
1200
+ } ,
1201
+ ) ,
1202
+ )
1203
+ . into( ) ,
1204
+ ] )
1187
1205
. into ( )
1188
1206
}
1189
1207
}
@@ -2339,6 +2357,35 @@ impl Application for App {
2339
2357
self . operation ( Operation :: Restore { paths } ) ;
2340
2358
}
2341
2359
}
2360
+ Message :: SaveSession => {
2361
+ if self . config . session . restore && self . mode == Mode :: App {
2362
+ let session = SessionConfig {
2363
+ tabs : Some (
2364
+ self . tab_model
2365
+ . iter ( )
2366
+ . filter_map ( |entity| {
2367
+ match self
2368
+ . tab_model
2369
+ . data :: < Tab > ( entity)
2370
+ . map ( |tab| & tab. location )
2371
+ {
2372
+ // Location's serialization implementation skips variants
2373
+ // such as mounts
2374
+ // However, we'd still clone all Locations here only for
2375
+ // some to be skipped, so it's best to avoid the clone
2376
+ loc @ Location :: Path ( _)
2377
+ | Location :: Recents
2378
+ | Location :: Trash => Some ( loc. clone ( ) ) ,
2379
+ _ => None ,
2380
+ }
2381
+ } )
2382
+ . collect ( ) ,
2383
+ ) ,
2384
+ ..self . config . session
2385
+ } ;
2386
+ config_set ! ( session, session) ;
2387
+ }
2388
+ }
2342
2389
Message :: SearchActivate => {
2343
2390
return if self . search_get ( ) . is_none ( ) {
2344
2391
self . search_set ( Some ( String :: new ( ) ) )
@@ -2352,6 +2399,9 @@ impl Application for App {
2352
2399
Message :: SearchInput ( input) => {
2353
2400
return self . search_set ( Some ( input) ) ;
2354
2401
}
2402
+ Message :: SessionConfig ( session) => {
2403
+ config_set ! ( session, session) ;
2404
+ }
2355
2405
Message :: SystemThemeModeChange ( _theme_mode) => {
2356
2406
return self . update_config ( ) ;
2357
2407
}
@@ -2419,9 +2469,12 @@ impl Application for App {
2419
2469
// Remove item
2420
2470
self . tab_model . remove ( entity) ;
2421
2471
2422
- // If that was the last tab, close window
2472
+ // If that was the last tab, close window and serialize empty session if necessary
2423
2473
if self . tab_model . iter ( ) . next ( ) . is_none ( ) {
2424
- return window:: close ( window:: Id :: MAIN ) ;
2474
+ return Command :: batch ( [
2475
+ self . update ( Message :: SaveSession ) ,
2476
+ window:: close ( window:: Id :: MAIN ) ,
2477
+ ] ) ;
2425
2478
}
2426
2479
2427
2480
return Command :: batch ( [ self . update_title ( ) , self . update_watcher ( ) ] ) ;
@@ -2681,6 +2734,7 @@ impl Application for App {
2681
2734
if let Some ( window_id) = self . window_id_opt . take ( ) {
2682
2735
return Command :: batch ( [
2683
2736
window:: close ( window_id) ,
2737
+ self . update ( Message :: SaveSession ) ,
2684
2738
Command :: perform ( async move { message:: app ( Message :: MaybeExit ) } , |x| x) ,
2685
2739
] ) ;
2686
2740
}
0 commit comments