@@ -2,7 +2,7 @@ use crate::common::document::{DataSourceReference, Document};
22use crate :: common:: search:: { QueryResponse , QuerySource , SearchQuery } ;
33use crate :: common:: traits:: { SearchError , SearchSource } ;
44use crate :: local:: LOCAL_QUERY_SOURCE_TYPE ;
5- use applications:: { AppInfo , AppInfoContext } ;
5+ use applications:: { App , AppInfo , AppInfoContext } ;
66use async_trait:: async_trait;
77use base64:: encode;
88use fuzzy_prefix_search:: Trie ;
@@ -17,8 +17,7 @@ pub fn get_default_search_paths() -> Vec<String> {
1717 let paths = applications:: get_default_search_paths ( ) ;
1818 let mut ret = Vec :: with_capacity ( paths. len ( ) ) ;
1919 for search_path in paths {
20- let path = search_path. path ;
21- let path_string = path
20+ let path_string = search_path
2221 . into_os_string ( )
2322 . into_string ( )
2423 . expect ( "path should be UTF-8 encoded" ) ;
@@ -29,6 +28,96 @@ pub fn get_default_search_paths() -> Vec<String> {
2928 ret
3029}
3130
31+ /// List apps that are in the `search_path`.
32+ #[ allow( unused) ] // for now, will be used in https://github.com/infinilabs/coco-app/pull/346
33+ fn list_app_in ( search_path : Vec < String > ) -> Result < Vec < App > , String > {
34+ let search_path = search_path
35+ . into_iter ( )
36+ . map ( PathBuf :: from)
37+ . collect :: < Vec < _ > > ( ) ;
38+ let apps = applications:: get_all_apps ( & search_path) . map_err ( |err| err. to_string ( ) ) ?;
39+
40+ Ok ( apps
41+ . into_iter ( )
42+ . filter ( |app| app. icon_path . is_none ( ) )
43+ . collect ( ) )
44+ }
45+
46+ #[ derive( serde:: Serialize ) ]
47+ pub struct AppMetadata {
48+ #[ serde( rename = "Name" ) ]
49+ name : String ,
50+ #[ serde( rename = "Where" ) ]
51+ r#where : PathBuf ,
52+ #[ serde( rename = "Size" ) ]
53+ size : u64 ,
54+ #[ serde( rename = "Created" ) ]
55+ created : u128 ,
56+ #[ serde( rename = "Modified" ) ]
57+ modified : u128 ,
58+ #[ serde( rename = "Last opened" ) ]
59+ last_opened : u128 ,
60+ }
61+
62+ /// List apps that are in the `search_path`.
63+ ///
64+ /// Different from `list_app_in()`, every app is JSON object containing its metadata, e.g.:
65+ ///
66+ /// ```json
67+ /// {
68+ /// "Name": "Finder",
69+ /// "Where": "/System/Library/CoreServices",
70+ /// "Size": 49283072,
71+ /// "Created": 1744625204,
72+ /// "Modified": 1744625204,
73+ /// "Last opened": 1744625250
74+ /// }
75+ /// ```
76+ #[ tauri:: command]
77+ pub async fn list_app_with_metadata_in (
78+ search_path : Vec < String > ,
79+ ) -> Result < Vec < AppMetadata > , String > {
80+ let apps = list_app_in ( search_path) ?;
81+
82+ let mut apps_with_meta = Vec :: with_capacity ( apps. len ( ) ) ;
83+
84+ // name version where Type(hardcoded Application) Size Created Modify
85+ for app in apps {
86+ let app_path = if cfg ! ( target_os = "windows" ) {
87+ app. app_path_exe
88+ . clone ( )
89+ . unwrap_or ( PathBuf :: from ( "Path not found" ) )
90+ } else {
91+ app. app_desktop_path . clone ( )
92+ } ;
93+ let app_name = name ( app_path. clone ( ) ) . await ;
94+ let app_path_where = {
95+ let mut app_path_clone = app_path. clone ( ) ;
96+ let truncated = app_path_clone. pop ( ) ;
97+ if !truncated {
98+ panic ! ( "every app file should live somewhere" ) ;
99+ }
100+
101+ app_path_clone
102+ } ;
103+
104+ let raw_app_metadata = tauri_plugin_fs_pro:: metadata ( app_path. clone ( ) , None ) . await ?;
105+
106+ let app_metadata = AppMetadata {
107+ name : app_name,
108+ r#where : app_path_where,
109+ size : raw_app_metadata. size ,
110+ created : raw_app_metadata. created_at ,
111+ modified : raw_app_metadata. modified_at ,
112+ last_opened : raw_app_metadata. accessed_at ,
113+ } ;
114+
115+ apps_with_meta. push ( app_metadata) ;
116+ }
117+
118+ Ok ( apps_with_meta)
119+ }
120+
32121pub struct ApplicationSearchSource {
33122 base_score : f64 ,
34123 icons : HashMap < String , PathBuf > ,
@@ -43,7 +132,12 @@ impl ApplicationSearchSource {
43132 let application_paths = Trie :: new ( ) ;
44133 let mut icons = HashMap :: new ( ) ;
45134
46- let mut ctx = AppInfoContext :: new ( vec ! [ ] ) ;
135+ let default_search_path = if cfg ! ( target_os = "macos" ) {
136+ vec ! [ "/Applications" . into( ) , "/System/Applications" . into( ) , "/System/Library/CoreServices" . into( ) ]
137+ } else {
138+ applications:: get_default_search_paths ( )
139+ } ;
140+ let mut ctx = AppInfoContext :: new ( default_search_path) ;
47141 ctx. refresh_apps ( ) . map_err ( |err| err. to_string ( ) ) ?; // must refresh apps before getting them
48142 let apps = ctx. get_all_apps ( ) ;
49143
0 commit comments