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 pub Name:String,
52 pub Index:usize,
53}
54
55impl From<&WorkspaceFolderStateDTO> for WorkspaceFolderPayload {
56 fn from(Dto:&WorkspaceFolderStateDTO) -> Self {
57 Self { Uri:Dto.URI.to_string(), Name:Dto.Name.clone(), Index:Dto.Index }
58 }
59}
60
61#[tauri::command]
67pub async fn MountainWorkspaceOpenFolder(
68 app_handle:AppHandle,
69 state:State<'_, Arc<ApplicationState>>,
70 paths:Vec<String>,
71) -> Result<Vec<WorkspaceFolderPayload>, String> {
72 if paths.is_empty() {
73 return Err("No paths provided".to_string());
74 }
75
76 let mut Folders:Vec<WorkspaceFolderStateDTO> = Vec::with_capacity(paths.len());
77 for (Index, Raw) in paths.iter().enumerate() {
78 let Uri = if Raw.starts_with("file:") {
79 Url::parse(Raw).map_err(|Error| format!("Invalid file URL {}: {}", Raw, Error))?
80 } else {
81 let Path = PathBuf::from(Raw);
82 if !Path.is_dir() {
83 return Err(format!("Not a directory: {}", Path.display()));
84 }
85 let Canonical = Path.canonicalize().unwrap_or(Path.clone());
86 Url::from_directory_path(&Canonical)
87 .map_err(|()| format!("Failed to build directory URL for {}", Canonical.display()))?
88 };
89 let Name = PathBuf::from(Raw)
90 .file_name()
91 .and_then(|N| N.to_str())
92 .map(str::to_string)
93 .unwrap_or_else(|| Raw.clone());
94 Folders.push(WorkspaceFolderStateDTO::New(Uri, Name, Index)?);
95 }
96
97 UpdateWorkspaceFoldersAndBroadcast(&app_handle, &state.Workspace, Folders.clone());
98 dev_log!(
99 "lifecycle",
100 "[WorkspaceFolderCommand] Opened {} folder(s); first URI={}",
101 Folders.len(),
102 Folders.first().map(|F| F.URI.as_str()).unwrap_or("")
103 );
104
105 Ok(Folders.iter().map(WorkspaceFolderPayload::from).collect())
106}
107
108#[tauri::command]
110pub async fn MountainWorkspaceListFolders(
111 state:State<'_, Arc<ApplicationState>>,
112) -> Result<Vec<WorkspaceFolderPayload>, String> {
113 Ok(state
114 .Workspace
115 .GetWorkspaceFolders()
116 .iter()
117 .map(WorkspaceFolderPayload::from)
118 .collect())
119}
120
121#[tauri::command]
126pub async fn MountainWorkspaceCloseAllFolders(
127 app_handle:AppHandle,
128 state:State<'_, Arc<ApplicationState>>,
129) -> Result<Value, String> {
130 UpdateWorkspaceFoldersAndBroadcast(&app_handle, &state.Workspace, Vec::new());
131 dev_log!("lifecycle", "[WorkspaceFolderCommand] All folders closed");
132 Ok(Value::Null)
133}