mobile: fix tabs

This commit is contained in:
Ammar Ahmed
2025-01-31 09:39:29 +05:00
committed by Abdullah Atta
parent 140e343289
commit 329c2e220f
5 changed files with 119 additions and 98 deletions

View File

@@ -627,17 +627,10 @@ export const useAppEvents = () => {
if (locked) {
useTabStore.getState().updateTab(tab.id, {
session: {
locked: true
locked: true,
noteLocked: true
}
});
if (
tab.id === useTabStore.getState().currentTab &&
locked &&
!editorState().movedAway
) {
// Show unlock note screen.
eSendEvent(eUnlockNote);
}
}
}
}),

View File

@@ -612,14 +612,6 @@ export const useEditorEvents = (
break;
}
case EditorEvents.tabFocused: {
console.log(
"Focused tab",
editorMessage.tabId,
editorMessage.noteId,
"Content:",
editorMessage.value
);
eSendEvent(eEditorTabFocused, editorMessage.tabId);
if (editorMessage.noteId) {

View File

@@ -32,9 +32,9 @@ import {
isEncryptedContent,
isTrashItem
} from "@notesnook/core";
import { strings } from "@notesnook/intl";
import { EditorEvents } from "@notesnook/editor-mobile/src/utils/editor-events";
import { NativeEvents } from "@notesnook/editor-mobile/src/utils/native-events";
import { strings } from "@notesnook/intl";
import { useThemeEngineStore } from "@notesnook/theme";
import { Mutex } from "async-mutex";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
@@ -500,6 +500,7 @@ export const useEditor = (
blockId?: string;
session?: TabSessionItem;
newTab?: boolean;
resetTabState?: boolean;
}) => {
loadNoteMutex.runExclusive(async () => {
if (!event) return;
@@ -544,7 +545,15 @@ export const useEditor = (
}
const item = event.item;
currentLoadingNoteId.current = item.id;
// If note is already open in a tab, focus that tab.
if (useTabStore.getState().hasTabForNote(item.id)) {
const tabId = useTabStore.getState().getTabForNote(item.id);
if (tabId !== useTabStore.getState().currentTab) {
useTabStore.getState().focusTab(tabId as string);
return;
}
}
const isLockedNote = await db.vaults.itemExists(
event.item as ItemReference
@@ -553,25 +562,24 @@ export const useEditor = (
const tabLocked =
isLockedNote && !(event.item as NoteWithContent).content;
let tabId = event.tabId;
if (tabId === undefined) tabId = useTabStore.getState().currentTab;
const tabId = event.tabId
? event.tabId
: useTabStore.getState().currentTab;
// Check if tab needs to be refreshed.
if (
!event.resetTabState &&
tabId &&
event.item.id === useTabStore.getState().getNoteIdForTab(tabId) &&
!localTabState.current?.needsRefresh(
tabId,
isLockedNote,
item.readonly
)
) {
console.log(
"Note is already updated, skipping refresh request on focus"
);
currentLoadingNoteId.current = undefined;
commands.setLoading(false, tabId);
return;
} else {
console.log("updating the tab in focus...");
localTabState.current?.setEditTime(
item.id,
localTabState.current?.noteEditedTime[item.id] || item.dateEdited
@@ -583,6 +591,9 @@ export const useEditor = (
});
}
currentLoadingNoteId.current = item.id;
// Show loading overlay if note is not already loaded.
if (
tabId &&
(event.item?.id !== useTabStore.getState().getNoteIdForTab(tabId) ||
@@ -592,38 +603,35 @@ export const useEditor = (
}
const session: Partial<TabSessionItem> = event.session || {
readonly: event.item.readonly,
locked: tabLocked,
noteLocked: isLockedNote,
noteId: event.item.id
};
session.noteLocked = isLockedNote;
session.locked = tabLocked;
session.readonly = item.readonly;
const tab = useTabStore.getState().getTab(tabId!);
if (useTabStore.getState().tabs.length === 0 || event.newTab) {
useTabStore.getState().newTab({
session: session
});
console.log("Creating a new tab...");
} else {
// A new session is created if the note is changed.
// If the note is already opened, the session is updated.
if (
event.item.id !== tab?.session?.noteId &&
tab?.session?.noteId
!tab?.session ||
(event.item.id !== tab?.session?.noteId && tab?.session?.noteId)
) {
useTabStore.getState().newTabSession(tabId!, session);
console.log("Creating a new tab session");
} else {
console.log("Updating tab session");
useTabStore.getState().updateTab(tabId!, {
session: session
});
}
}
if (lastTabFocused.current !== tabId) {
console.log("Waiting for tab to get focus");
return;
}
if (lastTabFocused.current !== tabId) return;
if (tabBarRef.current?.page() === 2) {
state.current.movedAway = false;
@@ -651,8 +659,6 @@ export const useEditor = (
await postMessage(NativeEvents.title, item.title, tabId);
overlay(false);
console.log("LOADING NOTE....", item.id, item.title);
await postMessage(
NativeEvents.html,
{
@@ -699,38 +705,34 @@ export const useEditor = (
isLocal?: boolean
) => {
try {
await (async () => {
if (SettingsService.get().disableRealtimeSync && !isLocal) return;
if (!data) return;
if (SettingsService.get().disableRealtimeSync && !isLocal) return;
if (!data) return;
if (isDeleted(data) || isTrashItem(data)) {
const tabId = useTabStore.getState().getTabForNote(data.id);
if (tabId !== undefined) {
await commands.clearContent(tabId);
useTabStore.getState().removeTab(tabId);
}
return;
if (isDeleted(data) || isTrashItem(data)) {
const tabId = useTabStore.getState().getTabForNote(data.id);
if (tabId !== undefined) {
await commands.clearContent(tabId);
useTabStore.getState().removeTab(tabId);
}
return;
}
const noteId =
(data as ContentItem).type === "tiptap"
? (data as ContentItem).noteId
: data.id;
const noteId =
(data as ContentItem).type === "tiptap"
? (data as ContentItem).noteId
: data.id;
if (!useTabStore.getState().hasTabForNote(noteId)) return;
const tabId = useTabStore.getState().getTabForNote(noteId) as string;
const note = data.type === "note" ? data : await db.notes?.note(noteId);
const tab = useTabStore.getState().getTab(tabId);
lock.current = true;
const note =
data.type === "note" ? data : await db.notes?.note(noteId);
// Handle this case where note was locked on another device and synced.
const locked = note
? await db.vaults.itemExists(note as ItemReference)
: false;
lock.current = true;
// Handle this case where note was locked on another device and synced.
const locked = note
? await db.vaults.itemExists(note as ItemReference)
: false;
useTabStore.getState().forEachNoteTab(noteId, async (tab) => {
const tabId = tab.id;
if (note) {
if (!locked && tab?.session?.noteLocked) {
@@ -738,8 +740,7 @@ export const useEditor = (
if (tab.session?.locked) {
if (useTabStore.getState().currentTab === tabId) {
eSendEvent(eOnLoadNote, {
item: note,
forced: true
item: note
});
} else {
useTabStore.getState().updateTab(tabId, {
@@ -748,7 +749,9 @@ export const useEditor = (
noteLocked: false
}
});
commands.setLoading(true, tabId);
localTabState.current?.set(tabId, {
editedAt: 0
});
}
}
} else if (!tab?.session?.noteLocked && locked) {
@@ -759,10 +762,13 @@ export const useEditor = (
noteLocked: true
}
});
commands.clearContent(tabId);
if (useTabStore.getState().currentTab !== tabId) {
commands.clearContent(tabId);
commands.setLoading(true, tabId);
}
localTabState.current?.set(tabId, {
editedAt: 0
});
}
if (currentNotes.current[noteId]?.title !== note.title) {
@@ -776,12 +782,13 @@ export const useEditor = (
tabId as string
);
}
useTabStore.getState().updateTab(tabId, {
session: {
readonly: note.readonly
}
});
if (tab.session?.readonly !== note.readonly) {
useTabStore.getState().updateTab(tabId, {
session: {
readonly: note.readonly
}
});
}
}
if (data.type === "tiptap" && note && !isLocal) {
@@ -792,7 +799,7 @@ export const useEditor = (
if (locked && isEncryptedContent(data)) {
const decryptedContent = await db.vault?.decryptContent(data);
if (!decryptedContent) {
useTabStore.getState().updateTab(tabId, {
useTabStore.getState().updateTab(tab.id, {
session: {
locked: true,
noteLocked: true
@@ -823,7 +830,7 @@ export const useEditor = (
}
}
}
})();
});
} catch (e) {
DatabaseLogger.error(e as Error, "Error when applying sync changes");
} finally {
@@ -980,6 +987,9 @@ export const useEditor = (
useTabStore.getState().currentTab!
))
) {
localTabState.current?.set(useTabStore.getState().currentTab!, {
editedAt: 0
});
eSendEvent(eEditorReset, "onReady");
return false;
} else {
@@ -998,6 +1008,10 @@ export const useEditor = (
);
await commands.setSettings();
localTabState.current?.set(useTabStore.getState().currentTab!, {
editedAt: 0
});
if (!state.current.ready) {
state.current.ready = true;
}

View File

@@ -148,7 +148,6 @@ export const tabSessionHistory = new TabSessionHistory({
return useTabStore.getState();
},
set(state) {
console.log("Set state", state.canGoBack, state.canGoForward);
useTabStore.setState({
...state
});
@@ -217,12 +216,37 @@ export const useTabStore = create<TabStore>(
) => {
const tabId = _id || (get().currentTab as string);
const sessionId = tabSessionHistory.add(tabId);
const session = {
id: sessionId,
...options
};
TabSessionStorage.set(sessionId, session);
const sessionHistory = get().tabSessionHistory[tabId];
let oldSessionId: string | undefined = undefined;
if (sessionHistory) {
const allSessions = sessionHistory.backStack.concat(
sessionHistory.forwardStack
);
allSessions.forEach((id) => {
if (TabSessionStorage.get(id)?.noteId === options?.noteId) {
oldSessionId = id;
}
});
}
const sessionId = tabSessionHistory.add(tabId, oldSessionId);
let session: Partial<TabSessionItem>;
if (!oldSessionId) {
session = {
id: sessionId,
...options
};
TabSessionStorage.set(sessionId, session as TabSessionItem);
} else {
session = {
...TabSessionStorage.get(oldSessionId),
...options
};
}
const index = get().tabs.findIndex((t) => t.id === tabId);
if (index == -1) return;
const tabs = [...get().tabs];
@@ -308,10 +332,9 @@ export const useTabStore = create<TabStore>(
if (note) {
const isLocked = await db.vaults.itemExists(note);
if (isLocked && !session?.noteLocked) {
session.locked = true;
session.noteLocked = true;
}
session.locked = isLocked;
session.noteLocked = isLocked && !session?.noteLocked;
session.readonly = note.readonly;
} else if (session.noteId) {
console.log("Failed to load session...");
@@ -325,12 +348,12 @@ export const useTabStore = create<TabStore>(
});
}
console.log("Loading session", session);
eSendEvent(eOnLoadNote, {
item: note,
newNote: !note,
tabId: get().currentTab,
session: session
session: session,
resetTabState: true
});
return true;
@@ -418,10 +441,7 @@ export const useTabStore = create<TabStore>(
return get().tabs.find((t) => t.id === id)?.session?.noteId;
},
hasTabForNote: (noteId: string) => {
return (
typeof get().tabs.find((t) => t.session?.noteId === noteId)?.id ===
"number"
);
return !!get().tabs.find((t) => t.session?.noteId === noteId);
},
getTabForNote: (noteId: string) => {
return get().tabs.find((t) => t.session?.noteId === noteId)?.id;
@@ -442,7 +462,7 @@ export const useTabStore = create<TabStore>(
}
}),
{
name: "tabs-storage",
name: "tabs-storage-v1",
getStorage: () => MMKV as unknown as StateStorage,
onRehydrateStorage: () => {
return (state) => {

View File

@@ -243,8 +243,10 @@ const Tiptap = ({
);
setTimeout(() => {
editorControllers[tabRef.current.id]?.setLoading(false);
restoreNoteSelection(scrollTop, selection);
}, 300);
setTimeout(() => {
restoreNoteSelection(scrollTop, selection);
}, 300);
}, 1);
},
[restoreNoteSelection]
);