mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-02-23 19:49:56 +01:00
web: added (highlighting search query in note) for search feature.
This commit is contained in:
@@ -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]
|
||||
|
||||
@@ -33,32 +33,39 @@ import { showToast } from "../utils/toast";
|
||||
import Reminders from "../views/reminders";
|
||||
|
||||
const routes = {
|
||||
"/notes": () => ({
|
||||
key: "home",
|
||||
type: "notes",
|
||||
title: "Notes",
|
||||
component: <Home />,
|
||||
buttons: {
|
||||
search: {
|
||||
title: "Search notes"
|
||||
"/notes": () => {
|
||||
notestore.clearSearch();
|
||||
return {
|
||||
key: "home",
|
||||
type: "notes",
|
||||
title: "Notes",
|
||||
component: <Home />,
|
||||
buttons: {
|
||||
search: {
|
||||
title: "Search notes"
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
"/notebooks": () => ({
|
||||
key: "notebooks",
|
||||
type: "notebooks",
|
||||
title: "Notebooks",
|
||||
component: <Notebooks />,
|
||||
buttons: {
|
||||
search: {
|
||||
title: "Search notebooks"
|
||||
};
|
||||
},
|
||||
"/notebooks": () => {
|
||||
notestore.clearSearch();
|
||||
return {
|
||||
key: "notebooks",
|
||||
type: "notebooks",
|
||||
title: "Notebooks",
|
||||
component: <Notebooks />,
|
||||
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: <Trash />,
|
||||
buttons: {
|
||||
search: {
|
||||
title: "Search trash"
|
||||
"/trash": () => {
|
||||
notestore.clearSearch();
|
||||
return {
|
||||
key: "trash",
|
||||
type: "trash",
|
||||
title: "Trash",
|
||||
component: <Trash />,
|
||||
buttons: {
|
||||
search: {
|
||||
title: "Search trash"
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
"/tags": () => ({
|
||||
key: "tags",
|
||||
title: "Tags",
|
||||
type: "tags",
|
||||
component: <Tags />,
|
||||
buttons: {
|
||||
search: {
|
||||
title: "Search tags"
|
||||
};
|
||||
},
|
||||
"/tags": () => {
|
||||
notestore.clearSearch();
|
||||
return {
|
||||
key: "tags",
|
||||
title: "Tags",
|
||||
type: "tags",
|
||||
component: <Tags />,
|
||||
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 />
|
||||
}),
|
||||
"/settings": () => {
|
||||
notestore.clearSearch();
|
||||
return {
|
||||
key: "settings",
|
||||
title: "Settings",
|
||||
component: <Settings />
|
||||
};
|
||||
},
|
||||
"/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: <Search type={type} />,
|
||||
buttons: {
|
||||
back: {
|
||||
title: `Go back to ${type}`,
|
||||
action: () => window.history.back()
|
||||
"/search/:type": ({ type }) => {
|
||||
return {
|
||||
type: "search",
|
||||
title: "Search",
|
||||
component: <Search type={type} />,
|
||||
buttons: {
|
||||
back: {
|
||||
title: `Go back to ${type}`,
|
||||
action: () => window.history.back()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export default routes;
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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 }) {
|
||||
</Flex>
|
||||
) : (
|
||||
<ListContainer
|
||||
context={context}
|
||||
context={{ type: "search" }}
|
||||
type={type}
|
||||
items={results}
|
||||
placeholder={() => (
|
||||
|
||||
@@ -101,6 +101,7 @@ export function SearchReplacePopup(props: SearchReplacePopupProps) {
|
||||
}}
|
||||
>
|
||||
<Input
|
||||
id={"search-replace-input"}
|
||||
variant={"clean"}
|
||||
defaultValue={selectedText}
|
||||
ref={searchInputRef}
|
||||
|
||||
Reference in New Issue
Block a user