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 _ViewIdentifier:String,
70 _ItemHandle:String,
71 _Options:Value,
72 ) -> Result<(), CommonError> {
73 Ok(())
74 }
75
76 async fn RefreshTreeView(&self, _ViewIdentifier:String, _ItemsToRefresh:Option<Value>) -> Result<(), CommonError> {
77 Ok(())
78 }
79
80 async fn SetTreeViewMessage(&self, _ViewIdentifier:String, _Message:Option<String>) -> Result<(), CommonError> {
81 Ok(())
82 }
83
84 async fn SetTreeViewTitle(
85 &self,
86 _ViewIdentifier:String,
87 _Title:Option<String>,
88 _Description:Option<String>,
89 ) -> Result<(), CommonError> {
90 Ok(())
91 }
92
93 async fn SetTreeViewBadge(&self, _ViewIdentifier:String, _BadgeValue:Option<Value>) -> Result<(), CommonError> {
94 Ok(())
95 }
96
97 async fn OnTreeNodeExpanded(
98 &self,
99 _ViewIdentifier:String,
100 _ElementHandle:String,
101 _IsExpanded:bool,
102 ) -> Result<(), CommonError> {
103 dev_log!("vfs", "[FileExplorer] OnTreeNodeExpanded - native provider no-op");
104 Ok(())
105 }
106
107 async fn OnTreeSelectionChanged(
108 &self,
109 _ViewIdentifier:String,
110 _SelectedHandles:Vec<String>,
111 ) -> Result<(), CommonError> {
112 dev_log!("vfs", "[FileExplorer] OnTreeSelectionChanged - native provider no-op");
113 Ok(())
114 }
115
116 async fn PersistTreeViewState(&self, _ViewIdentifier:String) -> Result<Value, CommonError> {
117 Ok(json!({ "supported": false }))
118 }
119
120 async fn RestoreTreeViewState(&self, _ViewIdentifier:String, _StateValue:Value) -> Result<(), CommonError> {
121 Ok(())
122 }
123
124 async fn GetChildren(
127 &self,
128 _ViewIdentifier:String,
129 ElementHandle:Option<String>,
130 ) -> Result<Vec<Value>, CommonError> {
131 let RunTime = self.AppicationHandle.state::<Arc<Runtime>>().inner().clone();
132 let AppState = RunTime.Environment.ApplicationState.clone();
133
134 let PathToRead = if let Some(Handle) = ElementHandle {
135 Url::parse(&Handle)
136 .map_err(|_| {
137 CommonError::InvalidArgument {
138 ArgumentName:"ElementHandle".into(),
139 Reason:"Handle is not a valid URI".into(),
140 }
141 })?
142 .to_file_path()
143 .map_err(|_| {
144 CommonError::InvalidArgument {
145 ArgumentName:"ElementHandle".into(),
146 Reason:"Handle URI is not a file path".into(),
147 }
148 })?
149 } else {
150 let Folders = AppState.Workspace.WorkspaceFolders.lock().unwrap();
151 let RootItems:Vec<Value> = Folders
152 .iter()
153 .map(|Folder| self.CreateTreeItemDTO(&Folder.Name, &Folder.URI, FileTypeDTO::Directory))
154 .collect();
155 return Ok(RootItems);
156 };
157
158 dev_log!("vfs", "[FileExplorer] GetChildren {}", PathToRead.display());
159
160 let Entries:Vec<(String, FileTypeDTO)> = RunTime.Run(ReadDirectory(PathToRead.clone())).await?;
161
162 Ok(Entries
163 .into_iter()
164 .map(|(Name, FileType)| {
165 let FullPath = PathToRead.join(&Name);
166 let URI = Url::from_file_path(FullPath).unwrap();
167 self.CreateTreeItemDTO(&Name, &URI, FileType)
168 })
169 .collect())
170 }
171
172 async fn GetTreeItem(&self, _ViewIdentifier:String, ElementHandle:String) -> Result<Value, CommonError> {
173 let URI = Url::parse(&ElementHandle).map_err(|Error| {
174 CommonError::InvalidArgument { ArgumentName:"ElementHandle".into(), Reason:Error.to_string() }
175 })?;
176
177 let Name = URI.path_segments().and_then(|S| S.last()).unwrap_or("").to_string();
178
179 let IsDirectory = URI.as_str().ends_with('/') || URI.to_file_path().map_or(false, |P| P.is_dir());
180
181 let FileType = if IsDirectory { FileTypeDTO::Directory } else { FileTypeDTO::File };
182
183 Ok(self.CreateTreeItemDTO(&Name, &URI, FileType))
184 }
185}