Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert #63

Open
wants to merge 59 commits into
base: patchwork
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
de3c038
hide comment highlights if timeline sidebar is open
paulsonnentag May 24, 2024
6c43b9c
reset history state when switching to review mode
paulsonnentag May 16, 2024
8a0215d
create a valid range when trying to comment on the end of the document
paulsonnentag May 16, 2024
e012520
filter out comments on empty ranges
paulsonnentag May 16, 2024
622ea3b
add global keyboard shortcut cmd+m+shift to comment
paulsonnentag May 24, 2024
0b111cb
handle setSelectedAnchors if selection is not a range
paulsonnentag May 17, 2024
9e134f5
fix stale annotations in hook
paulsonnentag May 17, 2024
75ae3f8
Add general comments without anchors above all other comments
paulsonnentag May 17, 2024
4786d1b
fix boundary check
paulsonnentag May 17, 2024
106e638
don't render duplicate hightlight + added annotation when commenting …
paulsonnentag May 17, 2024
b47da99
allow to use markdown in comments
paulsonnentag Jun 3, 2024
a070345
Render markdown comments
paulsonnentag May 21, 2024
b30c27c
support images in comments
paulsonnentag Jun 3, 2024
56d3f1a
WIP: add back inline comments for tee
paulsonnentag May 21, 2024
9cd72f4
hide inline comments when sidebar is open
paulsonnentag May 21, 2024
51a117f
tweak styling
paulsonnentag May 21, 2024
4952249
handle hover state
paulsonnentag May 21, 2024
7b1f509
tweak styling
paulsonnentag May 22, 2024
c424a0b
move resolve logic into AnnotationGroupView
paulsonnentag May 22, 2024
777765a
allow to edit own comments
paulsonnentag May 22, 2024
405180f
fix click handler
paulsonnentag May 22, 2024
81e67da
hoist up comment edit state to VersionControlEditor
paulsonnentag May 22, 2024
b0ddc33
Allow to reply to comments
paulsonnentag May 22, 2024
e3fffce
Add comment button
paulsonnentag May 23, 2024
f8eaf77
create pending discussion group when comment is added on new range
paulsonnentag May 23, 2024
cf8ed43
hide comment button if editor is not focused
paulsonnentag May 23, 2024
d6eeee5
allow to comment on end of document
paulsonnentag May 23, 2024
82cf2fc
Add comment button in sidebar
paulsonnentag May 23, 2024
70523cb
replace edit/create comment with setCommentState
paulsonnentag May 23, 2024
737980a
fix global comments
paulsonnentag May 23, 2024
de2b382
stop navigation key presses from bubbling up
paulsonnentag May 23, 2024
dfd480c
Fix adding replies
paulsonnentag May 23, 2024
29a8a91
fix keyboard shortcuts
paulsonnentag May 23, 2024
ea5d72d
fix filter out resolved discussions
paulsonnentag May 23, 2024
8f78944
adjust estimatedHeightOfAnnotationGroups function
paulsonnentag May 23, 2024
df233ba
tweak styling
paulsonnentag May 24, 2024
f7bb647
codemirror: avoid triggering redundant events
paulsonnentag May 24, 2024
ed5ca1f
fix global add coment keyboard shortcut
paulsonnentag May 24, 2024
d925c55
show comments without anchors always on top
paulsonnentag May 24, 2024
9c45b6f
render whitespaces in essay annotations correctly
paulsonnentag May 24, 2024
555fa18
fix commenting on edits
paulsonnentag May 24, 2024
f69dd01
don't filter out annotations at beginning of text
paulsonnentag May 24, 2024
5771f6d
cleanup higlight renders in EssayAnnotations view
paulsonnentag May 24, 2024
a8500a2
fix side by side
paulsonnentag May 24, 2024
b518caf
only highlight sidebar button for datatypes without inline comments
paulsonnentag May 24, 2024
7b1225e
fix type errors
paulsonnentag May 24, 2024
50e224b
fix view branch button
paulsonnentag May 24, 2024
e05e2d5
fix accesing property on undefined
paulsonnentag May 24, 2024
68c605c
add naive invert
paulsonnentag Jun 3, 2024
a7609b9
normalize redundant patches in essay
paulsonnentag Jun 3, 2024
5665824
fix offset bugs
paulsonnentag Jun 3, 2024
2c8261c
When normalizing an insert followed by a delete try to display it as …
paulsonnentag Jun 3, 2024
3ac26c5
handle complete overlaps correctly
paulsonnentag Jun 3, 2024
0e87a82
try to create full word replacements when normalizing changes with ov…
paulsonnentag Jun 3, 2024
dd1e822
Simplify diff normalization
paulsonnentag Jun 4, 2024
2aa300b
do a content based diff on subsequent insert delete patches
paulsonnentag Jun 4, 2024
c0b027c
add inverse patches to replace
paulsonnentag Jun 4, 2024
f684683
combine words
paulsonnentag Jun 4, 2024
5d92a28
make patches relative
paulsonnentag Jun 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"@codemirror/view": "^6.21.3",
"@handsontable/react": "^14.1.0",
"@lezer/highlight": "^1.1.6",
"@onsetsoftware/automerge-patcher": "^0.13.0",
"@radix-ui/react-avatar": "^1.0.4",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-context-menu": "^2.1.5",
Expand All @@ -51,6 +52,7 @@
"cmdk": "^0.2.0",
"codemirror": "^6.0.1",
"d3": "^7.8.5",
"diff": "^5.2.0",
"eventemitter3": "^5.0.1",
"haikunator": "^2.1.2",
"handsontable": "^14.1.0",
Expand Down Expand Up @@ -78,6 +80,7 @@
"devDependencies": {
"@rollup/plugin-node-resolve": "^15.2.3",
"@testing-library/react": "^15.0.2",
"@types/diff": "^5.2.1",
"@types/lodash": "^4.14.199",
"@types/node": "^20.8.2",
"@types/react": "^18.2.15",
Expand Down
4 changes: 2 additions & 2 deletions src/datatypes/bot/datatype.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ContactDoc, RegisteredContactDoc } from "@/os/explorer/account";
import { MarkdownDatatype } from "@/datatypes/markdown/datatype";
import { MarkdownDoc } from "@/datatypes/markdown/schema";
import { MarkdownDatatype } from "@/datatypes/essay/datatype";
import { MarkdownDoc } from "@/datatypes/essay/schema";
import { type DataType } from "@/os/datatypes";
import { AutomergeUrl, Repo } from "@automerge/automerge-repo";
import { Bot } from "lucide-react";
Expand Down
2 changes: 1 addition & 1 deletion src/datatypes/bot/essayEditingBot.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { RegisteredContactDoc } from "@/os/explorer/account";
import { DEFAULT_MODEL, openaiClient } from "@/os/lib/llm";
import { createBranch } from "@/os/versionControl/branches";
import { MarkdownDoc } from "@/datatypes/markdown/schema";
import { MarkdownDoc } from "@/datatypes/essay/schema";
import { AutomergeUrl, DocHandle, Repo } from "@automerge/automerge-repo";
import { splice } from "@automerge/automerge/next";
import { EssayEditingBotDoc } from "./schema";
Expand Down
181 changes: 155 additions & 26 deletions src/datatypes/markdown/datatype.ts → src/datatypes/essay/datatype.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ import {
} from "@/os/versionControl/utils";
import { next as A } from "@automerge/automerge";
import { Repo } from "@automerge/automerge-repo";
import { Doc, splice } from "@automerge/automerge/next";
import { splice } from "@automerge/automerge/next";
import { pick } from "lodash";
import { Text } from "lucide-react";
import { AssetsDoc } from "../../tools/essay/assets";
import { MarkdownDoc, MarkdownDocAnchor } from "./schema";
import { diffWords } from "diff";

