@@ -76,7 +76,7 @@ public async Task<bool> UpdateRecentFilesAsync()
7676 {
7777 return await Task . Run ( ( ) =>
7878 {
79- return UpdateRecentFilesInternal ( ) ;
79+ return UpdateRecentItems ( false ) ;
8080 } ) ;
8181 }
8282
@@ -85,7 +85,7 @@ public async Task<bool> UpdateRecentFoldersAsync()
8585 {
8686 return await Task . Run ( ( ) =>
8787 {
88- return false ;
88+ return UpdateRecentItems ( true ) ;
8989 } ) ;
9090 }
9191
@@ -109,7 +109,7 @@ public unsafe bool Add(string path)
109109 /// <inheritdoc/>
110110 public unsafe bool Remove ( RecentItem item )
111111 {
112- return false ; // TODO: Use IShellFileOperation interface
112+ return false ; // TODO: Use ContextMenu class to invoke "delete" verb
113113 }
114114
115115 /// <inheritdoc/>
@@ -131,47 +131,51 @@ public unsafe bool Clear()
131131 /// <inheritdoc/>
132132 public bool CheckIsRecentItemsEnabled ( )
133133 {
134- using var subkey = Registry . CurrentUser . OpenSubKey ( @"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer" ) ;
134+ using var explorerSubKey = Registry . CurrentUser . OpenSubKey ( @"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer" ) ;
135135 using var advSubkey = Registry . CurrentUser . OpenSubKey ( @"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" ) ;
136136 using var userPolicySubkey = Registry . CurrentUser . OpenSubKey ( @"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer" ) ;
137137 using var sysPolicySubkey = Registry . LocalMachine . OpenSubKey ( @"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer" ) ;
138138
139- if ( subkey is not null )
139+ if ( explorerSubKey is not null )
140140 {
141- // File Explorer settings
142- bool showRecentValue = Convert . ToBoolean ( subkey . GetValue ( "ShowRecent" , true ) ) ; // 1 by default
141+ // File Explorer settings (default: 1)
142+ bool showRecentValue = Convert . ToBoolean ( explorerSubKey . GetValue ( "ShowRecent" , true ) ) ;
143143 if ( ! showRecentValue )
144144 return false ;
145145 }
146146
147147 if ( advSubkey is not null )
148148 {
149- // Windows Settings
150- bool startTrackDocsValue = Convert . ToBoolean ( advSubkey . GetValue ( "Start_TrackDocs" , true ) ) ; // 1 by default
149+ // Windows Settings (default: 1)
150+ bool startTrackDocsValue = Convert . ToBoolean ( advSubkey . GetValue ( "Start_TrackDocs" , true ) ) ;
151151 if ( ! startTrackDocsValue )
152152 return false ;
153153 }
154154
155- // Group policy settings
155+ // Group Policy settings (default: 0)
156156 var policySubkey = userPolicySubkey ?? sysPolicySubkey ;
157157 if ( policySubkey is not null )
158158 {
159- bool noRecentDocsHistoryValue = Convert . ToBoolean ( policySubkey . GetValue ( "NoRecentDocsHistory" , false ) ) ; // 0 by default
159+ bool noRecentDocsHistoryValue = Convert . ToBoolean ( policySubkey . GetValue ( "NoRecentDocsHistory" , false ) ) ;
160160 if ( noRecentDocsHistoryValue )
161161 return false ;
162162 }
163163
164164 return true ;
165165 }
166166
167- private unsafe bool UpdateRecentFilesInternal ( )
167+ private unsafe bool UpdateRecentItems ( bool isFolder )
168168 {
169169 try
170170 {
171171 HRESULT hr = default ;
172172
173- // Get IShellItem of the quick access shell folder
174- string szFolderShellPath = "Shell:::{679f85cb-0220-4080-b29b-5540cc05aab6}" ;
173+ string szFolderShellPath =
174+ isFolder
175+ ? "Shell:::{22877a6d-37a1-461a-91b0-dbda5aaebc99}" // Recent Places folder
176+ : "Shell:::{679f85cb-0220-4080-b29b-5540cc05aab6}" ; // Quick Access folder
177+
178+ // Get IShellItem of the shell folder
175179 var shellItemIid = typeof ( IShellItem ) . GUID ;
176180 using ComPtr < IShellItem > pFolderShellItem = default ;
177181 fixed ( char * pszFolderShellPath = szFolderShellPath )
@@ -194,15 +198,14 @@ private unsafe bool UpdateRecentFilesInternal()
194198 break ;
195199
196200 // Get the target path
197- pShellItem . Get ( ) ->GetDisplayName ( SIGDN . SIGDN_DESKTOPABSOLUTEEDITING , out var szTargetItemPath ) ;
198- if ( szTargetItemPath . Value == null )
199- pShellItem . Get ( ) ->GetDisplayName ( SIGDN . SIGDN_FILESYSPATH , out szTargetItemPath ) ;
200- var targetPath = szTargetItemPath . ToString ( ) ;
201- PInvoke . CoTaskMemFree ( ( void * ) szTargetItemPath . Value ) ;
201+ pShellItem . Get ( ) ->GetDisplayName ( SIGDN . SIGDN_DESKTOPABSOLUTEEDITING , out var szDisplayName ) ;
202+ var targetPath = szDisplayName . ToString ( ) ;
203+ PInvoke . CoTaskMemFree ( ( void * ) szDisplayName . Value ) ;
202204
203205 // Get the display name
204- var fileName = GetPropertyKey ( pShellItem . Get ( ) , "System.ItemNameDisplay" ) ;
205- // TODO: Probably should try also SIGDN_NORMALDISPLAY and then SIGDN_PARENTRELATIVEPARSING too?
206+ pShellItem . Get ( ) ->GetDisplayName ( SIGDN . SIGDN_NORMALDISPLAY , out szDisplayName ) ;
207+ var fileName = szDisplayName . ToString ( ) ;
208+ PInvoke . CoTaskMemFree ( ( void * ) szDisplayName . Value ) ;
206209
207210 // Strip the file extension except when the file name only contains extension (e.g. ".gitignore")
208211 if ( ! FoldersSettingsService . ShowFileExtensions )
@@ -211,6 +214,8 @@ private unsafe bool UpdateRecentFilesInternal()
211214 fileName = string . IsNullOrEmpty ( strippedExtension ) ? SystemIO . Path . GetFileName ( fileName ) : strippedExtension ;
212215 }
213216
217+ // TODO: Get PIDL to prepare for removal of the item via "delete" verb for now
218+
214219 recentItems . Add ( new ( )
215220 {
216221 Path = targetPath ,
@@ -223,34 +228,40 @@ private unsafe bool UpdateRecentFilesInternal()
223228 if ( recentItems . Count is 0 )
224229 return false ;
225230
226- var snapshot = RecentFiles ;
231+ // TODO: Sort by last modified
227232
228- lock ( _RecentFiles )
233+ var snapshot = isFolder ? RecentFolders : RecentFiles ;
234+
235+ if ( isFolder )
236+ {
237+ lock ( _RecentFolders )
238+ {
239+ _RecentFolders . Clear ( ) ;
240+ _RecentFolders . AddRange ( recentItems ) ;
241+ }
242+ }
243+ else
229244 {
230- _RecentFiles . Clear ( ) ;
231- _RecentFiles . AddRange ( recentItems ) ;
245+ lock ( _RecentFiles )
246+ {
247+ _RecentFiles . Clear ( ) ;
248+ _RecentFiles . AddRange ( recentItems ) ;
249+ }
232250 }
233251
234252 var eventArgs = GetChangedActionEventArgs ( snapshot , recentItems ) ;
235- RecentFilesChanged ? . Invoke ( this , eventArgs ) ;
253+
254+ if ( isFolder )
255+ RecentFoldersChanged ? . Invoke ( this , eventArgs ) ;
256+ else
257+ RecentFilesChanged ? . Invoke ( this , eventArgs ) ;
236258
237259 return true ;
238260 }
239261 catch
240262 {
241263 return false ;
242264 }
243-
244- unsafe static string GetPropertyKey ( IShellItem * pShellItem , string propertyKeyName )
245- {
246- var shellItem2Iid = typeof ( IShellItem2 ) . GUID ;
247- using ComPtr < IShellItem2 > pShellItem2 = default ;
248- pShellItem ->QueryInterface ( & shellItem2Iid , ( void * * ) pShellItem2 . GetAddressOf ( ) ) ;
249- PInvoke . PSGetPropertyKeyFromName ( propertyKeyName , out var propertyKey ) ;
250- pShellItem2 . Get ( ) ->GetString ( propertyKey , out var szPropertyValue ) ;
251-
252- return szPropertyValue . ToString ( ) ;
253- }
254265 }
255266
256267 private void Watcher_Changed ( object sender , SystemIO . FileSystemEventArgs e )
0 commit comments