Mountain/Binary/IPC/
WorkspaceFolderCommand.rs1use std::{path::PathBuf, sync::Arc};
29
30use serde::{Deserialize, Serialize};
31use serde_json::Value;
32use tauri::{AppHandle, State};
33use url::Url;
34
35use crate::{
36 ApplicationState::{
37 DTO::WorkspaceFolderStateDTO::WorkspaceFolderStateDTO,
38 State::{
39 ApplicationState::ApplicationState,
40 WorkspaceState::WorkspaceDelta::UpdateWorkspaceFoldersAndBroadcast,
41 },
42 },
43 dev_log,
44};
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
48#[serde(rename_all = "camelCase")]
49pub struct WorkspaceFolderPayload {
50 pub Uri:String,
51
52 pub Name:String,
53
54 pub Index:usize,
55}
56
57impl From<&WorkspaceFolderStateDTO> for WorkspaceFolderPayload {
58 fn from(Dto:&WorkspaceFolderStateDTO) -> Self {
59 Self { Uri:Dto.URI.to_string(), Name:Dto.Name.clone(), Index:Dto.Index }
60 }
61}
62
63#[tauri::command]
69pub async fn MountainWorkspaceOpenFolder(
70 app_handle:AppHandle,
71
72 state:State<'_, Arc<ApplicationState>>,
73
74 paths:Vec<String>,
75) -> Result<Vec<WorkspaceFolderPayload>, String> {
76 if paths.is_empty() {
77 return Err("No paths provided".to_string());
78 }
79
80 let mut Folders:Vec<WorkspaceFolderStateDTO> = Vec::with_capacity(paths.len());
81
82 for (Index, Raw) in paths.iter().enumerate() {
83 let Uri = if Raw.starts_with("file:") {
84 Url::parse(Raw).map_err(|Error| format!("Invalid file URL {}: {}", Raw, Error))?
85 } else {
86 let Path = PathBuf::from(Raw);
87
88 if !Path.is_dir() {
89 return Err(format!("Not a directory: {}", Path.display()));
90 }
91
92 let Canonical = Path.canonicalize().unwrap_or(Path.clone());
93
94 Url::from_directory_path(&Canonical)
95 .map_err(|()| format!("Failed to build directory URL for {}", Canonical.display()))?
96 };
97
98 let Name = PathBuf::from(Raw)
99 .file_name()
100 .and_then(|N| N.to_str())
101 .map(str::to_string)
102 .unwrap_or_else(|| Raw.clone());
103
104 Folders.push(WorkspaceFolderStateDTO::New(Uri, Name, Index)?);
105 }
106
107 UpdateWorkspaceFoldersAndBroadcast(&app_handle, &state.Workspace, Folders.clone());
108
109 dev_log!(
110 "lifecycle",
111 "[WorkspaceFolderCommand] Opened {} folder(s); first URI={}",
112 Folders.len(),
113 Folders.first().map(|F| F.URI.as_str()).unwrap_or("")
114 );
115
116 Ok(Folders.iter().map(WorkspaceFolderPayload::from).collect())
117}
118
119#[tauri::command]
121pub async fn MountainWorkspaceListFolders(
122 state:State<'_, Arc<ApplicationState>>,
123) -> Result<Vec<WorkspaceFolderPayload>, String> {
124 Ok(state
125 .Workspace
126 .GetWorkspaceFolders()
127 .iter()
128 .map(WorkspaceFolderPayload::from)
129 .collect())
130}
131
132#[tauri::command]
137pub async fn MountainWorkspaceCloseAllFolders(
138 app_handle:AppHandle,
139
140 state:State<'_, Arc<ApplicationState>>,
141) -> Result<Value, String> {
142 UpdateWorkspaceFoldersAndBroadcast(&app_handle, &state.Workspace, Vec::new());
143
144 dev_log!("lifecycle", "[WorkspaceFolderCommand] All folders closed");
145
146 Ok(Value::Null)
147}