-
-
Save Rishabh-malhotraa/d77fded610f5d581bc2d33be553309b3 to your computer and use it in GitHub Desktop.
Ace-Bind
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { RealTimeElement, ModelReference } from "@convergence/convergence"; | |
import { | |
AceMultiCursorManager, | |
AceMultiSelectionManager, | |
} from "@convergencelabs/ace-collab-ext"; | |
import AceEditor from "react-ace"; | |
import { Range as AceRange } from "ace-builds"; | |
import { ColorAssigner } from "@convergence/color-assigner"; | |
import { IAceEditor } from "react-ace/lib/types"; | |
type AceEditorInstance = React.RefObject<AceEditor>; | |
export const initModel = ( | |
textModel: RealTimeElement<string>, | |
AceEditorRef: AceEditorInstance, | |
suppressEvents = false | |
) => { | |
const editor = AceEditorRef.current!.editor; | |
console.log("intiModel"); | |
console.log(editor); | |
const session = editor.getSession(); | |
const document = session.getDocument(); | |
session.setValue(textModel.value()); | |
textModel.on("insert", (e: Record<string, any>) => { | |
const pos = document.indexToPosition(e.index, 0); | |
suppressEvents = true; | |
document.insert(pos, e.value); | |
suppressEvents = false; | |
}); | |
textModel.on("remove", (e: Record<string, any>) => { | |
const start = document.indexToPosition(e.index, 0); | |
const end = document.indexToPosition(e.index + e.value.length, 0); | |
suppressEvents = true; | |
document.remove(new AceRange(start.row, start.column, end.row, end.column)); | |
suppressEvents = false; | |
}); | |
textModel.on("value", function (e: Record<string, any>) { | |
suppressEvents = true; | |
document.setValue(e.value); | |
suppressEvents = false; | |
}); | |
editor.on("change", (delta) => { | |
if (suppressEvents) { | |
return; | |
} | |
const pos = document.positionToIndex(delta.start); | |
switch (delta.action) { | |
case "insert": | |
//@ts-ignore | |
textModel.insert(pos, delta.lines.join("\n")); | |
break; | |
case "remove": | |
//@ts-ignore | |
textModel.remove(pos, delta.lines.join("\n").length); | |
break; | |
default: | |
throw new Error("unknown action: " + delta.action); | |
} | |
}); | |
}; | |
///////////////////////////////////////////////////////////////////////////// | |
// Cursor Binding | |
///////////////////////////////////////////////////////////////////////////// | |
export const initSharedCursors = ( | |
textModel: RealTimeElement<string>, | |
editor: IAceEditor, | |
suppressEvents = false, | |
cursorKey = "cursor" | |
) => { | |
console.log("insidde initSharedCursor"); | |
console.log(editor); | |
const session = editor.getSession(); | |
const document = session.getDocument(); | |
const cursorManager = new AceMultiCursorManager(editor.getSession()); | |
//@ts-ignore | |
const cursorReference = textModel.indexReference(cursorKey); | |
console.log(cursorReference); | |
const references = textModel.references({ key: cursorKey }); | |
references.forEach((reference) => { | |
if (!reference.isLocal()) { | |
addCursor(editor, reference, cursorManager); | |
} | |
}); | |
setLocalCursor(editor, cursorReference); | |
cursorReference.share(); | |
editor | |
.getSession() | |
.selection.on("changeCursor", () => setLocalCursor(editor, document)); | |
textModel.on("reference", (e: Record<string, any>) => { | |
if (e.reference.key() === cursorKey) { | |
addCursor(editor, e.reference, cursorManager); | |
} | |
}); | |
}; | |
function setLocalCursor(editor: IAceEditor, cursorReference: any) { | |
const position = editor.getCursorPosition(); | |
const document = editor.getSession().getDocument(); | |
const index = document.positionToIndex(position); | |
cursorReference.set(index); | |
} | |
function addCursor( | |
editor: IAceEditor, | |
reference: ModelReference<any>, | |
cursorManager: AceMultiCursorManager | |
) { | |
const colorAssigner = new ColorAssigner(ColorAssigner.Palettes.LIGHT_12); | |
const color = colorAssigner.getColorAsHex(reference.sessionId()); | |
const remoteCursorIndex = reference.value(); | |
cursorManager.addCursor( | |
reference.sessionId(), | |
"user-name", | |
color, | |
remoteCursorIndex | |
); | |
reference.on("cleared", () => | |
cursorManager.clearCursor(reference.sessionId()) | |
); | |
reference.on("disposed", () => | |
cursorManager.removeCursor(reference.sessionId()) | |
); | |
reference.on("set", () => { | |
const cursorIndex = reference.value(); | |
cursorManager.setCursor(reference.sessionId(), cursorIndex); | |
// check alert for 0 shizz | |
// const document = editor.getSession().getDocument(); | |
// const cursorRow = document.indexToPosition(cursorIndex, 0).row; | |
// if (radarView.hasView(reference.sessionId())) { | |
// radarView.setCursorRow(reference.sessionId(), cursorRow); | |
// } | |
}); | |
} | |
///////////////////////////////////////////////////////////////////////////// | |
// Selection Binding | |
///////////////////////////////////////////////////////////////////////////// | |
export const initSharedSelection = ( | |
textModel: RealTimeElement<any>, | |
AceEditorRef: AceEditorInstance, | |
suppressEvents = false, | |
selectionKey = "selection" | |
) => { | |
const editor = AceEditorRef.current!.editor; | |
const session = editor.getSession(); | |
console.log(editor); | |
const selectionManager = new AceMultiSelectionManager(editor.getSession()); | |
//@ts-ignore The type definations could be improved URGHHHH | |
const selectionReference = textModel.rangeReference(selectionKey); | |
setLocalSelection(editor, selectionReference); | |
selectionReference.share(); | |
session.selection.on("changeSelection", () => | |
setLocalSelection(editor, selectionReference) | |
); | |
const references = textModel.references({ key: selectionKey }); | |
references.forEach((reference) => { | |
if (!reference.isLocal()) { | |
addSelection(editor, reference, selectionManager); | |
} | |
}); | |
textModel.on("reference", (e: Record<string, any>) => { | |
console.log("textSelection"); | |
console.log(e); | |
if (e.reference.key() === selectionKey) { | |
addSelection(editor, e.reference, selectionManager); | |
} | |
}); | |
}; | |
function setLocalSelection(editor: IAceEditor, selectionReference: any) { | |
const document = editor.getSession().getDocument(); | |
if (!editor.selection.isEmpty()) { | |
const aceRanges = editor.selection.getAllRanges(); | |
const indexRanges = aceRanges.map((aceRagne) => { | |
const start = document.positionToIndex(aceRagne.start); | |
const end = document.positionToIndex(aceRagne.end); | |
return { start: start, end: end }; | |
}); | |
selectionReference.set(indexRanges); | |
} else if (selectionReference.isSet()) { | |
selectionReference.clear(); | |
} | |
} | |
function addSelection( | |
editor: IAceEditor, | |
reference: ModelReference<any>, | |
selectionManager: AceMultiSelectionManager | |
) { | |
const colorAssigner = new ColorAssigner(ColorAssigner.Palettes.LIGHT_12); | |
const color = colorAssigner.getColorAsHex(reference.sessionId()); | |
const remoteSelection = reference | |
.values() | |
.map((range) => toAceRange(editor, range)); | |
selectionManager.addSelection( | |
reference.sessionId(), | |
reference.user().username, | |
color, | |
//@ts-ignore | |
remoteSelection | |
); | |
reference.on("cleared", () => | |
selectionManager.clearSelection(reference.sessionId()) | |
); | |
reference.on("disposed", () => | |
selectionManager.removeSelection(reference.sessionId()) | |
); | |
reference.on("set", () => { | |
selectionManager.setSelection( | |
reference.sessionId(), | |
//@ts-ignore | |
reference.values().map((range) => toAceRange(editor, range)) | |
); | |
}); | |
} | |
function toAceRange(editor: IAceEditor, range: Record<string, number>) { | |
if (typeof range !== "object") { | |
return null; | |
} | |
let start = range.start; | |
let end = range.end; | |
if (start > end) { | |
const temp = start; | |
start = end; | |
end = temp; | |
} | |
const document = editor.getSession().getDocument(); | |
const rangeAnchor = document.indexToPosition(start, 0); | |
const rangeLead = document.indexToPosition(end, 0); | |
return new AceRange( | |
rangeAnchor.row, | |
rangeAnchor.column, | |
rangeLead.row, | |
rangeLead.column | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment