fix: collab editing in note edit

This commit is contained in:
Artemy 2023-05-02 18:12:01 +03:00
parent ac41dc7dd4
commit cdbf75a332
5 changed files with 120 additions and 79 deletions

View file

@ -20,21 +20,27 @@ import { timestamp2text } from "./utils";
function Note({ note }) { function Note({ note }) {
return ( return (
<div className="border border-blue-300 rounded-lg p-4"> <>
<div className="grid grid-cols-1 lg:grid-cols-2"> <div className="border border-blue-300 rounded-lg p-4">
<h2 className="font-medium text-center lg:text-left leading-tight text-4xl mt-0 mb-2"> <div className="grid grid-cols-1 lg:grid-cols-2">
{note.name} <h2 className="font-medium text-center lg:text-left leading-tight text-4xl mt-0 mb-2">
</h2> {note.name}
<div className="justify-self-center lg:justify-self-end"> </h2>
{`${timestamp2text(note.time)} ${ <div className="justify-self-center lg:justify-self-end">
note.pub ? `| ${locals.PublicNote}` : `| ${locals.LocalNote}` {`${timestamp2text(note.time)} ${
}`} note.pub ? `| ${locals.PublicNote}` : `| ${locals.LocalNote}`
}`}
</div>
</div>
<div className="w-full md break-words">
<RenderMarkdown>{note.text}</RenderMarkdown>
</div> </div>
</div> </div>
<div className="w-full md break-words"> <div className="hidden">
<RenderMarkdown>{note.text}</RenderMarkdown> <input type="text" id="noteTextArea" />
<input type="text" id="noteNameInput" />
</div> </div>
</div> </>
); );
} }

View file

@ -123,6 +123,7 @@ function NoteNameInput({ value, onChange, preview = false }) {
maxLength={64} maxLength={64}
defaultValue={value} defaultValue={value}
onChange={onChange} onChange={onChange}
id="noteNameInput"
/> />
); );
} }
@ -147,7 +148,8 @@ function NoteTextArea({ value, onChange, preview = false }) {
function NotesAdditionalSettings({ function NotesAdditionalSettings({
noteText = localStorage.getItem("NoteText"), noteText = localStorage.getItem("NoteText"),
onClick, onClickAIComp,
onClickCollabEdit,
}) { }) {
return ( return (
<> <>
@ -164,13 +166,14 @@ function NotesAdditionalSettings({
let text = await Complete(noteText); let text = await Complete(noteText);
document.getElementById("noteTextArea").value = text; document.getElementById("noteTextArea").value = text;
onClick(text); onClickAIComp(text);
}} }}
/> />
)} )}
<SettingsCheckBox <SettingsCheckBox
label={locals.CollabEdit} label={locals.CollabEdit}
settingName="CollabEdit" settingName="CollabEdit"
onClick={onClickCollabEdit}
/> />
</SettingsSection> </SettingsSection>
</div> </div>

View file

@ -48,4 +48,70 @@ async function getNetLocale(lang, fileName) {
return (await (await fetch(`localisation/${lang}/${fileName}`)).text()) || ""; return (await (await fetch(`localisation/${lang}/${fileName}`)).text()) || "";
} }
export { timestamp2text, reRenderPage, localesProcess, getNetLocale }; function nameUpdate(val) {
socket.emit("nameChanged", {
name: val,
room: settings.CollabEditPassword,
});
window.lastSocketUpdate = Date.now();
}
function textUpdate(val) {
socket.emit("textChanged", {
text: val,
room: settings.CollabEditPassword,
});
window.lastSocketUpdate = Date.now();
}
function collab_edit_init(setName, setText, saveToLocalStorage = true) {
if (settings.CollabEdit === true) {
if (!window.alreadyConnected) {
socket.emit("joinRoom", settings.CollabEditPassword);
window.alreadyConnected = true;
window.lastSocketUpdate = Date.now();
window.socketTimeout = 100;
window.nameChanged = false;
window.textChanged = false;
setInterval(() => {
if (window.nameChanged) {
nameUpdate(window.nameChanged);
window.nameChanged = false;
}
if (window.textChanged) {
textUpdate(window.textChanged);
window.textChanged = false;
}
}, window.socketTimeout);
}
socket.on("textChanged", (data) => {
setText(data.text);
if (saveToLocalStorage) localStorage.setItem("NoteText", data.text);
document.getElementById("noteTextArea").value = data.text;
});
socket.on("nameChanged", (data) => {
setName(data.name);
if (saveToLocalStorage) localStorage.setItem("NoteName", data.name);
document.getElementById("noteNameInput").value = data.name;
});
socket.on("roomJoined", () => {
nameUpdate(localStorage.getItem("NoteName"), true);
textUpdate(localStorage.getItem("NoteText"), true);
});
}
}
export {
timestamp2text,
reRenderPage,
localesProcess,
getNetLocale,
collab_edit_init,
nameUpdate,
textUpdate,
};

View file

