Skip to content

Commit

Permalink
web: better ux when autosave is off (#6610)
Browse files Browse the repository at this point in the history
Signed-off-by: 01zulfi <[email protected]>
  • Loading branch information
01zulfi committed Nov 11, 2024
1 parent 4014f2a commit 45f2732
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 85 deletions.
169 changes: 88 additions & 81 deletions apps/web/src/components/editor/action-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import {
} from "../icons";
import { ScrollContainer } from "@notesnook/ui";
import {
SaveState,
SessionType,
isLockedSession,
useEditorStore
Expand Down Expand Up @@ -302,89 +303,95 @@ function TabStrip() {
sessions.splice(to, 0, fromTab);
useEditorStore.setState({ sessions });
}}
renderItem={({ item: session, index: i }) => (
<Tab
id={session.id}
key={session.id}
title={
session.title ||
("note" in session ? session.note.title : "Untitled")
}
isTemporary={!!session.preview}
isActive={session.id === activeSessionId}
isPinned={!!session.pinned}
isLocked={isLockedSession(session)}
type={session.type}
onKeepOpen={() =>
useEditorStore
.getState()
.updateSession(
session.id,
[session.type],
(s) => (s.preview = false)
)
}
onFocus={() => {
if (session.id !== activeSessionId) {
useEditorStore.getState().openSession(session.id);
renderItem={({ item: session, index: i }) => {
const isUnsaved =
session.type === "default" &&
session.saveState === SaveState.NotSaved;
return (
<Tab
id={session.id}
key={session.id}
title={
(isUnsaved ? "* " : "") +
(session.title ||
("note" in session ? session.note.title : "Untitled"))
}
}}
onClose={() =>
useEditorStore.getState().closeSessions(session.id)
}
onCloseAll={() =>
useEditorStore
.getState()
.closeSessions(
...sessions.filter((s) => !s.pinned).map((s) => s.id)
)
}
onCloseOthers={() =>
useEditorStore
.getState()
.closeSessions(
...sessions
.filter((s) => s.id !== session.id && !s.pinned)
.map((s) => s.id)
)
}
onCloseToTheRight={() =>
useEditorStore
.getState()
.closeSessions(
...sessions
.filter((s, index) => index > i && !s.pinned)
.map((s) => s.id)
)
}
onCloseToTheLeft={() =>
useEditorStore
.getState()
.closeSessions(
...sessions
.filter((s, index) => index < i && !s.pinned)
.map((s) => s.id)
isTemporary={!!session.preview}
isActive={session.id === activeSessionId}
isPinned={!!session.pinned}
isLocked={isLockedSession(session)}
type={session.type}
onKeepOpen={() =>
useEditorStore
.getState()
.updateSession(
session.id,
[session.type],
(s) => (s.preview = false)
)
}
onFocus={() => {
if (session.id !== activeSessionId) {
useEditorStore.getState().openSession(session.id);
}
}}
onClose={() =>
useEditorStore.getState().closeSessions(session.id)
}
onCloseAll={() =>
useEditorStore
.getState()
.closeSessions(
...sessions.filter((s) => !s.pinned).map((s) => s.id)
)
}
onCloseOthers={() =>
useEditorStore
.getState()
.closeSessions(
...sessions
.filter((s) => s.id !== session.id && !s.pinned)
.map((s) => s.id)
)
}
onCloseToTheRight={() =>
useEditorStore
.getState()
.closeSessions(
...sessions
.filter((s, index) => index > i && !s.pinned)
.map((s) => s.id)
)
}
onCloseToTheLeft={() =>
useEditorStore
.getState()
.closeSessions(
...sessions
.filter((s, index) => index < i && !s.pinned)
.map((s) => s.id)
)
}
onRevealInList={() =>
AppEventManager.publish(
AppEvents.revealItemInList,
"note" in session ? session.note.id : session.id,
true
)
}
onRevealInList={() =>
AppEventManager.publish(
AppEvents.revealItemInList,
"note" in session ? session.note.id : session.id,
true
)
}
onPin={() => {
useEditorStore.setState((state) => {
// preview tabs can never be pinned.
if (!session.pinned) state.sessions[i].preview = false;
state.sessions[i].pinned = !session.pinned;
state.sessions.sort((a, b) =>
a.pinned === b.pinned ? 0 : a.pinned ? -1 : 1
);
});
}}
/>
)}
}
onPin={() => {
useEditorStore.setState((state) => {
// preview tabs can never be pinned.
if (!session.pinned) state.sessions[i].preview = false;
state.sessions[i].pinned = !session.pinned;
state.sessions.sort((a, b) =>
a.pinned === b.pinned ? 0 : a.pinned ? -1 : 1
);
});
}}
/>
);
}}
/>
</Flex>
</ScrollContainer>
Expand Down
2 changes: 2 additions & 0 deletions apps/web/src/components/editor/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ const [useEditorManager] = createStore<EditorManager>(

export { useEditorManager };

export const editorManager = useEditorManager.getState();

export function useEditor(id: string) {
return useEditorManager((store) => store.editors[id]);
}
Expand Down
26 changes: 23 additions & 3 deletions apps/web/src/components/editor/tiptap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,14 @@ import { debounce } from "@notesnook/common";
import { ScopedThemeProvider } from "../theme-provider";
import { useStore as useThemeStore } from "../../stores/theme-store";
import { writeToClipboard } from "../../utils/clipboard";
import { useEditorStore } from "../../stores/editor-store";
import { SaveState, useEditorStore } from "../../stores/editor-store";
import { parseInternalLink } from "@notesnook/core";
import Skeleton from "react-loading-skeleton";
import useMobile from "../../hooks/use-mobile";
import useTablet from "../../hooks/use-tablet";
import { TimeFormat } from "@notesnook/core";
import { BuyDialog } from "../../dialogs/buy-dialog";
import { showToast } from "../../utils/toast";

export type OnChangeHandler = (
content: () => string,
Expand Down Expand Up @@ -147,6 +148,7 @@ function TipTap(props: TipTapProps) {
} = props;

const isUserPremium = useIsUserPremium();
const setEditorSaveState = useEditorStore((store) => store.setSaveState);
const autoSave = useRef(true);
const { toolbarConfig } = useToolbarConfig();

Expand Down Expand Up @@ -241,7 +243,23 @@ function TipTap(props: TipTapProps) {
const ignoreEdit = transaction.getMeta("ignoreEdit") as boolean;
if (preventSave || !editor.isEditable || !onChange) return;

if (!autoSave.current) return;
if (!autoSave.current) {
setEditorSaveState(id, SaveState.NotSaved);
const { hide } = showToast(
"error",
"Auto-save is disabled for large notes. Press Ctrl + S to save.",
[
{
text: "Dismiss",
onClick: () => {
hide();
}
}
],
Infinity
);
return;
}

onChange(
() => getHTMLFromFragment(editor.state.doc.content, editor.schema),
Expand Down Expand Up @@ -549,7 +567,9 @@ function toIEditor(editor: Editor): IEditor {
},
{ query: (a) => a.hash === hash, preventUpdate: true }
),
startSearch: () => editor.commands.startSearch()
startSearch: () => editor.commands.startSearch(),
getContent: () =>
getHTMLFromFragment(editor.state.doc.content, editor.schema)
};
}

Expand Down
1 change: 1 addition & 0 deletions apps/web/src/components/editor/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ export interface IEditor {
attachFile: (file: Attachment) => void;
sendAttachmentProgress: (hash: string, progress: number) => void;
startSearch: () => void;
getContent: () => string;
}
44 changes: 43 additions & 1 deletion apps/web/src/stores/editor-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import { hashNavigate } from "../navigation";
import { AppEventManager, AppEvents } from "../common/app-events";
import Vault from "../common/vault";
import { Mutex } from "async-mutex";
import { editorManager } from "../components/editor/manager";

export enum SaveState {
NotSaved = -1,
Expand Down Expand Up @@ -500,6 +501,29 @@ class EditorStore extends BaseStore<EditorStore> {
const session = this.get().sessions.find((s) => s.id === id);
if (!session) id = undefined;

const activeSession = this.getActiveSession();

if (activeSession) {
const sessionSaveState = this.getSession(activeSession.id, [
"default"
])?.saveState;
if (sessionSaveState === SaveState.NotSaved) {
const editor = editorManager.getEditor(activeSession.id);
const content = editor?.editor?.getContent();
this.saveSession(
activeSession.id,
content
? {
content: {
data: content,
type: "tiptap"
}
}
: {}
);
}
}

if (
id &&
!settingStore.get().hideNoteTitle &&
Expand Down Expand Up @@ -847,7 +871,6 @@ class EditorStore extends BaseStore<EditorStore> {
sessionId
});
}

setDocumentTitle(
settingStore.get().hideNoteTitle ? undefined : note.title
);
Expand Down Expand Up @@ -888,6 +911,25 @@ class EditorStore extends BaseStore<EditorStore> {
continue;
}

const sessionSaveState = this.getSession(session.id, [
"default"
])?.saveState;
if (sessionSaveState === SaveState.NotSaved) {
const editor = editorManager.getEditor(session.id);
const content = editor?.editor?.getContent();
this.saveSession(
session.id,
content
? {
content: {
data: content,
type: "tiptap"
}
}
: {}
);
}

db.fs().cancel(session.id).catch(console.error);
if (state.history.includes(session.id))
state.history.splice(state.history.indexOf(session.id), 1);
Expand Down

0 comments on commit 45f2732

Please sign in to comment.