From f1ee3a6baffb22093d81e123d70f6ec9631c2075 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 15 Oct 2020 15:20:51 -0400 Subject: got rid of isDragging in favor of a field on the PresElement. fixed moving items in presBox by fixing websocket to maintain ordering on sequential operations on a list. fixed list splicing to not call addToSet unless splicing is at end of list. fixed setting return scale when following link into portal --- .../views/collections/CollectionStackingView.tsx | 23 +++--------- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 7 ++-- src/client/views/nodes/PresBox.tsx | 12 ++---- .../views/presentationview/PresElementBox.tsx | 43 +++++++++++----------- src/fields/Doc.ts | 2 +- src/fields/List.ts | 2 +- src/fields/util.ts | 2 +- src/server/websocket.ts | 3 ++ 9 files changed, 42 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 3607b97d0..fc4ca3100 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -292,25 +292,14 @@ export class CollectionStackingView extends CollectionSubView { - if (i === 0) { - if (doc.presentationTargetDoc) doc.dragging = false; //glr: so it only applies to items in presentation - DragManager.docsBeingDragged = []; - if (targInd === -1) targInd = docs.length; - else targInd = docs.indexOf(this.filteredChildren[targInd]); - const srcInd = docs.indexOf(doc); - docs.splice(srcInd, 1); - docs.splice((targInd > srcInd ? targInd - 1 : targInd) + plusOne, 0, doc); - } else if (i < (newDocs.length / 2)) { //glr: for some reason dragged documents are duplicated - if (doc.presentationTargetDoc) doc.dragging = false; - DragManager.docsBeingDragged = []; - if (targInd === -1) targInd = docs.length; - else targInd = docs.indexOf(newDocs[0]) + 1; - const srcInd = docs.indexOf(doc); - docs.splice(srcInd, 1); - docs.splice((targInd > srcInd ? targInd - 1 : targInd) + plusOne, 0, doc); - } + targInd = targInd === -1 ? docs.length : targInd; + const srcInd = docs.indexOf(doc); + if (targInd !== -1) targInd = i === 0 ? docs.indexOf(this.filteredChildren[targInd]) : docs.indexOf(newDocs[0]) + 1; + docs.splice(srcInd, 1); + docs.splice((targInd > srcInd ? targInd - 1 : targInd) + plusOne, 0, doc); }); } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 8b9e84bd6..2d770898b 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -922,6 +922,7 @@ export class CollectionFreeFormView extends CollectionSubView(Docu zorderItems.push({ description: this.rootDoc._raiseWhenDragged !== false ? "Keep ZIndex when dragged" : "Allow ZIndex to change when dragged", event: this.toggleRaiseWhenDragged, icon: "expand-arrows-alt" }); !zorders && cm.addItem({ description: "ZOrder...", subitems: zorderItems, icon: "compass" }); + onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" }); + onClicks.push({ description: "Toggle Detail", event: () => this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`), icon: "concierge-bell" }); + if (!this.Document.annotationOn) { const options = cm.findByDescription("Options..."); const optionItems: ContextMenuProps[] = options && "subitems" in options ? options.subitems : []; !this.props.treeViewDoc && this.props.ContainingCollectionDoc?._viewType === CollectionViewType.Freeform && optionItems.push({ description: this.Document.lockedPosition ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.Document.lockedPosition) ? "unlock" : "lock" }); !options && cm.addItem({ description: "Options...", subitems: optionItems, icon: "compass" }); - onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" }); - onClicks.push({ description: "Toggle Detail", event: () => this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`), icon: "concierge-bell" }); onClicks.push({ description: this.Document.ignoreClick ? "Select" : "Do Nothing", event: () => this.Document.ignoreClick = !this.Document.ignoreClick, icon: this.Document.ignoreClick ? "unlock" : "lock" }); onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link in Place", event: () => this.toggleFollowLink("inPlace", true, false), icon: "link" }); !this.Document.isLinkButton && onClicks.push({ description: "Follow Link on Right", event: () => this.toggleFollowLink("add:right", false, false), icon: "link" }); @@ -838,8 +839,8 @@ export class DocumentView extends DocComponent(Docu onClicks.push({ description: "Select on Click", event: () => this.selectOnClick(), icon: "link" }); onClicks.push({ description: "Follow Link on Click", event: () => this.followLinkOnClick(undefined, false), icon: "link" }); onClicks.push({ description: "Toggle Link Target on Click", event: () => this.toggleTargetOnClick(), icon: "map-pin" }); - !existingOnClick && cm.addItem({ description: "OnClick...", addDivider: true, subitems: onClicks, icon: "mouse-pointer" }); } + !existingOnClick && cm.addItem({ description: "OnClick...", addDivider: true, subitems: onClicks, icon: "mouse-pointer" }); } const funcs: ContextMenuProps[] = []; diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 8e2884968..352328ec6 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -599,13 +599,7 @@ export class PresBox extends ViewBoxBaseComponent */ @action sortArray = (): Doc[] => { - const sort: Doc[] = this._selectedArray; - this.childDocs.forEach((doc, i) => { - if (this._selectedArray.includes(doc)) { - sort.push(doc); - } - }); - return sort; + return this.childDocs.filter(doc => this._selectedArray.includes(doc)); } /** @@ -1731,8 +1725,8 @@ export class PresBox extends ViewBoxBaseComponent const frameItems = frameList.map((value) => {
-
- }) + ; + }); return
{frameItems}
; diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index 9052967e5..1d6721bca 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, IReactionDisposer, reaction, runInAction } from "mobx"; +import { action, computed, IReactionDisposer, reaction, runInAction, observable } from "mobx"; import { observer } from "mobx-react"; import { Doc, DataSym, DocListCast } from "../../../fields/Doc"; import { documentSchema } from '../../../fields/documentSchemas'; @@ -8,13 +8,11 @@ import { createSchema, makeInterface, listSpec } from '../../../fields/Schema'; import { Cast, NumCast, BoolCast, ScriptCast, StrCast } from "../../../fields/Types"; import { emptyFunction, emptyPath, returnFalse, returnTrue, returnOne, returnZero, numberRange, setupMoveUpEvents } from "../../../Utils"; import { Transform } from "../../util/Transform"; -import { CollectionViewType } from '../collections/CollectionView'; import { ViewBoxBaseComponent } from '../DocComponent'; import { ContentFittingDocumentView } from '../nodes/ContentFittingDocumentView'; import { FieldView, FieldViewProps } from '../nodes/FieldView'; import "./PresElementBox.scss"; import React = require("react"); -import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; import { PresBox, PresMovement } from "../nodes/PresBox"; import { DocumentType } from "../../documents/DocumentTypes"; import { Tooltip } from "@material-ui/core"; @@ -45,6 +43,8 @@ const PresDocument = makeInterface(presSchema, documentSchema); export class PresElementBox extends ViewBoxBaseComponent(PresDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresElementBox, fieldKey); } _heightDisposer: IReactionDisposer | undefined; + + @observable _dragging = false; // these fields are conditionally computed fields on the layout document that take this document as a parameter @computed get indexInPres() { return Number(this.lookupField("indexInPres")); } // the index field is where this document is in the presBox display list (since this value is different for each presentation element, the value can't be stored on the layout template which is used by all display elements) @computed get collapsedHeight() { return Number(this.lookupField("presCollapsedHeight")); } // the collapsed height changes depending on the state of the presBox. We could store this on the presentation element template if it's used by only one presentation - but if it's shared by multiple, then this value must be looked up @@ -159,9 +159,9 @@ export class PresElementBox extends ViewBoxBaseComponent { - const activeItem = this.rootDoc; - activeItem.dragging = false; + this._dragging = false; e.stopPropagation(); e.preventDefault(); } @@ -172,12 +172,12 @@ export class PresElementBox extends ViewBoxBaseComponent { const doc = ele; - doc.className = "presItem-slide" + doc.className = "presItem-slide"; dragItem.push(doc); }); if (activeItem) { DragManager.StartDocumentDrag(dragItem.map(ele => ele), dragData, e.clientX, e.clientY); - activeItem.dragging = true; + runInAction(() => this._dragging = true); return true; } return false; @@ -189,18 +189,20 @@ export class PresElementBox extends ViewBoxBaseComponent { - const slide = this._itemRef.current!; - const rect = slide?.getBoundingClientRect(); - let y = e.clientY - rect.top; //y position within the element. - let height = slide.clientHeight; - let halfLine = height / 2; - if (DragManager.docsBeingDragged.length > 1) { - if (y <= halfLine) { - slide.style.borderTop = "solid 2px #5B9FDD"; - slide.style.borderBottom = "0px"; - } else if (y > halfLine) { - slide.style.borderTop = "0px"; - slide.style.borderBottom = "solid 2px #5B9FDD"; + const slide = this._itemRef.current; + if (slide) { + const rect = slide.getBoundingClientRect(); + const y = e.clientY - rect.top; //y position within the element. + const height = slide.clientHeight; + const halfLine = height / 2; + if (DragManager.docsBeingDragged.length) { + if (y <= halfLine) { + slide.style.borderTop = "solid 2px #5B9FDD"; + slide.style.borderBottom = "0px"; + } else if (y > halfLine) { + slide.style.borderTop = "0px"; + slide.style.borderBottom = "solid 2px #5B9FDD"; + } } } document.removeEventListener("pointermove", this.onPointerMove); @@ -244,7 +246,6 @@ export class PresElementBox extends ViewBoxBaseComponent= 300; const targetDoc: Doc = Cast(this.rootDoc.presentationTargetDoc, Doc, null); @@ -252,7 +253,7 @@ export class PresElementBox extends ViewBoxBaseComponent { e.stopPropagation(); e.preventDefault(); diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index c8d28b4a2..4cf681482 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -399,7 +399,7 @@ export namespace Doc { // and returns the document who's proto is undefined or whose proto is marked as a base prototype ('isPrototype'). export function GetProto(doc: Doc): Doc { if (doc instanceof Promise) { - console.log("GetProto: warning: got Promise insead of Doc"); + // console.log("GetProto: warning: got Promise insead of Doc"); } const proto = doc && (Doc.GetT(doc, "isPrototype", "boolean", true) ? doc : (doc.proto || doc)); return proto === doc ? proto : Doc.GetProto(proto); diff --git a/src/fields/List.ts b/src/fields/List.ts index a0cbebaf5..215dff34b 100644 --- a/src/fields/List.ts +++ b/src/fields/List.ts @@ -78,7 +78,7 @@ const listHandlers: any = { } const res = list.__fields.splice(start, deleteCount, ...items); this[Update](items.length === 0 && deleteCount ? { op: "$remFromSet", items: removed, length: list.__fields.length } : - items.length && !deleteCount ? { op: "$addToSet", items, length: list.__fields.length } : undefined); + items.length && !deleteCount && start === list.__fields.length ? { op: "$addToSet", items, length: list.__fields.length } : undefined); return res.map(toRealField); }), unshift(...items: any[]) { diff --git a/src/fields/util.ts b/src/fields/util.ts index d48011194..15571ff8c 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -162,7 +162,7 @@ export function GetEffectiveAcl(target: any, user?: string): symbol { } function getPropAcl(target: any, prop: string | symbol | number) { - if (prop === UpdatingFromServer || target[UpdatingFromServer] || prop == AclSym) return AclAdmin; // requesting the UpdatingFromServer prop or AclSym must always go through to keep the local DB consistent + if (prop === UpdatingFromServer || target[UpdatingFromServer] || prop === AclSym) return AclAdmin; // requesting the UpdatingFromServer prop or AclSym must always go through to keep the local DB consistent if (prop && DocServer.PlaygroundFields?.includes(prop.toString())) return AclEdit; // playground props are always editable return GetEffectiveAcl(target); } diff --git a/src/server/websocket.ts b/src/server/websocket.ts index 1e02b9e58..e5692a7dd 100644 --- a/src/server/websocket.ts +++ b/src/server/websocket.ts @@ -313,6 +313,9 @@ export namespace WebSocket { function UpdateField(socket: Socket, diff: Diff) { if (diff.diff.$addToSet) return GetRefField([diff.id, (result?: Transferable) => addToListField(socket, diff, result)]); // would prefer to have Mongo handle list additions direclty, but for now handle it on our own if (diff.diff.$remFromSet) return GetRefField([diff.id, (result?: Transferable) => remFromListField(socket, diff, result)]); // would prefer to have Mongo handle list additions direclty, but for now handle it on our own + return GetRefField([diff.id, (result?: Transferable) => SetField(socket, diff, result)]); + } + function SetField(socket: Socket, diff: Diff, curListItems?: Transferable) { Database.Instance.update(diff.id, diff.diff, () => socket.broadcast.emit(MessageStore.UpdateField.Message, diff), false); const docfield = diff.diff.$set || diff.diff.$unset; -- cgit v1.2.3-70-g09d2 From 79b1ae37d4a89130026a33d52139a69fbe444698 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 15 Oct 2020 15:29:45 -0400 Subject: fixed warnings --- src/client/documents/Documents.ts | 12 ++++++------ src/client/util/SharingManager.tsx | 6 +++--- src/client/views/nodes/FilterBox.tsx | 4 ++-- src/client/views/search/SearchBox.tsx | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 159771145..45c465d84 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -895,8 +895,8 @@ export namespace Docs { export namespace DocUtils { export function Excluded(d: Doc, docFilters: string[]) { const filterFacets: { [key: string]: { [value: string]: string } } = {}; // maps each filter key to an object with value=>modifier fields - for (let i = 0; i < docFilters.length; i++) { - const fields = docFilters[i].split(":"); + docFilters.forEach(filter => { + const fields = filter.split(":"); const key = fields[0]; const value = fields[1]; const modifiers = fields[2]; @@ -904,7 +904,7 @@ export namespace DocUtils { filterFacets[key] = {}; } filterFacets[key][value] = modifiers; - } + }); if (d.z) return false; for (const facetKey of Object.keys(filterFacets)) { @@ -921,8 +921,8 @@ export namespace DocUtils { const childDocs = viewSpecScript ? docs.filter(d => viewSpecScript.script.run({ doc: d }, console.log).result) : docs; const filterFacets: { [key: string]: { [value: string]: string } } = {}; // maps each filter key to an object with value=>modifier fields - for (let i = 0; i < docFilters.length; i++) { - const fields = docFilters[i].split(":"); + docFilters.forEach(filter => { + const fields = filter.split(":"); const key = fields[0]; const value = fields[1]; const modifiers = fields[2]; @@ -930,7 +930,7 @@ export namespace DocUtils { filterFacets[key] = {}; } filterFacets[key][value] = modifiers; - } + }); const filteredDocs = docFilters.length ? childDocs.filter(d => { if (d.z) return true; diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 914253e3c..0cd5332ca 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -140,9 +140,9 @@ export class SharingManager extends React.Component<{}> { }); return Promise.all(evaluating).then(() => { runInAction(() => { - for (let i = 0; i < sharingDocs.length; i++) { - if (!this.users.find(user => user.user.email === sharingDocs[i].user.email)) { - this.users.push(sharingDocs[i]); + for (let sharer of sharingDocs) { + if (!this.users.find(user => user.user.email === sharer.user.email)) { + this.users.push(sharer); } } }); diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx index 0d02a4388..bb20f91c0 100644 --- a/src/client/views/nodes/FilterBox.tsx +++ b/src/client/views/nodes/FilterBox.tsx @@ -224,8 +224,8 @@ export class FilterBox extends ViewBoxBaseComponent Date: Thu, 15 Oct 2020 19:08:40 -0400 Subject: fixed list undo/redo to work with incremental list edits. makes presentation boxes work --- src/fields/Doc.ts | 1 - src/fields/util.ts | 42 +++++++++++++++++++++++++++--------------- 2 files changed, 27 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 4cf681482..1a062fa3b 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -500,7 +500,6 @@ export namespace Doc { alias.title = ComputedField.MakeFunction(`renameAlias(this, ${Doc.GetProto(doc).aliasNumber = NumCast(Doc.GetProto(doc).aliasNumber) + 1})`); } alias.author = Doc.CurrentUserEmail; - alias[AclSym] = doc[AclSym]; Doc.AddDocToList(doc[DataSym], "aliases", alias); diff --git a/src/fields/util.ts b/src/fields/util.ts index 15571ff8c..f27b45057 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -363,47 +363,59 @@ export function deleteProperty(target: any, prop: string | number | symbol) { } export function updateFunction(target: any, prop: any, value: any, receiver: any) { - let current = ObjectField.MakeCopy(value); + let lastValue = ObjectField.MakeCopy(value); return (diff?: any) => { const op = diff?.op === "$addToSet" ? { '$addToSet': { ["fields." + prop]: SerializationHelper.Serialize(new List(diff.items)) } } : diff?.op === "$remFromSet" ? { '$remFromSet': { ["fields." + prop]: SerializationHelper.Serialize(new List(diff.items)) } } : { '$set': { ["fields." + prop]: SerializationHelper.Serialize(value) } }; !op.$set && ((op as any).length = diff.length); + let prevValue = ObjectField.MakeCopy(lastValue as List); + lastValue = ObjectField.MakeCopy(value); + let newValue = ObjectField.MakeCopy(value); - const oldValue = current; - const newValue = ObjectField.MakeCopy(value); - current = newValue; if (!(value instanceof CursorField) && !(value?.some?.((v: any) => v instanceof CursorField))) { !receiver[UpdatingFromServer] && UndoManager.AddEvent( diff?.op === "$addToSet" ? { redo: () => { - receiver[prop].push(...diff.items); + receiver[prop].push(...diff.items.map((item: any) => item.value())); + lastValue = ObjectField.MakeCopy(receiver[prop]); }, undo: action(() => { - const curList = receiver[prop]; - //while (curList[ForwardUpates]) curList = curList[ForwardUpates]; diff.items.forEach((doc: any) => { - const ind = curList.indexOf(doc.value()); - ind !== -1 && curList.splice(ind, 1); + const ind = receiver[prop].indexOf(doc.value()); + ind !== -1 && receiver[prop].splice(ind, 1); }); + lastValue = ObjectField.MakeCopy(receiver[prop]); }) } : diff?.op === "$remFromSet" ? { redo: action(() => { - const curList = receiver[prop]; diff.items.forEach((doc: any) => { - const ind = curList.indexOf(doc.value()); - ind !== -1 && curList.splice(ind, 1); + const ind = receiver[prop].indexOf(doc.value()); + ind !== -1 && receiver[prop].splice(ind, 1); }); + lastValue = ObjectField.MakeCopy(receiver[prop]); }), - undo: () => receiver[prop].push(...diff.items) + undo: () => { + diff.items.map((item: any) => { + const ind = (prevValue as List).indexOf(diff.items[0].value()); + ind !== -1 && receiver[prop].indexOf(diff.items[0].value()) === -1 && receiver[prop].splice(ind, 0, item); + }); + lastValue = ObjectField.MakeCopy(receiver[prop]); + } } : { - redo: () => receiver[prop] = newValue, - undo: () => receiver[prop] = oldValue + redo: () => { + receiver[prop] = ObjectField.MakeCopy(newValue as List); + lastValue = ObjectField.MakeCopy(receiver[prop]); + }, + undo: () => { + receiver[prop] = ObjectField.MakeCopy(prevValue as List); + lastValue = ObjectField.MakeCopy(receiver[prop]); + } }); } target[Update](op); -- cgit v1.2.3-70-g09d2 From 63f2f4927f0fd3e4d1d74b91599bc585fe820a29 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 16 Oct 2020 00:45:17 -0400 Subject: fixed some exceptions. added text field to annotations on PDFs --- src/client/views/pdf/Annotation.tsx | 2 +- src/client/views/pdf/PDFViewer.tsx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/client/views/pdf/Annotation.tsx b/src/client/views/pdf/Annotation.tsx index a071abd21..20ea7bfe4 100644 --- a/src/client/views/pdf/Annotation.tsx +++ b/src/client/views/pdf/Annotation.tsx @@ -100,7 +100,7 @@ class RegionAnnotation extends React.Component { group.isPushpin = !group.isPushpin; }); - isPushpin = () => BoolCast(Cast(this.props.document.group, Doc, null).isPushpin); + isPushpin = () => BoolCast(Cast(this.props.document.group, Doc, null)?.isPushpin); @action onPointerDown = (e: React.PointerEvent) => { diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index d8be3defd..974d87fc7 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -353,6 +353,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent(annoDocs); } mainAnnoDocProto.title = "Annotation on " + this.Document.title; @@ -402,7 +403,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent { - this.Document._scrollY === undefined && (this.layoutDoc._scrollTop = this._mainCont.current!.scrollTop); + this.Document._scrollY === undefined && this._mainCont.current && (this.layoutDoc._scrollTop = this._mainCont.current.scrollTop); this.pageDelay = undefined; //this._pdfViewer && (this.Document._curPage = this._pdfViewer.currentPageNumber); }, 1000); @@ -543,8 +544,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent Date: Fri, 16 Oct 2020 00:51:59 -0400 Subject: fixed pinning multiple documents to undo all at once. --- src/client/views/DocumentButtonBar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index 9dddb4c44..076502042 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -189,7 +189,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV return !targetDoc ? (null) :
{"Pin to presentation"}
}>
this.props.views().map(view => view && TabDocView.PinDoc(view.props.Document, false))}> + onClick={undoBatch(e => this.props.views().map(view => view && TabDocView.PinDoc(view.props.Document, false)))}>
; } -- cgit v1.2.3-70-g09d2 From 375adfd63ec8a90d2b6ce146d581afdf1599e731 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 16 Oct 2020 01:14:44 -0400 Subject: fixed undoing of changing slide effect direction. Made PDFviewer's scroll duration use _viewTransition if specified. --- src/client/views/nodes/PresBox.tsx | 10 +++++----- src/client/views/pdf/PDFViewer.tsx | 8 +++++--- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index a6ba717b7..d03fbc03f 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -938,11 +938,11 @@ export class PresBox extends ViewBoxBaseComponent
-
{"Enter from left"}
}>
targetDoc.presEffectDirection = 'left'}>
-
{"Enter from right"}
}>
targetDoc.presEffectDirection = 'right'}>
-
{"Enter from top"}
}>
targetDoc.presEffectDirection = 'top'}>
-
{"Enter from bottom"}
}>
targetDoc.presEffectDirection = 'bottom'}>
-
{"Enter from center"}
}>
targetDoc.presEffectDirection = false}>
+
{"Enter from left"}
}>
targetDoc.presEffectDirection = 'left')}>
+
{"Enter from right"}
}>
targetDoc.presEffectDirection = 'right')}>
+
{"Enter from top"}
}>
targetDoc.presEffectDirection = 'top')}>
+
{"Enter from bottom"}
}>
targetDoc.presEffectDirection = 'bottom')}>
+
{"Enter from center"}
}>
targetDoc.presEffectDirection = false)}>
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 974d87fc7..375748311 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -10,7 +10,7 @@ import { InkTool } from "../../../fields/InkField"; import { List } from "../../../fields/List"; import { createSchema, makeInterface } from "../../../fields/Schema"; import { ScriptField } from "../../../fields/ScriptField"; -import { Cast, NumCast } from "../../../fields/Types"; +import { Cast, NumCast, StrCast } from "../../../fields/Types"; import { PdfField } from "../../../fields/URLField"; import { GetEffectiveAcl, TraceMobx } from "../../../fields/util"; import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, emptyPath, intersectRect, returnZero, smoothScroll, Utils, OmitKeys } from "../../../Utils"; @@ -181,8 +181,10 @@ export class PDFViewer extends ViewBoxAnnotatableComponent this._mainCont.current && smoothScroll(1000, this._mainCont.current, Math.abs(scrollY || 0)), delay); - setTimeout(() => { this.Document._scrollTop = scrollY; this.Document._scrollY = undefined; }, 1000 + delay); + const durationStr = StrCast(this.Document._viewTransition).match(/([0-9]*)ms/); + const duration = durationStr ? Number(durationStr[1]) : 1000; + setTimeout(() => this._mainCont.current && smoothScroll(duration, this._mainCont.current, Math.abs(scrollY || 0)), delay); + setTimeout(() => { this.Document._scrollTop = scrollY; this.Document._scrollY = undefined; }, duration + delay); } } }, -- cgit v1.2.3-70-g09d2 From 51066af7ddc8dc890ed67858579227f8484e7263 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 16 Oct 2020 01:24:28 -0400 Subject: fixed duration of slides so that 100ms works. --- src/client/views/nodes/PresBox.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index d03fbc03f..8e3679452 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -407,7 +407,7 @@ export class PresBox extends ViewBoxBaseComponent activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); duration = NumCast(activeItem.presDuration) + NumCast(activeItem.presTransition); - if (duration <= 100) { duration = 2500; } + if (duration < 100) { duration = 2500; } if (NumCast(targetDoc.lastFrame) > 0) { for (var f = 0; f < NumCast(targetDoc.lastFrame); f++) { await timer(duration / NumCast(targetDoc.lastFrame)); -- cgit v1.2.3-70-g09d2 From 67e3a220a622ff1a1a54f04df48d57c34a3a387d Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 16 Oct 2020 01:26:01 -0400 Subject: fixed compile warn ings. --- src/client/util/SharingManager.tsx | 2 +- src/client/views/nodes/FilterBox.tsx | 2 +- src/client/views/presentationview/PresElementBox.tsx | 6 +++--- src/client/views/search/SearchBox.tsx | 2 +- src/fields/util.ts | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 0cd5332ca..2b13d2a44 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -140,7 +140,7 @@ export class SharingManager extends React.Component<{}> { }); return Promise.all(evaluating).then(() => { runInAction(() => { - for (let sharer of sharingDocs) { + for (const sharer of sharingDocs) { if (!this.users.find(user => user.user.email === sharer.user.email)) { this.users.push(sharer); } diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx index bb20f91c0..6f01e5916 100644 --- a/src/client/views/nodes/FilterBox.tsx +++ b/src/client/views/nodes/FilterBox.tsx @@ -224,7 +224,7 @@ export class FilterBox extends ViewBoxBaseComponent 0) { const rect = slide.getBoundingClientRect(); - let y = e.clientY - rect.top; //y position within the element. - let height = slide.clientHeight; - let halfLine = height / 2; + const y = e.clientY - rect.top; //y position within the element. + const height = slide.clientHeight; + const halfLine = height / 2; if (y <= halfLine) { slide.style.borderTop = "solid 2px #5B9FDD"; slide.style.borderBottom = "0px"; diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 13fcccdcf..bc00e93a5 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -122,7 +122,7 @@ export class SearchBox extends ViewBoxBaseComponent(diff.items)) } } : { '$set': { ["fields." + prop]: SerializationHelper.Serialize(value) } }; !op.$set && ((op as any).length = diff.length); - let prevValue = ObjectField.MakeCopy(lastValue as List); + const prevValue = ObjectField.MakeCopy(lastValue as List); lastValue = ObjectField.MakeCopy(value); - let newValue = ObjectField.MakeCopy(value); + const newValue = ObjectField.MakeCopy(value); if (!(value instanceof CursorField) && !(value?.some?.((v: any) => v instanceof CursorField))) { !receiver[UpdatingFromServer] && UndoManager.AddEvent( -- cgit v1.2.3-70-g09d2 From acccc301ed77d6ea15f025ff746138911b9f9c16 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 16 Oct 2020 02:02:10 -0400 Subject: fixed RTF so that you can scroll smoothly in a presentation. --- src/client/util/DocumentManager.ts | 2 +- src/client/views/collections/CollectionMenu.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/nodes/LinkDocPreview.tsx | 2 +- src/client/views/nodes/formattedText/FormattedTextBox.tsx | 15 +++++++++++++-- .../views/nodes/formattedText/FormattedTextBoxComment.tsx | 2 +- src/client/views/pdf/PDFViewer.tsx | 6 +++--- 7 files changed, 21 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index a408e1df6..dc911ea75 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -190,7 +190,7 @@ export class DocumentManager { highlight(); } else { // otherwise try to get a view of the context of the target const targetDocContextView = getFirstDocView(targetDocContext); - targetDocContext._scrollY = targetDocContext._scrollPY = NumCast(targetDocContext._scrollTop, 0); // this will force PDFs to activate and load their annotations / allow scrolling + targetDocContext._scrollY = targetDocContext._scrollPreviewY = NumCast(targetDocContext._scrollTop, 0); // this will force PDFs to activate and load their annotations / allow scrolling if (targetDocContextView) { // we found a context view and aren't forced to create a new one ... focus on the context first.. targetDocContext._viewTransition = "transform 500ms"; targetDocContextView.props.focus(targetDocContextView.props.Document, willZoom); diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index d9924c299..b2b1b7d25 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -400,7 +400,7 @@ export class CollectionViewBaseChrome extends React.Component 5 ? 1000 : 0; !dontCenter && this.props.focus(this.props.Document); afterFocus && setTimeout(afterFocus, delay); diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 8f9cb5b0e..867be9735 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -64,7 +64,7 @@ export class LinkDocPreview extends React.Component { this._toolTipText = ""; LinkDocPreview.TargetDoc = this._targetDoc = target; if (anchor !== this._targetDoc && anchor && this._targetDoc) { - this._targetDoc._scrollPY = NumCast(anchor?.y); + this._targetDoc._scrollPreviewY = NumCast(anchor?.y); } }); } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index c3946dd57..903bbaaa3 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -23,7 +23,7 @@ import { RichTextUtils } from '../../../../fields/RichTextUtils'; import { makeInterface } from "../../../../fields/Schema"; import { Cast, DateCast, NumCast, StrCast, ScriptCast, BoolCast } from "../../../../fields/Types"; import { TraceMobx, GetEffectiveAcl } from '../../../../fields/util'; -import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, returnOne, returnZero, Utils, setupMoveUpEvents, OmitKeys } from '../../../../Utils'; +import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, returnOne, returnZero, Utils, setupMoveUpEvents, OmitKeys, smoothScroll } from '../../../../Utils'; import { GoogleApiClientUtils, Pulls, Pushes } from '../../../apis/google_docs/GoogleApiClientUtils'; import { DocServer } from "../../../DocServer"; import { Docs, DocUtils } from '../../../documents/Documents'; @@ -961,7 +961,18 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp { fireImmediately: true } ); this._disposers.scroll = reaction(() => NumCast(this.layoutDoc._scrollTop), - pos => this._scrollRef.current && this._scrollRef.current.scrollTo({ top: pos }), { fireImmediately: true } + pos => this._scrollRef.current?.scrollTo({ top: pos }), { fireImmediately: true } + ); + this._disposers.scrollY = reaction(() => Cast(this.layoutDoc._scrollY, "number", null), + scrollY => { + if (scrollY !== undefined) { + const delay = this._scrollRef.current ? 0 : 250; // wait for mainCont and try again to scroll + const durationStr = StrCast(this.Document._viewTransition).match(/([0-9]*)ms/); + const duration = durationStr ? Number(durationStr[1]) : 1000; + setTimeout(() => this._scrollRef.current && smoothScroll(duration, this._scrollRef.current, Math.abs(scrollY || 0)), delay); + setTimeout(() => { this.Document._scrollTop = scrollY; this.Document._scrollY = undefined; }, duration + delay); + } + }, { fireImmediately: true } ); setTimeout(() => this.tryUpdateHeight(NumCast(this.layoutDoc.limitHeight))); diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx index 0919b2b14..32038d1ee 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx @@ -260,7 +260,7 @@ export class FormattedTextBoxComment { const anchor = FieldValue(Doc.AreProtosEqual(FieldValue(Cast(linkDoc.anchor1, Doc)), textBox.dataDoc) ? Cast(linkDoc.anchor2, Doc) : (Cast(linkDoc.anchor1, Doc)) || linkDoc); const target = anchor?.annotationOn ? await DocCastAsync(anchor.annotationOn) : anchor; if (anchor !== target && anchor && target) { - target._scrollPY = NumCast(anchor?.y); + target._scrollPreviewY = NumCast(anchor?.y); } if (target?.author) { FormattedTextBoxComment.showCommentbox("", view, nbef); diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 375748311..a8a6e8c33 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -190,15 +190,15 @@ export class PDFViewer extends ViewBoxAnnotatableComponent Cast(this.Document._scrollPY, "number", null), + this._disposers.scrollPreviewY = reaction( + () => Cast(this.Document._scrollPreviewY, "number", null), (scrollY) => { if (scrollY !== undefined) { (this._showCover || this._showWaiting) && this.setupPdfJsViewer(); if (this.props.renderDepth === -1 && scrollY >= 0) { if (!this._mainCont.current) setTimeout(() => this._mainCont.current && smoothScroll(1000, this._mainCont.current, scrollY || 0)); else smoothScroll(1000, this._mainCont.current, scrollY || 0); - this.Document._scrollPY = undefined; + this.Document._scrollPreviewY = undefined; } } }, -- cgit v1.2.3-70-g09d2 From e6d700159cb6c273a2df0fd02469e72aa5b48c86 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 16 Oct 2020 02:09:31 -0400 Subject: fixed scrolling of web boxes for presentations, etc. --- src/client/views/nodes/WebBox.tsx | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 421aac69f..66dc3cdcc 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -14,7 +14,7 @@ import { listSpec, makeInterface } from "../../../fields/Schema"; import { Cast, NumCast, StrCast } from "../../../fields/Types"; import { WebField } from "../../../fields/URLField"; import { TraceMobx, GetEffectiveAcl } from "../../../fields/util"; -import { addStyleSheet, clearStyleSheetRules, emptyFunction, returnOne, returnZero, Utils, returnTrue, OmitKeys } from "../../../Utils"; +import { addStyleSheet, clearStyleSheetRules, emptyFunction, returnOne, returnZero, Utils, returnTrue, OmitKeys, smoothScroll } from "../../../Utils"; import { Docs, DocUtils } from "../../documents/Documents"; import { DragManager } from "../../util/DragManager"; import { ImageUtils } from "../../util/Import & Export/ImageUtils"; @@ -87,8 +87,20 @@ export class WebBox extends ViewBoxAnnotatableComponent ({ y: this.layoutDoc._scrollY, x: this.layoutDoc._scrollX }), - ({ x, y }) => this.updateScroll(x, y), + this._scrollReactionDisposer = reaction(() => ({ scrollY: this.layoutDoc._scrollY, scrollX: this.layoutDoc._scrollX }), + ({ scrollY, scrollX }) => { + const delay = this._outerRef.current ? 0 : 250; // wait for mainCont and try again to scroll + const durationStr = StrCast(this.Document._viewTransition).match(/([0-9]*)ms/); + const duration = durationStr ? Number(durationStr[1]) : 1000; + if (scrollY !== undefined) { + setTimeout(() => this._outerRef.current && smoothScroll(duration, this._outerRef.current, Math.abs(scrollY || 0)), delay); + setTimeout(() => { this.layoutDoc._scrollTop = scrollY; this.layoutDoc._scrollY = undefined; }, duration + delay); + } + if (scrollX !== undefined) { + setTimeout(() => this._outerRef.current && smoothScroll(duration, this._outerRef.current, Math.abs(scrollX || 0)), delay); + setTimeout(() => { this.layoutDoc._scrollLeft = scrollX; this.layoutDoc._scrollX = undefined; }, duration + delay); + } + }, { fireImmediately: true } ); }); -- cgit v1.2.3-70-g09d2