1+ using System ;
2+ using System . Collections . Generic ;
3+ using System . Diagnostics ;
4+ using System . IO ;
5+ using System . Threading . Tasks ;
6+ using System . Windows ;
7+ using Wox . Infrastructure . Logger ;
8+ using Wox . Infrastructure . Image ;
9+ using Wox . Plugin . SharedCommands ;
10+
11+ namespace Wox . Plugin . Folder
12+ {
13+ internal class ContextMenuLoader : IContextMenu
14+ {
15+ private readonly PluginInitContext _context ;
16+
17+ public ContextMenuLoader ( PluginInitContext context )
18+ {
19+ _context = context ;
20+ }
21+
22+ public List < Result > LoadContextMenus ( Result selectedResult )
23+ {
24+ var contextMenus = new List < Result > ( ) ;
25+ if ( selectedResult . ContextData is SearchResult record )
26+ {
27+ if ( record . Type == ResultType . File )
28+ {
29+ contextMenus . Add ( CreateOpenWithEditorResult ( record ) ) ;
30+ contextMenus . Add ( CreateOpenContainingFolderResult ( record ) ) ;
31+ }
32+
33+ var icoPath = ( record . Type == ResultType . File ) ? Main . FileImagePath : Main . FolderImagePath ;
34+ var fileOrFolder = ( record . Type == ResultType . File ) ? "file" : "folder" ;
35+ contextMenus . Add ( new Result
36+ {
37+ Title = "Copy path" ,
38+ SubTitle = $ "Copy the current { fileOrFolder } path to clipboard",
39+ Action = ( context ) =>
40+ {
41+ try
42+ {
43+ Clipboard . SetText ( record . FullPath ) ;
44+ return true ;
45+ }
46+ catch ( Exception e )
47+ {
48+ var message = "Fail to set text in clipboard" ;
49+ LogException ( message , e ) ;
50+ _context . API . ShowMsg ( message ) ;
51+ return false ;
52+ }
53+ } ,
54+ IcoPath = Main . CopyImagePath
55+ } ) ;
56+
57+ contextMenus . Add ( new Result
58+ {
59+ Title = $ "Copy { fileOrFolder } ",
60+ SubTitle = $ "Copy the { fileOrFolder } to clipboard",
61+ Action = ( context ) =>
62+ {
63+ try
64+ {
65+ Clipboard . SetFileDropList ( new System . Collections . Specialized . StringCollection { record . FullPath } ) ;
66+ return true ;
67+ }
68+ catch ( Exception e )
69+ {
70+ var message = $ "Fail to set { fileOrFolder } in clipboard";
71+ LogException ( message , e ) ;
72+ _context . API . ShowMsg ( message ) ;
73+ return false ;
74+ }
75+
76+ } ,
77+ IcoPath = icoPath
78+ } ) ;
79+
80+ if ( record . Type == ResultType . File || record . Type == ResultType . Folder )
81+ contextMenus . Add ( new Result
82+ {
83+ Title = $ "Delete { fileOrFolder } ",
84+ SubTitle = $ "Delete the selected { fileOrFolder } ",
85+ Action = ( context ) =>
86+ {
87+ try
88+ {
89+ if ( record . Type == ResultType . File )
90+ File . Delete ( record . FullPath ) ;
91+ else
92+ Directory . Delete ( record . FullPath ) ;
93+ }
94+ catch ( Exception e )
95+ {
96+ var message = $ "Fail to delete { fileOrFolder } at { record . FullPath } ";
97+ LogException ( message , e ) ;
98+ _context . API . ShowMsg ( message ) ;
99+ return false ;
100+ }
101+
102+ return true ;
103+ } ,
104+ IcoPath = Main . DeleteFileFolderImagePath
105+ } ) ;
106+
107+ if ( record . Type == ResultType . File && CanRunAsDifferentUser ( record . FullPath ) )
108+ contextMenus . Add ( new Result
109+ {
110+ Title = "Run as different user" ,
111+ Action = ( context ) =>
112+ {
113+ try
114+ {
115+ Task . Run ( ( ) => ShellCommand . RunAsDifferentUser ( record . FullPath . SetProcessStartInfo ( ) ) ) ;
116+ }
117+ catch ( FileNotFoundException e )
118+ {
119+ var name = "Plugin: Folder" ;
120+ var message = $ "File not found: { e . Message } ";
121+ _context . API . ShowMsg ( name , message ) ;
122+ }
123+
124+ return true ;
125+ } ,
126+ IcoPath = "Images/user.png"
127+ } ) ;
128+ }
129+
130+ return contextMenus ;
131+ }
132+
133+ private Result CreateOpenContainingFolderResult ( SearchResult record )
134+ {
135+ return new Result
136+ {
137+ Title = "Open containing folder" ,
138+ Action = _ =>
139+ {
140+ try
141+ {
142+ Process . Start ( "explorer.exe" , $ " /select,\" { record . FullPath } \" ") ;
143+ }
144+ catch ( Exception e )
145+ {
146+ var message = $ "Fail to open file at { record . FullPath } ";
147+ LogException ( message , e ) ;
148+ _context . API . ShowMsg ( message ) ;
149+ return false ;
150+ }
151+
152+ return true ;
153+ } ,
154+ IcoPath = Main . FolderImagePath
155+ } ;
156+ }
157+
158+
159+ private Result CreateOpenWithEditorResult ( SearchResult record )
160+ {
161+ string editorPath = "notepad.exe" ; // TODO add the ability to create a custom editor
162+
163+ var name = "Open With Editor: " + Path . GetFileNameWithoutExtension ( editorPath ) ;
164+ return new Result
165+ {
166+ Title = name ,
167+ Action = _ =>
168+ {
169+ try
170+ {
171+ Process . Start ( editorPath , record . FullPath ) ;
172+ return true ;
173+ }
174+ catch ( Exception e )
175+ {
176+ var message = $ "Fail to editor for file at { record . FullPath } ";
177+ LogException ( message , e ) ;
178+ _context . API . ShowMsg ( message ) ;
179+ return false ;
180+ }
181+ } ,
182+ IcoPath = editorPath
183+ } ;
184+ }
185+
186+ public void LogException ( string message , Exception e )
187+ {
188+ Log . Exception ( $ "|Wox.Plugin.Folder.ContextMenu|{ message } ", e ) ;
189+ }
190+
191+ private bool CanRunAsDifferentUser ( string path )
192+ {
193+ switch ( Path . GetExtension ( path ) )
194+ {
195+ case ".exe" :
196+ case ".bat" :
197+ return true ;
198+
199+ default :
200+ return false ;
201+
202+ }
203+ }
204+ }
205+
206+ public class SearchResult
207+ {
208+ public string FullPath { get ; set ; }
209+ public ResultType Type { get ; set ; }
210+ }
211+
212+ public enum ResultType
213+ {
214+ Volume ,
215+ Folder ,
216+ File
217+ }
218+ }
0 commit comments