@@ -23,6 +23,7 @@ import { IApplicationStorageMainService } from 'vs/platform/storage/electron-mai
23
23
import { IRecent , IRecentFile , IRecentFolder , IRecentlyOpened , IRecentWorkspace , isRecentFile , isRecentFolder , isRecentWorkspace , restoreRecentlyOpened , toStoreData } from 'vs/platform/workspaces/common/workspaces' ;
24
24
import { IWorkspaceIdentifier , WORKSPACE_EXTENSION } from 'vs/platform/workspace/common/workspace' ;
25
25
import { IWorkspacesManagementMainService } from 'vs/platform/workspaces/electron-main/workspacesManagementMainService' ;
26
+ import { ResourceMap } from 'vs/base/common/map' ;
26
27
27
28
export const IWorkspacesHistoryMainService = createDecorator < IWorkspacesHistoryMainService > ( 'workspacesHistoryMainService' ) ;
28
29
@@ -73,28 +74,28 @@ export class WorkspacesHistoryMainService extends Disposable implements IWorkspa
73
74
//#region Workspaces History
74
75
75
76
async addRecentlyOpened ( recentToAdd : IRecent [ ] ) : Promise < void > {
76
- const workspaces : Array < IRecentFolder | IRecentWorkspace > = [ ] ;
77
- const files : IRecentFile [ ] = [ ] ;
77
+ let workspaces : Array < IRecentFolder | IRecentWorkspace > = [ ] ;
78
+ let files : IRecentFile [ ] = [ ] ;
78
79
79
80
for ( const recent of recentToAdd ) {
80
81
81
82
// Workspace
82
83
if ( isRecentWorkspace ( recent ) ) {
83
- if ( ! this . workspacesManagementMainService . isUntitledWorkspace ( recent . workspace ) && this . indexOfWorkspace ( workspaces , recent . workspace ) === - 1 ) {
84
+ if ( ! this . workspacesManagementMainService . isUntitledWorkspace ( recent . workspace ) && ! this . containsWorkspace ( workspaces , recent . workspace ) ) {
84
85
workspaces . push ( recent ) ;
85
86
}
86
87
}
87
88
88
89
// Folder
89
90
else if ( isRecentFolder ( recent ) ) {
90
- if ( this . indexOfFolder ( workspaces , recent . folderUri ) === - 1 ) {
91
+ if ( ! this . containsFolder ( workspaces , recent . folderUri ) ) {
91
92
workspaces . push ( recent ) ;
92
93
}
93
94
}
94
95
95
96
// File
96
97
else {
97
- const alreadyExistsInHistory = this . indexOfFile ( files , recent . fileUri ) >= 0 ;
98
+ const alreadyExistsInHistory = this . containsFile ( files , recent . fileUri ) ;
98
99
const shouldBeFiltered = recent . fileUri . scheme === Schemas . file && WorkspacesHistoryMainService . COMMON_FILES_FILTER . indexOf ( basename ( recent . fileUri ) ) >= 0 ;
99
100
100
101
if ( ! alreadyExistsInHistory && ! shouldBeFiltered ) {
@@ -108,7 +109,9 @@ export class WorkspacesHistoryMainService extends Disposable implements IWorkspa
108
109
}
109
110
}
110
111
111
- await this . addEntriesFromStorage ( workspaces , files ) ;
112
+ const mergedEntries = await this . mergeEntriesFromStorage ( { workspaces, files } ) ;
113
+ workspaces = mergedEntries . workspaces ;
114
+ files = mergedEntries . files ;
112
115
113
116
if ( workspaces . length > WorkspacesHistoryMainService . MAX_TOTAL_RECENT_ENTRIES ) {
114
117
workspaces . length = WorkspacesHistoryMainService . MAX_TOTAL_RECENT_ENTRIES ;
@@ -163,35 +166,53 @@ export class WorkspacesHistoryMainService extends Disposable implements IWorkspa
163
166
}
164
167
165
168
async getRecentlyOpened ( ) : Promise < IRecentlyOpened > {
166
- const workspaces : Array < IRecentFolder | IRecentWorkspace > = [ ] ;
167
- const files : IRecentFile [ ] = [ ] ;
169
+ return this . mergeEntriesFromStorage ( ) ;
170
+ }
168
171
169
- await this . addEntriesFromStorage ( workspaces , files ) ;
172
+ private async mergeEntriesFromStorage ( existingEntries ?: IRecentlyOpened ) : Promise < IRecentlyOpened > {
170
173
171
- return { workspaces, files } ;
172
- }
174
+ // Build maps for more efficient lookup of existing entries that
175
+ // are passed in by storing based on workspace/file identifier
176
+
177
+ const mapWorkspaceIdToWorkspace = new ResourceMap < IRecentFolder | IRecentWorkspace > ( uri => extUriBiasedIgnorePathCase . getComparisonKey ( uri ) ) ;
178
+ if ( existingEntries ?. workspaces ) {
179
+ for ( const workspace of existingEntries . workspaces ) {
180
+ mapWorkspaceIdToWorkspace . set ( this . location ( workspace ) , workspace ) ;
181
+ }
182
+ }
173
183
174
- private async addEntriesFromStorage ( workspaces : Array < IRecentFolder | IRecentWorkspace > , files : IRecentFile [ ] ) : Promise < void > {
184
+ const mapFileIdToFile = new ResourceMap < IRecentFile > ( uri => extUriBiasedIgnorePathCase . getComparisonKey ( uri ) ) ;
185
+ if ( existingEntries ?. files ) {
186
+ for ( const file of existingEntries . files ) {
187
+ mapFileIdToFile . set ( this . location ( file ) , file ) ;
188
+ }
189
+ }
190
+
191
+ // Merge in entries from storage, preserving existing known entries
175
192
176
- // Get from storage
177
- const recents = await this . getRecentlyOpenedFromStorage ( ) ;
178
- for ( const recent of recents . workspaces ) {
179
- const index = isRecentFolder ( recent ) ? this . indexOfFolder ( workspaces , recent . folderUri ) : this . indexOfWorkspace ( workspaces , recent . workspace ) ;
180
- if ( index >= 0 ) {
181
- workspaces [ index ] . label = workspaces [ index ] . label || recent . label ;
193
+ const recentFromStorage = await this . getRecentlyOpenedFromStorage ( ) ;
194
+ for ( const recentWorkspaceFromStorage of recentFromStorage . workspaces ) {
195
+ const existingRecentWorkspace = mapWorkspaceIdToWorkspace . get ( this . location ( recentWorkspaceFromStorage ) ) ;
196
+ if ( existingRecentWorkspace ) {
197
+ existingRecentWorkspace . label = existingRecentWorkspace . label ?? recentWorkspaceFromStorage . label ;
182
198
} else {
183
- workspaces . push ( recent ) ;
199
+ mapWorkspaceIdToWorkspace . set ( this . location ( recentWorkspaceFromStorage ) , recentWorkspaceFromStorage ) ;
184
200
}
185
201
}
186
202
187
- for ( const recent of recents . files ) {
188
- const index = this . indexOfFile ( files , recent . fileUri ) ;
189
- if ( index >= 0 ) {
190
- files [ index ] . label = files [ index ] . label || recent . label ;
203
+ for ( const recentFileFromStorage of recentFromStorage . files ) {
204
+ const existingRecentFile = mapFileIdToFile . get ( this . location ( recentFileFromStorage ) ) ;
205
+ if ( existingRecentFile ) {
206
+ existingRecentFile . label = existingRecentFile . label ?? recentFileFromStorage . label ;
191
207
} else {
192
- files . push ( recent ) ;
208
+ mapFileIdToFile . set ( this . location ( recentFileFromStorage ) , recentFileFromStorage ) ;
193
209
}
194
210
}
211
+
212
+ return {
213
+ workspaces : [ ...mapWorkspaceIdToWorkspace . values ( ) ] ,
214
+ files : [ ...mapFileIdToFile . values ( ) ]
215
+ } ;
195
216
}
196
217
197
218
private async getRecentlyOpenedFromStorage ( ) : Promise < IRecentlyOpened > {
@@ -235,16 +256,16 @@ export class WorkspacesHistoryMainService extends Disposable implements IWorkspa
235
256
return recent . workspace . configPath ;
236
257
}
237
258
238
- private indexOfWorkspace ( recents : IRecent [ ] , candidate : IWorkspaceIdentifier ) : number {
239
- return recents . findIndex ( recent => isRecentWorkspace ( recent ) && recent . workspace . id === candidate . id ) ;
259
+ private containsWorkspace ( recents : IRecent [ ] , candidate : IWorkspaceIdentifier ) : boolean {
260
+ return ! ! recents . find ( recent => isRecentWorkspace ( recent ) && recent . workspace . id === candidate . id ) ;
240
261
}
241
262
242
- private indexOfFolder ( recents : IRecent [ ] , candidate : URI ) : number {
243
- return recents . findIndex ( recent => isRecentFolder ( recent ) && extUriBiasedIgnorePathCase . isEqual ( recent . folderUri , candidate ) ) ;
263
+ private containsFolder ( recents : IRecent [ ] , candidate : URI ) : boolean {
264
+ return ! ! recents . find ( recent => isRecentFolder ( recent ) && extUriBiasedIgnorePathCase . isEqual ( recent . folderUri , candidate ) ) ;
244
265
}
245
266
246
- private indexOfFile ( recents : IRecentFile [ ] , candidate : URI ) : number {
247
- return recents . findIndex ( recent => extUriBiasedIgnorePathCase . isEqual ( recent . fileUri , candidate ) ) ;
267
+ private containsFile ( recents : IRecentFile [ ] , candidate : URI ) : boolean {
268
+ return ! ! recents . find ( recent => extUriBiasedIgnorePathCase . isEqual ( recent . fileUri , candidate ) ) ;
248
269
}
249
270
250
271
//#endregion
0 commit comments