diff options
Diffstat (limited to 'src/client/util')
| -rw-r--r-- | src/client/util/DocumentManager.ts | 7 | ||||
| -rw-r--r-- | src/client/util/DragManager.ts | 5 | ||||
| -rw-r--r-- | src/client/util/DropConverter.ts | 14 | ||||
| -rw-r--r-- | src/client/util/Import & Export/DirectoryImportBox.tsx | 2 | ||||
| -rw-r--r-- | src/client/util/Import & Export/ImageUtils.ts | 2 | ||||
| -rw-r--r-- | src/client/util/InteractionUtils.tsx | 22 | ||||
| -rw-r--r-- | src/client/util/RichTextRules.ts | 29 | ||||
| -rw-r--r-- | src/client/util/RichTextSchema.tsx | 12 | ||||
| -rw-r--r-- | src/client/util/Scripting.ts | 4 |
9 files changed, 62 insertions, 35 deletions
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 3d5306841..2d6078cf3 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -148,7 +148,7 @@ export class DocumentManager { const highlight = () => { const finalDocView = getFirstDocView(targetDoc); if (finalDocView) { - finalDocView.Document.scrollToLinkID = linkId; + finalDocView.layoutDoc.scrollToLinkID = linkId; Doc.linkFollowHighlight(finalDocView.props.Document); } }; @@ -219,9 +219,12 @@ export class DocumentManager { if (linkDoc) { const target = (doc === linkDoc.anchor1 ? linkDoc.anchor2 : doc === linkDoc.anchor2 ? linkDoc.anchor1 : (Doc.AreProtosEqual(doc, linkDoc.anchor1 as Doc) ? linkDoc.anchor2 : linkDoc.anchor1)) as Doc; + const targetTimecode = (doc === linkDoc.anchor1 ? Cast(linkDoc.anchor2_timecode, "number") : + doc === linkDoc.anchor2 ? Cast(linkDoc.anchor1_timecode, "number"): + (Doc.AreProtosEqual(doc, linkDoc.anchor1 as Doc) ? Cast(linkDoc.anchor2_timecode, "number"):Cast(linkDoc.anchor1_timecode, "number"))); if (target) { const containerDoc = (await Cast(target.annotationOn, Doc)) || target; - containerDoc.currentTimecode !== undefined && (containerDoc.currentTimecode = NumCast(target?.timecode)); + containerDoc.currentTimecode = targetTimecode; const targetContext = await target?.context as Doc; const targetNavContext = !Doc.AreProtosEqual(targetContext, currentContext) ? targetContext : undefined; DocumentManager.Instance.jumpToDocument(target, zoom, (doc, finished) => createViewFunc(doc, StrCast(linkDoc.followLinkLocation, "onRight"), finished), targetNavContext, linkDoc[Id], undefined, doc, finished); diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index c856bbb1e..3e9a5b63a 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -220,9 +220,9 @@ export namespace DragManager { export function StartButtonDrag(eles: HTMLElement[], script: string, title: string, vars: { [name: string]: Field }, params: string[], initialize: (button: Doc) => void, downX: number, downY: number, options?: DragOptions) { const finishDrag = (e: DragCompleteEvent) => { const bd = Docs.Create.ButtonDocument({ _width: 150, _height: 50, title, onClick: ScriptField.MakeScript(script) }); - params.map(p => Object.keys(vars).indexOf(p) !== -1 && (Doc.GetProto(bd)[p] = new PrefetchProxy(vars[p] as Doc))); + params.map(p => Object.keys(vars).indexOf(p) !== -1 && (Doc.GetProto(bd)[p] = new PrefetchProxy(vars[p] as Doc))); // copy all "captured" arguments into document parameterfields initialize?.(bd); - bd.buttonParams = new List<string>(params); + Doc.GetProto(bd)["onClick-paramFieldKeys"] = new List<string>(params); e.docDragData && (e.docDragData.droppedDocuments = [bd]); }; StartDrag(eles, new DragManager.DocumentDragData([]), downX, downY, options, finishDrag); @@ -419,7 +419,6 @@ export namespace DragManager { if (target) { const complete = new DragCompleteEvent(false, dragData); finishDrag?.(complete); - console.log(complete.aborted); target.dispatchEvent( new CustomEvent<DropEvent>("dashOnDrop", { bubbles: true, diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts index d572e64a6..60a6bbb3c 100644 --- a/src/client/util/DropConverter.ts +++ b/src/client/util/DropConverter.ts @@ -35,8 +35,14 @@ export function makeTemplate(doc: Doc, first: boolean = true, rename: Opt<string any = makeTemplate(d, false) || any; } }); - if (!docs.length && first) { - any = Doc.MakeMetadataFieldTemplate(doc, Doc.GetProto(layoutDoc)) || any; + if (first) { + if (docs.length) { // bcz: feels hacky : if the root level document has items, it's not a field template, but we still want its caption to be a textTemplate + if (doc.caption instanceof RichTextField && !doc.caption.Empty()) { + doc["caption-textTemplate"] = ComputedField.MakeFunction(`copyField(this.caption)`); + } + } else { + any = Doc.MakeMetadataFieldTemplate(doc, Doc.GetProto(layoutDoc)) || any; + } } if (layoutDoc[fieldKey] instanceof RichTextField || layoutDoc[fieldKey] instanceof ImageField) { if (!StrCast(layoutDoc.title).startsWith("-")) { @@ -52,10 +58,8 @@ export function convertDropDataToButtons(data: DragManager.DocumentDragData) { // bcz: isButtonBar is intended to allow a collection of linear buttons to be dropped and nested into another collection of buttons... it's not being used yet, and isn't very elegant if (!doc.onDragStart && !doc.isButtonBar) { const layoutDoc = doc.layout instanceof Doc && doc.layout.isTemplateForField ? doc.layout : doc; - if (layoutDoc.type === DocumentType.COL || layoutDoc.type === DocumentType.RTF || layoutDoc.type === DocumentType.IMG) { + if (layoutDoc.type !== DocumentType.FONTICON) { !layoutDoc.isTemplateDoc && makeTemplate(layoutDoc); - } else { - (layoutDoc.layout instanceof Doc) && !data.userDropAction; } layoutDoc.isTemplateDoc = true; dbox = Docs.Create.FontIconDocument({ diff --git a/src/client/util/Import & Export/DirectoryImportBox.tsx b/src/client/util/Import & Export/DirectoryImportBox.tsx index 3d8bcbab7..438904688 100644 --- a/src/client/util/Import & Export/DirectoryImportBox.tsx +++ b/src/client/util/Import & Export/DirectoryImportBox.tsx @@ -126,7 +126,7 @@ export default class DirectoryImportBox extends React.Component<FieldViewProps> const document = await Docs.Get.DocumentFromType(type, path, { _width: 300, title: name }); const { data, error } = exifData; if (document) { - Doc.GetProto(document).exif = error || Docs.Get.DocumentHierarchyFromJson(data); + Doc.GetProto(document).exif = error || Docs.Get.FromJson({ data }); docs.push(document); } })); diff --git a/src/client/util/Import & Export/ImageUtils.ts b/src/client/util/Import & Export/ImageUtils.ts index ab8c73d15..9fae5ff93 100644 --- a/src/client/util/Import & Export/ImageUtils.ts +++ b/src/client/util/Import & Export/ImageUtils.ts @@ -20,7 +20,7 @@ export namespace ImageUtils { nativeHeight, exifData: { error, data } } = await Networking.PostToServer("/inspectImage", { source }); - document.exif = error || Docs.Get.DocumentHierarchyFromJson(data); + document.exif = error || Docs.Get.FromJson({ data }); const proto = Doc.GetProto(document); proto["data-nativeWidth"] = nativeWidth; proto["data-nativeHeight"] = nativeHeight; diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx index f2d569cf3..b1f136430 100644 --- a/src/client/util/InteractionUtils.tsx +++ b/src/client/util/InteractionUtils.tsx @@ -13,7 +13,6 @@ export namespace InteractionUtils { export class MultiTouchEvent<T extends React.TouchEvent | TouchEvent> { constructor( readonly fingers: number, - // readonly points: T extends React.TouchEvent ? React.TouchList : TouchList, readonly targetTouches: T extends React.TouchEvent ? React.Touch[] : Touch[], readonly touches: T extends React.TouchEvent ? React.Touch[] : Touch[], readonly changedTouches: T extends React.TouchEvent ? React.Touch[] : Touch[], @@ -23,6 +22,11 @@ export namespace InteractionUtils { export interface MultiTouchEventDisposer { (): void; } + /** + * + * @param element - element to turn into a touch target + * @param startFunc - event handler, typically Touchable.onTouchStart (classes that inherit touchable can pass in this.onTouchStart) + */ export function MakeMultiTouchTarget( element: HTMLElement, startFunc: (e: Event, me: MultiTouchEvent<React.TouchEvent>) => void @@ -48,6 +52,11 @@ export namespace InteractionUtils { }; } + /** + * Turns an element onto a target for touch hold handling. + * @param element - element to add events to + * @param func - function to add to the event + */ export function MakeHoldTouchTarget( element: HTMLElement, func: (e: Event, me: MultiTouchEvent<React.TouchEvent>) => void @@ -78,7 +87,6 @@ export namespace InteractionUtils { return myTouches; } - // TODO: find a way to reference this function from InkingStroke instead of copy pastign here. copied bc of weird error when on mobile view export function CreatePolyline(points: { X: number, Y: number }[], left: number, top: number, color: string, width: number) { const pts = points.reduce((acc: string, pt: { X: number, Y: number }) => acc + `${pt.X - left},${pt.Y - top} `, ""); return ( @@ -93,6 +101,11 @@ export namespace InteractionUtils { ); } + /** + * Returns whether or not the pointer event passed in is of the type passed in + * @param e - pointer event. this event could be from a mouse, a pen, or a finger + * @param type - InteractionUtils.(PENTYPE | ERASERTYPE | MOUSETYPE | TOUCHTYPE) + */ export function IsType(e: PointerEvent | React.PointerEvent, type: string): boolean { switch (type) { // pen and eraser are both pointer type 'pen', but pen is button 0 and eraser is button 5. -syip2 @@ -105,6 +118,11 @@ export namespace InteractionUtils { } } + /** + * Returns euclidean distance between two points + * @param pt1 + * @param pt2 + */ export function TwoPointEuclidist(pt1: React.Touch, pt2: React.Touch): number { return Math.sqrt(Math.pow(pt1.clientX - pt2.clientX, 2) + Math.pow(pt1.clientY - pt2.clientY, 2)); } diff --git a/src/client/util/RichTextRules.ts b/src/client/util/RichTextRules.ts index b0a124cb8..6bbe81115 100644 --- a/src/client/util/RichTextRules.ts +++ b/src/client/util/RichTextRules.ts @@ -62,6 +62,17 @@ export class RichTextRules { // ``` code block textblockTypeInputRule(/^```$/, schema.nodes.code_block), + // create an inline view of a tag stored under the '#' field + new InputRule( + new RegExp(/#([a-zA-Z_\-]+[a-zA-Z_\-0-9]*)\s$/), + (state, match, start, end) => { + const tag = match[1]; + if (!tag) return state.tr; + this.Document[DataSym]["#"] = tag; + const fieldView = state.schema.nodes.dashField.create({ fieldKey: "#" }); + return state.tr.deleteRange(start, end).insert(start, fieldView); + }), + // # heading textblockTypeInputRule( new RegExp(/^(#{1,6})\s$/), @@ -81,7 +92,7 @@ export class RichTextRules { // create a text display of a metadata field on this or another document, or create a hyperlink portal to another document [[ <fieldKey> : <Doc>]] // [[:Doc]] => hyperlink [[fieldKey]] => show field [[fieldKey:Doc]] => show field of doc new InputRule( - new RegExp(/\[\[([a-zA-Z_#@\? \-0-9]*)(=[a-zA-Z_#@\? \-0-9]*)?(:[a-zA-Z_#@\? \-0-9]+)?\]\]$/), + new RegExp(/\[\[([a-zA-Z_@\? \-0-9]*)(=[a-zA-Z_@\? \-0-9]*)?(:[a-zA-Z_@\? \-0-9]+)?\]\]$/), (state, match, start, end) => { const fieldKey = match[1]; const docid = match[3]?.substring(1); @@ -104,16 +115,6 @@ export class RichTextRules { const fieldView = state.schema.nodes.dashField.create({ fieldKey, docid }); return state.tr.deleteRange(start, end).insert(start, fieldView); }), - // create an inline view of a tag stored under the '#' field - new InputRule( - new RegExp(/#([a-zA-Z_\-0-9]+)\s$/), - (state, match, start, end) => { - const tag = match[1]; - if (!tag) return state.tr; - this.Document[DataSym]["#"] = tag; - const fieldView = state.schema.nodes.dashField.create({ fieldKey: "#" }); - return state.tr.deleteRange(start, end).insert(start, fieldView); - }), // create an inline view of a document {{ <layoutKey> : <Doc> }} // {{:Doc}} => show default view of document {{<layout>}} => show layout for this doc {{<layout> : Doc}} => show layout for another doc new InputRule( new RegExp(/\{\{([a-zA-Z_ \-0-9]*)(\([a-zA-Z0-9…._\-]*\))?(:[a-zA-Z_ \-0-9]+)?\}\}$/), @@ -129,12 +130,12 @@ export class RichTextRules { } }); const node = (state.doc.resolve(start) as any).nodeAfter; - const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 75, title: "dashDoc", docid, fieldKey: fieldKey + fieldParam, float: "right", alias: Utils.GenerateGuid() }); + const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 75, title: "dashDoc", docid, fieldKey: fieldKey + fieldParam, float: "unset", alias: Utils.GenerateGuid() }); const sm = state.storedMarks || undefined; return node ? state.tr.replaceRangeWith(start, end, dashDoc).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr; }), new InputRule( - new RegExp(/##$/), + new RegExp(/>>$/), (state, match, start, end) => { const textDoc = this.Document[DataSym]; const numInlines = NumCast(textDoc.inlineTextCount); @@ -146,7 +147,7 @@ export class RichTextRules { textDocInline.customTitle = true; // And make sure that it's 'custom' so that editing text doesn't change the title of the containing doc textDocInline.isTemplateForField = inlineFieldKey; // this is needed in case the containing text doc is converted to a template at some point textDocInline.proto = textDoc; // make the annotation inherit from the outer text doc so that it can resolve any nested field references, e.g., [[field]] - textDocInline._textContext = ComputedField.MakeFunction(`copyField(this.${inlineFieldKey})`, { this: Doc.name }); + textDocInline._textContext = ComputedField.MakeFunction(`copyField(self.${inlineFieldKey})`); textDoc[inlineLayoutKey] = FormattedTextBox.LayoutString(inlineFieldKey); // create a layout string for the layout key that will render the annotation text textDoc[inlineFieldKey] = ""; // set a default value for the annotation const node = (state.doc.resolve(start) as any).nodeAfter; diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index de2707d36..0599b3ebe 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -27,8 +27,12 @@ import ParagraphNodeSpec from "./ParagraphNodeSpec"; import { Transform } from "./Transform"; import React = require("react"); -const blockquoteDOM: DOMOutputSpecArray = ["blockquote", 0], hrDOM: DOMOutputSpecArray = ["hr"], - preDOM: DOMOutputSpecArray = ["pre", ["code", 0]], brDOM: DOMOutputSpecArray = ["br"], ulDOM: DOMOutputSpecArray = ["ul", 0]; +const + blockquoteDOM: DOMOutputSpecArray = ["blockquote", 0], + hrDOM: DOMOutputSpecArray = ["hr"], + preDOM: DOMOutputSpecArray = ["pre", ["code", 0]], + brDOM: DOMOutputSpecArray = ["br"], + ulDOM: DOMOutputSpecArray = ["ul", 0]; // :: Object // [Specs](#model.NodeSpec) for the nodes defined in this schema. @@ -738,7 +742,7 @@ export class DashDocView { this._outer = document.createElement("span"); this._outer.style.position = "relative"; this._outer.style.textIndent = "0"; - this._outer.style.border = "1px solid " + StrCast(tbox.Document.color, (Cast(Doc.UserDoc().activeWorkspace, Doc, null).darkScheme ? "dimGray" : "lightGray")); + this._outer.style.border = "1px solid " + StrCast(tbox.layoutDoc.color, (Cast(Doc.UserDoc().activeWorkspace, Doc, null).darkScheme ? "dimGray" : "lightGray")); this._outer.style.width = node.attrs.width; this._outer.style.height = node.attrs.height; this._outer.style.display = node.attrs.hidden ? "none" : "inline-block"; @@ -959,8 +963,6 @@ export class DashFieldView { if (self._options?.length && !self._dashDoc[self._fieldKey]) { self._dashDoc[self._fieldKey] = StrCast(self._options[0].title); } - // NOTE: if the field key starts with "@", then the actual field key is stored in the field 'fieldKey' (removing the @). - self._fieldKey = self._fieldKey.startsWith("@") ? StrCast(tbox.props.Document[StrCast(self._fieldKey).substring(1)]) : self._fieldKey; this._labelSpan.innerHTML = `${self._fieldKey}: `; const fieldVal = Cast(this._dashDoc?.[self._fieldKey], "boolean", null); this._fieldCheck.style.display = (fieldVal === true || fieldVal === false) ? "inline-block" : "none"; diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index 57d22eaf8..12628273b 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -41,9 +41,9 @@ export interface CompileError { export type CompileResult = CompiledScript | CompileError; export function isCompileError(toBeDetermined: CompileResult): toBeDetermined is CompileError { if ((toBeDetermined as CompileError).errors) { - return true + return true; } - return false + return false; } export namespace Scripting { |
