@@ -23,7 +23,7 @@ use iced::{
2323} ;
2424use serde:: { Deserialize , Serialize } ;
2525use simdock_core:: {
26- DoctorReport , InstallRequest , Platform , TaskEvent ,
26+ DoctorReport , InstallRequest , Platform , SimulatorDevice , TaskEvent ,
2727 provider:: { PlatformProvider , android:: AndroidProvider , ios:: IosProvider } ,
2828 service:: SimdockService ,
2929} ;
@@ -179,13 +179,15 @@ struct CleanupDialog {
179179#[ derive( Debug , Clone ) ]
180180struct CleanupItemView {
181181 kind : CleanupItemKind ,
182+ label : String ,
182183 checked : bool ,
183184}
184185
185- #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
186+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
186187pub ( crate ) enum CleanupItemKind {
187188 DownloadCache ,
188189 LogsAndSnapshot ,
190+ IosSimulatorDevice { udid : String } ,
189191 ManagedJavaRuntime ,
190192 AndroidVirtualDevices ,
191193 AndroidSdk ,
@@ -207,6 +209,7 @@ enum Message {
207209 OpenSimulatorRequested ( Platform ) ,
208210 OpenSimulatorFinished ( Platform , Result < ( ) , String > ) ,
209211 ManageInstalledContentRequested ( Platform ) ,
212+ CleanupDialogPrepared ( Result < CleanupDialog , String > ) ,
210213 CleanupItemToggled ( CleanupItemKind , bool ) ,
211214 CleanupCancelled ,
212215 CleanupConfirmed ,
@@ -333,32 +336,17 @@ impl InstallTasks {
333336}
334337
335338impl CleanupDialog {
336- fn new ( platform : Platform ) -> Self {
339+ fn new ( platform : Platform , language : AppLanguage ) -> Self {
337340 let mut items = vec ! [
338- CleanupItemView {
339- kind: CleanupItemKind :: DownloadCache ,
340- checked: true ,
341- } ,
342- CleanupItemView {
343- kind: CleanupItemKind :: LogsAndSnapshot ,
344- checked: true ,
345- } ,
341+ cleanup_item_view( CleanupItemKind :: DownloadCache , language, true ) ,
342+ cleanup_item_view( CleanupItemKind :: LogsAndSnapshot , language, true ) ,
346343 ] ;
347344
348345 if platform == Platform :: Android {
349346 items. extend ( [
350- CleanupItemView {
351- kind : CleanupItemKind :: ManagedJavaRuntime ,
352- checked : false ,
353- } ,
354- CleanupItemView {
355- kind : CleanupItemKind :: AndroidVirtualDevices ,
356- checked : false ,
357- } ,
358- CleanupItemView {
359- kind : CleanupItemKind :: AndroidSdk ,
360- checked : false ,
361- } ,
347+ cleanup_item_view ( CleanupItemKind :: ManagedJavaRuntime , language, false ) ,
348+ cleanup_item_view ( CleanupItemKind :: AndroidVirtualDevices , language, false ) ,
349+ cleanup_item_view ( CleanupItemKind :: AndroidSdk , language, false ) ,
362350 ] ) ;
363351 }
364352
@@ -370,11 +358,22 @@ impl CleanupDialog {
370358 }
371359 }
372360
361+ fn add_ios_simulator_devices ( & mut self , devices : Vec < SimulatorDevice > ) {
362+ self . items . extend ( devices. into_iter ( ) . map ( |device| {
363+ let label = device. display_label ( ) ;
364+ CleanupItemView {
365+ kind : CleanupItemKind :: IosSimulatorDevice { udid : device. id } ,
366+ label,
367+ checked : false ,
368+ }
369+ } ) ) ;
370+ }
371+
373372 fn selected_items ( & self ) -> Vec < CleanupItemKind > {
374373 self . items
375374 . iter ( )
376375 . filter ( |item| item. checked )
377- . map ( |item| item. kind )
376+ . map ( |item| item. kind . clone ( ) )
378377 . collect ( )
379378 }
380379
@@ -383,6 +382,18 @@ impl CleanupDialog {
383382 }
384383}
385384
385+ fn cleanup_item_view (
386+ kind : CleanupItemKind ,
387+ language : AppLanguage ,
388+ checked : bool ,
389+ ) -> CleanupItemView {
390+ CleanupItemView {
391+ label : i18n:: cleanup_item_label ( & kind, language) . to_string ( ) ,
392+ kind,
393+ checked,
394+ }
395+ }
396+
386397impl InstallTaskView {
387398 fn idle ( platform : Platform ) -> Self {
388399 Self {
@@ -776,7 +787,22 @@ fn update(app: &mut DoctorApp, message: Message) -> Task<Message> {
776787 }
777788 Message :: ManageInstalledContentRequested ( platform) => {
778789 if !app. install_task ( platform) . is_busy ( ) {
779- app. cleanup_dialog = Some ( CleanupDialog :: new ( platform) ) ;
790+ app. cleanup_dialog = None ;
791+ let language = app. language ;
792+ return Task :: perform ( prepare_cleanup_dialog ( platform, language) , |result| {
793+ Message :: CleanupDialogPrepared ( result)
794+ } ) ;
795+ }
796+ Task :: none ( )
797+ }
798+ Message :: CleanupDialogPrepared ( result) => {
799+ match result {
800+ Ok ( dialog) => app. cleanup_dialog = Some ( dialog) ,
801+ Err ( error) => {
802+ let mut dialog = CleanupDialog :: new ( app. active_tab , app. language ) ;
803+ dialog. error = Some ( i18n:: cleanup_failed_message ( & error, app. language ) ) ;
804+ app. cleanup_dialog = Some ( dialog) ;
805+ }
780806 }
781807 Task :: none ( )
782808 }
@@ -1202,17 +1228,32 @@ fn cleanup_dialog_overlay<'a>(
12021228) -> Element < ' a , Message > {
12031229 let mut checklist = column ! [ ] . spacing ( 12 ) ;
12041230 for item in & dialog. items {
1205- let kind = item. kind ;
1206- let mut row = checkbox ( i18n :: cleanup_item_label ( kind , language ) , item. checked )
1231+ let kind = item. kind . clone ( ) ;
1232+ let mut row = checkbox ( item . label . clone ( ) , item. checked )
12071233 . text_size ( 14 )
12081234 . size ( 18 ) ;
12091235
12101236 if !dialog. running {
1211- row = row. on_toggle ( move |checked| Message :: CleanupItemToggled ( kind, checked) ) ;
1237+ row = row. on_toggle ( move |checked| Message :: CleanupItemToggled ( kind. clone ( ) , checked) ) ;
12121238 }
12131239
12141240 checklist = checklist. push ( row) ;
12151241 }
1242+ let checklist_height = if dialog. items . len ( ) > 8 {
1243+ Length :: Fixed ( 260.0 )
1244+ } else {
1245+ Length :: Shrink
1246+ } ;
1247+ let checklist = container (
1248+ scrollable ( checklist. width ( Length :: Fill ) )
1249+ . height ( checklist_height)
1250+ . direction ( Direction :: Vertical (
1251+ Scrollbar :: new ( ) . width ( 18 ) . scroller_width ( 8 ) . margin ( 0 ) ,
1252+ ) )
1253+ . style ( main_scrollbar_style) ,
1254+ )
1255+ . width ( Length :: Fill )
1256+ . height ( checklist_height) ;
12161257
12171258 let mut confirm_button = button ( text ( i18n:: cleanup_confirm_button_label ( language) ) . size ( 14 ) )
12181259 . padding ( [ 10 , 16 ] )
@@ -1262,7 +1303,7 @@ fn cleanup_dialog_overlay<'a>(
12621303 container (
12631304 container ( content)
12641305 . padding ( 24 )
1265- . width ( 520 )
1306+ . width ( 640 )
12661307 . style ( cleanup_dialog_card_style) ,
12671308 )
12681309 . width ( Length :: Fill )
@@ -2137,6 +2178,23 @@ fn load_doctor_task() -> Task<Message> {
21372178 Task :: perform ( load_doctor_snapshot ( ) , Message :: DoctorLoaded )
21382179}
21392180
2181+ async fn prepare_cleanup_dialog (
2182+ platform : Platform ,
2183+ language : AppLanguage ,
2184+ ) -> Result < CleanupDialog , String > {
2185+ let mut dialog = CleanupDialog :: new ( platform, language) ;
2186+
2187+ if platform == Platform :: Ios {
2188+ let devices = IosProvider :: new ( )
2189+ . list_simulator_devices ( )
2190+ . await
2191+ . map_err ( |error| error. to_string ( ) ) ?;
2192+ dialog. add_ios_simulator_devices ( devices) ;
2193+ }
2194+
2195+ Ok ( dialog)
2196+ }
2197+
21402198async fn cleanup_selected_items (
21412199 platform : Platform ,
21422200 items : Vec < CleanupItemKind > ,
@@ -2145,12 +2203,23 @@ async fn cleanup_selected_items(
21452203 let mut removed_paths = 0 ;
21462204
21472205 for item in items {
2148- for path in cleanup_paths_for_item ( platform, item, & paths) {
2149- if remove_known_path ( & path)
2150- . map_err ( |error| format ! ( "failed to remove {}: {error}" , path. to_string_lossy( ) ) ) ?
2151- {
2206+ match & item {
2207+ CleanupItemKind :: IosSimulatorDevice { udid } => {
2208+ IosProvider :: new ( )
2209+ . delete_simulator_device ( udid)
2210+ . await
2211+ . map_err ( |error| error. to_string ( ) ) ?;
21522212 removed_paths += 1 ;
21532213 }
2214+ _ => {
2215+ for path in cleanup_paths_for_item ( platform, & item, & paths) {
2216+ if remove_known_path ( & path) . map_err ( |error| {
2217+ format ! ( "failed to remove {}: {error}" , path. to_string_lossy( ) )
2218+ } ) ? {
2219+ removed_paths += 1 ;
2220+ }
2221+ }
2222+ }
21542223 }
21552224 }
21562225
@@ -2159,7 +2228,7 @@ async fn cleanup_selected_items(
21592228
21602229fn cleanup_paths_for_item (
21612230 platform : Platform ,
2162- item : CleanupItemKind ,
2231+ item : & CleanupItemKind ,
21632232 paths : & AppPaths ,
21642233) -> Vec < PathBuf > {
21652234 match item {
@@ -2174,6 +2243,7 @@ fn cleanup_paths_for_item(
21742243 paths. logs_dir. clone( ) ,
21752244 paths. app_support_dir. join( OPERATION_SNAPSHOT_FILE ) ,
21762245 ] ,
2246+ CleanupItemKind :: IosSimulatorDevice { .. } => Vec :: new ( ) ,
21772247 CleanupItemKind :: ManagedJavaRuntime => vec ! [ paths. app_support_dir. join( "java-runtime" ) ] ,
21782248 CleanupItemKind :: AndroidVirtualDevices => vec ! [ paths. android_avd_root. clone( ) ] ,
21792249 CleanupItemKind :: AndroidSdk => vec ! [ paths. android_sdk_root. clone( ) ] ,
0 commit comments