-
Notifications
You must be signed in to change notification settings - Fork 0
/
websocket.js
160 lines (145 loc) · 6.33 KB
/
websocket.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import { diff_editor_config, editor_config, editor_keybinds, global_editor_config } from "./config.js";
import { editors_to_json, getParentDiffEditor, json_to_content, swap_to_diff_editor, swap_to_normal_editor } from "./editors.js";
var app_div = document.querySelector(".app");
export function connectWebSocket() {
var socket = new WebSocket("ws://localhost:8336");
socket.onopen = function () {
console.log("Socket connected");
socket.send("Socket connected"); // Handshake message
};
socket.onmessage = function (event) {
// Expects to receive a list of dicts
// - Each list element dict has the same keys
// - We will create one column for each key
// - We will join the values list with newlines and put into the editor for each column
var message = JSON.parse(event.data);
var fields = Object.keys(message[0]);
fields.forEach(function (field_name) {
// For each metadata field, create a column directly in the body
var column_div = document.createElement("div");
app_div.appendChild(column_div);
column_div.id = field_name;
column_div.style.width = 100 / (fields.length - 1) + "%";
if (field_name === "id") {
column_div.style.display = "none";
}
// Within the column, create a div for the field name
var column_name_div = document.createElement("div");
column_name_div.className = "column_name no-select";
column_name_div.innerHTML = field_name;
column_name_div.style.width = "100%";
column_div.appendChild(column_name_div)
// Create separate divs for the single editor and the diff editor
var editor_div = document.createElement("div");
editor_div.className = "column";
editor_div.style.width = "100%";
var diff_editor_div = document.createElement("div");
diff_editor_div.className = "column";
diff_editor_div.style.width = "100%";
// Append the new divs to the column_div
column_div.appendChild(editor_div);
column_div.appendChild(diff_editor_div);
// Set keybindings
monaco.editor.addKeybindingRules(editor_keybinds);
// Create editors
let editor = monaco.editor.create(editor_div, {
...global_editor_config,
...editor_config,
readOnly: field_name === "id",
});
editor.field_name = field_name;
editor.editor_type = "normal";
// Create diff editors
let diff_editor = monaco.editor.createDiffEditor(diff_editor_div, {
...global_editor_config,
...editor_config,
...diff_editor_config,
readOnly: field_name === "id",
});
diff_editor.getOriginalEditor().field_name = field_name;
diff_editor.getModifiedEditor().field_name = field_name;
diff_editor.getOriginalEditor().editor_type = "diff_orig";
diff_editor.getModifiedEditor().editor_type = "diff_mod";
});
// Populate the editors line-by-line
var original_content = json_to_content(message, fields);
monaco.editor.getEditors().forEach(function (editor, index) {
editor.original_content = original_content[editor.field_name];
if (editor.editor_type === "normal") {
editor.setValue(editor.original_content);
} else if (editor.editor_type === "diff_mod") {
var original_model = monaco.editor.createModel(editor.original_content, "plaintext");
var modified_model = monaco.editor.createModel(editor.original_content, "plaintext");
var diff_editor = getParentDiffEditor(editor);
diff_editor.setModel({ original: original_model, modified: modified_model });
}
});
// Editor callbacks
// Includes normal editors, original/modified editors of diff editors, but not the diff editors themselves
monaco.editor.getEditors().forEach(function (editor, index) {
// Synchronise line changes
editor.onDidChangeCursorPosition(function (e) {
monaco.editor.getEditors().forEach(function (otherEditor, otherIndex) {
// source could be "mouse", "keyboard", "api", "model"
if (otherEditor !== editor && e.source !== "api" && e.source !== "model") {
if (otherEditor.field_name !== editor.field_name) {
// Between columns, the content likely differs, so only set the line number
otherEditor.setPosition({ lineNumber: e.position.lineNumber, column: 1 });
} else {
// Between normal/diff editors, the content should be the same, so use the full position
otherEditor.setPosition(e.position);
}
}
});
});
// Synchronise scrolling
editor.onDidScrollChange(function (e) {
monaco.editor.getEditors().forEach(function (otherEditor, otherIndex) {
// There is no e.source for scroll events, but it should be OK without filtering that
if (otherEditor !== editor) {
otherEditor.setScrollTop(e.scrollTop);
}
});
});
// Catch changed content
if (editor.editor_type === "normal") {
editor.onDidChangeModelContent(function (e) {
// https://github.com/microsoft/monaco-editor/issues/432#issuecomment-749198333
if (!e.isFlush) {
var mod_editor = monaco.editor.getEditors().find(other_editor => other_editor.field_name === editor.field_name && other_editor.editor_type === "diff_mod");
var diff_editor = getParentDiffEditor(mod_editor);
var model = diff_editor.getModel()
model.modified.setValue(editor.getValue());
diff_editor.setModel(model);
// Shouldn't need to set position: Impossible to change content without a position change
if (editor.getValue() !== editor.original_content) {
swap_to_diff_editor(editor.field_name);
}
}
});
} else if (editor.editor_type === "diff_mod") {
editor.onDidChangeModelContent(function (e) {
// https://github.com/microsoft/monaco-editor/issues/432#issuecomment-749198333
if (!e.isFlush) {
var normal_editor = monaco.editor.getEditors().find(other_editor => other_editor.field_name === editor.field_name && other_editor.editor_type === "normal");
normal_editor.setValue(editor.getValue());
// onDidChangeCursorPosition is not enough: content can change without a position change
normal_editor.setPosition(editor.getPosition());
if (editor.getValue() === editor.original_content) {
swap_to_normal_editor(editor.field_name);
}
}
});
}
});
document.querySelector(".button.submit").addEventListener("click", function () {
socket.send(editors_to_json());
});
};
socket.onclose = function (event) {
console.log("Socket closed, attempting to reconnect...");
setTimeout(function () {
connectWebSocket();
}, 1000);
};
}