Skip to content

Commit ed17796

Browse files
authored
Add diff view and upgrade monaco from 0.46.0 => 0.47.0 (#6215)
1 parent 32a5a45 commit ed17796

File tree

4 files changed

+3649
-1858
lines changed

4 files changed

+3649
-1858
lines changed

enterprise/app/code/code.tsx

Lines changed: 57 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ interface State {
7676
contextMenuFile?: github.TreeNode;
7777
}
7878

79+
// When upgrading monaco, make sure to run
80+
// cp node_modules/monaco-editor/min/vs/editor/editor.main.css enterprise/app/code/monaco.css
81+
// and replace ../base/browser/ui/codicons/codicon/codicon.ttf
82+
// with https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.47.0/min/vs/base/browser/ui/codicons/codicon/codicon.ttf
83+
const MONACO_VERSION = "0.47.0";
7984
const LOCAL_STORAGE_STATE_KEY = "code-state-v1";
8085
const textEncoder = new TextEncoder();
8186
const textDecoder = new TextDecoder();
@@ -297,6 +302,8 @@ export default class CodeComponent extends React.Component<Props, State> {
297302
this.state.mergeConflicts.get(this.currentPath())!,
298303
undefined
299304
);
305+
} else if (this.isDiffView()) {
306+
this.handleViewDiffClicked(this.currentPath());
300307
} else {
301308
this.editor.setModel(this.state.fullPathToModelMap.get(this.currentPath()) || null);
302309
}
@@ -765,6 +772,7 @@ export default class CodeComponent extends React.Component<Props, State> {
765772
}
766773

767774
handleRevertClicked(path: string, event: React.MouseEvent<HTMLSpanElement, MouseEvent>) {
775+
window.location.hash = "";
768776
this.state.changes.delete(path);
769777
if (this.state.originalFileContents.has(path)) {
770778
this.state.fullPathToModelMap.get(path)?.setValue(this.state.originalFileContents.get(path) || "");
@@ -899,11 +907,8 @@ export default class CodeComponent extends React.Component<Props, State> {
899907
}
900908
let fileContents = textDecoder.decode(response.content);
901909
let editedModel = this.state.fullPathToModelMap.get(fullPath)!;
902-
let uri = monaco.Uri.file(`${fullPath}-${sha}`);
903-
let latestModel = monaco.editor.getModel(uri);
904-
if (!latestModel) {
905-
latestModel = monaco.editor.createModel(fileContents, langFromPath(uri.path), uri);
906-
}
910+
let uri = monaco.Uri.file(`${sha}-${fullPath}`);
911+
let latestModel = getOrCreateModel(uri.path, fileContents);
907912
let diffModel = { original: latestModel, modified: editedModel };
908913
this.diffEditor.setModel(diffModel);
909914
this.state.fullPathToDiffModelMap.set(fullPath, diffModel);
@@ -915,6 +920,22 @@ export default class CodeComponent extends React.Component<Props, State> {
915920
});
916921
}
917922

923+
handleViewDiffClicked(fullPath: string, event?: React.MouseEvent<HTMLSpanElement, MouseEvent>) {
924+
event?.stopPropagation();
925+
if (!this.diffEditor) {
926+
this.diffEditor = monaco.editor.createDiffEditor(this.diffViewer.current!);
927+
}
928+
let editedModel = this.state.fullPathToModelMap.get(fullPath)!;
929+
let uri = monaco.Uri.file(`original-${fullPath}`);
930+
let latestModel = getOrCreateModel(uri.path, this.state.originalFileContents.get(fullPath)!);
931+
let diffModel = { original: latestModel, modified: editedModel };
932+
this.diffEditor.setModel(diffModel);
933+
this.navigateToPath(fullPath + "#diff");
934+
this.updateState({ fullPathToDiffModelMap: this.state.fullPathToDiffModelMap }, () => {
935+
this.diffEditor?.layout();
936+
});
937+
}
938+
918939
handleCloseReviewModal() {
919940
this.updateState({ reviewRequestModalVisible: false });
920941
}
@@ -931,6 +952,10 @@ export default class CodeComponent extends React.Component<Props, State> {
931952
return paths.filter((p) => p).join("");
932953
}
933954

