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