Open tu2-atmanand opened 1 month ago
Yes the above thing makes sense, because, if the user add Task Description and i also have a Markdown Renderer at the bottom. That doesnt makes sense, becase the ultimate goal is to make the AddTaskModal/EditTaskModal like adding issues in Github Project. So, the best solution here is remove the Task Description part from the Modal. Now First there will be TaskTitle, then Subtasks. After that i can directly put the Task Description and i can tell user by mentioning a small note : "Edit the Task from belive live preview". So in this live preview user will able to add task Description, create more sub-subTasks and also if its possible user will able to paste images or drag and drop files as well, since its a MarkdownRenderedSection.
So, Basically what i want is a function by Obsidian, similar to MarkdownRenderer, where i wont be passing a complete file to edit. I will only pass the previous task content, or the content which the user has entered, and now the user can edit that content, add anything he wants and then, i will receive this content entered/edited by user in a variable. From this received data, i will fetch all the fields and update them in json and file when the user will press save button.
This editor, will also help me for the adding Comments feature i want to have in future just like this Github. But, notice one this in, github also, right now i am adding this comment using simple text editor. And there is a button to Preview this into Markdow, if you have entered any image or any other document. But in Obsidian it will be live, just like Obisidian's Live Editor.
I am going to use the code from the following link and create a new file in my project : https://github.com/mgmeyers/obsidian-kanban/blob/main/src/components/Editor/MarkdownEditor.tsx
Then I will update the below code in my AddOrEditTaskModal to use this MarkdownEditor :
To embed the `MarkdownEditor` inside the `EditTaskContent` component and replace the existing `textarea`, here’s how you can modify the code.
### Steps:
1. **Create the `EmbeddedMarkdownEditor.tsx` file**:
Place the provided `MarkdownEditor` code in the `EmbeddedMarkdownEditor.tsx` file as planned.
2. **Modify `EditTaskContent` to Use `MarkdownEditor`**:
Replace the existing `textarea` with the `MarkdownEditor` from your `EmbeddedMarkdownEditor.tsx` file, while handling the necessary props, such as `value`, `onChange`, `onSubmit`, etc.
Here is how you can update the `EditTaskContent` component to use the new `MarkdownEditor`:
### Code Changes in `EditTaskContent`:
Replace the `textarea` block with the following:
```tsx
// Import the MarkdownEditor from the EmbeddedMarkdownEditor file
import { MarkdownEditor } from './Editor/EmbeddedMarkdownEditor';
// ...
const EditTaskContent: React.FC<{ app: App, plugin: TaskBoard, root: HTMLElement, task?: taskItem, taskExists?: boolean, filePath: string; onSave: (updatedTask: taskItem) => void; onClose: () => void }> = ({ app, plugin, root, task = taskItemEmpty, taskExists, filePath, onSave, onClose }) => {
// Replace the textarea state handler with the MarkdownEditor state handler
const [taskContent, setTaskContent] = useState(task.body ? task.body.join('\n') : '');
// Function to handle the submission of the task from MarkdownEditor
const handleMarkdownSubmit = (editor: EditorView) => {
const updatedContent = editor.state.doc.toString();
const updatedTask = parseTaskContent(updatedContent);
setTaskContent(updatedContent);
setUpdatedTask(updatedTask);
onSave(updatedTask);
onClose();
};
return (
<div className="EditTaskModalHome">
{/* Your other code */}
{/* Conditional rendering based on active tab */}
<div className={`EditTaskModalTabContent ${activeTab === 'preview' ? 'show' : 'hide'}`}>
{/* Preview Section */}
<div className="EditTaskModalHomePreview" style={{ display: activeTab === 'preview' ? 'block' : 'none' }}>
{/* Your Preview logic */}
</div>
</div>
<div className={`EditTaskModalTabContent ${activeTab === 'editor' ? 'show' : 'hide'}`}>
<div className="EditTaskModalHomePreviewHeader">
Directly Edit any value or add more sub tasks and description for this task.
</div>
{/* Embed the MarkdownEditor */}
<MarkdownEditor
value={taskContent}
onChange={(update) => setTaskContent(update.state.doc.toString())}
onSubmit={handleMarkdownSubmit}
className="EditTaskModalBodyDescription"
placeholder="Body content"
/>
</div>
{/* Rest of your component code */}
<button className="EditTaskModalHomeSaveBtn" onClick={handleSave}>Save</button>
</div>
);
};
// Rest of your modal logic
MarkdownEditor Integration:
MarkdownEditor
replaces the textarea
to provide a richer editing experience.onSubmit
handler is configured to save and close the modal when the user finishes editing.State Management:
taskContent
and updated using the onChange
event of the MarkdownEditor
.Preview Tab:
By following these steps, you'll be able to replace the standard textarea
with the custom MarkdownEditor
while keeping the task's editing and previewing functionalities intact.
Following is the simplest code GPT gave using the codeMirror library, just sharing here to refer, because I am deleting the below file /src/components/MarkdownEditor.tsx :
// /src/components/MarkdownEditor.tsx
import { EditorView, basicSetup } from 'codemirror';
import React, { useEffect, useRef, useState } from 'react';
import { markdown, markdownLanguage } from '@codemirror/lang-markdown';
import { indentWithTab } from '@codemirror/commands';
import { keymap } from '@codemirror/view';
import { oneDark } from '@codemirror/theme-one-dark';
class MarkdownEditor {
private editorView: EditorView | null = null;
private onChangeCallback: (value: string) => void;
constructor(onChangeCallback: (value: string) => void) {
this.onChangeCallback = onChangeCallback;
}
initializeEditor(editorContainer: HTMLDivElement, initialValue: string) {
if (this.editorView) {
this.editorView.destroy();
}
this.editorView = new EditorView({
doc: initialValue,
extensions: [
basicSetup,
markdown({ base: markdownLanguage }),
oneDark,
keymap.of([indentWithTab]), // Correctly wrap keybindings with `keymap.of()`
EditorView.updateListener.of((update) => {
if (update.docChanged) {
const currentValue = this.editorView?.state.doc.toString() || '';
this.onChangeCallback(currentValue);
}
}),
],
parent: editorContainer,
});
}
destroyEditor() {
if (this.editorView) {
this.editorView.destroy();
this.editorView = null;
}
}
getEditorValue(): string {
return this.editorView?.state.doc.toString() || '';
}
static extractIndentedLines(content: string): string[] {
return content
.split('\n')
.filter((line) => /^\s+[^- \[]/.test(line)); // lines with indentation not starting with `- [ ]`
}
}
export default function CodeMirrorEditor({ initialContent, onChange }: { initialContent: string, onChange: (bodyContent: string[]) => void }) {
const editorRef = useRef<HTMLDivElement>(null);
const [editorInstance, setEditorInstance] = useState<MarkdownEditor | null>(null);
useEffect(() => {
if (editorRef.current) {
const editor = new MarkdownEditor((value: string) => {
const indentedLines = MarkdownEditor.extractIndentedLines(value);
onChange(indentedLines);
});
editor.initializeEditor(editorRef.current, initialContent);
setEditorInstance(editor);
return () => {
editor.destroyEditor();
};
}
}, [initialContent, onChange]);
return <div ref={editorRef} className="markdown-editor"></div>;
}
Creating a new branch for this Markdown Editor Implementation called markdownEditorEmbed
As of now, i have the TextArea element to edit/add description for the task. Will release the plugin with this state. The work can be parallely dont on this branch to achieve this feature, with the current state of the plugin, later on, i can simply merge.
Right now, in the AddOrEdiTaskModal i only have a MarkdownRenderer, which renders the passed content in the format of Obsidians Reading View mode. But i want to now convert it into Obsidian's Edit View. Where the user can see the live Preview of the content the user has entered, as well as, the user will able to edit right from the modal itself, the things he want to edit. Also more powerful features like making font bold, italic, adding code, pasting images and documents, literally everything just like the Obsidian Editor.
So I just have to find a way to add this Editor inside this modal. Then i can simply remove the TextArea input element to take task Description and mention as a message that, add the Description in the below Editor.