diff options
author | usodhi <61431818+usodhi@users.noreply.github.com> | 2020-06-30 23:47:16 +0530 |
---|---|---|
committer | usodhi <61431818+usodhi@users.noreply.github.com> | 2020-06-30 23:47:16 +0530 |
commit | b9eb75e743ceaf8540a7a7d3b6f08b42e75de25c (patch) | |
tree | d5b6e0c34cf1deae5deaa508f4c8d49e53534294 /src | |
parent | 4590467260a783e7d83adb20631c3b575d7e4cd3 (diff) | |
parent | 5d7823da144191930ead98a60aedd6543748d4a1 (diff) |
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into acls_uv
Diffstat (limited to 'src')
-rw-r--r-- | src/client/util/SearchUtil.ts | 2 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 5 | ||||
-rw-r--r-- | src/client/views/collections/CollectionSubView.tsx | 15 | ||||
-rw-r--r-- | src/client/views/collections/CollectionTreeView.tsx | 10 | ||||
-rw-r--r-- | src/client/views/collections/CollectionView.tsx | 31 | ||||
-rw-r--r-- | src/client/views/nodes/VideoBox.tsx | 28 | ||||
-rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBox.tsx | 11 | ||||
-rw-r--r-- | src/client/views/nodes/formattedText/marks_rts.ts | 1 | ||||
-rw-r--r-- | src/fields/Doc.ts | 33 |
9 files changed, 83 insertions, 53 deletions
diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts index 5679c0a14..1ac68480e 100644 --- a/src/client/util/SearchUtil.ts +++ b/src/client/util/SearchUtil.ts @@ -74,7 +74,7 @@ export namespace SearchUtil { const docs = ids.map((id: string) => docMap[id]).map(doc => doc as Doc); for (let i = 0; i < ids.length; i++) { const testDoc = docs[i]; - if (testDoc instanceof Doc && testDoc.type !== DocumentType.KVP && (options.allowAliases || theDocs.findIndex(d => Doc.AreProtosEqual(d, testDoc)) === -1)) { + if (testDoc instanceof Doc && testDoc.type !== DocumentType.KVP && (options.allowAliases || testDoc.proto === undefined || theDocs.findIndex(d => Doc.AreProtosEqual(d, testDoc)) === -1)) { theDocs.push(testDoc); theLines.push([]); } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index cea664543..200486279 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -383,7 +383,8 @@ export class MainView extends React.Component { doc.dockingConfig ? this.openWorkspace(doc) : CollectionDockingView.AddRightSplit(doc, libraryPath); } - mainContainerXf = () => new Transform(0, -this._buttonBarHeight, 1); + sidebarScreenToLocal = () => new Transform(0, RichTextMenu.Instance.Pinned ? -35 : 0, 1); + mainContainerXf = () => this.sidebarScreenToLocal().translate(0, -this._buttonBarHeight); @computed get flyout() { const sidebarContent = this.userDoc?.["tabs-panelContainer"]; @@ -402,7 +403,7 @@ export class MainView extends React.Component { pinToPres={emptyFunction} removeDocument={undefined} onClick={undefined} - ScreenToLocalTransform={Transform.Identity} + ScreenToLocalTransform={this.sidebarScreenToLocal} ContentScaling={returnOne} NativeHeight={returnZero} NativeWidth={returnZero} diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 29144abaf..d107db86b 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -1,13 +1,13 @@ import { action, computed, IReactionDisposer, reaction } from "mobx"; import { basename } from 'path'; import CursorField from "../../../fields/CursorField"; -import { Doc, Opt } from "../../../fields/Doc"; +import { Doc, Opt, Field } from "../../../fields/Doc"; import { Id } from "../../../fields/FieldSymbols"; import { List } from "../../../fields/List"; import { listSpec } from "../../../fields/Schema"; import { ScriptField } from "../../../fields/ScriptField"; import { WebField } from "../../../fields/URLField"; -import { Cast, ScriptCast, NumCast } from "../../../fields/Types"; +import { Cast, ScriptCast, NumCast, StrCast } from "../../../fields/Types"; import { GestureUtils } from "../../../pen-gestures/GestureUtils"; import { Upload } from "../../../server/SharedMediaTypes"; import { Utils, returnFalse, returnEmptyFilter } from "../../../Utils"; @@ -136,8 +136,12 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?: const filteredDocs = docFilters.length && !this.props.dontRegisterView ? childDocs.filter(d => { for (const facetKey of Object.keys(filterFacets)) { const facet = filterFacets[facetKey]; - const satisfiesFacet = Object.keys(facet).some(value => - (facet[value] === "x") !== Doc.matchFieldValue(d, facetKey, value)); + const satisfiesFacet = Object.keys(facet).some(value => { + if (facet[value] === "match") { + return d[facetKey] === undefined || Field.toString(d[facetKey] as Field).includes(value); + } + return (facet[value] === "x") !== Doc.matchFieldValue(d, facetKey, value); + }); if (!satisfiesFacet) { return false; } @@ -354,7 +358,7 @@ export function CollectionSubView<T, X>(schemaCtor: (doc: Doc) => T, moreProps?: } if (text) { - if (text.includes("www.youtube.com/watch")) { + if (text.includes("www.youtube.com/watch") || text.includes("www.youtube.com/embed")) { const url = text.replace("youtube.com/watch?v=", "youtube.com/embed/").split("&")[0]; addDocument(Docs.Create.VideoDocument(url, { ...options, @@ -472,3 +476,4 @@ import { DocumentType } from "../../documents/DocumentTypes"; import { FormattedTextBox, GoogleRef } from "../nodes/formattedText/FormattedTextBox"; import { CollectionView } from "./CollectionView"; import { SelectionManager } from "../../util/SelectionManager"; + diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index f6f6fb7cc..620b977fa 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -304,7 +304,7 @@ class TreeView extends React.Component<TreeViewProps> { } rtfWidth = () => Math.min(this.layoutDoc?.[WidthSym](), this.props.panelWidth() - 20); - rtfHeight = () => this.rtfWidth() < this.layoutDoc?.[WidthSym]() ? Math.min(this.layoutDoc?.[HeightSym](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT; + rtfHeight = () => this.rtfWidth() <= this.layoutDoc?.[WidthSym]() ? Math.min(this.layoutDoc?.[HeightSym](), this.MAX_EMBED_HEIGHT) : this.MAX_EMBED_HEIGHT; @computed get renderContent() { TraceMobx(); @@ -332,8 +332,8 @@ class TreeView extends React.Component<TreeViewProps> { </div></ul>; } else { const layoutDoc = this.layoutDoc; - const panelHeight = layoutDoc.type === DocumentType.RTF ? this.rtfHeight : this.docHeight; - const panelWidth = layoutDoc.type === DocumentType.RTF ? this.rtfWidth : this.docWidth; + const panelHeight = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfHeight : this.docHeight; + const panelWidth = StrCast(Doc.LayoutField(layoutDoc)).includes("FormattedTextBox") ? this.rtfWidth : this.docWidth; return <div ref={this._dref} style={{ display: "inline-block", height: panelHeight() }} key={this.doc[Id]}> <ContentFittingDocumentView Document={layoutDoc} @@ -386,8 +386,8 @@ class TreeView extends React.Component<TreeViewProps> { e.stopPropagation(); } - @computed - get renderBullet() { + @computed get renderBullet() { + TraceMobx(); const checked = this.doc.type === DocumentType.COL ? undefined : this.onCheckedClick ? (this.doc.treeViewChecked ?? "unchecked") : undefined; return <div className="bullet" title={this.childDocs?.length ? `click to see ${this.childDocs?.length} items` : "view fields"} diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index f2ffe7835..6acf78af7 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -47,6 +47,8 @@ import { CollectionGridView } from './collectionGrid/CollectionGridView'; import './CollectionView.scss'; import { CollectionViewBaseChrome } from './CollectionViewChromes'; import { UndoManager } from '../../util/UndoManager'; +import { RichTextField } from '../../../fields/RichTextField'; +import { TextField } from '../../util/ProsemirrorCopy/prompt'; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -357,8 +359,9 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus return viewSpecScript ? docs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result) : docs; } @computed get _allFacets() { - const facets = new Set<string>(); - this.childDocs.filter(child => child).forEach(child => Object.keys(Doc.GetProto(child)).forEach(key => facets.add(key))); + TraceMobx(); + const facets = new Set<string>(["type", "text", "data", "author", "ACL"]); + this.childDocs.filter(child => child).forEach(child => child && Object.keys(Doc.GetProto(child)).forEach(key => facets.add(key))); Doc.AreProtosEqual(this.dataDoc, this.props.Document) && this.childDocs.filter(child => child).forEach(child => Object.keys(child).forEach(key => facets.add(key))); return Array.from(facets).filter(f => !f.startsWith("_") && !["proto", "zIndex", "isPrototype", "context", "text-noTemplate"].includes(f)).sort(); } @@ -387,8 +390,13 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus } } else { const allCollectionDocs = DocListCast(this.dataDoc[this.props.fieldKey]); - const facetValues = Array.from(allCollectionDocs.reduce((set, child) => - set.add(Field.toString(child[facetHeader] as Field)), new Set<string>())); + var rtfields = 0; + const facetValues = Array.from(allCollectionDocs.reduce((set, child) => { + const field = child[facetHeader] as Field; + const fieldStr = Field.toString(field); + if (field instanceof RichTextField || (typeof (field) === "string" && fieldStr.split(" ").length > 2)) rtfields++; + return set.add(fieldStr); + }, new Set<string>())); let nonNumbers = 0; let minVal = Number.MAX_VALUE, maxVal = -Number.MAX_VALUE; @@ -402,13 +410,18 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus } }); let newFacet: Opt<Doc>; - if (nonNumbers / allCollectionDocs.length < .1) { - newFacet = Docs.Create.SliderDocument({ title: facetHeader }); + if (facetHeader === "text" || rtfields / allCollectionDocs.length > 0.1) { + newFacet = Docs.Create.TextDocument("", { _width: 100, _height: 25, treeViewExpandedView: "layout", title: facetHeader, treeViewOpen: true, forceActive: true, ignoreClick: true }); + Doc.GetProto(newFacet).type = DocumentType.COL; // forces item to show an open/close button instead ofa checkbox + newFacet.target = this.props.Document; + newFacet._textBoxPadding = 4; + const scriptText = `setDocFilter(this.target, "${facetHeader}", text, "match")`; + newFacet.onTextChanged = ScriptField.MakeScript(scriptText, { this: Doc.name, text: "string" }); + } else if (nonNumbers / facetValues.length < .1) { + newFacet = Docs.Create.SliderDocument({ title: facetHeader, treeViewExpandedView: "layout", treeViewOpen: true }); const newFacetField = Doc.LayoutFieldKey(newFacet); const ranged = Doc.readDocRangeFilter(this.props.Document, facetHeader); Doc.GetProto(newFacet).type = DocumentType.COL; // forces item to show an open/close button instead ofa checkbox - newFacet.treeViewExpandedView = "layout"; - newFacet.treeViewOpen = true; const extendedMinVal = minVal - Math.min(1, Math.abs(maxVal - minVal) * .05); const extendedMaxVal = maxVal + Math.min(1, Math.abs(maxVal - minVal) * .05); newFacet[newFacetField + "-min"] = ranged === undefined ? extendedMinVal : ranged[0]; @@ -418,7 +431,6 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus newFacet.target = this.props.Document; const scriptText = `setDocFilterRange(this.target, "${facetHeader}", range)`; newFacet.onThumbChanged = ScriptField.MakeScript(scriptText, { this: Doc.name, range: "number" }); - Doc.AddDocToList(facetCollection, this.props.fieldKey + "-filter", newFacet); } else { newFacet = new Doc(); @@ -445,6 +457,7 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus return ScriptField.MakeScript(scriptText, { this: Doc.name, heading: "string", checked: "string", containingTreeView: Doc.name }); } @computed get filterView() { + TraceMobx(); const facetCollection = this.props.Document; const flyout = ( <div className="collectionTimeView-flyout" style={{ width: `${this.facetWidth()}`, height: this.props.PanelHeight() - 30 }} onWheel={e => e.stopPropagation()}> diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 71556bfd3..a5c6c4a48 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -19,6 +19,7 @@ import { FieldView, FieldViewProps } from './FieldView'; import "./VideoBox.scss"; import { documentSchema } from "../../../fields/documentSchemas"; import { Networking } from "../../Network"; +import { SnappingManager } from "../../util/SnappingManager"; const path = require('path'); export const timeSchema = createSchema({ @@ -58,21 +59,21 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD @action public Play = (update: boolean = true) => { this._playing = true; - update && this.player && this.player.play(); - update && this._youtubePlayer && this._youtubePlayer.playVideo(); + update && this.player?.play(); + update && this._youtubePlayer?.playVideo(); this._youtubePlayer && !this._playTimer && (this._playTimer = setInterval(this.updateTimecode, 5)); this.updateTimecode(); } @action public Seek(time: number) { - this._youtubePlayer && this._youtubePlayer.seekTo(Math.round(time), true); + this._youtubePlayer?.seekTo(Math.round(time), true); this.player && (this.player.currentTime = time); } @action public Pause = (update: boolean = true) => { this._playing = false; - update && this.player && this.player.pause(); - update && this._youtubePlayer && this._youtubePlayer.pauseVideo && this._youtubePlayer.pauseVideo(); + update && this.player?.pause(); + update && this._youtubePlayer?.pauseVideo(); this._youtubePlayer && this._playTimer && clearInterval(this._playTimer); this._playTimer = undefined; this.updateTimecode(); @@ -261,21 +262,20 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD const onYoutubePlayerStateChange = (event: any) => runInAction(() => { if (started && event.data === YT.PlayerState.PLAYING) { started = false; - this._youtubePlayer && this._youtubePlayer.unMute(); - this.Pause(); + this._youtubePlayer?.unMute(); + //this.Pause(); return; } if (event.data === YT.PlayerState.PLAYING && !this._playing) this.Play(false); if (event.data === YT.PlayerState.PAUSED && this._playing) this.Pause(false); }); const onYoutubePlayerReady = (event: any) => { - this._reactionDisposer && this._reactionDisposer(); - this._youtubeReactionDisposer && this._youtubeReactionDisposer(); + this._reactionDisposer?.(); + this._youtubeReactionDisposer?.(); this._reactionDisposer = reaction(() => this.layoutDoc.currentTimecode, () => !this._playing && this.Seek((this.layoutDoc.currentTimecode || 0))); - this._youtubeReactionDisposer = reaction(() => [this.props.isSelected(), DocumentDecorations.Instance.Interacting, Doc.GetSelectedTool()], () => { - const interactive = Doc.GetSelectedTool() === InkTool.None && this.props.isSelected(true) && !DocumentDecorations.Instance.Interacting; - iframe.style.pointerEvents = interactive ? "all" : "none"; - }, { fireImmediately: true }); + this._youtubeReactionDisposer = reaction( + () => Doc.GetSelectedTool() === InkTool.None && this.props.isSelected(true) && !SnappingManager.GetIsDragging() && !DocumentDecorations.Instance.Interacting, + (interactive) => iframe.style.pointerEvents = interactive ? "all" : "none", { fireImmediately: true }); }; this._youtubePlayer = new YT.Player(`${this.youtubeVideoId + this._youtubeIframeId}-player`, { events: { @@ -346,7 +346,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD const start = untracked(() => Math.round((this.layoutDoc.currentTimecode || 0))); return <iframe key={this._youtubeIframeId} id={`${this.youtubeVideoId + this._youtubeIframeId}-player`} onLoad={this.youtubeIframeLoaded} className={`${style}`} width={(this.layoutDoc._nativeWidth || 640)} height={(this.layoutDoc._nativeHeight || 390)} - src={`https://www.youtube.com/embed/${this.youtubeVideoId}?enablejsapi=1&rel=0&showinfo=1&autoplay=1&mute=1&start=${start}&modestbranding=1&controls=${VideoBox._showControls ? 1 : 0}`} />; + src={`https://www.youtube.com/embed/${this.youtubeVideoId}?enablejsapi=1&rel=0&showinfo=1&autoplay=0&mute=1&start=${start}&modestbranding=1&controls=${VideoBox._showControls ? 1 : 0}`} />; } @action.bound diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 90f379525..2cb55e0fa 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -22,7 +22,7 @@ import { PrefetchProxy } from '../../../../fields/Proxy'; import { RichTextField } from "../../../../fields/RichTextField"; import { RichTextUtils } from '../../../../fields/RichTextUtils'; import { createSchema, makeInterface } from "../../../../fields/Schema"; -import { Cast, DateCast, NumCast, StrCast } from "../../../../fields/Types"; +import { Cast, DateCast, NumCast, StrCast, ScriptCast } from "../../../../fields/Types"; import { TraceMobx, OVERRIDE_ACL } from '../../../../fields/util'; import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, returnOne, returnZero, Utils, setupMoveUpEvents } from '../../../../Utils'; import { GoogleApiClientUtils, Pulls, Pushes } from '../../../apis/google_docs/GoogleApiClientUtils'; @@ -203,13 +203,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp if (!this.dataDoc[AclSym]) { if (!this._applyingChange && json.replace(/"selection":.*/, "") !== curProto?.Data.replace(/"selection":.*/, "")) { this._applyingChange = true; - this.dataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now())); + (curText !== Cast(this.dataDoc[this.fieldKey], RichTextField)?.Text) && (this.dataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now()))); if ((!curTemp && !curProto) || curText || curLayout?.Data.includes("dash")) { // if no template, or there's text that didn't come from the layout template, write it to the document. (if this is driven by a template, then this overwrites the template text which is intended) if (json !== curLayout?.Data) { !curText && tx.storedMarks?.map(m => m.type.name === "pFontSize" && (Doc.UserDoc().fontSize = this.layoutDoc._fontSize = m.attrs.fontSize)); !curText && tx.storedMarks?.map(m => m.type.name === "pFontFamily" && (Doc.UserDoc().fontFamily = this.layoutDoc._fontFamily = m.attrs.fontFamily)); this.dataDoc[this.props.fieldKey] = new RichTextField(json, curText); this.dataDoc[this.props.fieldKey + "-noTemplate"] = (curTemp?.Text || "") !== curText; // mark the data field as being split from the template if it has been edited + ScriptCast(this.layoutDoc.onTextChanged, null)?.script.run({ this: this.layoutDoc, self: this.rootDoc, text: curText }); } } else { // if we've deleted all the text in a note driven by a template, then restore the template data this.dataDoc[this.props.fieldKey] = undefined; @@ -970,7 +971,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp } (selectOnLoad /* || !rtfField?.Text*/) && this._editorView!.focus(); // add user mark for any first character that was typed since the user mark that gets set in KeyPress won't have been called yet. - this._editorView!.state.storedMarks = [...(this._editorView!.state.storedMarks ? this._editorView!.state.storedMarks : []), schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) })]; + if (!this._editorView!.state.storedMarks || !this._editorView!.state.storedMarks.some(mark => mark.type === schema.marks.user_mark)) { + this._editorView!.state.storedMarks = [...(this._editorView!.state.storedMarks ? this._editorView!.state.storedMarks : []), schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) })]; + } } getFont(font: string) { switch (font) { @@ -1305,7 +1308,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp onScroll={this.onscrolled} onDrop={this.ondrop} > <div className={`formattedTextBox-inner${rounded}${selclass}`} ref={this.createDropTarget} style={{ - padding: `${Math.max(0, NumCast(this.layoutDoc._yMargin, this.props.yMargin || 0) + selPad)}px ${NumCast(this.layoutDoc._xMargin, this.props.xMargin || 0) + selPad}px`, + padding: this.layoutDoc._textBoxPadding ? this.layoutDoc._textBoxPadding : `${Math.max(0, NumCast(this.layoutDoc._yMargin, this.props.yMargin || 0) + selPad)}px ${NumCast(this.layoutDoc._xMargin, this.props.xMargin || 0) + selPad}px`, pointerEvents: !this.props.isSelected() ? ((this.layoutDoc.isLinkButton || this.props.onClick) ? "none" : "all") : undefined }} /> diff --git a/src/client/views/nodes/formattedText/marks_rts.ts b/src/client/views/nodes/formattedText/marks_rts.ts index b09ac0678..54b61aa20 100644 --- a/src/client/views/nodes/formattedText/marks_rts.ts +++ b/src/client/views/nodes/formattedText/marks_rts.ts @@ -270,6 +270,7 @@ export const marks: { [index: string]: MarkSpec } = { userid: { default: "" }, modified: { default: "when?" }, // 1 second intervals since 1970 }, + excludes: "user_mark", group: "inline", toDOM(node: any) { const uid = node.attrs.userid.replace(".", "").replace("@", ""); diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index bef8acb06..e4d11dd4d 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -945,20 +945,27 @@ export namespace Doc { // filters document in a container collection: // all documents with the specified value for the specified key are included/excluded // based on the modifiers :"check", "x", undefined - export function setDocFilter(container: Doc, key: string, value: any, modifiers?: "check" | "x" | undefined) { + export function setDocFilter(container: Doc, key: string, value: any, modifiers?: "match" | "check" | "x" | undefined) { const docFilters = Cast(container._docFilters, listSpec("string"), []); - for (let i = 0; i < docFilters.length; i += 3) { - if (docFilters[i] === key && docFilters[i + 1] === value) { - docFilters.splice(i, 3); - break; + runInAction(() => { + for (let i = 0; i < docFilters.length; i += 3) { + if (docFilters[i] === key && (docFilters[i + 1] === value || modifiers === "match")) { + if (docFilters[i + 2] === modifiers && modifiers && docFilters[i + 1] === value) return; + docFilters.splice(i, 3); + break; + } } - } - if (typeof modifiers === "string") { - docFilters.push(key); - docFilters.push(value); - docFilters.push(modifiers); - container._docFilters = new List<string>(docFilters); - } + if (typeof modifiers === "string") { + if (!docFilters.length && modifiers === "match" && value === undefined) { + container._docFilters = undefined; + } else { + docFilters.push(key); + docFilters.push(value); + docFilters.push(modifiers); + container._docFilters = new List<string>(docFilters); + } + } + }) } export function readDocRangeFilter(doc: Doc, key: string) { const docRangeFilters = Cast(doc._docRangeFilters, listSpec("string"), []); @@ -1168,5 +1175,5 @@ Scripting.addGlobal(function selectedDocs(container: Doc, excludeCollections: bo (!excludeCollections || d.type !== DocumentType.COL || !Cast(d.data, listSpec(Doc), null))); return docs.length ? new List(docs) : prevValue; }); -Scripting.addGlobal(function setDocFilter(container: Doc, key: string, value: any, modifiers?: "check" | "x" | undefined) { Doc.setDocFilter(container, key, value, modifiers); }); +Scripting.addGlobal(function setDocFilter(container: Doc, key: string, value: any, modifiers?: "match" | "check" | "x" | undefined) { Doc.setDocFilter(container, key, value, modifiers); }); Scripting.addGlobal(function setDocFilterRange(container: Doc, key: string, range: number[]) { Doc.setDocFilterRange(container, key, range); });
\ No newline at end of file |