fixed issues
This commit is contained in:
Generated
+14
@@ -9,9 +9,11 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/cors": "^2.8.19",
|
"@types/cors": "^2.8.19",
|
||||||
|
"@types/diff-match-patch": "^1.0.36",
|
||||||
"@types/express": "^5.0.6",
|
"@types/express": "^5.0.6",
|
||||||
"axios": "^1.13.5",
|
"axios": "^1.13.5",
|
||||||
"cors": "^2.8.6",
|
"cors": "^2.8.6",
|
||||||
|
"diff-match-patch": "^1.0.5",
|
||||||
"express": "^5.2.1"
|
"express": "^5.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -302,6 +304,12 @@
|
|||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/diff-match-patch": {
|
||||||
|
"version": "1.0.36",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/diff-match-patch/-/diff-match-patch-1.0.36.tgz",
|
||||||
|
"integrity": "sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/express": {
|
"node_modules/@types/express": {
|
||||||
"version": "5.0.6",
|
"version": "5.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.6.tgz",
|
||||||
@@ -1244,6 +1252,12 @@
|
|||||||
"node": ">=0.3.1"
|
"node": ">=0.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/diff-match-patch": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==",
|
||||||
|
"license": "Apache-2.0"
|
||||||
|
},
|
||||||
"node_modules/dir-glob": {
|
"node_modules/dir-glob": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
|
||||||
|
|||||||
@@ -84,9 +84,11 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/cors": "^2.8.19",
|
"@types/cors": "^2.8.19",
|
||||||
|
"@types/diff-match-patch": "^1.0.36",
|
||||||
"@types/express": "^5.0.6",
|
"@types/express": "^5.0.6",
|
||||||
"axios": "^1.13.5",
|
"axios": "^1.13.5",
|
||||||
"cors": "^2.8.6",
|
"cors": "^2.8.6",
|
||||||
|
"diff-match-patch": "^1.0.5",
|
||||||
"express": "^5.2.1"
|
"express": "^5.2.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+74
-32
@@ -1,70 +1,112 @@
|
|||||||
import * as vscode from "vscode";
|
import * as vscode from "vscode";
|
||||||
|
import { diff_match_patch, Diff } from "diff-match-patch";
|
||||||
import { LiveRunMove } from "./types";
|
import { LiveRunMove } from "./types";
|
||||||
import { addRunMoves } from "./client";
|
import { addRunMoves } from "./client";
|
||||||
|
|
||||||
export function startMonitoring(runId: string) {
|
export function startMonitoring(runId: string) {
|
||||||
|
const dmp = new diff_match_patch();
|
||||||
|
|
||||||
let moveId = 0;
|
let moveId = 0;
|
||||||
let moves: LiveRunMove[] = [];
|
let moves: LiveRunMove[] = [];
|
||||||
let lastLatency = Date.now();
|
|
||||||
|
let lastText = "";
|
||||||
|
let lastEventTime = Date.now();
|
||||||
let idleTimeout: NodeJS.Timeout | undefined;
|
let idleTimeout: NodeJS.Timeout | undefined;
|
||||||
let isSending = false;
|
let isSending = false;
|
||||||
|
|
||||||
const SEND_IDLE_MS = 350;
|
const IDLE_MS = 350;
|
||||||
|
|
||||||
const flushMoves = async () => {
|
const editor = vscode.window.activeTextEditor;
|
||||||
|
if (editor) {
|
||||||
|
lastText = editor.document.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function flush() {
|
||||||
if (!moves.length || isSending) return;
|
if (!moves.length || isSending) return;
|
||||||
|
|
||||||
isSending = true;
|
isSending = true;
|
||||||
const toSend = moves;
|
const batch = moves;
|
||||||
moves = [];
|
moves = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await addRunMoves(runId, toSend);
|
await addRunMoves(runId, batch);
|
||||||
} finally {
|
} finally {
|
||||||
isSending = false;
|
isSending = false;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const docSub = vscode.workspace.onDidChangeTextDocument((e) => {
|
const readInterval = setInterval(() => {
|
||||||
const editor = vscode.window.activeTextEditor;
|
const editor = vscode.window.activeTextEditor;
|
||||||
if (!editor || e.document !== editor.document) return;
|
if (!editor) return;
|
||||||
|
|
||||||
const edit = e.contentChanges[0];
|
const newText = editor.document.getText();
|
||||||
if (!edit) return;
|
if (newText === lastText) return;
|
||||||
|
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const latency = capToZeroAbove(now - lastLatency, SEND_IDLE_MS);
|
const latency = capLatency(now - lastEventTime, IDLE_MS);
|
||||||
lastLatency = now;
|
lastEventTime = now;
|
||||||
|
|
||||||
const cursorOffset = editor.document.offsetAt(editor.selection.active);
|
const diffs = dmp.diff_main(lastText, newText);
|
||||||
|
dmp.diff_cleanupEfficiency(diffs);
|
||||||
|
|
||||||
moves.push({
|
const changes = diffsToChanges(diffs);
|
||||||
latency,
|
|
||||||
cursor: cursorOffset,
|
|
||||||
changes: {
|
|
||||||
from: edit.rangeOffset,
|
|
||||||
to: edit.rangeOffset + edit.rangeLength,
|
|
||||||
insert: edit.text,
|
|
||||||
},
|
|
||||||
moveId: moveId++,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (idleTimeout) {
|
lastText = newText;
|
||||||
clearTimeout(idleTimeout);
|
|
||||||
|
for (const change of changes) {
|
||||||
|
moves.push({
|
||||||
|
moveId: moveId++,
|
||||||
|
latency,
|
||||||
|
cursor: editor.document.offsetAt(editor.selection.active),
|
||||||
|
changes: change,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
idleTimeout = setTimeout(() => {
|
if (idleTimeout) clearTimeout(idleTimeout);
|
||||||
flushMoves();
|
idleTimeout = setTimeout(flush, IDLE_MS);
|
||||||
}, SEND_IDLE_MS);
|
}, 500);
|
||||||
});
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
docSub.dispose();
|
clearInterval(readInterval);
|
||||||
if (idleTimeout) clearTimeout(idleTimeout);
|
if (idleTimeout) clearTimeout(idleTimeout);
|
||||||
flushMoves();
|
flush();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function capToZeroAbove(value: number, max: number) {
|
function diffsToChanges(diffs: Diff[]) {
|
||||||
|
const changes: {
|
||||||
|
from: number;
|
||||||
|
to: number;
|
||||||
|
insert: string;
|
||||||
|
}[] = [];
|
||||||
|
|
||||||
|
let offset = 0;
|
||||||
|
|
||||||
|
for (const [op, text] of diffs) {
|
||||||
|
if (op === 0) {
|
||||||
|
// equal
|
||||||
|
offset += text.length;
|
||||||
|
} else if (op === -1) {
|
||||||
|
// delete
|
||||||
|
changes.push({
|
||||||
|
from: offset,
|
||||||
|
to: offset + text.length,
|
||||||
|
insert: "",
|
||||||
|
});
|
||||||
|
} else if (op === 1) {
|
||||||
|
// insert
|
||||||
|
changes.push({
|
||||||
|
from: offset,
|
||||||
|
to: offset,
|
||||||
|
insert: text,
|
||||||
|
});
|
||||||
|
offset += text.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
function capLatency(value: number, max: number) {
|
||||||
return value > max ? 0 : value;
|
return value > max ? 0 : value;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user