Fix remote cursor duplication
This commit is contained in:
parent
c0171ad72f
commit
088f474a2e
3 changed files with 48 additions and 7 deletions
|
|
@ -9,6 +9,7 @@ import type {
|
||||||
ViewUpdate
|
ViewUpdate
|
||||||
} from "@codemirror/view";
|
} from "@codemirror/view";
|
||||||
import { RemoteCursorWidget } from "./remote-cursor-widget";
|
import { RemoteCursorWidget } from "./remote-cursor-widget";
|
||||||
|
import type { RelativePath } from "sync-client";
|
||||||
import {
|
import {
|
||||||
utils,
|
utils,
|
||||||
type CursorSpan,
|
type CursorSpan,
|
||||||
|
|
@ -32,12 +33,14 @@ export class RemoteCursorsPluginValue implements PluginValue {
|
||||||
isOutdated: boolean;
|
isOutdated: boolean;
|
||||||
}[] = [];
|
}[] = [];
|
||||||
|
|
||||||
|
private static app: App;
|
||||||
public decorations: DecorationSet = RangeSet.of([]);
|
public decorations: DecorationSet = RangeSet.of([]);
|
||||||
|
|
||||||
public static setCursors(
|
public static setCursors(
|
||||||
clients: MaybeOutdatedClientCursors[],
|
clients: MaybeOutdatedClientCursors[],
|
||||||
app: App
|
app: App
|
||||||
): void {
|
): void {
|
||||||
|
RemoteCursorsPluginValue.app = app;
|
||||||
RemoteCursorsPluginValue.cursors = [
|
RemoteCursorsPluginValue.cursors = [
|
||||||
...RemoteCursorsPluginValue.cursors.filter(({ deviceId }) =>
|
...RemoteCursorsPluginValue.cursors.filter(({ deviceId }) =>
|
||||||
clients.some(
|
clients.some(
|
||||||
|
|
@ -82,6 +85,30 @@ export class RemoteCursorsPluginValue implements PluginValue {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static findFileForEditor(
|
||||||
|
editor: EditorView
|
||||||
|
): RelativePath | undefined {
|
||||||
|
return RemoteCursorsPluginValue.app.workspace
|
||||||
|
.getLeavesOfType("markdown")
|
||||||
|
.map((leaf) => leaf.view)
|
||||||
|
.filter((view) => view instanceof MarkdownView)
|
||||||
|
.flatMap((view) => {
|
||||||
|
// @ts-expect-error, not typed
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||||
|
if ((view.editor.cm as EditorView) !== editor) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const { file } = view;
|
||||||
|
if (!file) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [file.path];
|
||||||
|
})
|
||||||
|
.first();
|
||||||
|
}
|
||||||
|
|
||||||
private static interpolateRemoteCursorPositions(
|
private static interpolateRemoteCursorPositions(
|
||||||
original: string,
|
original: string,
|
||||||
edited: string
|
edited: string
|
||||||
|
|
@ -155,9 +182,12 @@ export class RemoteCursorsPluginValue implements PluginValue {
|
||||||
);
|
);
|
||||||
|
|
||||||
const decorations: Range<Decoration>[] = [];
|
const decorations: Range<Decoration>[] = [];
|
||||||
|
const relative_path = RemoteCursorsPluginValue.findFileForEditor(
|
||||||
RemoteCursorsPluginValue.cursors.forEach(
|
update.view
|
||||||
({ name, span: { start, end } }) => {
|
);
|
||||||
|
RemoteCursorsPluginValue.cursors
|
||||||
|
.filter(({ path }) => path == relative_path)
|
||||||
|
.forEach(({ name, span: { start, end } }) => {
|
||||||
const color = utils.getRandomColor(name);
|
const color = utils.getRandomColor(name);
|
||||||
const startLine = update.view.state.doc.lineAt(start);
|
const startLine = update.view.state.doc.lineAt(start);
|
||||||
const endLine = update.view.state.doc.lineAt(end);
|
const endLine = update.view.state.doc.lineAt(end);
|
||||||
|
|
@ -221,8 +251,7 @@ export class RemoteCursorsPluginValue implements PluginValue {
|
||||||
widget: new RemoteCursorWidget(color, name)
|
widget: new RemoteCursorWidget(color, name)
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
this.decorations = Decoration.set(decorations, true);
|
this.decorations = Decoration.set(decorations, true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,4 +27,4 @@
|
||||||
"prettier": "^3.6.2",
|
"prettier": "^3.6.2",
|
||||||
"typescript-eslint": "8.41.0"
|
"typescript-eslint": "8.41.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,19 @@ async fn websocket(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
send_update_over_websocket(&update.message, &mut sender).await?;
|
let message = match update.message {
|
||||||
|
WebSocketServerMessage::CursorPositions(CursorPositionFromServer { clients }) => {
|
||||||
|
WebSocketServerMessage::CursorPositions(CursorPositionFromServer {
|
||||||
|
clients: clients
|
||||||
|
.into_iter()
|
||||||
|
.filter(|client| client.device_id != device_id)
|
||||||
|
.collect(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
WebSocketServerMessage::VaultUpdate(_) => update.message,
|
||||||
|
};
|
||||||
|
|
||||||
|
send_update_over_websocket(&message, &mut sender).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok::<(), SyncServerError>(())
|
Ok::<(), SyncServerError>(())
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue