diff --git a/apps/web/src/components/editor/tiptap.tsx b/apps/web/src/components/editor/tiptap.tsx
index 12531b203..2e01ffc24 100644
--- a/apps/web/src/components/editor/tiptap.tsx
+++ b/apps/web/src/components/editor/tiptap.tsx
@@ -52,6 +52,7 @@ import { showBuyDialog } from "../../common/dialog-controller";
import { useStore as useSettingsStore } from "../../stores/setting-store";
import { debounceWithId } from "../../utils/debounce";
import { store as editorstore } from "../../stores/editor-store";
+import { useStore as useNoteStore } from "../../stores/note-store";
type TipTapProps = {
editorContainer: HTMLElement;
@@ -121,6 +122,7 @@ function TipTap(props: TipTapProps) {
const doubleSpacedLines = useSettingsStore(
(store) => store.doubleSpacedLines
);
+ const search = useNoteStore((store) => store.search);
const { toolbarConfig } = useToolbarConfig();
const { isSearching, toggleSearch } = useSearch();
@@ -170,6 +172,8 @@ function TipTap(props: TipTapProps) {
}
});
if (onLoad) onLoad();
+
+ if (search && !isSearching) toggleSearch();
},
onUpdate: ({ editor, transaction }) => {
onContentChange?.();
@@ -251,6 +255,20 @@ function TipTap(props: TipTapProps) {
() => {
const isEditorSearching = editor?.storage.searchreplace?.isSearching;
if (isSearching && !isEditorSearching) toggleSearch();
+ if (search && !isSearching) toggleSearch();
+
+ if (search && isSearching && isEditorSearching) {
+ setTimeout(() => {
+ (
+ document.getElementById("search-replace-input") as HTMLInputElement
+ ).value = search["query"];
+ editor.commands.search(search["query"], {
+ enableRegex: true,
+ matchCase: false,
+ matchWholeWord: false
+ });
+ }, 500);
+ }
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[toggleSearch, editor?.storage.searchreplace?.isSearching]
diff --git a/apps/web/src/navigation/routes.js b/apps/web/src/navigation/routes.js
index f6c4f2422..c1c2d4519 100644
--- a/apps/web/src/navigation/routes.js
+++ b/apps/web/src/navigation/routes.js
@@ -33,32 +33,39 @@ import { showToast } from "../utils/toast";
import Reminders from "../views/reminders";
const routes = {
- "/notes": () => ({
- key: "home",
- type: "notes",
- title: "Notes",
- component: ,
- buttons: {
- search: {
- title: "Search notes"
+ "/notes": () => {
+ notestore.clearSearch();
+ return {
+ key: "home",
+ type: "notes",
+ title: "Notes",
+ component: ,
+ buttons: {
+ search: {
+ title: "Search notes"
+ }
}
- }
- }),
- "/notebooks": () => ({
- key: "notebooks",
- type: "notebooks",
- title: "Notebooks",
- component: ,
- buttons: {
- search: {
- title: "Search notebooks"
+ };
+ },
+ "/notebooks": () => {
+ notestore.clearSearch();
+ return {
+ key: "notebooks",
+ type: "notebooks",
+ title: "Notebooks",
+ component: ,
+ buttons: {
+ search: {
+ title: "Search notebooks"
+ }
}
- }
- }),
+ };
+ },
"/notebooks/:notebookId": ({ notebookId }) => {
const notebook = db.notebooks.notebook(notebookId);
if (!notebook) return false;
nbstore.setSelectedNotebook(notebookId);
+ notestore.clearSearch();
return {
key: "topics",
type: "topics",
@@ -82,6 +89,7 @@ const routes = {
type: "topic",
value: { id: notebookId, topic: topicId }
});
+ notestore.clearSearch();
return {
key: "notes",
type: "notes",
@@ -106,6 +114,7 @@ const routes = {
},
"/favorites": () => {
notestore.setContext({ type: "favorite" });
+ notestore.clearSearch();
return {
key: "notes",
title: "Favorites",
@@ -119,6 +128,7 @@ const routes = {
};
},
"/reminders": () => {
+ notestore.clearSearch();
return {
key: "reminders",
title: "Reminders",
@@ -131,34 +141,41 @@ const routes = {
}
};
},
- "/trash": () => ({
- key: "trash",
- type: "trash",
- title: "Trash",
- component: ,
- buttons: {
- search: {
- title: "Search trash"
+ "/trash": () => {
+ notestore.clearSearch();
+ return {
+ key: "trash",
+ type: "trash",
+ title: "Trash",
+ component: ,
+ buttons: {
+ search: {
+ title: "Search trash"
+ }
}
- }
- }),
- "/tags": () => ({
- key: "tags",
- title: "Tags",
- type: "tags",
- component: ,
- buttons: {
- search: {
- title: "Search tags"
+ };
+ },
+ "/tags": () => {
+ notestore.clearSearch();
+ return {
+ key: "tags",
+ title: "Tags",
+ type: "tags",
+ component: ,
+ buttons: {
+ search: {
+ title: "Search tags"
+ }
}
- }
- }),
+ };
+ },
"/tags/:tagId": ({ tagId }) => {
const tag = db.tags.tag(tagId);
if (!tag) return false;
const { id } = tag;
notestore.setContext({ type: "tag", value: id });
const title = db.tags.alias(id);
+ notestore.clearSearch();
return {
key: "notes",
type: "notes",
@@ -181,6 +198,7 @@ const routes = {
const { id } = color;
const title = db.colors.alias(id);
notestore.setContext({ type: "color", value: id });
+ notestore.clearSearch();
return {
key: "notes",
type: "notes",
@@ -193,13 +211,17 @@ const routes = {
}
};
},
- "/settings": () => ({
- key: "settings",
- title: "Settings",
- component:
- }),
+ "/settings": () => {
+ notestore.clearSearch();
+ return {
+ key: "settings",
+ title: "Settings",
+ component:
+ };
+ },
"/monographs": () => {
notestore.setContext({ type: "monographs" });
+ notestore.clearSearch();
return {
key: "notes",
title: "Monographs",
@@ -212,17 +234,19 @@ const routes = {
}
};
},
- "/search/:type": ({ type }) => ({
- type: "search",
- title: "Search",
- component: ,
- buttons: {
- back: {
- title: `Go back to ${type}`,
- action: () => window.history.back()
+ "/search/:type": ({ type }) => {
+ return {
+ type: "search",
+ title: "Search",
+ component: ,
+ buttons: {
+ back: {
+ title: `Go back to ${type}`,
+ action: () => window.history.back()
+ }
}
- }
- })
+ };
+ }
};
export default routes;
diff --git a/apps/web/src/stores/note-store.js b/apps/web/src/stores/note-store.js
index 303e2da14..bf313112a 100644
--- a/apps/web/src/stores/note-store.js
+++ b/apps/web/src/stores/note-store.js
@@ -35,6 +35,7 @@ class NoteStore extends BaseStore {
selectedNote = 0;
nonce = 0;
viewMode = Config.get("notes:viewMode", "detailed");
+ search = undefined;
setViewMode = (viewMode) => {
this.set((state) => (state.viewMode = viewMode));
@@ -170,6 +171,14 @@ class NoteStore extends BaseStore {
}
};
+ setSearch = (query) => {
+ this.set((state) => (state.search = { query }));
+ };
+
+ clearSearch = () => {
+ this.set((state) => (state.search = undefined));
+ };
+
/**
* @private
*/
diff --git a/apps/web/src/views/search.js b/apps/web/src/views/search.js
index b54fee3c9..719185f33 100644
--- a/apps/web/src/views/search.js
+++ b/apps/web/src/views/search.js
@@ -62,12 +62,14 @@ function Search({ type }) {
const [results, setResults] = useState([]);
const context = useNoteStore((store) => store.context);
const nonce = useNoteStore((store) => store.nonce);
+ const setSearch = useNoteStore((store) => store.setSearch);
const cachedQuery = useRef();
const onSearch = useCallback(
async (query) => {
if (!query) return;
cachedQuery.current = query;
+ setSearch(query);
const [lookupType, items] = await typeToItems(type, context);
setResults([]);
@@ -81,7 +83,7 @@ function Search({ type }) {
setResults(results);
setSearchState({ isSearching: false, totalItems: 0 });
},
- [context, type]
+ [context, type, setSearch]
);
const title = useMemo(() => {
@@ -161,7 +163,7 @@ function Search({ type }) {
) : (
(
diff --git a/packages/editor/src/toolbar/popups/search-replace.tsx b/packages/editor/src/toolbar/popups/search-replace.tsx
index f6e76362b..979511b15 100644
--- a/packages/editor/src/toolbar/popups/search-replace.tsx
+++ b/packages/editor/src/toolbar/popups/search-replace.tsx
@@ -101,6 +101,7 @@ export function SearchReplacePopup(props: SearchReplacePopupProps) {
}}
>