Mountain/FileSystem/
FileExplorerViewProvider.rs1
2use std::sync::Arc;
11
12use CommonLibrary::{
13 Effect::ApplicationRunTime::ApplicationRunTime as _,
14 Environment::Environment::Environment,
15 Error::CommonError::CommonError,
16 FileSystem::{DTO::FileTypeDTO::FileTypeDTO, ReadDirectory::ReadDirectory},
17 TreeView::TreeViewProvider::TreeViewProvider,
18};
19use async_trait::async_trait;
20use serde_json::{Value, json};
21use tauri::{AppHandle, Manager};
22use url::Url;
23
24use crate::{RunTime::ApplicationRunTime::ApplicationRunTime as Runtime, dev_log};
25
26#[derive(Clone)]
27pub struct Struct {
28 AppicationHandle:AppHandle,
29}
30
31impl Environment for Struct {}
32
33impl Struct {
34 pub fn New(AppicationHandle:AppHandle) -> Self { Self { AppicationHandle } }
35
36 fn CreateTreeItemDTO(&self, Name:&str, URI:&Url, FileType:FileTypeDTO) -> Value {
37 json!({
38 "handle": URI.to_string(),
39 "label": { "label": Name },
40 "collapsibleState": if FileType == FileTypeDTO::Directory { 1 } else { 0 },
42 "resourceUri": json!({ "external": URI.to_string() }),
43 "command": if FileType == FileTypeDTO::File {
44 Some(json!({
45 "id": "vscode.open",
46 "title": "Open File",
47 "arguments": [json!({ "external": URI.to_string() })]
48 }))
49 } else {
50 None
51 }
52 })
53 }
54}
55
56#[async_trait]
57impl TreeViewProvider for Struct {
58 async fn RegisterTreeDataProvider(&self, _ViewIdentifier:String, _Options:Value) -> Result<(), CommonError> {
61 Ok(())
62 }
63
64 async fn UnregisterTreeDataProvider(&self, _ViewIdentifier:String) -> Result<(), CommonError> { Ok(()) }
65
66 async fn RevealTreeItem(
67 &self,
68
69 _ViewIdentifier:String,
70
71 _ItemHandle:String,
72
73 _Options:Value,
74 ) -> Result<(), CommonError> {
75 Ok(())
76 }
77
78 async fn RefreshTreeView(&self, _ViewIdentifier:String, _ItemsToRefresh:Option<Value>) -> Result<(), CommonError> {
79 Ok(())
80 }
81
82 async fn SetTreeViewMessage(&self, _ViewIdentifier:String, _Message:Option<String>) -> Result<(), CommonError> {
83 Ok(())
84 }
85
86 async fn SetTreeViewTitle(
87 &self,
88
89 _ViewIdentifier:String,
90
91 _Title:Option<String>,
92
93 _Description:Option<String>,
94 ) -> Result<(), CommonError> {
95 Ok(())
96 }
97
98 async fn SetTreeViewBadge(&self, _ViewIdentifier:String, _BadgeValue:Option<Value>) -> Result<(), CommonError> {
99 Ok(())
100 }
101
102 async fn OnTreeNodeExpanded(
103 &self,
104
105 _ViewIdentifier:String,
106
107 _ElementHandle:String,
108
109 _IsExpanded:bool,
110 ) -> Result<(), CommonError> {
111 dev_log!("vfs", "[FileExplorer] OnTreeNodeExpanded - native provider no-op");
112
113 Ok(())
114 }
115
116 async fn OnTreeSelectionChanged(
117 &self,
118
119 _ViewIdentifier:String,
120
121 _SelectedHandles:Vec<String>,
122 ) -> Result<(), CommonError> {
123 dev_log!("vfs", "[FileExplorer] OnTreeSelectionChanged - native provider no-op");
124
125 Ok(())
126 }
127
128 async fn PersistTreeViewState(&self, _ViewIdentifier:String) -> Result<Value, CommonError> {
129 Ok(json!({ "supported": false }))
130 }
131
132 async fn RestoreTreeViewState(&self, _ViewIdentifier:String, _StateValue:Value) -> Result<(), CommonError> {
133 Ok(())
134 }
135
136 async fn GetChildren(
139 &self,
140
141 _ViewIdentifier:String,
142
143 ElementHandle:Option<String>,
144 ) -> Result<Vec<Value>, CommonError> {
145 let RunTime = self.AppicationHandle.state::<Arc<Runtime>>().inner().clone();
146
147 let AppState = RunTime.Environment.ApplicationState.clone();
148
149 let PathToRead = if let Some(Handle) = ElementHandle {
150 Url::parse(&Handle)
151 .map_err(|_| {
152 CommonError::InvalidArgument {
153 ArgumentName:"ElementHandle".into(),
154 Reason:"Handle is not a valid URI".into(),
155 }
156 })?
157 .to_file_path()
158 .map_err(|_| {
159 CommonError::InvalidArgument {
160 ArgumentName:"ElementHandle".into(),
161 Reason:"Handle URI is not a file path".into(),
162 }
163 })?
164 } else {
165 let Folders = AppState.Workspace.WorkspaceFolders.lock().unwrap();
166
167 let RootItems:Vec<Value> = Folders
168 .iter()
169 .map(|Folder| self.CreateTreeItemDTO(&Folder.Name, &Folder.URI, FileTypeDTO::Directory))
170 .collect();
171
172 return Ok(RootItems);
173 };
174
175 dev_log!("vfs", "[FileExplorer] GetChildren {}", PathToRead.display());
176
177 let Entries:Vec<(String, FileTypeDTO)> = RunTime.Run(ReadDirectory(PathToRead.clone())).await?;
178
179 Ok(Entries
180 .into_iter()
181 .map(|(Name, FileType)| {
182 let FullPath = PathToRead.join(&Name);
183 let URI = Url::from_file_path(FullPath).unwrap();
184 self.CreateTreeItemDTO(&Name, &URI, FileType)
185 })
186 .collect())
187 }
188
189 async fn GetTreeItem(&self, _ViewIdentifier:String, ElementHandle:String) -> Result<Value, CommonError> {
190 let URI = Url::parse(&ElementHandle).map_err(|Error| {
191 CommonError::InvalidArgument { ArgumentName:"ElementHandle".into(), Reason:Error.to_string() }
192 })?;
193
194 let Name = URI.path_segments().and_then(|S| S.last()).unwrap_or("").to_string();
195
196 let IsDirectory = URI.as_str().ends_with('/') || URI.to_file_path().map_or(false, |P| P.is_dir());
197
198 let FileType = if IsDirectory { FileTypeDTO::Directory } else { FileTypeDTO::File };
199
200 Ok(self.CreateTreeItemDTO(&Name, &URI, FileType))
201 }
202}