Repository: GraphiteEditor/Graphite
File: desktop/src/app.rs (Rust)

Code before:
			cef_window_size_sender: window_size_sender,
			wgpu_context,
			app_event_receiver,
			app_event_scheduler,
			desktop_wrapper: DesktopWrapper::new(),
			last_ui_update: Instant::now(),
			avg_frame_time: 0.,
			start_render_sender,
			web_communication_initialized: false,
			web_communication_startup_buffer: Vec::new(),
			persistent_data,
			native_window: Default::default(),
			cli_files,
		}
	}

	fn handle_desktop_frontend_message(&mut self, message: DesktopFrontendMessage) {
		match message {
			DesktopFrontendMessage::ToWeb(messages) => {
				let Some(bytes) = serialize_frontend_messages(messages) else {
					tracing::error!("Failed to serialize frontend messages");
					return;
				};
				self.send_or_queue_web_message(bytes);
			}
			DesktopFrontendMessage::Init => {
				tracing::info!("Initializing application...");
				if let Some(paths) = self.cli_files.clone() {
					for path in paths {
						tracing::info!("Opening file from command line: {}", path.display());
						if let Ok(content) = std::fs::read(&path) {
							let message = DesktopWrapperMessage::OpenFile { path, content };
							self.dispatch_desktop_wrapper_message(message);
						} else {
							tracing::error!("Failed to read file: {}", path.display());
						}
					}
				}
			}
			DesktopFrontendMessage::OpenFileDialog { title, filters, context } => {
				let app_event_scheduler = self.app_event_scheduler.clone();
				let _ = thread::spawn(move || {
					let mut dialog = AsyncFileDialog::new().set_title(title);
					for filter in filters {
						dialog = dialog.add_filter(filter.name, &filter.extensions);
					}

					let show_dialog = async move { dialog.pick_file().await.map(|f| f.path().to_path_buf()) };

					if let Some(path) = futures::executor::block_on(show_dialog)
						&& let Ok(content) = std::fs::read(&path)

Review comment (suggestion):
We need to ensure that all auto saved documents are loaded at this point. You assume this message is handled after Portfolio::Init, this works because of the current ordering of message dispatch in desktop wrapper, but this assumption should not be made in my opinion. Maybe a special `FrontendMessage::OpenDocumetnsSuppliedAtStartup` (I'm tired, could not think of a better name) would be a better solution. Could also be used for opening documents from the URL in web.

Code after:
			cef_schedule: Some(Instant::now()),
			graphics_state: None,
			cef_window_size_sender: window_size_sender,
			wgpu_context,
			app_event_receiver,
			app_event_scheduler,
			desktop_wrapper: DesktopWrapper::new(),
			last_ui_update: Instant::now(),
			avg_frame_time: 0.,
			start_render_sender,
			web_communication_initialized: false,
			web_communication_startup_buffer: Vec::new(),
			persistent_data,
			native_window: Default::default(),
			launch_documents,
		}
	}

	fn handle_desktop_frontend_message(&mut self, message: DesktopFrontendMessage, responses: &mut Vec<DesktopWrapperMessage>) {
		match message {
			DesktopFrontendMessage::ToWeb(messages) => {
				let Some(bytes) = serialize_frontend_messages(messages) else {
					tracing::error!("Failed to serialize frontend messages");
					return;
				};
				self.send_or_queue_web_message(bytes);
			}
			DesktopFrontendMessage::OpenFileDialog { title, filters, context } => {
				let app_event_scheduler = self.app_event_scheduler.clone();
				let _ = thread::spawn(move || {
					let mut dialog = AsyncFileDialog::new().set_title(title);
					for filter in filters {
						dialog = dialog.add_filter(filter.name, &filter.extensions);
					}

					let show_dialog = async move { dialog.pick_file().await.map(|f| f.path().to_path_buf()) };

					if let Some(path) = futures::executor::block_on(show_dialog)
						&& let Ok(content) = fs::read(&path)
					{
						let message = DesktopWrapperMessage::OpenFileDialogResult { path, content, context };
						app_event_scheduler.schedule(AppEvent::DesktopWrapperMessage(message));
					}
				});
			}
			DesktopFrontendMessage::SaveFileDialog {
				title,
				default_filename,
				default_folder,
				filters,
				context,