Skip to content

Commit

Permalink
[lexical-yjs] Feature: Expose function to get anchor and focus nodes …
Browse files Browse the repository at this point in the history
…for given user awareness state (facebook#6942)
  • Loading branch information
amanharwara authored Jan 4, 2025
1 parent 8100d6d commit 2b4252d
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 73 deletions.
147 changes: 75 additions & 72 deletions packages/lexical-yjs/src/SyncCursors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
createRelativePositionFromTypeIndex,
} from 'yjs';

import {Provider} from '.';
import {Provider, UserState} from '.';
import {CollabDecoratorNode} from './CollabDecoratorNode';
import {CollabElementNode} from './CollabElementNode';
import {CollabLineBreakNode} from './CollabLineBreakNode';
Expand Down Expand Up @@ -295,50 +295,73 @@ function updateCursor(
}
}

export function $syncLocalCursorPosition(
binding: Binding,
provider: Provider,
): void {
const awareness = provider.awareness;
const localState = awareness.getLocalState();
type AnyCollabNode =
| CollabDecoratorNode
| CollabElementNode
| CollabTextNode
| CollabLineBreakNode;

if (localState === null) {
return;
}
export function getAnchorAndFocusCollabNodesForUserState(
binding: Binding,
userState: UserState,
) {
const {anchorPos, focusPos} = userState;

const anchorPos = localState.anchorPos;
const focusPos = localState.focusPos;
let anchorCollabNode: AnyCollabNode | null = null;
let anchorOffset = 0;
let focusCollabNode: AnyCollabNode | null = null;
let focusOffset = 0;

if (anchorPos !== null && focusPos !== null) {
const anchorAbsPos = createAbsolutePosition(anchorPos, binding);
const focusAbsPos = createAbsolutePosition(focusPos, binding);

if (anchorAbsPos !== null && focusAbsPos !== null) {
const [anchorCollabNode, anchorOffset] = getCollabNodeAndOffset(
[anchorCollabNode, anchorOffset] = getCollabNodeAndOffset(
anchorAbsPos.type,
anchorAbsPos.index,
);
const [focusCollabNode, focusOffset] = getCollabNodeAndOffset(
[focusCollabNode, focusOffset] = getCollabNodeAndOffset(
focusAbsPos.type,
focusAbsPos.index,
);
}
}

if (anchorCollabNode !== null && focusCollabNode !== null) {
const anchorKey = anchorCollabNode.getKey();
const focusKey = focusCollabNode.getKey();
return {
anchorCollabNode,
anchorOffset,
focusCollabNode,
focusOffset,
};
}

const selection = $getSelection();
export function $syncLocalCursorPosition(
binding: Binding,
provider: Provider,
): void {
const awareness = provider.awareness;
const localState = awareness.getLocalState();

if (!$isRangeSelection(selection)) {
return;
}
const anchor = selection.anchor;
const focus = selection.focus;
if (localState === null) {
return;
}

$setPoint(anchor, anchorKey, anchorOffset);
$setPoint(focus, focusKey, focusOffset);
}
const {anchorCollabNode, anchorOffset, focusCollabNode, focusOffset} =
getAnchorAndFocusCollabNodesForUserState(binding, localState);

if (anchorCollabNode !== null && focusCollabNode !== null) {
const anchorKey = anchorCollabNode.getKey();
const focusKey = focusCollabNode.getKey();

const selection = $getSelection();

if (!$isRangeSelection(selection)) {
return;
}

$setPoint(selection.anchor, anchorKey, anchorOffset);
$setPoint(selection.focus, focusKey, focusOffset);
}
}

Expand All @@ -363,16 +386,7 @@ function getCollabNodeAndOffset(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
sharedType: any,
offset: number,
): [
(
| null
| CollabDecoratorNode
| CollabElementNode
| CollabTextNode
| CollabLineBreakNode
),
number,
] {
): [null | AnyCollabNode, number] {
const collabNode = sharedType._collabNode;

if (collabNode === undefined) {
Expand Down Expand Up @@ -413,7 +427,7 @@ export function syncCursorPositions(

if (clientID !== localClientID) {
visitedClientIDs.add(clientID);
const {anchorPos, focusPos, name, color, focusing} = awareness;
const {name, color, focusing} = awareness;
let selection = null;

let cursor = cursors.get(clientID);
Expand All @@ -423,41 +437,30 @@ export function syncCursorPositions(
cursors.set(clientID, cursor);
}

if (anchorPos !== null && focusPos !== null && focusing) {
const anchorAbsPos = createAbsolutePosition(anchorPos, binding);
const focusAbsPos = createAbsolutePosition(focusPos, binding);

if (anchorAbsPos !== null && focusAbsPos !== null) {
const [anchorCollabNode, anchorOffset] = getCollabNodeAndOffset(
anchorAbsPos.type,
anchorAbsPos.index,
);
const [focusCollabNode, focusOffset] = getCollabNodeAndOffset(
focusAbsPos.type,
focusAbsPos.index,
);

if (anchorCollabNode !== null && focusCollabNode !== null) {
const anchorKey = anchorCollabNode.getKey();
const focusKey = focusCollabNode.getKey();
selection = cursor.selection;

if (selection === null) {
selection = createCursorSelection(
cursor,
anchorKey,
anchorOffset,
focusKey,
focusOffset,
);
} else {
const anchor = selection.anchor;
const focus = selection.focus;
anchor.key = anchorKey;
anchor.offset = anchorOffset;
focus.key = focusKey;
focus.offset = focusOffset;
}
if (focusing) {
const {anchorCollabNode, anchorOffset, focusCollabNode, focusOffset} =
getAnchorAndFocusCollabNodesForUserState(binding, awareness);

if (anchorCollabNode !== null && focusCollabNode !== null) {
const anchorKey = anchorCollabNode.getKey();
const focusKey = focusCollabNode.getKey();
selection = cursor.selection;

if (selection === null) {
selection = createCursorSelection(
cursor,
anchorKey,
anchorOffset,
focusKey,
focusOffset,
);
} else {
const anchor = selection.anchor;
const focus = selection.focus;
anchor.key = anchorKey;
anchor.offset = anchorOffset;
focus.key = focusKey;
focus.offset = focusOffset;
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion packages/lexical-yjs/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,10 @@ export function setLocalStateFocus(
localState.focusing = focusing;
awareness.setLocalState(localState);
}
export {syncCursorPositions} from './SyncCursors';
export {
getAnchorAndFocusCollabNodesForUserState,
syncCursorPositions,
} from './SyncCursors';
export {
syncLexicalUpdateToYjs,
syncYjsChangesToLexical,
Expand Down

0 comments on commit 2b4252d

Please sign in to comment.