Skip to main content

Mountain/IPC/WindServiceHandlers/NativeHost/
PickFolder.rs

1#![allow(non_snake_case, unused_variables, dead_code, unused_imports)]
2
3//! Wire method: `nativeHost:pickFolderAndOpen`, `:pickFileAndOpen`,
4//! `:pickFileFolderAndOpen`, `:pickWorkspaceAndOpen`.
5//!
6//! Atom I1 (2026-04-21): before webview reload, mutate
7//! ApplicationState.Workspace and fire `$deltaWorkspaceFolders` to Cocoon so
8//! extensions see the folder arrive synchronously.
9
10use std::sync::Arc;
11
12use serde_json::Value;
13use tauri::{AppHandle, Manager};
14
15use crate::{
16	ApplicationState::{
17		DTO::WorkspaceFolderStateDTO::WorkspaceFolderStateDTO,
18		State::{
19			ApplicationState::ApplicationState,
20			WorkspaceState::WorkspaceDelta::UpdateWorkspaceFoldersAndBroadcast,
21		},
22	},
23	dev_log,
24};
25
26pub async fn NativePickFolder(ApplicationHandle:AppHandle, _Arguments:Vec<Value>) -> Result<Value, String> {
27	use std::path::PathBuf;
28
29	use tauri_plugin_dialog::DialogExt;
30
31	dev_log!("folder", "pickFolderAndOpen requested");
32
33	let Handle = ApplicationHandle.clone();
34
35	tokio::task::spawn_blocking(move || {
36		let FolderPath = Handle.dialog().file().blocking_pick_folder();
37
38		if let Some(Path) = FolderPath {
39			let PathStr = Path.to_string();
40			dev_log!("folder", "picked: {}", PathStr);
41
42			if let Some(State) = Handle.try_state::<Arc<ApplicationState>>() {
43				let PathBuf = PathBuf::from(&PathStr);
44				let Canonical = PathBuf.canonicalize().unwrap_or(PathBuf.clone());
45				if let Ok(Uri) = url::Url::from_directory_path(&Canonical) {
46					let Name = Canonical
47						.file_name()
48						.and_then(|N| N.to_str())
49						.map(str::to_string)
50						.unwrap_or_else(|| Canonical.display().to_string());
51					match WorkspaceFolderStateDTO::New(Uri, Name, 0) {
52						Ok(Dto) => {
53							dev_log!("folder", "pre-nav workspace-delta: broadcasting 1 folder to Cocoon");
54							UpdateWorkspaceFoldersAndBroadcast(&Handle, &State.Workspace, vec![Dto]);
55						},
56						Err(Error) => {
57							dev_log!(
58								"folder",
59								"warn: [pickFolderAndOpen] WorkspaceFolderStateDTO::New failed: {}",
60								Error
61							);
62						},
63					}
64				} else {
65					dev_log!(
66						"folder",
67						"warn: [pickFolderAndOpen] path → file URI conversion failed for {}",
68						PathStr
69					);
70				}
71			} else {
72				dev_log!(
73					"folder",
74					"warn: [pickFolderAndOpen] ApplicationState not managed by Tauri - delta skipped"
75				);
76			}
77
78			if let Some(Window) = Handle.get_webview_window("main") {
79				if let Ok(CurrentUrl) = Window.url() {
80					let Origin = CurrentUrl.origin().unicode_serialization();
81					let EncodedPath = url::form_urlencoded::Serializer::new(String::new())
82						.append_pair("folder", &PathStr)
83						.finish();
84					let NewUrl = format!("{}/?{}", Origin, EncodedPath);
85					dev_log!("folder", "navigating: {}", NewUrl);
86					let _ = Window.navigate(NewUrl.parse().unwrap());
87					dev_log!("folder", "post-nav Window.navigate() returned; webview reloading");
88				}
89			}
90		} else {
91			dev_log!("folder", "pickFolderAndOpen cancelled by user");
92		}
93	});
94
95	Ok(Value::Null)
96}