@ -20,7 +20,11 @@ import { ChevronDoubleRightIcon } from "@heroicons/react/24/outline";
import { CheckBox } from "../components/checkbox"; import { CheckBox } from "../components/checkbox";
import { useState } from "react"; import { useState } from "react";
import RenderMarkdown from "../components/markdown"; import RenderMarkdown from "../components/markdown";
import { timestamp2text } from "../components/utils"; import {
collab_edit_init,
timestamp2text,
textUpdate,
} from "../components/utils";
import rehypeRemark from "rehype-remark/lib"; import rehypeRemark from "rehype-remark/lib";
import ContentEditable from "react-contenteditable"; import ContentEditable from "react-contenteditable";
import ReactDOMServer from "react-dom/server"; import ReactDOMServer from "react-dom/server";
@ -36,26 +40,6 @@ import {
SettingsCheckBox, SettingsCheckBox,
} from "../components/settingsInputs"; } from "../components/settingsInputs";
function nameUpdate(val, force) {
if (Date.now() - window.lastSocketUpdate > window.socketTimeout || force) {
socket.emit("nameChanged", {
name: val,
room: settings.CollabEditPassword,
});
window.lastSocketUpdate = Date.now();
}
}
function textUpdate(val, force) {
if (Date.now() - window.lastSocketUpdate > window.socketTimeout || force) {
socket.emit("textChanged", {
text: val,
room: settings.CollabEditPassword,
});
window.lastSocketUpdate = Date.now();
}
}
function CreateNote() { function CreateNote() {
const [preview, setPreview] = useState(false); const [preview, setPreview] = useState(false);
const [publicState, setPublicState] = useState(settings.publicNote); const [publicState, setPublicState] = useState(settings.publicNote);
@ -83,29 +67,7 @@ function CreateNote() {
} }
} }
if (settings.CollabEdit === true) { collab_edit_init(setName, setText, false);
if (!window.alreadyConnected) {
socket.emit("joinRoom", settings.CollabEditPassword);
window.alreadyConnected = true;
window.lastSocketUpdate = Date.now();
window.socketTimeout = 100;
}
socket.on("textChanged", (data) => {
setText(data.text);
localStorage.setItem("NoteText", data.text);
});
socket.on("nameChanged", (data) => {
setName(data.name);
localStorage.setItem("NoteName", data.name);
});
socket.on("roomJoined", () => {
nameUpdate(localStorage.getItem("NoteName"), true);
textUpdate(localStorage.getItem("NoteText"), true);
});
}
return ( return (
<div> <div>
@ -129,13 +91,7 @@ function CreateNote() {
onChange={(e) => { onChange={(e) => {
setName(e.target.value); setName(e.target.value);
localStorage.setItem("NoteName", e.target.value); localStorage.setItem("NoteName", e.target.value);
window.nameChanged = e.target.value;
if (settings.CollabEdit === true) {
nameUpdate(e.target.value);
setTimeout(() => {
nameUpdate(e.target.value);
}, window.socketTimeout);
}
}} }}
preview={preview} preview={preview}
/> />
@ -145,13 +101,7 @@ function CreateNote() {
onChange={(e) => { onChange={(e) => {
setText(e.target.value); setText(e.target.value);
localStorage.setItem("NoteText", e.target.value); localStorage.setItem("NoteText", e.target.value);
window.textChanged = e.target.value;
if (settings.CollabEdit === true) {
textUpdate(e.target.value);
setTimeout(() => {
textUpdate(e.target.value);
}, window.socketTimeout);
}
}} }}
preview={preview} preview={preview}
/> />
@ -200,12 +150,12 @@ function CreateNote() {
</div> </div>
<NotesAdditionalSettings <NotesAdditionalSettings
onClick={(text) => { onClickAIComp={(text) => {
localStorage.setItem("NoteText", text); localStorage.setItem("NoteText", text);
setText(text); setText(text);
if (settings.CollabEdit === true) { if (settings.CollabEdit === true) {
textUpdate(text, true); textUpdate(text);
} }
}} }}
/> />

View file

@ -31,6 +31,7 @@ import {
NoteTextArea, NoteTextArea,
NotesAdditionalSettings, NotesAdditionalSettings,
} from "../components/settingsInputs"; } from "../components/settingsInputs";
import { collab_edit_init, nameUpdate, textUpdate } from "../components/utils";
function NotePage() { function NotePage() {
let params = useParams(); let params = useParams();
@ -42,6 +43,8 @@ function NotePage() {
let [text, setText] = useState(note.text); let [text, setText] = useState(note.text);
let [name, setName] = useState(note.name); let [name, setName] = useState(note.name);
collab_edit_init(setName, setText, false);
return ( return (
<div className=""> <div className="">
<ButtonWithIcon <ButtonWithIcon
@ -56,17 +59,26 @@ function NotePage() {
<> <>
<NoteNameInput <NoteNameInput
value={name} value={name}
onChange={(e) => setName(e.target.value)} onChange={(e) => {
setName(e.target.value);
window.nameChanged = e.target.value;
}}
/> />
<NoteTextArea <NoteTextArea
value={text} value={text}
onChange={(e) => setText(e.target.value)} onChange={(e) => {
setText(e.target.value);
window.textChanged = e.target.value;
}}
/> />
<div className="grid grid-cols-1 lg:grid-cols-2 justify-items-center w-full"> <div className="grid grid-cols-1 lg:grid-cols-2 justify-items-center w-full">
<NotesAdditionalSettings <NotesAdditionalSettings
noteText={text} noteText={text}
onClick={(text) => { onClickAIComp={(text) => {
setText(text); setText(text);
if (settings.CollabEdit === true) {
textUpdate(text);
}
}} }}
/> />
</div> </div>
@ -85,10 +97,14 @@ function NotePage() {
text={edit ? locals.Save : locals.Edit} text={edit ? locals.Save : locals.Edit}
icon={edit ? ArchiveBoxArrowDownIcon : PencilIcon} icon={edit ? ArchiveBoxArrowDownIcon : PencilIcon}
onClick={() => { onClick={() => {
if (settings.CollabEdit === true) {
textUpdate(notes[params.id].text);
nameUpdate(notes[params.id].name);
}
if (edit) { if (edit) {
notes[params.id].name = name; notes[params.id].name = name;
notes[params.id].text = text; notes[params.id].text = text;
localStorage.setObj("Notes", notes); localStorage.setObj("Notes", notes);
} }