mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-09-01 19:49:54 +02:00
editor: choose virtualization mode between blocks and pages
This commit is contained in:
@@ -39,6 +39,7 @@ import {
|
||||
getChangedNodes,
|
||||
LinkAttributes,
|
||||
profiler,
|
||||
type VirtualizationMode,
|
||||
type Selection
|
||||
} from "@notesnook/editor";
|
||||
import { installProfilerGlobals, setProfiledEditor } from "./profiling";
|
||||
@@ -117,7 +118,7 @@ type TipTapProps = {
|
||||
dayFormat: DayFormat;
|
||||
markdownShortcuts: boolean;
|
||||
fontLigatures: boolean;
|
||||
virtualization: boolean;
|
||||
virtualization: VirtualizationMode;
|
||||
};
|
||||
|
||||
function countCharacters(text: string) {
|
||||
@@ -292,7 +293,7 @@ function TipTap(props: TipTapProps) {
|
||||
onFocus,
|
||||
onCreate: async ({ editor }) => {
|
||||
setProfiledEditor(editor as Editor);
|
||||
profiler.setContext("virtualization", !!virtualization);
|
||||
profiler.setContext("virtualization", virtualization);
|
||||
profiler.setContext("noteId", id);
|
||||
profiler.setContext("topLevelBlocks", editor.state.doc.childCount);
|
||||
profiler.setContext("characters", editor.state.doc.textContent.length);
|
||||
|
||||
@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { SettingsGroup } from "./types";
|
||||
import { VirtualizationMode } from "@notesnook/editor";
|
||||
import {
|
||||
editorConfig,
|
||||
onEditorConfigChange,
|
||||
@@ -165,10 +166,18 @@ export const EditorSettings: SettingsGroup[] = [
|
||||
useSettingStore.subscribe((c) => c.editorVirtualization, listener),
|
||||
components: [
|
||||
{
|
||||
type: "toggle",
|
||||
isToggled: () => useSettingStore.getState().editorVirtualization,
|
||||
toggle: () =>
|
||||
useSettingStore.getState().toggleEditorVirtualization()
|
||||
type: "dropdown",
|
||||
options: [
|
||||
{ value: "off", title: strings.editorVirtualizationOff() },
|
||||
{ value: "blocks", title: strings.editorVirtualizationBlocks() },
|
||||
{ value: "pages", title: strings.editorVirtualizationPages() }
|
||||
],
|
||||
selectedOption: () =>
|
||||
useSettingStore.getState().editorVirtualization,
|
||||
onSelectionChanged: (value) =>
|
||||
useSettingStore
|
||||
.getState()
|
||||
.setEditorVirtualization(value as VirtualizationMode)
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import Config from "../utils/config";
|
||||
import BaseStore from "./index";
|
||||
import { TimeFormat, DayFormat, WeekFormat, EVENTS } from "@notesnook/core";
|
||||
import { Profile, TrashCleanupInterval } from "@notesnook/core";
|
||||
import { VirtualizationMode, toVirtualizationMode } from "@notesnook/editor";
|
||||
import { showToast } from "../utils/toast";
|
||||
import { ConfirmDialog } from "../dialogs/confirm";
|
||||
import * as openpgp from "openpgp";
|
||||
@@ -57,7 +58,9 @@ class SettingStore extends BaseStore<SettingStore> {
|
||||
doubleSpacedParagraphs = Config.get("doubleSpacedLines", true);
|
||||
markdownShortcuts = Config.get("markdownShortcuts", false);
|
||||
fontLigatures = Config.get("fontLigatures", false);
|
||||
editorVirtualization = Config.get("editorVirtualization", false);
|
||||
editorVirtualization: VirtualizationMode = toVirtualizationMode(
|
||||
Config.get<VirtualizationMode | boolean>("editorVirtualization", "off")
|
||||
);
|
||||
notificationsSettings = Config.get("notifications", { reminder: true });
|
||||
isFullOfflineMode = Config.get("fullOfflineMode", false);
|
||||
serverUrls: Partial<Record<HostId, string>> = Config.get("serverUrls", {});
|
||||
@@ -251,11 +254,9 @@ class SettingStore extends BaseStore<SettingStore> {
|
||||
Config.set("fontLigatures", !fontLigatures);
|
||||
};
|
||||
|
||||
toggleEditorVirtualization = (toggleState?: boolean) => {
|
||||
const editorVirtualization = this.get().editorVirtualization;
|
||||
const next = toggleState ?? !editorVirtualization;
|
||||
this.set((state) => (state.editorVirtualization = next));
|
||||
Config.set("editorVirtualization", next);
|
||||
setEditorVirtualization = (mode: VirtualizationMode) => {
|
||||
this.set((state) => (state.editorVirtualization = mode));
|
||||
Config.set("editorVirtualization", mode);
|
||||
};
|
||||
|
||||
togglePrivacyMode = async () => {
|
||||
|
||||
@@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import {
|
||||
EditorOptions,
|
||||
Node as TiptapNode,
|
||||
extensions as TiptapCoreExtensions,
|
||||
getHTMLFromFragment
|
||||
} from "@tiptap/core";
|
||||
@@ -84,6 +85,7 @@ import { Callout } from "./extensions/callout/index.js";
|
||||
import BlockId from "./extensions/block-id/index.js";
|
||||
import { Virtualization } from "./extensions/virtualization/index.js";
|
||||
import { EditorProfiler } from "./extensions/profiler/index.js";
|
||||
import { Page, Paging } from "./extensions/paging/index.js";
|
||||
import { useEditorSearchStore } from "./toolbar/stores/search-store.js";
|
||||
import { DiffHighlighter } from "./extensions/diff-highlighter/index.js";
|
||||
import { getChangedNodes } from "./utils/prosemirror.js";
|
||||
@@ -139,7 +141,7 @@ export type TiptapOptions = EditorOptions &
|
||||
isMobile?: boolean;
|
||||
doubleSpacedLines?: boolean;
|
||||
enableFontLigatures?: boolean;
|
||||
virtualization?: boolean;
|
||||
virtualization?: VirtualizationMode | boolean;
|
||||
} & {
|
||||
placeholder: string;
|
||||
};
|
||||
@@ -192,8 +194,9 @@ const useTiptap = (
|
||||
};
|
||||
}, [closeAllPopups]);
|
||||
|
||||
const defaultOptions = useMemo<Partial<EditorOptions>>(
|
||||
() => ({
|
||||
const defaultOptions = useMemo<Partial<EditorOptions>>(() => {
|
||||
const mode = toVirtualizationMode(virtualization);
|
||||
return {
|
||||
enableCoreExtensions: false,
|
||||
editorProps: {
|
||||
...editorProps,
|
||||
@@ -237,6 +240,7 @@ const useTiptap = (
|
||||
doubleSpaced: doubleSpacedLines
|
||||
}),
|
||||
StarterKit.configure({
|
||||
document: false,
|
||||
code: false,
|
||||
codeBlock: false,
|
||||
listItem: false,
|
||||
@@ -276,7 +280,10 @@ const useTiptap = (
|
||||
}
|
||||
}),
|
||||
BlockId,
|
||||
Virtualization.configure({ enabled: !!virtualization }),
|
||||
PagedDocument,
|
||||
Page,
|
||||
Virtualization.configure({ enabled: mode === "blocks" }),
|
||||
Paging.configure({ enabled: mode === "pages" }),
|
||||
EditorProfiler,
|
||||
Blockquote,
|
||||
CharacterCount,
|
||||
@@ -417,23 +424,22 @@ const useTiptap = (
|
||||
},
|
||||
injectCSS: false,
|
||||
parseOptions: { preserveWhitespace: true }
|
||||
}),
|
||||
[
|
||||
isMobile,
|
||||
previewAttachment,
|
||||
downloadAttachment,
|
||||
openAttachmentPicker,
|
||||
getAttachmentData,
|
||||
onBeforeCreate,
|
||||
openLink,
|
||||
dateFormat,
|
||||
timeFormat,
|
||||
editorProps,
|
||||
copyToClipboard,
|
||||
createInternalLink,
|
||||
virtualization
|
||||
]
|
||||
);
|
||||
};
|
||||
}, [
|
||||
isMobile,
|
||||
previewAttachment,
|
||||
downloadAttachment,
|
||||
openAttachmentPicker,
|
||||
getAttachmentData,
|
||||
onBeforeCreate,
|
||||
openLink,
|
||||
dateFormat,
|
||||
timeFormat,
|
||||
editorProps,
|
||||
copyToClipboard,
|
||||
createInternalLink,
|
||||
virtualization
|
||||
]);
|
||||
|
||||
const editor = useEditor(
|
||||
{
|
||||
@@ -446,6 +452,26 @@ const useTiptap = (
|
||||
return editor;
|
||||
};
|
||||
|
||||
/**
|
||||
* Pages are optional in the schema so an unpaged document stays valid: nothing
|
||||
* has to be migrated, and turning paging off simply stops producing them.
|
||||
*/
|
||||
const PagedDocument = TiptapNode.create({
|
||||
name: "doc",
|
||||
topNode: true,
|
||||
content: "(page | block)+"
|
||||
});
|
||||
|
||||
export type VirtualizationMode = "off" | "blocks" | "pages";
|
||||
|
||||
export function toVirtualizationMode(
|
||||
value: VirtualizationMode | boolean | undefined
|
||||
): VirtualizationMode {
|
||||
if (value === true) return "blocks";
|
||||
if (!value) return "off";
|
||||
return value;
|
||||
}
|
||||
|
||||
function hasStyle(element: HTMLElement | string) {
|
||||
const style = (element as HTMLElement).getAttribute("style");
|
||||
if (!style || style === "font-family: inherit;") return false;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -2479,6 +2479,9 @@ Use this if changes from other devices are not appearing on this device. This wi
|
||||
editorVirtualization: () => t`Editor paging (experimental)`,
|
||||
editorVirtualizationDesc: () =>
|
||||
t`Only render the part of a note that is currently on screen. Makes very large notes much faster to open, scroll and type in. While this is on, your browser's find (Ctrl+F) and printing will only cover the visible part of a note — use the editor's own search instead. If you face any issues, please turn it off.`,
|
||||
editorVirtualizationOff: () => t`Off`,
|
||||
editorVirtualizationBlocks: () => t`Blocks`,
|
||||
editorVirtualizationPages: () => t`Pages`,
|
||||
expandSidebar: () => t`Expand sidebar`,
|
||||
viewAllLimits: () => `View all limits`,
|
||||
freePlan: () => t`Free plan`,
|
||||
|
||||
Reference in New Issue
Block a user