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