perf: remove wordcount from state

This commit is contained in:
thecodrr
2021-12-06 09:24:31 +05:00
parent d293ed1517
commit 49bb64a82b
5 changed files with 52 additions and 39 deletions

View File

@@ -142,6 +142,7 @@ export async function verifyAccount() {
export const AppEventManager = new EventManager();
export const AppEvents = {
UPDATE_ATTACHMENT_PROGRESS: "updateAttachmentProgress",
UPDATE_WORD_COUNT: "updateWordCount",
};
export function totalSubscriptionConsumed(user) {

View File

@@ -1,13 +1,25 @@
import React from "react";
import React, { useEffect, useState } from "react";
import { Flex, Text } from "rebass";
import { AppEventManager, AppEvents } from "../../common";
import { useStore } from "../../stores/editor-store";
import { timeConverter } from "../../utils/time";
function EditorFooter() {
const [totalWords, setTotalWords] = useState(0);
const dateEdited = useStore((store) => store.session.dateEdited);
const id = useStore((store) => store.session.id);
const totalWords = useStore((store) => store.session.totalWords);
const isSaving = useStore((store) => store.session.isSaving);
useEffect(() => {
const updateWordCountEvent = AppEventManager.subscribe(
AppEvents.UPDATE_WORD_COUNT,
(count) => setTotalWords(count)
);
return () => {
updateWordCountEvent.unsubscribe();
};
}, []);
if (!id) return null;
return (
<Flex alignItems="center">

View File

@@ -21,15 +21,22 @@ import useTablet from "../../utils/use-tablet";
import Toolbar from "./toolbar";
import EditorLoading from "./loading";
import { db } from "../../common/db";
import { AppEventManager, AppEvents } from "../../common";
import debounce from "just-debounce-it";
const ReactMCE = React.lazy(() => import("./tinymce"));
function updateWordCount(editor) {
if (!editor.countWords) return;
AppEventManager.publish(AppEvents.UPDATE_WORD_COUNT, editor.countWords());
}
const debouncedUpdateWordCount = debounce(updateWordCount, 1000);
function Editor({ noteId, nonce }) {
const editorRef = useRef();
const [isEditorLoading, setIsEditorLoading] = useState(true);
const sessionId = useStore((store) => store.session.id);
const contentType = useStore((store) => store.session.content?.type);
const setSession = useStore((store) => store.setSession);
const saveSession = useStore((store) => store.saveSession);
const newSession = useStore((store) => store.newSession);
const openSession = useStore((store) => store.openSession);
@@ -50,7 +57,6 @@ function Editor({ noteId, nonce }) {
const startSession = useCallback(
async function startSession(noteId) {
console.log("starting session", nonce, noteId);
if (noteId === 0) newSession(nonce);
else if (noteId) {
await openSession(noteId);
@@ -117,7 +123,6 @@ function Editor({ noteId, nonce }) {
})();
}, [startSession, noteId, nonce]);
// if (!isSessionReady) return <EditorLoading />;
return (
<Flex
flexDirection="column"
@@ -200,8 +205,7 @@ function Editor({ noteId, nonce }) {
onFocus={() => toggleProperties(false)}
onSave={saveSession}
sessionId={sessionId}
initialValue={editorstore.get()?.session?.content?.data}
onChange={(content) => {
onChange={(content, editor) => {
if (!content || content === "<p><br></pr>") return;
setSession((state) => {
@@ -210,9 +214,10 @@ function Editor({ noteId, nonce }) {
data: content,
};
});
debouncedUpdateWordCount(editor);
}}
changeInterval={100}
onWordCountChanged={updateWordCount}
onInit={(editor) => {
editor.focus();
setTimeout(() => {

View File

@@ -2,7 +2,7 @@ import React, { useEffect } from "react";
import "./editor.css";
import "@streetwritersco/tinymce-plugins/codeblock/styles.css";
import "@streetwritersco/tinymce-plugins/collapsibleheaders/styles.css";
import "tinymce/tinymce";
import "tinymce/tinymce.js";
// eslint-disable-next-line import/no-webpack-loader-syntax
import "file-loader?name=static/js/icons/default/icons.js&esModule=false!tinymce/icons/default/icons.min.js";
// eslint-disable-next-line import/no-webpack-loader-syntax
@@ -45,7 +45,7 @@ import { useIsUserPremium } from "../../hooks/use-is-user-premium";
import { AppEventManager, AppEvents } from "../../common";
import { EV, EVENTS } from "notes-core/common";
import { downloadAttachment } from "../../common/attachments";
import debounce from "just-debounce";
import debounce from "just-debounce-it";
const markdownPatterns = [
{ start: "```", replacement: "<pre></pre>" },
@@ -124,17 +124,15 @@ const plugins = {
pro: "textpattern picker",
};
const changeEvents = "change input compositionend paste";
const changeEvents = "change keyup input compositionend paste";
function TinyMCE(props) {
const {
changeInterval,
onChange,
onWordCountChanged,
onSave,
placeholder,
simple,
initialValue,
onFocus,
editorRef,
onInit,
@@ -142,6 +140,7 @@ function TinyMCE(props) {
} = props;
const [oldSkin, newSkin] = useSkin();
const isUserPremium = useIsUserPremium();
const tinymceRef = editorRef;
useEffect(() => {
if (!tinymceRef.current.editor.dom) return;
@@ -188,7 +187,6 @@ function TinyMCE(props) {
id={sessionId}
ref={tinymceRef}
onFocus={onFocus}
initialValue={initialValue}
init={{
//experimental
keep_styles: false,
@@ -225,40 +223,46 @@ function TinyMCE(props) {
imagetools_toolbar:
"rotateleft rotateright | flipv fliph | alignleft aligncenter alignright",
init_instance_callback: (editor) => {
editor.serializer.addTempAttr("data-progress");
clearTimeout(editor.changeTimeout);
onInit && onInit(editor);
console.log("init");
},
setup: (editor) => {
editor.on("tap", (e) => {
function onTap(e) {
if (
e.target.classList.contains("mce-content-body") &&
!e.target.innerText.length > 0
) {
e.preventDefault();
}
});
}
editor.on("ScrollIntoView", (e) => {
e.preventDefault();
e.elm.scrollIntoView({
behavior: "smooth",
block: "nearest",
});
});
const onEditorChange = debounce(() => {
if (onWordCountChanged) onWordCountChanged(editor.countWords());
const onEditorChange = debounce((e) => {
if (editor.isLoading) {
editor.isLoading = false;
return;
}
if (!editor.getHTML) return;
editor.getHTML().then((html) => {
onChange(html, editor);
});
}, changeInterval);
function onScrollIntoView(e) {
e.preventDefault();
e.elm.scrollIntoView({
behavior: "smooth",
block: "nearest",
});
}
editor.on("ScrollIntoView", onScrollIntoView);
editor.on("tap", onTap);
editor.on(changeEvents, onEditorChange);
editor.on("remove", () => {
editor.off("ScrollIntoView", onScrollIntoView);
editor.off("tap", onTap);
editor.off(changeEvents, onEditorChange);
});
},
toolbar_persist: true,
toolbar_sticky: false,

View File

@@ -29,7 +29,6 @@ const getDefaultSession = () => {
context: undefined,
color: undefined,
dateEdited: 0,
totalWords: 0,
attachments: [],
content: {
type: "tiny",
@@ -65,7 +64,6 @@ class EditorStore extends BaseStore {
...note,
id: undefined, // NOTE: we give a session id only after the note is opened.
content: note.content,
totalWords: state.session.totalWords,
state: SESSION_STATES.unlocked,
};
});
@@ -108,7 +106,6 @@ class EditorStore extends BaseStore {
...defaultSession,
...note,
content: content || defaultSession.content,
totalWords: state.session.totalWords,
state: SESSION_STATES.new,
attachments: db.attachments.ofNote(note.id, "files") || [],
};
@@ -234,12 +231,6 @@ class EditorStore extends BaseStore {
);
};
updateWordCount = (count) => {
this.set((state) => {
state.session.totalWords = count;
});
};
/**
* @private internal
* @param {Boolean} isLocked