aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/views/collections/CollectionSchemaCells.tsx26
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx2
-rw-r--r--src/client/views/nodes/FieldView.tsx3
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx39
-rw-r--r--src/client/views/pdf/PDFViewer.tsx4
-rw-r--r--src/client/views/search/SearchBox.tsx34
-rw-r--r--src/fields/Doc.ts25
7 files changed, 69 insertions, 64 deletions
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx
index ea786800c..4bd69041b 100644
--- a/src/client/views/collections/CollectionSchemaCells.tsx
+++ b/src/client/views/collections/CollectionSchemaCells.tsx
@@ -894,26 +894,22 @@ export class CollectionSchemaCheckboxCell extends CollectionSchemaCell {
export class CollectionSchemaButtons extends CollectionSchemaCell {
render() {
const doc = this.props.rowProps.original;
- const searchMatch = (backward: boolean = true) => { doc.searchMatch = undefined; setTimeout(() => doc.searchMatch = backward, 0); };
+ const searchMatch = (backward: boolean = true) => Doc.SearchMatchNext(doc, backward);
// const reference = React.createRef<HTMLDivElement>();
// const onItemDown = (e: React.PointerEvent) => {
// (!this.props.CollectionView || !this.props.CollectionView.props.isSelected() ? undefined :
// SetupDrag(reference, () => this._document, this.props.moveDocument, this.props.Document.schemaDoc ? "copy" : undefined)(e));
// };
return !BoolCast(this.props.Document._searchDoc) ? <></>
- : StrCast(doc.type) === DocumentType.PDF ?
- <button style={{ position: "relative", height: 30, width: 28, left: 1, }} onClick={() => searchMatch(false)}>
- <FontAwesomeIcon icon="arrow-down" size="sm" />
- </button>
- : StrCast(doc.type) === DocumentType.RTF ?
- <div style={{ paddingTop: 8, paddingLeft: 3, }} >
- <button style={{ padding: 2, left: 77 }} onClick={() => searchMatch(true)}>
- <FontAwesomeIcon icon="arrow-up" size="sm" />
- </button>
- <button style={{ padding: 2 }} onClick={() => searchMatch(false)} >
- <FontAwesomeIcon icon="arrow-down" size="sm" />
- </button>
- </div> :
- <></>;
+ : [DocumentType.PDF, DocumentType.RTF].includes(StrCast(doc.type) as DocumentType) ?
+ <div style={{ paddingTop: 8, paddingLeft: 3, }} >
+ <button style={{ padding: 2, left: 77 }} onClick={() => searchMatch(true)}>
+ <FontAwesomeIcon icon="arrow-up" size="sm" />
+ </button>
+ <button style={{ padding: 2 }} onClick={() => searchMatch(false)} >
+ <FontAwesomeIcon icon="arrow-down" size="sm" />
+ </button>
+ </div> :
+ <></>;
}
} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 4503b0fb3..8440d3e9b 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -472,7 +472,7 @@ class TreeView extends React.Component<TreeViewProps> {
return <>
<div className="docContainer" ref={this._tref} title="click to edit title" id={`docContainer-${this.props.parentKey}`}
style={{
- fontWeight: this.doc.searchMatch !== undefined ? "bold" : undefined,
+ fontWeight: Doc.IsSearchMatch(this.doc) !== undefined ? "bold" : undefined,
textDecoration: Doc.GetT(this.doc, "title", "string", true) ? "underline" : undefined,
outline: BoolCast(this.doc.dashboardBrush) ? "dashed 1px #06123232" : undefined,
pointerEvents: this.props.active() || SnappingManager.GetIsDragging() ? undefined : "none"
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index d95951f3a..3726f1d5f 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -58,9 +58,6 @@ export interface FieldViewProps {
ChromeHeight?: () => number;
childLayoutTemplate?: () => Opt<Doc>;
- highlighting?: string[];
- lines?: string[];
- doc?: Doc;
// properties intended to be used from within layout strings (otherwise use the function equivalents that work more efficiently with React)
height?: number;
width?: number;
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 6b4115e53..5250a8f58 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -376,8 +376,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
public highlightSearchTerms = (terms: string[], backward: boolean) => {
if (this._editorView && (this._editorView as any).docView && terms.some(t => t)) {
-
-
const mark = this._editorView.state.schema.mark(this._editorView.state.schema.marks.search_highlight);
const activeMark = this._editorView.state.schema.mark(this._editorView.state.schema.marks.search_highlight, { selected: true });
const res = terms.filter(t => t).map(term => this.findInNode(this._editorView!, this._editorView!.state.doc, term));
@@ -385,24 +383,19 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
let tr = this._editorView.state.tr;
const flattened: TextSelection[] = [];
res.map(r => r.map(h => flattened.push(h)));
- if (BoolCast(Doc.GetProto(this.dataDoc).resetSearch) === true) {
- this._searchIndex = 0;
- Doc.GetProto(this.dataDoc).resetSearch = undefined;
- }
- else {
- this._searchIndex = ++this._searchIndex > flattened.length - 1 ? 0 : this._searchIndex;
- if (backward === true) {
- if (this._searchIndex > 1) {
- this._searchIndex += -2;
- }
- else if (this._searchIndex === 1) {
- this._searchIndex = length - 1;
- }
- else if (this._searchIndex === 0 && length !== 1) {
- this._searchIndex = length - 2;
- }
-
+ console.log("Search:" + this.rootDoc.title + " " + this._searchIndex + " => " + (this._searchIndex + 1 > flattened.length - 1 ? 0 : this._searchIndex + 1));
+ this._searchIndex = ++this._searchIndex > flattened.length - 1 ? 0 : this._searchIndex;
+ if (backward === true) {
+ if (this._searchIndex > 1) {
+ this._searchIndex += -2;
+ }
+ else if (this._searchIndex === 1) {
+ this._searchIndex = length - 1;
}
+ else if (this._searchIndex === 0 && length !== 1) {
+ this._searchIndex = length - 2;
+ }
+
}
const lastSel = Math.min(flattened.length - 1, this._searchIndex);
@@ -909,9 +902,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
this.setupEditor(this.config, this.props.fieldKey);
- this._disposers.search = reaction(() => this.rootDoc.searchMatch,
- search => search !== undefined ? this.highlightSearchTerms([Doc.SearchQuery()], BoolCast(search)) : this.unhighlightSearchTerms(),
- { fireImmediately: this.rootDoc.searchMatch !== undefined ? true : false });
+ this._disposers.search = reaction(() => Doc.IsSearchMatch(this.rootDoc),
+ search => {
+ search ? this.highlightSearchTerms([Doc.SearchQuery()], search.searchMatch < 0) : this.unhighlightSearchTerms();
+ },
+ { fireImmediately: Doc.IsSearchMatch(this.rootDoc) ? true : false });
this._disposers.record = reaction(() => this._recording,
() => {
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 0916e8b0c..f2aa9fa3f 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -150,9 +150,9 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
runInAction(() => this._showWaiting = this._showCover = true);
this.props.startupLive && this.setupPdfJsViewer();
this._mainCont.current && (this._mainCont.current.scrollTop = this.layoutDoc._scrollTop || 0);
- this._searchReactionDisposer = reaction(() => this.Document.searchMatch,
+ this._searchReactionDisposer = reaction(() => Doc.IsSearchMatch(this.rootDoc),
m => {
- if (m !== undefined) (this._lastSearch = true) && this.search(Doc.SearchQuery(), true);
+ if (m) (this._lastSearch = true) && this.search(Doc.SearchQuery(), m.searchMatch > 0);
else !(this._lastSearch = false) && setTimeout(() => !this._lastSearch && this.search("", false, true), 200);
}, { fireImmediately: true });
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx
index d7c065a75..c571adefe 100644
--- a/src/client/views/search/SearchBox.tsx
+++ b/src/client/views/search/SearchBox.tsx
@@ -84,21 +84,17 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
Object.values(this._disposers).forEach(disposer => disposer?.());
}
- @action
- getViews = (doc: Doc) => SearchUtil.GetViewsOfDocument(doc)
-
@action.bound
onChange(e: React.ChangeEvent<HTMLInputElement>) {
this.layoutDoc._searchString = e.target.value;
this.newsearchstring = e.target.value;
if (e.target.value === "") {
if (this.currentSelectedCollection) {
- this.doLoop(this.currentSelectedCollection, undefined);
+ this.setSearchDocsRecursive(this.currentSelectedCollection, undefined);
}
this.closeSearch(false);
if (this.currentSelectedCollection !== undefined) {
- this.currentSelectedCollection.props.Document._searchDocs = new List<Doc>([]);
this.currentSelectedCollection = undefined;
this.props.Document.selectedDoc = undefined;
}
@@ -242,14 +238,12 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
while (docs.length > 0) {
newarray = [];
docs.forEach((d) => {
- if (d.data !== undefined) {
- newarray.push(...DocListCast(d.data));
- }
- const hlights: string[] = [];
+ d.data && newarray.push(...DocListCast(d.data));
+ const hlights = new Set<string>();
this.documentKeys(d).forEach(key =>
- Field.toString(d[key] as Field).toLowerCase().includes(query) && !hlights.includes(key) && hlights.push(key));
- if (hlights.length > 0) {
- found.push([d, hlights, []]);
+ Field.toString(d[key] as Field).toLowerCase().includes(query) && hlights.add(key));
+ if (Array.from(hlights.keys()).length > 0) {
+ found.push([d, Array.from(hlights.keys()), []]);
docsforFilter.push(d);
}
});
@@ -259,7 +253,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
this.docsforfilter = docsforFilter;
if (this.filter === true) {
selectedCollection.props.Document._searchDocs = new List<Doc>(docsforFilter);
- this.doLoop(selectedCollection, docsforFilter);
+ this.setSearchDocsRecursive(selectedCollection, docsforFilter);
}
this._numTotalResults = found.length;
this.realTotalResults = found.length;
@@ -285,7 +279,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
@action
submitSearch = async (reset?: boolean) => {
if (this.currentSelectedCollection !== undefined) {
- this.doLoop(this.currentSelectedCollection, undefined);
+ this.setSearchDocsRecursive(this.currentSelectedCollection, undefined);
}
if (reset) {
this.layoutDoc._searchString = "";
@@ -434,7 +428,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
closeSearch = (closesearchbar = true) => {
this._results.forEach(result => {
Doc.UnBrushDoc(result[0]);
- result[0].searchMatch = undefined;
+ Doc.ClearSearchMatches();
});
closesearchbar && (this._searchbarOpen = false);
}
@@ -479,9 +473,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
const highlights = Array.from([...Array.from(new Set(result[1]).values())]);
const lines = new List<string>(result[2]);
highlights.forEach((item) => headers.add(item));
- result[0].lines = lines;
- result[0].highlighting = highlights.join(", ");
- result[0].searchMatch = true;
+ Doc.SetSearchMatch(result[0], { searchMatch: 1 });
if (i < this._visibleDocuments.length) {
this._visibleDocuments[i] = result[0];
Doc.BrushDoc(result[0]);
@@ -530,7 +522,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
this._searchFullDB = scope;
this.dataDoc[this.fieldKey] = new List<Doc>([]);
if (this.currentSelectedCollection !== undefined) {
- this.doLoop(this.currentSelectedCollection, undefined);
+ this.setSearchDocsRecursive(this.currentSelectedCollection, undefined);
}
this.submitSearch();
}
@@ -566,7 +558,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
</div>;
}
- doLoop = (collectionView: DocumentView, filter: Doc[] | undefined) => {
+ setSearchDocsRecursive = (collectionView: DocumentView, filter: Doc[] | undefined) => {
let docs = DocListCast(collectionView.dataDoc[Doc.LayoutFieldKey(collectionView.dataDoc)]);
let newarray: Doc[] = [];
while (docs.length > 0) {
@@ -614,7 +606,7 @@ export class SearchBox extends ViewBoxBaseComponent<FieldViewProps, SearchBoxDoc
onPointerDown={e => { e.stopPropagation(); SetupDrag(this.collectionRef, () => this.layoutDoc._searchString ? this.startDragCollection() : undefined); }}
onClick={action(() => {
this.filter = !this.filter && !this._searchFullDB;
- this.currentSelectedCollection && this.doLoop(this.currentSelectedCollection, this.filter ? this.docsforfilter : undefined);
+ this.currentSelectedCollection && this.setSearchDocsRecursive(this.currentSelectedCollection, this.filter ? this.docsforfilter : undefined);
})} />
</div>
</Tooltip>
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index c78b01def..dc274a063 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -23,6 +23,7 @@ import { deleteProperty, getField, getter, makeEditable, makeReadOnly, setter, u
import { LinkManager } from "../client/util/LinkManager";
import JSZip = require("jszip");
import { saveAs } from "file-saver";
+import { result } from "lodash";
export namespace Field {
export function toKeyValueString(doc: Doc, key: string): string {
@@ -881,6 +882,7 @@ export namespace Doc {
export class DocBrush {
BrushedDoc: ObservableMap<Doc, boolean> = new ObservableMap();
+ SearchMatchDoc: ObservableMap<Doc, { searchMatch: number }> = new ObservableMap();
}
const brushManager = new DocBrush();
@@ -906,6 +908,29 @@ export namespace Doc {
export function SetSelectedTool(tool: InkTool) { Doc.UserDoc().activeInkTool = tool; }
export function GetSelectedTool(): InkTool { return StrCast(Doc.UserDoc().activeInkTool, InkTool.None) as InkTool; }
export function SetUserDoc(doc: Doc) { manager._user_doc = doc; }
+
+ export function IsSearchMatch(doc: Doc) {
+ return computedFn(function IsSearchMatch(doc: Doc) {
+ return brushManager.SearchMatchDoc.has(doc) ? brushManager.SearchMatchDoc.get(doc) :
+ brushManager.SearchMatchDoc.has(Doc.GetProto(doc)) ? brushManager.SearchMatchDoc.get(Doc.GetProto(doc)) : undefined;
+ })(doc);
+ }
+ export function SetSearchMatch(doc: Doc, results: { searchMatch: number }) {
+ if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return doc;
+ brushManager.SearchMatchDoc.set(doc, results);
+ return doc;
+ }
+ export function SearchMatchNext(doc: Doc, backward: boolean) {
+ if (!doc || GetEffectiveAcl(doc) === AclPrivate || GetEffectiveAcl(Doc.GetProto(doc)) === AclPrivate) return doc;
+ const result = brushManager.SearchMatchDoc.get(doc);
+ const num = Math.abs(result?.searchMatch || 0) + 1;
+ runInAction(() => result && brushManager.SearchMatchDoc.set(doc, { searchMatch: backward ? -num : num }));
+ return doc;
+ }
+ export function ClearSearchMatches() {
+ brushManager.SearchMatchDoc.clear();
+ }
+
export function IsBrushed(doc: Doc) {
return computedFn(function IsBrushed(doc: Doc) {
return brushManager.BrushedDoc.has(doc) || brushManager.BrushedDoc.has(Doc.GetProto(doc));