Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/sessions/contrib/changes/browser/changesMultiDiffSourceResolver.ts
13401 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { Disposable } from '../../../../base/common/lifecycle.js';
7
import { derivedObservableWithCache, derivedOpts, ValueWithChangeEventFromObservable } from '../../../../base/common/observable.js';
8
import { equals as arraysEqual } from '../../../../base/common/arrays.js';
9
import { isEqual } from '../../../../base/common/resources.js';
10
import { URI } from '../../../../base/common/uri.js';
11
import { comparePaths } from '../../../../base/common/comparers.js';
12
import { isIChatSessionFileChange2 } from '../../../../workbench/contrib/chat/common/chatSessionsService.js';
13
import { IMultiDiffSourceResolver, IMultiDiffSourceResolverService, IResolvedMultiDiffSource, MultiDiffEditorItem } from '../../../../workbench/contrib/multiDiffEditor/browser/multiDiffSourceResolverService.js';
14
import { ISessionFileChange } from '../../../services/sessions/common/session.js';
15
import { ChangesViewModel } from './changesViewModel.js';
16
17
const CHANGES_MULTI_DIFF_SOURCE_SCHEME = 'changes-multi-diff-source';
18
19
interface ChangesMultiDiffUriFields {
20
readonly sessionResource: string;
21
}
22
23
/**
24
* Build the multi-diff source URI for a session. The URI is used to identify
25
* the multi-diff editor so subsequent opens with the same session reuse the
26
* same input while the resource list updates reactively.
27
*/
28
export function getChangesMultiDiffSourceUri(sessionResource: URI): URI {
29
return URI.from({
30
scheme: CHANGES_MULTI_DIFF_SOURCE_SCHEME,
31
query: JSON.stringify({ sessionResource: sessionResource.toString() } satisfies ChangesMultiDiffUriFields),
32
});
33
}
34
35
function parseUri(uri: URI): { sessionResource: URI } | undefined {
36
if (uri.scheme !== CHANGES_MULTI_DIFF_SOURCE_SCHEME) {
37
return undefined;
38
}
39
40
let query: ChangesMultiDiffUriFields;
41
try {
42
query = JSON.parse(uri.query) as ChangesMultiDiffUriFields;
43
} catch {
44
return undefined;
45
}
46
47
if (typeof query !== 'object' || query === null || typeof query.sessionResource !== 'string') {
48
return undefined;
49
}
50
51
return { sessionResource: URI.parse(query.sessionResource) };
52
}
53
54
function compareChanges(a: ISessionFileChange, b: ISessionFileChange): number {
55
const aPath = isIChatSessionFileChange2(a) ? a.uri.fsPath : a.modifiedUri.fsPath;
56
const bPath = isIChatSessionFileChange2(b) ? b.uri.fsPath : b.modifiedUri.fsPath;
57
return comparePaths(aPath, bPath);
58
}
59
60
export class ChangesMultiDiffSourceResolver extends Disposable implements IMultiDiffSourceResolver {
61
62
constructor(
63
private readonly _viewModel: ChangesViewModel,
64
@IMultiDiffSourceResolverService multiDiffSourceResolverService: IMultiDiffSourceResolverService
65
) {
66
super();
67
this._register(multiDiffSourceResolverService.registerResolver(this));
68
}
69
70
canHandleUri(uri: URI): boolean {
71
return parseUri(uri) !== undefined;
72
}
73
74
async resolveDiffSource(uri: URI): Promise<IResolvedMultiDiffSource> {
75
const parsed = parseUri(uri)!;
76
77
const changesObs = derivedObservableWithCache<readonly ISessionFileChange[]>({
78
owner: this,
79
}, (reader, lastValue) => {
80
if (this._viewModel.activeSessionIsLoadingObs.read(reader)) {
81
return lastValue ?? [];
82
}
83
84
const activeSessionResource = this._viewModel.activeSessionResourceObs.read(reader);
85
if (!activeSessionResource || !isEqual(activeSessionResource, parsed.sessionResource)) {
86
return lastValue ?? [];
87
}
88
89
return this._viewModel.activeSessionChangesObs.read(reader);
90
});
91
92
const resourcesObs = derivedOpts<readonly MultiDiffEditorItem[]>({
93
owner: this,
94
equalsFn: (a, b) => arraysEqual(a, b, (x, y) =>
95
isEqual(x.originalUri, y.originalUri) &&
96
isEqual(x.modifiedUri, y.modifiedUri)),
97
}, reader => {
98
const changes = changesObs.read(reader);
99
return [...changes].sort(compareChanges).map(change =>
100
new MultiDiffEditorItem(change.originalUri, change.modifiedUri, change.modifiedUri));
101
});
102
103
return { resources: new ValueWithChangeEventFromObservable(resourcesObs) };
104
}
105
}
106
107