955+
isDiffView() {
956+
return window.location.hash == "#diff";
957+
}
958+
934959
async handleRename(node: github.TreeNode, path: string, newValue: string, existingFile: boolean) {
935960
if (!newValue) {
936961
return;
@@ -1036,7 +1061,7 @@ export default class CodeComponent extends React.Component<Props, State> {
10361061
this.editor?.layout();
10371062
}, 0);
10381063

1039-
let showDiffView = this.state.fullPathToDiffModelMap.has(this.currentPath());
1064+
let showDiffView = this.state.fullPathToDiffModelMap.has(this.currentPath()) || this.isDiffView();
10401065
let applicableInstallation = this.state.installationsResponse?.installations.find(
10411066
(i) => i.login == this.currentOwner()
10421067
);
@@ -1284,6 +1309,16 @@ export default class CodeComponent extends React.Component<Props, State> {
12841309
Resolve Conflict
12851310
</span>
12861311
)}
1312+
{!this.isDiffView() && (
1313+
<span className="code-revert-button" onClick={this.handleViewDiffClicked.bind(this, fullPath)}>
1314+
View Diff
1315+
</span>
1316+
)}
1317+
{this.isDiffView() && (
1318+
<span className="code-revert-button" onClick={() => (window.location.hash = "")}>
1319+
Hide Diff
1320+
</span>
1321+
)}
12871322
<span className="code-revert-button" onClick={this.handleRevertClicked.bind(this, fullPath)}>
12881323
Revert
12891324
</span>
@@ -1380,9 +1415,9 @@ self.MonacoEnvironment = {
13801415
//https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.25.2/min/vs/basic-languages/go/go.min.js
13811416
return `data:text/javascript;charset=utf-8,${encodeURIComponent(`
13821417
self.MonacoEnvironment = {
1383-
baseUrl: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.25.2/min/'
1418+
baseUrl: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/${MONACO_VERSION}/min/'
13841419
};
1385-
importScripts('https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.25.2/min/vs/base/worker/workerMain.js');`)}`;
1420+
importScripts('https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/${MONACO_VERSION}/min/vs/base/worker/workerMain.js');`)}`;
13861421
},
13871422
};
13881423

@@ -1410,8 +1445,8 @@ function stateReplacer(key: string, value: any) {
14101445
key: e[0],
14111446
original: e[1].original.getValue(),
14121447
modified: e[1].modified.getValue(),
1413-
originalUri: e[1].original.uri,
1414-
modifiedUri: e[1].modified.uri,
1448+
originalUri: e[1].original.uri.path,
1449+
modifiedUri: e[1].modified.uri.path,
14151450
};
14161451
}),
14171452
};
@@ -1425,6 +1460,15 @@ function stateReplacer(key: string, value: any) {
14251460
return value;
14261461
}
14271462

1463+
function getOrCreateModel(url: string, value: string) {
1464+
let existingModel = monaco.editor.getModel(monaco.Uri.file(url));
1465+
if (existingModel) {
1466+
existingModel.setValue(value);
1467+
return existingModel;
1468+
}
1469+
return monaco.editor.createModel(value, "text/plain", monaco.Uri.file(url));
1470+
}
1471+
14281472
// This revives any non-serializable objects in state from their seralized form.
14291473
function stateReviver(key: string, value: any) {
14301474
if (typeof value === "object" && value !== null) {
@@ -1434,12 +1478,7 @@ function stateReviver(key: string, value: any) {
14341478
if (value.dataType === "ModelMap") {
14351479
return new Map(
14361480
value.value.map((e: { key: string; value: string }) => {
1437-
let existingModel = monaco.editor.getModel(monaco.Uri.file(e.key));
1438-
if (existingModel) {
1439-
existingModel.setValue(e.value);
1440-
return [e.key, existingModel];
1441-
}
1442-
return [e.key, monaco.editor.createModel(e.value, langFromPath(e.key), monaco.Uri.file(e.key))];
1481+
return [e.key, getOrCreateModel(e.key, e.value)];
14431482
})
14441483
);
14451484
}
@@ -1449,16 +1488,8 @@ function stateReviver(key: string, value: any) {
14491488
(e: { key: string; original: string; originalUri: string; modified: string; modifiedUri: string }) => [
14501489
e.key,
14511490
{
1452-
original: monaco.editor.createModel(
1453-
e.original,
1454-
langFromPath(e.originalUri),
1455-
monaco.Uri.file(e.originalUri)
1456-
),
1457-
modified: monaco.editor.createModel(
1458-
e.modified,
1459-
langFromPath(e.modifiedUri),
1460-
monaco.Uri.file(e.modifiedUri)
1461-
),
1491+
original: getOrCreateModel(e.originalUri, e.original),
1492+
modified: getOrCreateModel(e.modifiedUri, e.modified),
14621493
},
14631494
]
14641495
)

0 commit comments

Comments
 (0)