Skip to content

Commit

Permalink
[#71910] Add vim mode setting and support editor settings in comments
Browse files Browse the repository at this point in the history
  • Loading branch information
Mikolaj Trzcinski authored and mgielda committed Feb 4, 2025
1 parent ae76128 commit 76cb585
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 5 deletions.
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"@codemirror/view": "^6.16.0",
"@preact/compat": "^17.1.2",
"@preact/signals": "^1.3.0",
"@replit/codemirror-vim": "^6.2.1",
"codemirror": "^6.0.1",
"dompurify": "^2.3.5",
"imurmurhash": "^0.1.4",
Expand Down
18 changes: 15 additions & 3 deletions src/components/Comment.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useRef, useEffect, useState, useCallback, useMemo, useContext } from "preact/hooks";
import { styled } from "styled-components";
import { EditorView } from "codemirror";
import { EditorState } from "@codemirror/state";
import { Compartment, EditorState } from "@codemirror/state";
import { ExtensionBuilder } from "../extensions";
import { YComments } from "../comments/ycomments";
import commentIcon from "../icons/comment.svg?url";
Expand Down Expand Up @@ -71,9 +71,12 @@ const YCommentWrapper = styled.div`
}
`;

const commentUserSettingsCompartment = new Compartment();

const YComment = ({ commentId }) => {
const { options, collab } = useContext(MystState);
const { options, collab, userSettings } = useContext(MystState);
let cmref = useRef(null);
const cmView = useRef(null);

const lineAuthors = useMemo(() => collab.value.ycomments.lineAuthors(commentId), [commentId]);

Expand All @@ -85,6 +88,14 @@ const YComment = ({ commentId }) => {

const parentHeight = collab.value.ycomments.parentLineHeight(commentId) - 1;

useEffect(() => {
if (!cmView.current) return;
const userExtensions = userSettings.value.filter((s) => s.enabled && s.extension && s.comments).map((s) => s.extension);
cmView.current.dispatch({
effects: commentUserSettingsCompartment.reconfigure(userExtensions),
});
}, [userSettings.value, cmView.current]);

useEffect(() => {
if (!cmref.current) {
return;
Expand All @@ -96,14 +107,15 @@ const YComment = ({ commentId }) => {
extensions: ExtensionBuilder.minimalSetup()
.disable(["Mod-z", "Mod-y", "Mod-Z"])
.useCollaboration({ collabClient: { ytext, provider: collab.value.provider } })
.useDefaultHistory()
.addUpdateListener(updateHeight)
.showCommentLineAuthors(lineAuthors)
.useRemoveSelectionOnBlur()
.useCompartment(commentUserSettingsCompartment, [])
.create(),
}),
parent: cmref.current,
});
cmView.current = view;

collab.value.ycomments.syncSuggestions(commentId);
collab.value.ycomments.registerCommentEditor(commentId, view);
Expand Down
4 changes: 3 additions & 1 deletion src/extensions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
crosshairCursor,
keymap,
} from "@codemirror/view";
import { EditorSelection, EditorState, Prec } from "@codemirror/state";
import { EditorSelection, EditorState, Facet, Prec } from "@codemirror/state";
import { EditorView } from "codemirror";
import { yCollab } from "y-codemirror.next";
import { markdown } from "@codemirror/lang-markdown";
Expand Down Expand Up @@ -57,6 +57,7 @@ const restoreCursorLocation = (view, location) => {
};

export const folded = (update) => update.transactions.some((t) => t.effects.some((e) => e.is(foldEffect) || e.is(unfoldEffect)));
export const collabClientFacet = Facet.define();

export class ExtensionBuilder {
constructor(base = []) {
Expand Down Expand Up @@ -193,6 +194,7 @@ export class ExtensionBuilder {
const collab = yCollab(collabClient.ytext, collabClient.provider.awareness, { undoManager: collabClient.undoManager });
collab[1] = ySync;
this.extensions.push(collab);
this.extensions.push(collabClientFacet.of(collabClient));

if (collabClient.undoManager) {
collabClient.undoManager.on("stack-item-added", (event) => {
Expand Down
2 changes: 1 addition & 1 deletion src/extensions/suggestions.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export function suggestionPopup(/** @type {ViewUpdate} */ update, /** @type {YCo
const mainSel = update.state.selection.main;
const noSelection = mainSel.head === mainSel.anchor;
const multilineSelection = update.state.doc.lineAt(mainSel.head).number !== update.state.doc.lineAt(mainSel.anchor).number;
if (!update.selectionSet || noSelection || multilineSelection) {
if (!update.view.hasFocus || noSelection || multilineSelection) {
addSuggestionBtn.style.display = "none";
return;
}
Expand Down
25 changes: 25 additions & 0 deletions src/mystState.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { createContext } from "preact";
import { closeBrackets } from "@codemirror/autocomplete";
import Settings from "./components/Settings";
import { CollaborationClient } from "./collaboration";
import { CodeMirror as VimCM, vim } from "@replit/codemirror-vim";
import { collabClientFacet } from "./extensions";

export const predefinedButtons = {
printToPdf: {
Expand All @@ -30,6 +32,12 @@ export const defaultButtons = [
predefinedButtons.templateManager,
];

// The vim plugin stores some functions as globals, but we need to differentiate between editors
const undoManagers = new WeakMap();
const { undo: originalUndo, redo: originalRedo } = VimCM.commands;
VimCM.commands.undo = (cm) => (undoManagers.get(cm)?.undo ?? originalUndo)(cm);
VimCM.commands.redo = (cm) => (undoManagers.get(cm)?.redo ?? originalRedo)(cm);

const defaultUserSettings = [
{
id: "auto-markdown",
Expand Down Expand Up @@ -77,6 +85,23 @@ const defaultUserSettings = [
},
),
},
{
id: "vim",
title: "Vim mode",
enabled: false,
comments: true,
extension: [
Prec.high(vim()),
ViewPlugin.fromClass(
class {
constructor(view) {
const undoManager = view.state.facet(collabClientFacet)[0]?.undoManager;
if (undoManager) undoManagers.set(view.cm, { undo: () => undoManager.undo(), redo: () => undoManager.redo() });
}
},
),
],
},
];

const defaults = {
Expand Down

0 comments on commit 76cb585

Please sign in to comment.