Skip to content

Commit

Permalink
fix: removing readonly editor
Browse files Browse the repository at this point in the history
  • Loading branch information
Palanikannan1437 committed Dec 9, 2024
1 parent b1c340b commit d29ab80
Show file tree
Hide file tree
Showing 23 changed files with 296 additions and 291 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, { useEffect, useState } from "react";
// components
import { DocumentContentLoader, PageRenderer } from "@/components/editors";
// constants
Expand All @@ -19,6 +19,7 @@ const CollaborativeDocumentEditor = (props: ICollaborativeDocumentEditor) => {
containerClassName,
disabledExtensions,
displayConfig = DEFAULT_DISPLAY_CONFIG,
editable,
editorClassName = "",
embedHandler,
fileHandler,
Expand All @@ -43,33 +44,56 @@ const CollaborativeDocumentEditor = (props: ICollaborativeDocumentEditor) => {
}

// use document editor
const { editor, hasServerConnectionFailed, hasServerSynced } = useCollaborativeEditor({
onTransaction,
disabledExtensions,
editorClassName,
embedHandler,
extensions,
fileHandler,
forwardedRef,
handleEditorReady,
id,
mentionHandler,
placeholder,
realtimeConfig,
serverHandler,
tabIndex,
user,
});
const { editor, hasServerConnectionFailed, hasServerSynced, localProvider, hasIndexedDbSynced } =
useCollaborativeEditor({
disabledExtensions,
editable,
editorClassName,
embedHandler,
extensions,
fileHandler,
forwardedRef,
handleEditorReady,
id,
mentionHandler,
onTransaction,
placeholder,
realtimeConfig,
serverHandler,
tabIndex,
user,
});

const editorContainerClassNames = getEditorClassNames({
noBorder: true,
borderOnFocus: false,
containerClassName,
});

const [hasIndexedDbEntry, setHasIndexedDbEntry] = useState(null);

useEffect(() => {
async function documentIndexedDbEntry(dbName: string) {
try {
const databases = await indexedDB.databases();
const hasEntry = databases.some((db) => db.name === dbName);
setHasIndexedDbEntry(hasEntry);
} catch (error) {
console.error("Error checking database existence:", error);
return false;
}
}
documentIndexedDbEntry(id);
}, [id, localProvider]);

if (!editor) return null;

if (!hasServerSynced && !hasServerConnectionFailed) return <DocumentContentLoader />;
// Wait until we know about IndexedDB status
if (hasIndexedDbEntry === null) return null;

if (hasServerConnectionFailed || (!hasIndexedDbEntry && !hasServerSynced) || !hasIndexedDbSynced) {
return <DocumentContentLoader />;
}

return (
<PageRenderer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ export const PageRenderer = (props: IPageRenderer) => {
[editor, cleanup]
);

console.log("rendered");
return (
<>
<div className="frame-renderer flex-grow w-full -mx-5" onMouseOver={handleLinkHover}>
Expand All @@ -139,12 +140,12 @@ export const PageRenderer = (props: IPageRenderer) => {
id={id}
>
<EditorContentWrapper editor={editor} id={id} tabIndex={tabIndex} />
{editor.isEditable && (
<>
<BlockMenu editor={editor} />
<AIFeaturesMenu menu={aiHandler?.menu} />
</>
)}
{/* {editor.isEditable && ( */}
{/* <> */}
{/* <BlockMenu editor={editor} /> */}
{/* <AIFeaturesMenu menu={aiHandler?.menu} /> */}
{/* </> */}
{/* )} */}
</EditorContainer>
</div>
{isOpen && linkViewProps && coordinates && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const EditorWrapper: React.FC<Props> = (props) => {
containerClassName,
disabledExtensions,
displayConfig = DEFAULT_DISPLAY_CONFIG,
editable,
editorClassName = "",
extensions,
id,
Expand All @@ -38,6 +39,7 @@ export const EditorWrapper: React.FC<Props> = (props) => {
} = props;

const editor = useEditor({
editable,
disabledExtensions,
editorClassName,
enableHistory: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,24 +127,30 @@ export const CustomImageUploader = (props: CustomImageUploaderProps) => {
return "Uploading...";
}

if (draggedInside) {
if (draggedInside && editor.isEditable) {
return "Drop image here";
}

return "Add an image";
if (!editor.isEditable) {
return "Viewing Mode: Image Upload Disabled";
} else {
return "Add an image";
}
}, [draggedInside, failedToLoadImage, isImageBeingUploaded]);

return (
<div
className={cn(
"image-upload-component flex items-center justify-start gap-2 py-3 px-2 rounded-lg text-custom-text-300 hover:text-custom-text-200 bg-custom-background-90 hover:bg-custom-background-80 border border-dashed border-custom-border-300 transition-all duration-200 ease-in-out cursor-default",
"image-upload-component flex items-center justify-start gap-2 py-3 px-2 rounded-lg text-custom-text-300 bg-custom-background-90 border border-dashed border-custom-border-300 transition-all duration-200 ease-in-out cursor-default",
{
"hover:text-custom-text-200 cursor-pointer": editor.isEditable,
"bg-custom-background-80 text-custom-text-200": draggedInside,
"text-custom-primary-200 bg-custom-primary-100/10 hover:bg-custom-primary-100/10 hover:text-custom-primary-200 border-custom-primary-200/10":
selected,
"text-red-500 cursor-default hover:text-red-500": failedToLoadImage,
"bg-red-500/10 hover:bg-red-500/10": failedToLoadImage && selected,
"hover:text-custom-text-200 hover:bg-custom-background-80 cursor-pointer": editor.isEditable,
"bg-custom-background-80 text-custom-text-200": draggedInside && editor.isEditable,
"text-custom-primary-200 bg-custom-primary-100/10 border-custom-primary-200/10 hover:bg-custom-primary-100/10 hover:text-custom-primary-200":
selected && editor.isEditable,
"text-red-500 cursor-default": failedToLoadImage,
"hover:text-red-500": failedToLoadImage && editor.isEditable,
"bg-red-500/10": failedToLoadImage && selected,
"hover:bg-red-500/10": failedToLoadImage && selected && editor.isEditable,
}
)}
onDrop={onDrop}
Expand Down
97 changes: 53 additions & 44 deletions packages/editor/src/core/extensions/drop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,58 +2,67 @@ import { Extension, Editor } from "@tiptap/core";
import { Plugin, PluginKey } from "@tiptap/pm/state";
import { EditorView } from "@tiptap/pm/view";

export const DropHandlerExtension = () =>
Extension.create({
name: "dropHandler",
priority: 1000,
export const DropHandlerExtension = Extension.create({
name: "dropHandler",
priority: 1000,

addProseMirrorPlugins() {
const editor = this.editor;
return [
new Plugin({
key: new PluginKey("drop-handler-plugin"),
props: {
handlePaste: (view: EditorView, event: ClipboardEvent) => {
if (event.clipboardData && event.clipboardData.files && event.clipboardData.files.length > 0) {
event.preventDefault();
const files = Array.from(event.clipboardData.files);
const imageFiles = files.filter((file) => file.type.startsWith("image"));
addProseMirrorPlugins() {
const editor = this.editor;
return [
new Plugin({
key: new PluginKey("drop-handler-plugin"),
props: {
handlePaste: (view: EditorView, event: ClipboardEvent) => {
if (
editor.isEditable &&
event.clipboardData &&
event.clipboardData.files &&
event.clipboardData.files.length > 0
) {
event.preventDefault();
const files = Array.from(event.clipboardData.files);
const imageFiles = files.filter((file) => file.type.startsWith("image"));

if (imageFiles.length > 0) {
const pos = view.state.selection.from;
insertImagesSafely({ editor, files: imageFiles, initialPos: pos, event: "drop" });
}
return true;
if (imageFiles.length > 0) {
const pos = view.state.selection.from;
insertImagesSafely({ editor, files: imageFiles, initialPos: pos, event: "drop" });
}
return false;
},
handleDrop: (view: EditorView, event: DragEvent, _slice: any, moved: boolean) => {
if (!moved && event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files.length > 0) {
event.preventDefault();
const files = Array.from(event.dataTransfer.files);
const imageFiles = files.filter((file) => file.type.startsWith("image"));
return true;
}
return false;
},
handleDrop: (view: EditorView, event: DragEvent, _slice: any, moved: boolean) => {
if (
editor.isEditable &&
!moved &&
event.dataTransfer &&
event.dataTransfer.files &&
event.dataTransfer.files.length > 0
) {
event.preventDefault();
const files = Array.from(event.dataTransfer.files);
const imageFiles = files.filter((file) => file.type.startsWith("image"));

if (imageFiles.length > 0) {
const coordinates = view.posAtCoords({
left: event.clientX,
top: event.clientY,
});
if (imageFiles.length > 0) {
const coordinates = view.posAtCoords({
left: event.clientX,
top: event.clientY,
});

if (coordinates) {
const pos = coordinates.pos;
insertImagesSafely({ editor, files: imageFiles, initialPos: pos, event: "drop" });
}
return true;
if (coordinates) {
const pos = coordinates.pos;
insertImagesSafely({ editor, files: imageFiles, initialPos: pos, event: "drop" });
}
return true;
}
return false;
},
}
return false;
},
}),
];
},
});

},
}),
];
},
});
export const insertImagesSafely = async ({
editor,
files,
Expand Down
9 changes: 5 additions & 4 deletions packages/editor/src/core/extensions/extensions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,11 @@ type TArguments = {
};
placeholder?: string | ((isFocused: boolean, value: string) => string);
tabIndex?: number;
editable?: boolean;
};

export const CoreEditorExtensions = (args: TArguments): Extensions => {
const { disabledExtensions, enableHistory, fileHandler, mentionConfig, placeholder, tabIndex } = args;
const { disabledExtensions, enableHistory, fileHandler, mentionConfig, placeholder, tabIndex, editable } = args;

return [
StarterKit.configure({
Expand Down Expand Up @@ -89,7 +90,7 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => {
...(enableHistory ? {} : { history: false }),
}),
CustomQuoteExtension,
DropHandlerExtension(),
DropHandlerExtension,
CustomHorizontalRule.configure({
HTMLAttributes: {
class: "py-4 border-custom-border-400",
Expand Down Expand Up @@ -145,9 +146,9 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => {
TableCell,
TableRow,
CustomMention({
mentionSuggestions: mentionConfig.mentionSuggestions,
mentionSuggestions: editable ? mentionConfig.mentionSuggestions : undefined,
mentionHighlights: mentionConfig.mentionHighlights,
readonly: false,
readonly: !editable,
}),
Placeholder.configure({
placeholder: ({ editor, node }) => {
Expand Down
18 changes: 15 additions & 3 deletions packages/editor/src/core/hooks/use-collaborative-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const useCollaborativeEditor = (props: TCollaborativeEditorProps) => {
const {
onTransaction,
disabledExtensions,
editable,
editorClassName,
editorProps = {},
embedHandler,
Expand All @@ -33,6 +34,7 @@ export const useCollaborativeEditor = (props: TCollaborativeEditorProps) => {
// states
const [hasServerConnectionFailed, setHasServerConnectionFailed] = useState(false);
const [hasServerSynced, setHasServerSynced] = useState(false);
const [hasIndexedDbSynced, setHasIndexedDbSynced] = useState(false);
// initialize Hocuspocus provider
const provider = useMemo(
() =>
Expand All @@ -53,7 +55,10 @@ export const useCollaborativeEditor = (props: TCollaborativeEditorProps) => {
setHasServerConnectionFailed(true);
}
},
onSynced: () => setHasServerSynced(true),
onSynced: () => {
serverHandler?.onServerSync?.();
setHasServerSynced(true);
},
}),
[id, realtimeConfig, serverHandler, user]
);
Expand All @@ -63,6 +68,10 @@ export const useCollaborativeEditor = (props: TCollaborativeEditorProps) => {
[id, provider]
);

localProvider?.on("synced", () => {
setHasIndexedDbSynced(true);
});

// destroy and disconnect all providers connection on unmount
useEffect(
() => () => {
Expand All @@ -75,7 +84,7 @@ export const useCollaborativeEditor = (props: TCollaborativeEditorProps) => {
const editor = useEditor({
disabledExtensions,
id,
onTransaction,
editable,
editorProps,
editorClassName,
enableHistory: false,
Expand All @@ -97,9 +106,10 @@ export const useCollaborativeEditor = (props: TCollaborativeEditorProps) => {
}),
],
fileHandler,
handleEditorReady,
forwardedRef,
handleEditorReady,
mentionHandler,
onTransaction,
placeholder,
provider,
tabIndex,
Expand All @@ -109,5 +119,7 @@ export const useCollaborativeEditor = (props: TCollaborativeEditorProps) => {
editor,
hasServerConnectionFailed,
hasServerSynced,
hasIndexedDbSynced,
localProvider,
};
};
Loading

0 comments on commit d29ab80

Please sign in to comment.