import JSZip from "jszip";

Expand Down Expand Up @@ -148,13 +149,13 @@ export const patchesToAnnotations = (

switch (patch.action) {
case "splice": {
const patchStart = patch.path[1] as number;
const patchEnd = Math.min(
let fromPos = patch.path[1] as number;
let toPos = Math.min(
(patch.path[1] as number) + patch.value.length,
doc.content.length - 1
);
const fromCursor = getCursorSafely(doc, ["content"], patchStart);
const toCursor = getCursorSafely(doc, ["content"], patchEnd);
let fromCursor = A.getCursor(doc, ["content"], fromPos);
let toCursor = A.getCursor(doc, ["content"], toPos);

if (!fromCursor || !toCursor) {
console.warn("Failed to get cursor for patch", patch);
Expand All @@ -165,25 +166,17 @@ export const patchesToAnnotations = (
if (
nextPatch &&
nextPatch.action === "del" &&
nextPatch.path[1] === patchEnd
nextPatch.path[1] === toPos
) {
const before = docBefore.content.slice(
patchStart - offset,
patchStart - offset + nextPatch.length
let deleted = docBefore.content.slice(
fromPos - offset,
fromPos - offset + (nextPatch.length ?? 1)
);
let inserted = patch.value;

annotations.push({
type: "changed",
before,
after: patch.value,
anchor: {
fromCursor: fromCursor,
toCursor: toCursor,
},
});
annotations.push(...diffText(deleted, inserted, doc, fromPos));

offset += patch.value.length - nextPatch.length;

i += 1;
} else {
annotations.push({
Expand All @@ -193,6 +186,14 @@ export const patchesToAnnotations = (
fromCursor: fromCursor,
toCursor: toCursor,
},
inversePatches: [
{
action: "del",
path: ["content"],
cursor: fromCursor,
length: patch.value.length,
},
],
});

offset += patch.value.length;
Expand All @@ -201,18 +202,17 @@ export const patchesToAnnotations = (
}
case "del": {
const patchStart = patch.path[1] as number;
const patchEnd = (patch.path[1] as number) + 1;
const fromCursor = getCursorSafely(doc, ["content"], patchStart);
const toCursor = getCursorSafely(doc, ["content"], patchEnd);
const cursor = getCursorSafely(doc, ["content"], patchStart);

const patchLength = patch.length ?? 1; // length is undefined if only one character is deleted
const deleted = docBefore.content.slice(
patchStart - offset,
patchStart - offset + patch.length
patchStart - offset + patchLength
);

offset -= patch.length;

if (!fromCursor || !toCursor) {
if (!cursor) {
console.warn("Failed to get cursor for patch", patch);
break;
}
Expand All @@ -221,9 +221,17 @@ export const patchesToAnnotations = (
type: "deleted",
deleted,
anchor: {
fromCursor: fromCursor,
toCursor: toCursor,
fromCursor: cursor,
toCursor: cursor,
},
inversePatches: [
{
action: "splice",
path: ["content"],
cursor,
value: deleted,
},
],
});
break;
}
Expand All @@ -236,10 +244,130 @@ export const patchesToAnnotations = (
return annotations;
};

const diffText = (
before: string,
after: string,
doc: MarkdownDoc,
offset: number
): Annotation<MarkdownDocAnchor, string>[] => {
const annotations: Annotation<MarkdownDocAnchor, string>[] = [];
const parts = diffWords(before, after);

for (let i = 0; i < parts.length; i++) {
let deleted = "";
let added = "";

for (; i < parts.length; i++) {
let part = parts[i];

if (part.added) {
added += part.value;
offset += part.value.length;
} else if (part.removed) {
deleted += part.value;
} else {
if (part.value.trim() === "") {
added += part.value;
deleted += part.value;
offset += part.value.length;
} else if (deleted === "" && added === "") {
offset += part.value.length;
} else {
i--;
break;
}
}

const nextPart = parts[i + 1];
if (
nextPart &&
!nextPart.added &&
!nextPart.removed &&
nextPart.value.trim() !== ""
) {
break;
}
}

if (deleted.length > 0 && added.length > 0) {
const anchor = {
fromCursor: A.getCursor(doc, ["content"], offset - added.length),
toCursor: A.getCursor(doc, ["content"], offset),
};

annotations.push({
type: "changed",
anchor,
before: deleted,
after: added,
inversePatches: [
{
action: "del",
path: ["content"],
cursor: anchor.fromCursor,
length: added.length,
},
{
action: "splice",
path: ["content"],
cursor: anchor.fromCursor,
value: deleted,
},
],
});
} else if (deleted.length > 0) {
const cursor = A.getCursor(doc, ["content"], offset);

annotations.push({
type: "deleted",
anchor: {
fromCursor: cursor,
toCursor: cursor,
},
deleted,
inversePatches: [
{
action: "splice",
path: ["content"],
cursor,
value: deleted,
},
],
});
} else if (added.length > 0) {
const anchor = {
fromCursor: A.getCursor(doc, ["content"], offset - added.length),
toCursor: A.getCursor(doc, ["content"], offset),
};
annotations.push({
type: "added",
anchor,
added,
inversePatches: [
{
action: "del",
path: ["content"],
cursor: anchor.fromCursor,
length: added.length,
},
],
});
}
}

return annotations;
};

const valueOfAnchor = (doc: MarkdownDoc, anchor: MarkdownDocAnchor) => {
const from = getCursorPositionSafely(doc, ["content"], anchor.fromCursor);
const to = getCursorPositionSafely(doc, ["content"], anchor.toCursor);

// if the anchor points to an empty range return undefined
// so highlight comments that point to this will be filtered out
if (from === to) {
return undefined;
}

return doc.content.slice(from, to);
};

Expand Down Expand Up @@ -308,4 +436,5 @@ export const MarkdownDatatype: DataType<
doAnchorsOverlap,
sortAnchorsBy,
fileExportMethods,
supportsInlineComments: true, // todo: this should be part of the viewer
};
File renamed without changes.
File renamed without changes.
20 changes: 1 addition & 19 deletions src/datatypes/markdown/utils.ts → src/datatypes/essay/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as A from "@automerge/automerge/next";
import { ReactElement, useEffect, useState } from "react";
import { ReactElement } from "react";
import ReactDOMServer from "react-dom/server";
import { MarkdownDoc } from "./schema";

Expand All @@ -8,24 +8,6 @@ export const isMarkdownDoc = (doc: A.Doc<unknown>): doc is MarkdownDoc => {
return typeof typedDoc.content === "string";
};

export const useScrollPosition = (container: HTMLElement | null) => {
const [scrollPosition, setScrollPosition] = useState(0);

useEffect(() => {
if (!container) {
return;
}
const updatePosition = () => {
setScrollPosition(container.scrollTop);
};
container.addEventListener("scroll", () => updatePosition());
updatePosition();
return () => container.removeEventListener("scroll", updatePosition);
}, [container]);

return scrollPosition;
};

// Utils for converting back and forth between CodeMirror and Automerge ranges.
// The end of a Codemirror range can be an index past the last character in the
// document, but we can't get an Automerge cursor for that position.
Expand Down
3 changes: 3 additions & 0 deletions src/datatypes/tldraw/datatype.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
initVersionControlMetadata,
} from "@/os/versionControl/schema";
import { defaultShapeUtils, Editor } from "@tldraw/tldraw";
import { unpatch } from "@onsetsoftware/automerge-patcher";

// When a copy of the document has been made,
// update the title so it's more clear which one is the copy vs original.
Expand Down Expand Up @@ -119,6 +120,7 @@ export const patchesToAnnotations = (
type: "deleted",
deleted: docBefore.store[shapeId],
anchor: shapeId,
inversePatches: [unpatch(docBefore, patch)],
} as Annotation<TLDrawDocAnchor, TLShape>,
];

Expand All @@ -128,6 +130,7 @@ export const patchesToAnnotations = (
type: "added",
added: doc.store[shapeId],
anchor: shapeId,
inversePatches: [unpatch(docBefore, patch)],
} as Annotation<TLDrawDocAnchor, TLShape>,
];

Expand Down
7 changes: 6 additions & 1 deletion src/os/datatypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ import bot from "@/datatypes/bot";
import datagrid from "@/datatypes/datagrid";
import folder from "@/datatypes/folder";
import kanban from "@/datatypes/kanban";
import markdown from "@/datatypes/markdown";
import markdown from "@/datatypes/essay";
import tldraw from "@/datatypes/tldraw";
import { FileExportMethod } from "./fileExports";
import { HasAssets } from "@/tools/essay/assets";

export type CoreDataType<D> = {
id: string;
Expand Down Expand Up @@ -108,6 +109,10 @@ export type VersionedDataType<D, T, V> = {
* If this method is not implemented the anchors will not be sorted.
*/
sortAnchorsBy?: (doc: D, anchor: T) => any;

// flag wether or not this data type has support for rendering comments inline or if it
// relies exclusively on the review sidebar to show comments
supportsInlineComments?: boolean;
};

export type DataType<D, T, V> = CoreDataType<D> & VersionedDataType<D, T, V>;
Expand Down
Loading