web: added (highlighting search query in note) for search feature.

This commit is contained in:
alihamuh
2023-01-27 09:16:51 +05:00
parent 95ee494612
commit cf33cea1c9
5 changed files with 111 additions and 57 deletions

View File

@@ -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]

View File

@@ -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;

View File

@@ -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
*/

View File

@@ -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={() => (

View File

@@ -101,6 +101,7 @@ export function SearchReplacePopup(props: SearchReplacePopupProps) {
}}
>
<Input
id={"search-replace-input"}
variant={"clean"}
defaultValue={selectedText}
ref={searchInputRef}