From 4433afe837412c10a278e54ee8069cad992900a0 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 13 Mar 2025 19:23:31 -0400 Subject: cleaned up how Presboxelement finds PresBox --- src/client/views/nodes/trails/PresBox.tsx | 1 + src/client/views/nodes/trails/PresElementBox.tsx | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'src/client/views/nodes/trails') diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 9ab5fb1bd..f818c6e20 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -210,6 +210,7 @@ export class PresBox extends ViewBoxBaseComponent() { } componentDidMount() { + this._props.setContentViewBox?.(this); this._disposers.pause = reaction( () => SnappingManager.UserPanned, () => this.pauseAutoPres() diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index a76805960..957df894c 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -52,7 +52,11 @@ export class PresElementBox extends ViewBoxBaseComponent() { // the presentation view that renders this slide @computed get presBoxView() { - return this.DocumentView?.().containerViewPath?.().lastElement()?.ComponentView as PresBox; + return this.DocumentView?.() + .containerViewPath?.() + .slice() + .reverse() + .find(dv => dv?.ComponentView instanceof PresBox)?.ComponentView as PresBox; } // the presentation view document that renders this slide -- cgit v1.2.3-70-g09d2 From 45a9f5789fa6eaacca9a39cb96cc2a8e3ebe649c Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 14 Mar 2025 12:20:41 -0400 Subject: simplified anchorMenu to just have an AskAI button .. then updated GPtPopup's summaryBox to have a flashcard option. --- src/client/views/StyleProviderQuiz.tsx | 31 ++-- .../views/nodes/formattedText/FormattedTextBox.tsx | 41 +----- src/client/views/nodes/trails/PresElementBox.tsx | 5 +- src/client/views/pdf/AnchorMenu.tsx | 26 +--- src/client/views/pdf/GPTPopup/GPTPopup.scss | 16 +-- src/client/views/pdf/GPTPopup/GPTPopup.tsx | 160 +++++++++++++++------ src/client/views/pdf/PDFViewer.tsx | 21 +-- 7 files changed, 152 insertions(+), 148 deletions(-) (limited to 'src/client/views/nodes/trails') diff --git a/src/client/views/StyleProviderQuiz.tsx b/src/client/views/StyleProviderQuiz.tsx index acda38dd7..f9ee8d3db 100644 --- a/src/client/views/StyleProviderQuiz.tsx +++ b/src/client/views/StyleProviderQuiz.tsx @@ -9,7 +9,7 @@ import { DocData } from '../../fields/DocSymbols'; import { List } from '../../fields/List'; import { NumCast, StrCast } from '../../fields/Types'; import { Networking } from '../Network'; -import { GPTCallType, gptAPICall, gptImageLabel } from '../apis/gpt/GPT'; +import { GPTCallType, gptAPICall } from '../apis/gpt/GPT'; import { Docs } from '../documents/Documents'; import { ContextMenu } from './ContextMenu'; import { ContextMenuProps } from './ContextMenuItem'; @@ -110,20 +110,21 @@ export namespace styleProviderQuiz { const blob = await ImageUtility.canvasToBlob(canvas); return selectUrlToBase64(blob); } - /** - * Create flashcards from an image. - */ - async function makeFlashcardsForImage(img: ImageBox) { - img.Loading = true; - try { - const hrefBase64 = await createCanvas(img); - const response = await gptImageLabel(hrefBase64, 'Make flashcards out of this image with each question and answer labeled as "question" and "answer". Do not label each flashcard and do not include asterisks: '); - AnchorMenu.Instance.transferToFlashcard(response, NumCast(img.layoutDoc.x), NumCast(img.layoutDoc.y)); - } catch (error) { - console.log('Error', error); - } - img.Loading = false; - } + + // /** + // * Create flashcards from an image. + // */ + // async function makeFlashcardsForImage(img: ImageBox) { + // img.Loading = true; + // try { + // const hrefBase64 = await createCanvas(img); + // const response = await gptImageLabel(hrefBase64, 'Make flashcards out of this image with each question and answer labeled as "question" and "answer". Do not label each flashcard and do not include asterisks: '); + // AnchorMenu.Instance.transferToFlashcard(response, NumCast(img.layoutDoc.x), NumCast(img.layoutDoc.y)); + // } catch (error) { + // console.log('Error', error); + // } + // img.Loading = false; + // } /** * Calls the createCanvas and pushInfo methods to convert the diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index b86536f86..7b24125e7 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -13,7 +13,7 @@ import { EditorState, NodeSelection, Plugin, Selection, TextSelection, Transacti import { EditorView, NodeViewConstructor } from 'prosemirror-view'; import * as React from 'react'; import { BsMarkdownFill } from 'react-icons/bs'; -import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, ClientUtils, DivWidth, imageUrlToBase64, returnFalse, returnZero, setupMoveUpEvents, simMouseEvent, smoothScroll, StopEvent } from '../../../../ClientUtils'; +import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, ClientUtils, DivWidth, returnFalse, returnZero, setupMoveUpEvents, simMouseEvent, smoothScroll, StopEvent } from '../../../../ClientUtils'; import { DateField } from '../../../../fields/DateField'; import { CreateLinkToActiveAudio, Doc, DocListCast, Field, FieldType, Opt, StrListCast } from '../../../../fields/Doc'; import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, DocCss, DocData, ForceServerWrite, UpdatingFromServer } from '../../../../fields/DocSymbols'; @@ -26,7 +26,7 @@ import { ComputedField } from '../../../../fields/ScriptField'; import { BoolCast, Cast, DateCast, DocCast, FieldValue, NumCast, RTFCast, ScriptCast, StrCast } from '../../../../fields/Types'; import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util'; import { emptyFunction, numberRange, unimplementedFunction, Utils } from '../../../../Utils'; -import { gptAPICall, GPTCallType, gptImageLabel } from '../../../apis/gpt/GPT'; +import { gptAPICall, GPTCallType } from '../../../apis/gpt/GPT'; import { DocServer } from '../../../DocServer'; import { Docs } from '../../../documents/Documents'; import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes'; @@ -226,18 +226,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { - const queryText = window.getSelection()?.toString() ?? ''; - try { - if (queryText) { - const res = await gptAPICall(queryText, GPTCallType.FLASHCARD); - AnchorMenu.Instance.transferToFlashcard(res || 'Something went wrong', NumCast(this.layoutDoc.x), NumCast(this.layoutDoc.y)); - } - } catch (err) { - console.error(err); - } - }; - @action setupAnchorMenu = () => { AnchorMenu.Instance.Status = 'marquee'; @@ -1012,31 +1000,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { - const c = this.ProseRef?.getElementsByTagName('img'); - if (c) { - for (const i of c) { - // console.log(canvas.toDataURL()); - // canvas.style.zIndex = '2000000'; - // document.body.appendChild(canvas); - if (i.className !== 'ProseMirror-separator') this.getImageDesc(i.src); - } - } - }; - - getImageDesc = async (u: string) => { - try { - const hrefBase64 = await imageUrlToBase64(u); - const response = await gptImageLabel( - hrefBase64, - 'Make flashcards out of this text and image with each question and answer labeled as question and answer. Do not label each flashcard and do not include asterisks: ' + (this.dataDoc.text as RichTextField)?.Text - ); - AnchorMenu.Instance.transferToFlashcard(response || 'Something went wrong', NumCast(this.dataDoc['x']), NumCast(this.dataDoc['y'])); - } catch (error) { - console.log('Error', error); - } - }; - animateRes = (resIndex: number, newText: string) => { if (resIndex < newText.length) { const marks = this.EditorView?.state.storedMarks ?? []; diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index 957df894c..31cd1603f 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -239,10 +239,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { e.clientY, undefined, action(() => { - Array.from(classesToRestore).forEach(pair => { - // eslint-disable-next-line prefer-destructuring - pair[0].className = pair[1]; - }); + Array.from(classesToRestore).forEach(pair => (pair[0].className = pair[1])); this._dragging = false; }) ); diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx index 6ae659ac1..eb6516403 100644 --- a/src/client/views/pdf/AnchorMenu.tsx +++ b/src/client/views/pdf/AnchorMenu.tsx @@ -10,7 +10,6 @@ import { Doc, Opt } from '../../../fields/Doc'; import { SettingsManager } from '../../util/SettingsManager'; import { AntimodeMenu, AntimodeMenuProps } from '../AntimodeMenu'; import { LinkPopup } from '../linking/LinkPopup'; -import { ComparisonBox } from '../nodes/ComparisonBox'; import { DocumentView } from '../nodes/DocumentView'; import { RichTextMenu } from '../nodes/formattedText/RichTextMenu'; import './AnchorMenu.scss'; @@ -69,7 +68,6 @@ export class AnchorMenu extends AntimodeMenu { public MakeTargetToggle: () => void = unimplementedFunction; public ShowTargetTrail: () => void = unimplementedFunction; public IsTargetToggler: () => boolean = returnFalse; - public gptFlashcards: () => void = unimplementedFunction; public makeLabels: () => void = unimplementedFunction; public marqueeWidth = 0; public marqueeHeight = 0; @@ -94,22 +92,9 @@ export class AnchorMenu extends AntimodeMenu { * Invokes the API with the selected text and stores it in the summarized text. * @param e pointer down event */ - gptSummarize = () => GPTPopup.Instance.generateSummary(this._selectedText); - - /* - * Transfers the flashcard text generated by GPT on flashcards and creates a collection out them. - */ - - transferToFlashcard = (text: string, x: number, y: number) => { - ComparisonBox.createFlashcardDeck(text, 250, 200, 'data_front', 'data_back').then( - action(newCol => { - newCol.x = x; - newCol.y = y; - newCol.zIndex = 1000; - this.addToCollection?.(newCol); - this._loading = false; - }) - ); + gptAskAboutSelection = () => { + GPTPopup.Instance.askAIAboutSelection(this._selectedText); + AnchorMenu.Instance.fadeOut(true); }; pointerDown = (e: React.PointerEvent) => { @@ -188,14 +173,13 @@ export class AnchorMenu extends AntimodeMenu { {/* GPT Summarize icon only shows up when text is highlighted, not on marquee selection */} {this._selectedText && ( } color={SettingsManager.userColor} /> )} {/* Adds a create flashcards option to the anchor menu, which calls the gptFlashcard method. */} - {this.gptFlashcards === unimplementedFunction ? null : } color={SettingsManager.userColor} />} {this.makeLabels === unimplementedFunction ? null : } color={SettingsManager.userColor} />} {this._selectedText && RichTextMenu.Instance?.createLinkButton()} {AnchorMenu.Instance.OnAudio === unimplementedFunction ? null : ( diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.scss b/src/client/views/pdf/GPTPopup/GPTPopup.scss index c8903e09f..18441f76e 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.scss +++ b/src/client/views/pdf/GPTPopup/GPTPopup.scss @@ -15,12 +15,8 @@ $headingHeight: 32px; height: 100%; top: 0; left: 0; - pointer-events: none; border-top: solid gray 20px; border-radius: 16px; - padding: 16px; - padding-bottom: 0; - padding-top: 0px; z-index: 999; display: flex; flex-direction: column; @@ -29,11 +25,13 @@ $headingHeight: 32px; box-shadow: 0 2px 5px #7474748d; color: $textgrey; - .gptPopup-sortBox { + .gptPopup-summaryBox-content { + padding-right: 16px; + padding-left: 16px; + position: relative; + overflow: hidden; display: flex; flex-direction: column; - height: calc(100% - $inputHeight - $headingHeight); - pointer-events: all; } .summary-heading { @@ -65,7 +63,9 @@ $headingHeight: 32px; .gptPopup-content-wrapper { padding-top: 10px; min-height: 50px; - height: calc(100% - 32px); + white-space: pre-line; + overflow: auto; + margin-bottom: 10px; } .inputWrapper { diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx index 4dc45e6a0..67213382d 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx +++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx @@ -31,6 +31,7 @@ import { OpenWhere } from '../../nodes/OpenWhere'; import { DrawingFillHandler } from '../../smartdraw/DrawingFillHandler'; import { ImageField } from '../../../../fields/URLField'; import { List } from '../../../../fields/List'; +import { ComparisonBox } from '../../nodes/ComparisonBox'; export enum GPTPopupMode { SUMMARY, // summary of seleted document text @@ -56,7 +57,7 @@ export class GPTPopup extends ObservableReactComponent { private _dataJson: string = ''; private _documentDescriptions: Promise | undefined; // a cache of the descriptions of all docs in the selected collection. makes it more efficient when asking GPT multiple questions about the collection. private _sidebarFieldKey: string = ''; - private _textToSummarize: string = ''; + private _aiReferenceText: string = ''; private _imageDescription: string = ''; private _textToDocMap = new Map(); // when GPT answers with a doc's content, this helps us find the Doc private _addToCollection: ((doc: Doc | Doc[], annotationKey?: string | undefined) => boolean) | undefined; @@ -79,7 +80,7 @@ export class GPTPopup extends ObservableReactComponent { }; componentDidUpdate() { - this._gptProcessing && this.setStopAnimatingResponse(false); + //this._gptProcessing && this.setStopAnimatingResponse(false); } componentDidMount(): void { reaction( @@ -100,14 +101,14 @@ export class GPTPopup extends ObservableReactComponent { ); } + @observable private _showOriginal = true; + @observable private _responseText: string = ''; @observable private _conversationArray: string[] = ['Hi! In this pop up, you can ask ChatGPT questions about your documents and filter / sort them. ']; @observable private _fireflyArray: string[] = ['Hi! In this pop up, you can ask Firefly to create images. ']; @observable private _chatEnabled: boolean = false; @action private setChatEnabled = (start: boolean) => (this._chatEnabled = start); @observable private _gptProcessing: boolean = false; @action private setGptProcessing = (loading: boolean) => (this._gptProcessing = loading); - @observable private _responseText: string = ''; - @action private setResponseText = (text: string) => (this._responseText = text); @observable private _imgUrls: string[][] = []; @action private setImgUrls = (imgs: string[][]) => (this._imgUrls = imgs); @observable private _collectionContext: Doc | undefined = undefined; @@ -286,18 +287,30 @@ export class GPTPopup extends ObservableReactComponent { /** * Completes an API call to generate a summary of the specified text * - * @param text the text to summarizz + * @param text the text to summarize */ - generateSummary = (text: string) => { + private generateSummary = action((text: string) => { SnappingManager.SetChatVisible(true); - this._textToSummarize = text; - this.setMode(GPTPopupMode.SUMMARY); + this._showOriginal = false; this.setGptProcessing(true); return gptAPICall(text, GPTCallType.SUMMARY) - .then(res => this.setResponseText(res || 'Something went wrong.')) + .then(action(res => (this._responseText = res || 'Something went wrong.'))) .catch(err => console.error(err)) .finally(() => this.setGptProcessing(false)); - }; + }); + + /** + * Completes an API call to generate a summary of the specified text + * + * @param text the text to summarizz + */ + askAIAboutSelection = action((text: string) => { + SnappingManager.SetChatVisible(true); + this._aiReferenceText = text; + this._responseText = ''; + this._showOriginal = true; + this.setMode(GPTPopupMode.SUMMARY); + }); /** * Completes an API call to generate an analysis of @@ -306,14 +319,16 @@ export class GPTPopup extends ObservableReactComponent { generateDataAnalysis = () => { this.setGptProcessing(true); return gptAPICall(this._dataJson, GPTCallType.DATA, this._dataChatPrompt) - .then(res => { - const json = JSON.parse(res! as string); - const keys = Object.keys(json); - this._correlatedColumns = []; - this._correlatedColumns.push(json[keys[0]]); - this._correlatedColumns.push(json[keys[1]]); - this.setResponseText(json[keys[2]] || 'Something went wrong.'); - }) + .then( + action(res => { + const json = JSON.parse(res! as string); + const keys = Object.keys(json); + this._correlatedColumns = []; + this._correlatedColumns.push(json[keys[0]]); + this._correlatedColumns.push(json[keys[1]]); + this._responseText = json[keys[2]] || 'Something went wrong.'; + }) + ) .catch(err => console.error(err)) .finally(() => this.setGptProcessing(false)); }; @@ -336,6 +351,24 @@ export class GPTPopup extends ObservableReactComponent { }); } }; + /** + * Create Flashcards for the selected text + */ + private createFlashcards = action( + () => + this.setGptProcessing(true) && + gptAPICall(this._aiReferenceText, GPTCallType.FLASHCARD, undefined, true) + .then(res => + ComparisonBox.createFlashcardDeck(res, 250, 200, 'data_front', 'data_back').then( + action(newCol => { + newCol.zIndex = 1000; + DocumentViewInternal.addDocTabFunc(newCol, OpenWhere.addRight); + }) + ) + ) + .catch(console.error) + .finally(action(() => (this._gptProcessing = false))) + ); /** * Creates a histogram to show the correlation relationship that was found @@ -536,35 +569,80 @@ export class GPTPopup extends ObservableReactComponent { summaryBox = () => ( <> -
- {this.heading('SUMMARY')} +
+
(this._showOriginal = !this._showOriginal))}>{this.heading(this._showOriginal ? 'SELECTION' : 'SUMMARY')}
- {!this._gptProcessing && - (!this._stopAnimatingResponse ? ( - { - setTimeout(() => this.setStopAnimatingResponse(true), 500); - }, - ]} - /> + {!this._gptProcessing && !this._stopAnimatingResponse && this._responseText ? ( + { + setTimeout(() => this.setStopAnimatingResponse(true), 500); + }, + ]} + /> + ) : this._showOriginal ? ( + this._gptProcessing ? ( + '...generating cards...' ) : ( - this._responseText - ))} + this._aiReferenceText + ) + ) : ( + this._responseText || (this._gptProcessing ? '...generating summary...' : '-no ai summary-') + )}
- {!this._gptProcessing && ( -
- {this._stopAnimatingResponse ? ( - <> - this.generateSummary(this._textToSummarize + ' ')} icon={} color={StrCast(SettingsManager.userVariantColor)} /> -
) : (
- Summarizing + {this._showOriginal ? 'Creating Cards...' : 'Summarizing'}
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index a50526223..83b3dffe5 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -28,7 +28,6 @@ import { AnchorMenu } from './AnchorMenu'; import { Annotation } from './Annotation'; import { GPTPopup } from './GPTPopup/GPTPopup'; import './PDFViewer.scss'; -import { GPTCallType, gptAPICall } from '../../apis/gpt/GPT'; import ReactLoading from 'react-loading'; import { Transform } from '../../util/Transform'; @@ -392,23 +391,6 @@ export class PDFViewer extends ObservableReactComponent { } }; - /** - * Create a flashcard pile based on the selected text of a pdf. - */ - gptPDFFlashcards = async () => { - const queryText = this._selectionText; - runInAction(() => (this._loading = true)); - try { - const res = await gptAPICall(queryText, GPTCallType.FLASHCARD); - - AnchorMenu.Instance.transferToFlashcard(res || 'Something went wrong', NumCast(this._props.layoutDoc['x']), NumCast(this._props.layoutDoc['y'])); - this._selectionText = ''; - } catch (err) { - console.error(err); - } - runInAction(() => (this._loading = false)); - }; - @action finishMarquee = (/* x?: number, y?: number */) => { AnchorMenu.Instance.makeLabels = unimplementedFunction; @@ -430,7 +412,7 @@ export class PDFViewer extends ObservableReactComponent { if (sel) { AnchorMenu.Instance.setSelectedText(sel.toString()); - AnchorMenu.Instance.setLocation(NumCast(this._props.layoutDoc['x']), NumCast(this._props.layoutDoc['y'])); + AnchorMenu.Instance.setLocation(NumCast(this._props.layoutDoc.x), NumCast(this._props.layoutDoc.y)); } if (sel?.type === 'Range') { @@ -442,7 +424,6 @@ export class PDFViewer extends ObservableReactComponent { GPTPopup.Instance.addDoc = this._props.sidebarAddDoc; // allows for creating collection AnchorMenu.Instance.addToCollection = this._props.DocumentView?.()._props.addDocument; - AnchorMenu.Instance.gptFlashcards = this.gptPDFFlashcards; AnchorMenu.Instance.makeLabels = unimplementedFunction; AnchorMenu.Instance.AddDrawingAnnotation = this.addDrawingAnnotation; }; -- cgit v1.2.3-70-g09d2 From 7e4d793eaa7e5b6b564355a11fa02a5611645f20 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 21 Mar 2025 18:58:21 -0400 Subject: trying to improve how data / layout / root and templtae docs are accessed. --- src/client/documents/DocUtils.ts | 11 +++--- src/client/util/CalendarManager.tsx | 11 ++---- src/client/util/CurrentUserUtils.ts | 17 +++++---- src/client/util/DictationManager.ts | 6 ++-- src/client/util/DocumentManager.ts | 11 ++---- src/client/util/DragManager.ts | 5 +-- src/client/util/History.ts | 2 +- src/client/util/Import & Export/ImageUtils.ts | 14 ++++---- src/client/views/DashboardView.tsx | 26 +++++++------- src/client/views/DocComponent.tsx | 14 ++++---- src/client/views/DocumentDecorations.tsx | 4 +-- src/client/views/FilterPanel.tsx | 3 +- src/client/views/InkStrokeProperties.ts | 3 +- src/client/views/MainView.tsx | 3 +- src/client/views/MarqueeAnnotator.tsx | 22 ++++++------ src/client/views/PinFuncs.ts | 3 +- src/client/views/PropertiesButtons.tsx | 6 ++-- src/client/views/PropertiesView.tsx | 42 +++++++++++----------- src/client/views/ScriptBox.tsx | 6 ++-- .../views/collections/CollectionDockingView.tsx | 13 ++++--- src/client/views/nodes/DocumentView.tsx | 36 +++++++++---------- src/client/views/nodes/KeyValueBox.tsx | 36 +++++++++++-------- src/client/views/nodes/KeyValuePair.tsx | 18 +++++----- .../views/nodes/formattedText/FormattedTextBox.tsx | 9 +++-- .../views/nodes/formattedText/RichTextRules.ts | 36 ++++++++----------- src/client/views/nodes/trails/PresBox.tsx | 10 +++--- src/client/views/pdf/PDFViewer.tsx | 2 +- src/client/views/search/FaceRecognitionHandler.tsx | 21 ++++++----- src/client/views/search/SearchBox.tsx | 1 - src/client/views/smartdraw/DrawingFillHandler.tsx | 6 ++-- src/fields/Doc.ts | 14 +++++--- src/fields/util.ts | 10 ++++++ 32 files changed, 203 insertions(+), 218 deletions(-) (limited to 'src/client/views/nodes/trails') diff --git a/src/client/documents/DocUtils.ts b/src/client/documents/DocUtils.ts index 1c7ccadd1..13f6f6920 100644 --- a/src/client/documents/DocUtils.ts +++ b/src/client/documents/DocUtils.ts @@ -8,7 +8,6 @@ import * as JSZipUtils from '../../JSZipUtils'; import { decycle } from '../../decycler/decycler'; import { DateField } from '../../fields/DateField'; import { Doc, DocListCast, Field, FieldResult, FieldType, LinkedTo, Opt, StrListCast } from '../../fields/Doc'; -import { DocData } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; import { InkData, InkDataFieldName, InkField } from '../../fields/InkField'; import { List, ListFieldName } from '../../fields/List'; @@ -383,10 +382,10 @@ export namespace DocUtils { event: undoable(() => { const newDoc = DocUtils.copyDragFactory(dragDoc); if (newDoc) { - newDoc.author = ClientUtils.CurrentUserEmail(); - newDoc.x = x; - newDoc.y = y; - newDoc[DocData].backgroundColor = Doc.UserDoc().textBackgroundColor; + newDoc._author = ClientUtils.CurrentUserEmail(); + newDoc._x = x; + newDoc._y = y; + newDoc.$backgroundColor = Doc.UserDoc().textBackgroundColor; DocumentView.SetSelectOnLoad(newDoc); if (pivotField) { newDoc[pivotField] = pivotValue; @@ -745,7 +744,7 @@ export namespace DocUtils { if (defaultTextTemplate) { tbox.layout_fieldKey = 'layout_' + StrCast(defaultTextTemplate.title); Doc.GetProto(tbox)[StrCast(tbox.layout_fieldKey)] = defaultTextTemplate; // set the text doc's layout to render with the text template - tbox[DocData].proto = defaultTextTemplate; // and also set the text doc to inherit from the template (this allows the template to specify default field values) + tbox.$proto = defaultTextTemplate; // and also set the text doc to inherit from the template (this allows the template to specify default field values) } return tbox; } diff --git a/src/client/util/CalendarManager.tsx b/src/client/util/CalendarManager.tsx index d28b3a2c9..a0db4e32e 100644 --- a/src/client/util/CalendarManager.tsx +++ b/src/client/util/CalendarManager.tsx @@ -8,7 +8,6 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import Select from 'react-select'; import { Doc, DocListCast } from '../../fields/Doc'; -import { DocData } from '../../fields/DocSymbols'; import { StrCast } from '../../fields/Types'; import { Docs } from '../documents/Documents'; import { MainViewModal } from '../views/MainViewModal'; @@ -51,8 +50,6 @@ export class CalendarManager extends ObservableReactComponent { @observable private targetDocView: DocumentView | undefined = undefined; // the DocumentView of the target doc @observable private dialogueBoxOpacity = 1; // for the modal - @observable private layoutDocAcls: boolean = false; // whether the layout doc or data doc's acls are to be used - @observable private creationType: CreationType = 'new-calendar'; @observable private existingCalendars: Doc[] = DocListCast(Doc.MyCalendars?.data); @@ -97,7 +94,6 @@ export class CalendarManager extends ObservableReactComponent { }), 500 ); - this.layoutDocAcls = false; }); constructor(props: object) { @@ -122,9 +118,8 @@ export class CalendarManager extends ObservableReactComponent { // TODO: Make undoable private addToCalendar = () => { const docs = DocumentView.Selected().length < 2 ? [this.targetDoc] : DocumentView.Selected().map(docView => docView.Document); - const targetDoc = this.layoutDocAcls ? docs[0] : docs[0]?.[DocData]; // doc to add to calendar + const targetDoc = docs[0]; // doc to add to calendar - console.log(targetDoc); if (targetDoc) { let calendar: Doc; if (this.creationType === 'new-calendar') { @@ -234,7 +229,7 @@ export class CalendarManager extends ObservableReactComponent { @computed get calendarInterface() { const docs = DocumentView.Selected().length < 2 ? [this.targetDoc] : DocumentView.Selected().map(docView => docView.Document); - const targetDoc = this.layoutDocAcls ? docs[0] : docs[0]?.[DocData]; + const targetDoc = docs[0]; return (
{
Select a date range:
- this.setSelectedDateRange(v)} /> + v && this.setSelectedDateRange(v)} />
{this.createButtonActive && ( diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 21e1d3e12..924041552 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -3,7 +3,6 @@ import { reaction, runInAction } from "mobx"; import * as rp from 'request-promise'; import { ClientUtils, OmitKeys } from "../../ClientUtils"; import { Doc, DocListCast, DocListCastAsync, FieldType, Opt } from "../../fields/Doc"; -import { DocData } from "../../fields/DocSymbols"; import { InkEraserTool, InkInkTool, InkProperty, InkTool } from "../../fields/InkField"; import { List } from "../../fields/List"; import { PrefetchProxy } from "../../fields/Proxy"; @@ -323,10 +322,10 @@ export class CurrentUserUtils { type: 'scatter' }`); const slide = Docs.Create.TextDocument("", opts); - slide[DocData].text = rtfield; - slide[DocData].layout_textPainted = ``; - slide[DocData]._type_collection = CollectionViewType.Freeform; - slide.onPaint = ScriptField.MakeScript(`toggleDetail(documentView, "textPainted")`, {documentView:"any"}); + slide.$text = rtfield; + slide.$layout_textPainted = ``; + slide.$type_collection = CollectionViewType.Freeform; + slide._onPaint = ScriptField.MakeScript(`toggleDetail(documentView, "textPainted")`, {documentView:"any"}); return slide; } const mermaidsApi = () => { @@ -374,10 +373,10 @@ pie title Minerals in my tap water "Potassium" : 50 "Magnesium" : 10.01`); const slide = Docs.Create.TextDocument("", opts); - slide[DocData].text = rtfield; - slide[DocData].layout_textPainted = ``; - slide[DocData]._type_collection = CollectionViewType.Freeform; - slide.onPaint = ScriptField.MakeScript(`toggleDetail(documentView, "textPainted")`, {documentView:"any"}); + slide.$text = rtfield; + slide.$layout_textPainted = ``; + slide.$_type_collection = CollectionViewType.Freeform; + slide._onPaint = ScriptField.MakeScript(`toggleDetail(documentView, "textPainted")`, {documentView:"any"}); return slide; } plotlyApi(); mermaidsApi(); diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts index 897366757..44fbda319 100644 --- a/src/client/util/DictationManager.ts +++ b/src/client/util/DictationManager.ts @@ -2,7 +2,6 @@ import * as interpreter from 'words-to-numbers'; import { ClientUtils } from '../../ClientUtils'; import { Doc, Opt } from '../../fields/Doc'; -import { DocData } from '../../fields/DocSymbols'; import { List } from '../../fields/List'; import { RichTextField } from '../../fields/RichTextField'; import { listSpec } from '../../fields/Schema'; @@ -339,13 +338,12 @@ export namespace DictationManager { { action: (target: DocumentView) => { const newBox = Docs.Create.TextDocument('', { _width: 400, _height: 200, title: 'My Outline', _layout_autoHeight: true }); - const proto = newBox[DocData]; const prompt = 'Press alt + r to start dictating here...'; const head = 3; const anchor = head + prompt.length; const proseMirrorState = `{"doc":{"type":"doc","content":[{"type":"ordered_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"type":"text","text":"${prompt}"}]}]}]}]},"selection":{"type":"text","anchor":${anchor},"head":${head}}}`; - proto.data = new RichTextField(proseMirrorState, prompt); - proto.backgroundColor = '#eeffff'; + newBox.$data = new RichTextField(proseMirrorState, prompt); + newBox.$backgroundColor = '#eeffff'; target.props.addDocTab(newBox, OpenWhere.addRight); }, }, diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index e33449782..5ce005811 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -2,7 +2,6 @@ import { Howl } from 'howler'; import { action, computed, makeObservable, observable, ObservableSet, observe } from 'mobx'; import { Doc, Opt } from '../../fields/Doc'; import { Animation, DocData } from '../../fields/DocSymbols'; -import { Id } from '../../fields/FieldSymbols'; import { listSpec } from '../../fields/Schema'; import { Cast, DocCast, NumCast, StrCast } from '../../fields/Types'; import { AudioField } from '../../fields/URLField'; @@ -108,16 +107,16 @@ export class DocumentManager { }); // gets all views - public getDocumentViewsById(id: string) { + public getAllDocumentViews(doc: Doc) { const toReturn: DocumentView[] = []; DocumentManager.Instance.DocumentViews.forEach(view => { - if (view.Document[Id] === id) { + if (view.Document === doc) { toReturn.push(view); } }); if (toReturn.length === 0) { DocumentManager.Instance.DocumentViews.forEach(view => { - if (view.Document[DocData]?.[Id] === id) { + if (view.Document[DocData] === doc) { toReturn.push(view); } }); @@ -125,10 +124,6 @@ export class DocumentManager { return toReturn; } - public getAllDocumentViews(doc: Doc) { - return this.getDocumentViewsById(doc[Id]); - } - public getDocumentView(target: Doc | undefined, preferredCollection?: DocumentView): DocumentView | undefined { const docViewArray = DocumentManager.Instance.DocumentViews; const passes = !target ? [] : preferredCollection ? [preferredCollection, undefined] : [undefined]; diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 2a7859f09..e2e4c0fe4 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -280,11 +280,12 @@ export namespace DragManager { export function StartButtonDrag(eles: HTMLElement[], script: string, title: string, vars: { [name: string]: FieldType }, params: string[], initialize: (button: Doc) => void, downX: number, downY: number, options?: DragOptions) { const finishDrag = (e: DragCompleteEvent) => { const bd = Docs.Create.ButtonDocument({ toolTip: title, z: 1, _width: 150, _height: 50, title, onClick: ScriptField.MakeScript(script) }); + const bdData = bd[DocData]; params.forEach(p => { - Object.keys(vars).indexOf(p) !== -1 && (bd[DocData][p] = new PrefetchProxy(vars[p] as Doc)); + Object.keys(vars).indexOf(p) !== -1 && (bdData[p] = new PrefetchProxy(vars[p] as Doc)); }); // copy all "captured" arguments into document parameterfields initialize?.(bd); - bd[DocData]['onClick-paramFieldKeys'] = new List(params); + bd.$onClick_paramFieldKeys = new List(params); e.docDragData && (e.docDragData.droppedDocuments = [bd]); return e; }; diff --git a/src/client/util/History.ts b/src/client/util/History.ts index 9728e3177..0df0ec337 100644 --- a/src/client/util/History.ts +++ b/src/client/util/History.ts @@ -94,7 +94,7 @@ export namespace HistoryUtil { } if (Array.isArray(value)) { } else if (parser === true || parser === 'json') { - value = JSON.parse(value); + value = value === 'undefined' ? undefined : JSON.parse(value); } else if (parser === 'none') { } else { value = parser(value); diff --git a/src/client/util/Import & Export/ImageUtils.ts b/src/client/util/Import & Export/ImageUtils.ts index 43807397f..9c32ca25a 100644 --- a/src/client/util/Import & Export/ImageUtils.ts +++ b/src/client/util/Import & Export/ImageUtils.ts @@ -1,6 +1,5 @@ import { ClientUtils } from '../../../ClientUtils'; import { Doc } from '../../../fields/Doc'; -import { DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { Cast, NumCast, StrCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; @@ -16,13 +15,12 @@ export namespace ImageUtils { export const AssignImgInfo = (document: Doc, data?: Upload.InspectionResults) => { if (data) { data.nativeWidth && (document._height = (NumCast(document._width) * data.nativeHeight) / data.nativeWidth); - const proto = document[DocData]; - const field = Doc.LayoutFieldKey(document); - proto[`${field}_nativeWidth`] = data.nativeWidth; - proto[`${field}_nativeHeight`] = data.nativeHeight; - proto[`${field}_path`] = data.source; - proto[`${field}_exif`] = JSON.stringify(data.exifData.data); - proto[`${field}_contentSize`] = data.contentSize ? data.contentSize : undefined; + const field = '$' + Doc.LayoutFieldKey(document); + document[`${field}_nativeWidth`] = data.nativeWidth; + document[`${field}_nativeHeight`] = data.nativeHeight; + document[`${field}_path`] = data.source; + document[`${field}_exif`] = JSON.stringify(data.exifData.data); + document[`${field}_contentSize`] = data.contentSize ? data.contentSize : undefined; } return document; }; diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx index 7f0118ed3..f61f6db18 100644 --- a/src/client/views/DashboardView.tsx +++ b/src/client/views/DashboardView.tsx @@ -6,7 +6,7 @@ import * as React from 'react'; import { FaPlus } from 'react-icons/fa'; import { ClientUtils } from '../../ClientUtils'; import { Doc, DocListCast } from '../../fields/Doc'; -import { AclPrivate, DocAcl, DocData } from '../../fields/DocSymbols'; +import { AclPrivate, DocAcl } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; import { List } from '../../fields/List'; import { PrefetchProxy } from '../../fields/Proxy'; @@ -113,7 +113,7 @@ export class DashboardView extends ObservableReactComponent { getDashboards = (whichGroup: DashboardGroup) => { if (whichGroup === DashboardGroup.MyDashboards) { - return DocListCast(Doc.MyDashboards.data).filter(dashboard => dashboard[DocData].author === ClientUtils.CurrentUserEmail()); + return DocListCast(Doc.MyDashboards.data).filter(dashboard => dashboard.$author === ClientUtils.CurrentUserEmail()); } return DocListCast(Doc.MySharedDocs.data_dashboards).filter(doc => doc.dockingConfig); }; @@ -226,7 +226,7 @@ export class DashboardView extends ObservableReactComponent { color={color} val={StrCast(dashboard.title)} setVal={val => { - dashboard[DocData].title = val; + dashboard.$title = val; }} /> {this.selectedDashboardGroup === DashboardGroup.SharedDashboards && this.isUnviewedSharedDashboard(dashboard) ?
unviewed
:
} @@ -403,8 +403,8 @@ export class DashboardView extends ObservableReactComponent { }, ], }; - if (dashboard.dockingConfig && dashboard.dockingConfig !== dashboard[DocData].dockingConfig) dashboard.dockingConfig = JSON.stringify(reset); - else Doc.SetInPlace(dashboard, 'dockingConfig', JSON.stringify(reset), true); + const dockingOnLayout = dashboard._dockingConfig && dashboard._dockingConfig !== dashboard.$dockingConfig; + dashboard[`${dockingOnLayout ? '_' : '$'}dockingConfig`] = JSON.stringify(reset); return reset; }; @@ -427,14 +427,14 @@ export class DashboardView extends ObservableReactComponent { Doc.AddDocToList(Doc.MyHeaderBar, 'data', freeformDoc, undefined, undefined, true); Doc.AddDocToList(Doc.MyDashboards, 'data', dashboardDoc); - dashboardDoc.pane_count = 1; - freeformDoc.embedContainer = dashboardDoc; - dashboardDoc.myOverlayDocs = new List(); - dashboardDoc[DocData].myPublishedDocs = new List(); - dashboardDoc[DocData].myTagCollections = new List(); - dashboardDoc[DocData].myUniqueFaces = new List(); - dashboardDoc[DocData].myTrails = DashboardView.SetupDashboardTrails(); - dashboardDoc[DocData].myCalendars = DashboardView.SetupDashboardCalendars(); + freeformDoc._embedContainer = dashboardDoc; + dashboardDoc.$myPaneCount = 1; + dashboardDoc.$myOverlayDocs = new List(); + dashboardDoc.$myPublishedDocs = new List(); + dashboardDoc.$myTagCollections = new List(); + dashboardDoc.$myUniqueFaces = new List(); + dashboardDoc.$myTrails = DashboardView.SetupDashboardTrails(); + dashboardDoc.$myCalendars = DashboardView.SetupDashboardCalendars(); // open this new dashboard Doc.ActiveDashboard = dashboardDoc; Doc.ActivePage = 'dashboard'; diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index e351e2dec..064906530 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -5,7 +5,7 @@ import { DateField } from '../../fields/DateField'; import { Doc, DocListCast, Opt } from '../../fields/Doc'; import { AclAdmin, AclAugment, AclEdit, AclPrivate, AclReadonly, DocData } from '../../fields/DocSymbols'; import { List } from '../../fields/List'; -import { toList } from '../../fields/Types'; +import { DocCast, toList } from '../../fields/Types'; import { GetEffectiveAcl, inheritParentAcls } from '../../fields/util'; import { DocumentType } from '../documents/DocumentTypes'; import { ObservableReactComponent } from './ObservableReactComponent'; @@ -35,14 +35,14 @@ export function DocComponent

() { * Rather, it specifies the shared properties of all layouts of the document (eg, x,y,) */ get Document() { - return this._props.Document; + return DocCast(this._props.Document.rootDocument, this._props.Document); } /** * This is the document being rendered. It may be a template so it may or may no inherit from the data doc. */ @computed get layoutDoc() { - return this._props.LayoutTemplateString ? this.Document : Doc.Layout(this.Document, this._props.LayoutTemplate?.()); + return this._props.LayoutTemplateString ? this.Document : Doc.Layout(this._props.Document, this._props.LayoutTemplate?.()); } /** @@ -80,13 +80,13 @@ export function ViewBoxBaseComponent

() { * Rather, it specifies the shared properties of all layouts of the document (eg, x,y,) */ get Document() { - return this._props.Document; + return DocCast(this._props.Document.rootDocument, this._props.Document); } /** * This is the document being rendered. It may be a template so it may or may no inherit from the data doc. */ @computed get layoutDoc() { - return Doc.Layout(this.Document); + return Doc.Layout(this._props.Document); } /** @@ -138,13 +138,13 @@ export function ViewBoxAnnotatableComponent

() { * Rather, it specifies the shared properties of all layouts of the document (eg, x,y,) */ @computed get Document() { - return this._props.Document; + return DocCast(this._props.Document.rootDocument, this._props.Document); } /** * This is the document being rendered. It may be a template so it may or may no inherit from the data doc. */ @computed get layoutDoc() { - return Doc.Layout(this.Document); + return Doc.Layout(this._props.Document); } /** diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 54e050f9f..92b4d6fbf 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -127,7 +127,7 @@ export class DocumentDecorations extends ObservableReactComponent#')) { DocumentView.SelectedDocs().forEach(doc => { - doc[DocData].onViewMounted = ScriptField.MakeScript(`updateTagsCollection(this)`); + doc.$onViewMounted = ScriptField.MakeScript(`updateTagsCollection(this)`); }); } const titleFieldKey = this._titleControlString.substring(1); @@ -621,7 +621,7 @@ export class DocumentDecorations extends ObservableReactComponent ({ oldbds, inkPts: Cast(oldbds.doc.data, InkField)?.inkData || [] })) .forEach(({ oldbds: { doc, x, y, width, height }, inkPts }) => { - doc[DocData].data = new InkField(inkPts.map( + doc.$data = new InkField(inkPts.map( (ipt) => ({// (new x — oldx) + newWidth * (oldxpoint /oldWidth) X: NumCast(doc.x) - x + (NumCast(doc.width) * ipt.X) / width, Y: NumCast(doc.y) - y + (NumCast(doc.height) * ipt.Y) / height, diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx index 99738052d..4fc8d7a68 100644 --- a/src/client/views/FilterPanel.tsx +++ b/src/client/views/FilterPanel.tsx @@ -9,7 +9,6 @@ import { Handles, Rail, Slider, Ticks, Tracks } from 'react-compound-slider'; import { AiOutlineMinusSquare, AiOutlinePlusSquare } from 'react-icons/ai'; import { CiCircleRemove } from 'react-icons/ci'; import { Doc, DocListCast, Field, FieldType, LinkedTo, StrListCast } from '../../fields/Doc'; -import { DocData } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; import { List } from '../../fields/List'; import { RichTextField } from '../../fields/RichTextField'; @@ -89,7 +88,7 @@ const HotKeyIconButton: React.FC = observer(({ hotKey /*, sel key={icon.toString()} onClick={undoable(e => { e.stopPropagation; - hotKey[DocData].icon = icon.toString(); + hotKey.$icon = icon.toString(); }, '')} className="icon-panel-button"> diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts index 358274f0e..6854476e2 100644 --- a/src/client/views/InkStrokeProperties.ts +++ b/src/client/views/InkStrokeProperties.ts @@ -3,7 +3,6 @@ import * as fitCurve from 'fit-curve'; import * as _ from 'lodash'; import { action, makeObservable, observable, reaction, runInAction } from 'mobx'; import { Doc, NumListCast, Opt } from '../../fields/Doc'; -import { DocData } from '../../fields/DocSymbols'; import { InkData, InkField, InkTool } from '../../fields/InkField'; import { List } from '../../fields/List'; import { listSpec } from '../../fields/Schema'; @@ -509,7 +508,7 @@ export class InkStrokeProperties { const inkStroke = inkView?.ComponentView as InkingStroke; const polylinePoints = this.sampleBezier(inkStroke?.inkScaledData().inkData ?? [])?.map(pt => [pt.x, pt.y]); if (polylinePoints) { - inkDoc[DocData].stroke = new InkField( + inkDoc.$stroke = new InkField( fitCurve.default(polylinePoints, tolerance) .reduce((cpts, bez) => ({n: cpts.push(...bez.map(cpt => ({X:cpt[0], Y:cpt[1]}))), cpts}).cpts, diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index ef8d0c197..e70f9e5ed 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -11,7 +11,6 @@ import '@dash/components/src/global/globalCssVariables.scss'; import { ClientUtils, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents } from '../../ClientUtils'; import { emptyFunction } from '../../Utils'; import { Doc, DocListCast, GetDocFromUrl, Opt, returnEmptyDoclist } from '../../fields/Doc'; -import { DocData } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; import { DocCast, StrCast, toList } from '../../fields/Types'; import { DocServer } from '../DocServer'; @@ -849,7 +848,7 @@ export class MainView extends ObservableReactComponent { @action selectMenu = (button: Doc) => { - const title = StrCast(button[DocData].title); + const title = StrCast(button.$title); const willOpen = !this._leftMenuFlyoutWidth || this._panelContent !== title; this.closeFlyout(); if (willOpen) { diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index 3f4200dce..e4811a902 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -97,7 +97,6 @@ export class MarqueeAnnotator extends ObservableReactComponent' + this.props.Document.title, }); - const textRegionAnnoProto = textRegionAnno[DocData]; let minX = Number.MAX_VALUE; let maxX = -Number.MAX_VALUE; let minY = Number.MAX_VALUE; @@ -118,15 +117,15 @@ export class MarqueeAnnotator extends ObservableReactComponent(annoRects); - textRegionAnnoProto.opacity = 0; - textRegionAnnoProto.layout_unrendered = true; + textRegionAnno.$text_inlineAnnotations = new List(annoRects); + textRegionAnno.$opacity = 0; + textRegionAnno.$layout_unrendered = true; savedAnnoMap.clear(); return textRegionAnno; }; @@ -226,9 +225,8 @@ export class MarqueeAnnotator extends ObservableReactComponent { if (!dragEx.aborted && dragEx.linkDocument) { - const linkDocData = dragEx.linkDocument[DocData]; - linkDocData.link_relationship = 'cropped image'; - linkDocData.title = 'crop: ' + this.props.Document.title; + dragEx.linkDocument.$link_relationship = 'cropped image'; + dragEx.linkDocument.$title = 'crop: ' + this.props.Document.title; } }, }); diff --git a/src/client/views/PinFuncs.ts b/src/client/views/PinFuncs.ts index ab02c2d07..1ab8575a8 100644 --- a/src/client/views/PinFuncs.ts +++ b/src/client/views/PinFuncs.ts @@ -1,5 +1,4 @@ import { Doc, DocListCast, Field } from '../../fields/Doc'; -import { DocData } from '../../fields/DocSymbols'; import { Copy, Id } from '../../fields/FieldSymbols'; import { List } from '../../fields/List'; import { ObjectField } from '../../fields/ObjectField'; @@ -78,7 +77,7 @@ export function PinDocView(pinDocIn: Doc, pinProps: PinProps, targetDoc: Doc) { } if (pinProps.pinData.dataannos) { const fieldKey = Doc.LayoutFieldKey(targetDoc); - pinDoc.config_annotations = new List(DocListCast(targetDoc[DocData][fieldKey + '_annotations']).filter(doc => !doc.layout_unrendered)); + pinDoc.config_annotations = new List(DocListCast(targetDoc['$' + fieldKey + '_annotations']).filter(doc => !doc.layout_unrendered)); } if (pinProps.pinData.inkable) { pinDoc.config_fillColor = targetDoc.fillColor; diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index 606fb17ed..2b4fe478e 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react/no-unused-class-component-methods */ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Dropdown, DropdownType, IListItemProps, Toggle, ToggleType, Type } from '@dash/components'; import { action, computed, observable } from 'mobx'; @@ -14,7 +13,6 @@ import { RxWidth } from 'react-icons/rx'; import { TbEditCircle, TbEditCircleOff, TbHandOff, TbHandStop, TbHighlight, TbHighlightOff } from 'react-icons/tb'; import { TfiBarChart } from 'react-icons/tfi'; import { Doc, Opt } from '../../fields/Doc'; -import { DocData } from '../../fields/DocSymbols'; import { ScriptField } from '../../fields/ScriptField'; import { BoolCast, ScriptCast, StrCast } from '../../fields/Types'; import { ImageField } from '../../fields/URLField'; @@ -134,8 +132,8 @@ export class PropertiesButtons extends React.Component { () => , (dv, doc) => { const on = !!doc.onPaint; - doc[DocData].onPaint = on ? undefined : ScriptField.MakeScript(`toggleDetail(documentView, "textPainted")`, { documentView: 'any' }); - doc[DocData].layout_textPainted = on ? undefined : ``; + doc.$onPaint = on ? undefined : ScriptField.MakeScript(`toggleDetail(documentView, "textPainted")`, { documentView: 'any' }); + doc.$layout_textPainted = on ? undefined : ``; } ); } diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 11adf7435..c72f958fc 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -282,7 +282,7 @@ export class PropertiesView extends ObservableReactComponent(tags) : undefined; + doc.$tags = tags.length ? new List(tags) : undefined; } return true; } @@ -498,7 +498,7 @@ export class PropertiesView extends ObservableReactComponent { let userOnDoc = true; @@ -777,7 +777,7 @@ export class PropertiesView extends ObservableReactComponent doc.layout_isSvg); + return this.containsInkDoc ? DocListCast(this.selectedDoc.$data) : DocumentView.SelectedSchemaDoc() ? [DocumentView.SelectedSchemaDoc()!] : DocumentView.SelectedDocs().filter(doc => doc.layout_isSvg); } @computed get shapeXps() { return NumCast(this.selectedDoc?.x); } // prettier-ignore set shapeXps(value) { this.selectedDoc && (this.selectedDoc.x = Math.round(value * 100) / 100); } // prettier-ignore @@ -839,10 +839,10 @@ export class PropertiesView extends ObservableReactComponent { - doc[DocData].stroke_width = Math.round(value * 100) / 100; + doc.$stroke_width = Math.round(value * 100) / 100; }); } @@ -881,20 +881,20 @@ export class PropertiesView extends ObservableReactComponent { const inkStroke = DocumentView.getDocumentView(doc)?.ComponentView as InkingStroke; const { inkData } = inkStroke.inkScaledData(); if (InkingStroke.IsClosed(inkData)) { - doc[DocData].fillColor = value || undefined; + doc.$fillColor = value || undefined; } }); } - @computed get colorStk() { return StrCast(this.selectedStrokes.lastElement()?.[DocData].color); } // prettier-ignore + @computed get colorStk() { return StrCast(this.selectedStrokes.lastElement()?.$olor); } // prettier-ignore set colorStk(value) { this.selectedStrokes.forEach(doc => { - doc[DocData].color = value || undefined; + doc.$color = value || undefined; }); } @computed get borderColor() { @@ -902,7 +902,7 @@ export class PropertiesView extends ObservableReactComponent void) { return ( @@ -1034,41 +1034,41 @@ export class PropertiesView extends ObservableReactComponent { - doc[DocData].stroke_dash = value ? this._lastDash : undefined; + doc.$stroke_dash = value ? this._lastDash : undefined; }); } @computed get widthStk() { return this.getField('stroke_width') || '1'; } // prettier-ignore set widthStk(value) { this.selectedStrokes.forEach(doc => { - doc[DocData].stroke_width = Number(value); + doc.$stroke_width = Number(value); }); } @computed get markScal() { return Number(this.getField('stroke_markerScale') || '1'); } // prettier-ignore set markScal(value) { this.selectedStrokes.forEach(doc => { - doc[DocData].stroke_markerScale = Number(value); + doc.$stroke_markerScale = Number(value); }); } @computed get refStrength() { return Number(this.getField('drawing_refStrength') || '50'); } // prettier-ignore set refStrength(value) { - this.selectedDoc[DocData].drawing_refStrength = Number(value); + this.selectedDoc.$drawing_refStrength = Number(value); } @computed get smoothAmt() { return Number(this.getField('stroke_smoothAmount') || '5'); } // prettier-ignore set smoothAmt(value) { this.selectedStrokes.forEach(doc => { - doc[DocData].stroke_smoothAmount = Number(value); + doc.$stroke_smoothAmount = Number(value); }); } @computed get markHead() { return this.getField('stroke_startMarker') || ''; } // prettier-ignore set markHead(value) { this.selectedStrokes.forEach(doc => { - doc[DocData].stroke_startMarker = value; + doc.$stroke_startMarker = value; }); } @computed get markTail() { return this.getField('stroke_endMarker') || ''; } // prettier-ignore set markTail(value) { this.selectedStrokes.forEach(doc => { - doc[DocData].stroke_endMarker = value; + doc.$stroke_endMarker = value; }); } @@ -1356,7 +1356,7 @@ export class PropertiesView extends ObservableReactComponent { - const childDocs: Doc[] = DocListCast(selectedDoc[DocData].data); + const childDocs: Doc[] = DocListCast(selectedDoc.$data); for (let i = 0; i < childDocs.length; i++) { if (DocumentView.getDocumentView(childDocs[i])?.layoutDoc?.layout_isSvg) { return true; @@ -1454,7 +1454,7 @@ export class PropertiesView extends ObservableReactComponent { if (this.selectedLink) { - this.selectedLink[DocData].link_description = value; + this.selectedLink.$link_description = value; } }); diff --git a/src/client/views/ScriptBox.tsx b/src/client/views/ScriptBox.tsx index d05b0a6b6..52c0227d8 100644 --- a/src/client/views/ScriptBox.tsx +++ b/src/client/views/ScriptBox.tsx @@ -3,7 +3,6 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import { emptyFunction } from '../../Utils'; import { Doc, Opt } from '../../fields/Doc'; -import { DocData } from '../../fields/DocSymbols'; import { ScriptField } from '../../fields/ScriptField'; import { ScriptCast } from '../../fields/Types'; import { DragManager } from '../util/DragManager'; @@ -101,7 +100,6 @@ export class ScriptBox extends React.Component { ); } // let l = docList(this.source[0].data).length; if (l) { let ind = this.target[0].index !== undefined ? (this.target[0].index+1) % l : 0; this.target[0].index = ind; this.target[0].proto = getProto(docList(this.source[0].data)[ind]);} - // eslint-disable-next-line react/sort-comp public static EditButtonScript(title: string, doc: Doc, fieldKey: string, clientX: number, clientY: number, contextParams?: { [name: string]: string }, defaultScript?: ScriptField) { let overlayDisposer: () => void = emptyFunction; const script = ScriptCast(doc[fieldKey]) || defaultScript; @@ -119,7 +117,7 @@ export class ScriptBox extends React.Component { onCancel={overlayDisposer} onSave={(text, onError) => { if (!text) { - doc[DocData][fieldKey] = undefined; + doc['$' + fieldKey] = undefined; } else { const compScript = CompileScript(text, { params: { this: Doc.name, ...contextParams }, @@ -142,7 +140,7 @@ export class ScriptBox extends React.Component { div.innerHTML = 'button'; params.length && DragManager.StartButtonDrag([div], text, doc.title + '-instance', {}, params, () => {}, clientX, clientY); - doc[DocData][fieldKey] = new ScriptField(compScript); + doc['$' + fieldKey] = new ScriptField(compScript); overlayDisposer(); } }} diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index e51bc18ef..a45b37f43 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -503,9 +503,8 @@ export class CollectionDockingView extends CollectionSubView() { }); const dashboardDoc = Docs.Create.DockDocument(newtabs, json, { title: incrementTitleCopy(StrCast(doc.title)) }); - dashboardDoc.pane_count = 1; - dashboardDoc.myOverlayDocs = new List(); - dashboardDoc.myPublishedDocs = new List(); + dashboardDoc.$myOverlayDocs = new List(); + dashboardDoc.$myPublishedDocs = new List(); DashboardView.SetupDashboardTrails(); DashboardView.SetupDashboardCalendars(); // Zaul TODO: needed? @@ -555,13 +554,13 @@ export class CollectionDockingView extends CollectionSubView() { stack.header?.element.on('mousedown', (e: MouseEvent) => { const dashboard = Doc.ActiveDashboard; if (dashboard && e.target === stack.header?.element[0] && e.button === 2) { - dashboard.pane_count = NumCast(dashboard.pane_count) + 1; + dashboard.$myPaneCount = NumCast(dashboard.$myPaneCount) + 1; const docToAdd = Docs.Create.FreeformDocument([], { _width: this._props.PanelWidth(), _height: this._props.PanelHeight(), _freeform_backgroundGrid: true, _layout_fitWidth: true, - title: `Untitled Tab ${NumCast(dashboard.pane_count)}`, + title: `Untitled Tab ${NumCast(dashboard.$myPaneCount)}`, }); Doc.AddDocToList(Doc.MyHeaderBar, 'data', docToAdd, undefined, undefined, true); inheritParentAcls(this.Document, docToAdd, false); @@ -572,13 +571,13 @@ export class CollectionDockingView extends CollectionSubView() { const addNewDoc = undoable(() => { const dashboard = Doc.ActiveDashboard; if (dashboard) { - dashboard.pane_count = NumCast(dashboard.pane_count) + 1; + dashboard.$myPaneCount = NumCast(dashboard.$myPaneCount) + 1; const docToAdd = Docs.Create.FreeformDocument([], { _width: this._props.PanelWidth(), _height: this._props.PanelHeight(), _layout_fitWidth: true, _freeform_backgroundGrid: true, - title: `Untitled Tab ${NumCast(dashboard.pane_count)}`, + title: `Untitled Tab ${NumCast(dashboard.$myPaneCount)}`, }); Doc.AddDocToList(Doc.MyHeaderBar, 'data', docToAdd, undefined, undefined, true); inheritParentAcls(this.dataDoc, docToAdd, false); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index cac276535..fdaf13733 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -88,7 +88,7 @@ export interface DocumentViewProps extends FieldViewSharedProps { @observer export class DocumentViewInternal extends DocComponent() { // this makes mobx trace() statements more descriptive - public get displayName() { return 'DocumentViewInternal(' + this.Document.title + ')'; } // prettier-ignore + public get displayName() { return 'DocumentViewInternal(' + this.Document.$title + ')'; } // prettier-ignore public static SelectAfterContextMenu = true; // whether a document should be selected after it's contextmenu is triggered. /** @@ -143,10 +143,10 @@ export class DocumentViewInternal extends DocComponent 0)) stopPropagate = false; preventDefault = false; } - this._singleClickFunc = undoable(clickFunc ?? sendToBack ?? selectFunc, 'click: ' + this.Document.title); + this._singleClickFunc = undoable(clickFunc ?? sendToBack ?? selectFunc, 'click: ' + this.Document.$title); const waitForDblClick = this._props.waitForDoubleClickToClick?.() ?? this.Document.waitForDoubleClickToClick; if ((clickFunc && waitForDblClick !== 'never') || waitForDblClick === 'always') { this._doubleClickTimeout && clearTimeout(this._doubleClickTimeout); @@ -519,7 +519,7 @@ export class DocumentViewInternal extends DocComponent { - if (this.Document.type !== DocumentType.MAP) DocumentViewInternal.SelectAfterContextMenu && this._props.select(false); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up. by delaying the selection until hopefully after the pointer up, the context menu will appear. + if (this.Document.$type !== DocumentType.MAP) DocumentViewInternal.SelectAfterContextMenu && this._props.select(false); // on a mac, the context menu is triggered on mouse down, but a YouTube video becaomes interactive when selected which means that the context menu won't show up. by delaying the selection until hopefully after the pointer up, the context menu will appear. setTimeout(() => simulateMouseClick(document.elementFromPoint(e.clientX, e.clientY), e.clientX, e.clientY, e.screenX, e.screenY)); }; if (navigator.userAgent.includes('Macintosh')) { @@ -545,7 +545,7 @@ export class DocumentViewInternal extends DocComponent (item.method ? item.method() : item.script?.script.run({ this: this.Document, documentView: this, scriptContext: this._props.scriptContext })), icon: item.icon as IconProp }) ); - if (!this.Document.isFolder) { + if (!this.Document.$isFolder) { const templateDoc = Cast(this.Document[StrCast(this.Document.layout_fieldKey)], Doc, null); const appearance = cm.findByDescription('Appearance...'); const appearanceItems = appearance?.subitems ?? []; @@ -635,7 +635,7 @@ export class DocumentViewInternal extends DocComponent= 1 ? 0 : 1 / (1 + x * (viewXfScale - 1)); - const y = NumCast(this.Document.width) / viewXfScale / 200; + const y = NumCast(this.Document._width) / viewXfScale / 200; const yscale = y >= 1 ? 0 : 1 / (1 + y * viewXfScale - 1); return Math.max(xscale, yscale, 1 / viewXfScale); } @@ -735,7 +735,7 @@ export class DocumentViewInternal extends DocComponent
- {this._componentView?.isUnstyledView?.() || this.Document.type === DocumentType.CONFIG || !renderDoc ? renderDoc : DocumentViewInternal.AnimationEffect(renderDoc, this.Document[Animation], this.Document)} + {this._componentView?.isUnstyledView?.() || this.Document.$type === DocumentType.CONFIG || !renderDoc ? renderDoc : DocumentViewInternal.AnimationEffect(renderDoc, this.Document[Animation], this.Document)} {jsx}
); @@ -1210,7 +1210,7 @@ export class DocumentView extends DocComponent() { } @computed private get nativeScaling() { if (this.shouldNotScale) return 1; - const minTextScale = this.Document.type === DocumentType.RTF ? 0.1 : 0; + const minTextScale = this.Document.$type === DocumentType.RTF ? 0.1 : 0; const ai = this._showAIEditor && this.nativeWidth === this.layoutDoc.width ? 95 : 0; const effNW = Math.max(this.effectiveNativeWidth - ai, 1); const effNH = Math.max(this.effectiveNativeHeight - ai, 1); @@ -1325,7 +1325,7 @@ export class DocumentView extends DocComponent() { public startDragging = (x: number, y: number, dropAction: dropActionType | undefined, hideSource = false) => this._docViewInternal?.startDragging(x, y, dropAction, hideSource); public showContextMenu = (pageX: number, pageY: number) => this._docViewInternal?.onContextMenu(undefined, pageX, pageY); - public toggleNativeDimensions = () => this._docViewInternal && this.Document.type !== DocumentType.INK && Doc.toggleNativeDimensions(this.layoutDoc, this.NativeDimScaling() ?? 1, this._props.PanelWidth(), this._props.PanelHeight()); + public toggleNativeDimensions = () => this._docViewInternal && this.Document.$type !== DocumentType.INK && Doc.toggleNativeDimensions(this.layoutDoc, this.NativeDimScaling() ?? 1, this._props.PanelWidth(), this._props.PanelHeight()); public iconify(finished?: () => void, animateTime?: number) { this.ComponentView?.updateIcon?.(); diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 40c687b7e..9795febbe 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -54,16 +54,12 @@ export class KeyValueBox extends ViewBoxBaseComponent() { @observable private rows: KeyValuePair[] = []; @observable _splitPercentage = 50; - get fieldDocToLayout() { - return DocCast(this.Document); - } - @action onEnterKey = (e: React.KeyboardEvent): void => { if (e.key === 'Enter') { e.stopPropagation(); - if (this._keyInput.current?.value && this._valInput.current?.value && this.fieldDocToLayout) { - if (KeyValueBox.SetField(this.fieldDocToLayout, this._keyInput.current.value, this._valInput.current.value)) { + if (this._keyInput.current?.value && this._valInput.current?.value && this._props.Document) { + if (KeyValueBox.SetField(this._props.Document, this._keyInput.current.value, this._valInput.current.value)) { this._keyInput.current.value = ''; this._valInput.current.value = ''; document.body.focus(); @@ -114,7 +110,7 @@ export class KeyValueBox extends ViewBoxBaseComponent() { if (key) target[key] = script.originalScript; return false; } - field === undefined && (field = res.result instanceof Array ? new List(res.result) : (typeof res.result === 'function' ? res.result.name : res.result as FieldType)); + field === undefined && (field = res.result instanceof Array ? new List(res.result) : typeof res.result === 'function' ? res.result.name : (res.result as FieldType)); } } if (!key) return false; @@ -141,7 +137,7 @@ export class KeyValueBox extends ViewBoxBaseComponent() { rowHeight = () => 30; @computed get createTable() { - const doc = this.fieldDocToLayout; + const doc = this._props.Document; if (!doc) { return ( @@ -149,25 +145,35 @@ export class KeyValueBox extends ViewBoxBaseComponent() { ); } - const realDoc = doc; const ids: { [key: string]: string } = {}; const protos = Doc.GetAllPrototypes(doc); protos.forEach(proto => { Object.keys(proto).forEach(key => { - if (!(key in ids) && realDoc[key] !== ComputedField.undefined) { + if (!(key in ids) && doc[key] !== ComputedField.undefined) { ids[key] = key; } }); }); + const layoutProtos = Doc.GetAllPrototypes(this.layoutDoc); + layoutProtos.forEach(proto => { + Object.keys(proto) + .map(key => '_' + key) + .forEach(key => { + if (!(key.replace(/^_/, '') in ids) && doc[key] !== ComputedField.undefined) { + ids[key] = key; + } + }); + }); + const rows: JSX.Element[] = []; let i = 0; const keys = Object.keys(ids).slice(); // for (const key of [...keys.filter(id => id !== 'layout' && !id.includes('_')).sort(), ...keys.filter(id => id === 'layout' || id.includes('_')).sort()]) { const sortedKeys = keys.sort((a: string, b: string) => { - const a_ = a.split('_')[0]; - const b_ = b.split('_')[0]; + const a_ = a.replace(/^_/, '').split('_')[0]; + const b_ = b.replace(/^_/, '').split('_')[0]; if (a_ < b_) return -1; if (a_ > b_) return 1; if (a === a_) return -1; @@ -177,7 +183,7 @@ export class KeyValueBox extends ViewBoxBaseComponent() { sortedKeys.forEach(key => { rows.push( () { openItems.push({ description: 'Default Perspective', event: () => { - this._props.addDocTab(this.Document, OpenWhere.close); - this._props.addDocTab(this.fieldDocToLayout, OpenWhere.addRight); + this._props.addDocTab(this._props.Document, OpenWhere.close); + this._props.addDocTab(this._props.Document, OpenWhere.addRight); }, icon: 'image', }); diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 85aff04c3..93f5231cb 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -61,17 +61,18 @@ export class KeyValuePair extends ObservableReactComponent { render() { // let fieldKey = Object.keys(props.Document).indexOf(props.fieldKey) !== -1 ? props.fieldKey : "(" + props.fieldKey + ")"; - let protoCount = 0; - let { doc } = this._props; + const layoutField = this._props.keyName.startsWith('_'); + let doc = layoutField ? Doc.Layout(this._props.doc) : this._props.doc; + let protoCount = doc !== this._props.doc && !layoutField ? 1 : 0; while (doc) { - if (Object.keys(doc).includes(this._props.keyName)) { + if (Object.keys(doc).includes(this._props.keyName.replace(/^_/, ''))) { break; } protoCount++; doc = DocCast(doc.proto); } - const parenCount = Math.max(0, protoCount - 1); - const keyStyle = protoCount === 0 ? 'black' : 'blue'; + const parenCount = Math.max(0, protoCount); + const keyStyle = protoCount === 0 && doc === this._props.doc ? 'black' : 'blue'; const hover = { transition: '0.3s ease opacity', opacity: this.isPointerOver || this.isChecked ? 1 : 0 }; @@ -99,10 +100,9 @@ export class KeyValuePair extends ObservableReactComponent { pair[0].replace(/^_/, '') === this._props.keyName)?.[1].description ?? ''}> -
- {'('.repeat(parenCount)} - {this._props.keyName} - {')'.repeat(parenCount)} +
+ {(layoutField ? '_' : '$').repeat(parenCount)} + {(keyStyle === 'blue' && !layoutField && !parenCount ? '$' : '') + this._props.keyName}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index b84575389..9078648e9 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -245,9 +245,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent void = emptyFunction; - const targetData = target[DocData]; - targetData.mediaState = mediaState.Recording; - DictationManager.recordAudioAnnotation(targetData, Doc.LayoutFieldKey(target), stop => { stopFunc = stop }); // prettier-ignore + target.$mediaState = mediaState.Recording; + DictationManager.recordAudioAnnotation(target[DocData], Doc.LayoutFieldKey(target), stop => { stopFunc = stop }); // prettier-ignore const reactionDisposer = reaction( () => target.mediaState, @@ -1067,7 +1066,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent::$/, (state, match, start, end) => { const creator = (doc: Doc) => { - const textDoc = this.Document[DocData]; - const numInlines = NumCast(textDoc.inlineTextCount); - textDoc.inlineTextCount = numInlines + 1; + const numInlines = NumCast(this.Document.$inlineTextCount); + this.Document.$inlineTextCount = numInlines + 1; const node = state.doc.resolve(start).nodeAfter; const newNode = schema.nodes.dashComment.create({ docId: doc[Id], reflow: false }); const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 35, title: 'dashDoc', docId: doc[Id], float: 'right' }); @@ -109,16 +108,15 @@ export class RichTextRules { }), // Create annotation to a field on the text document new InputRule(/>>$/, (state, match, start, end) => { - const textDoc = this.Document[DocData]; - const numInlines = NumCast(textDoc.inlineTextCount); - textDoc.inlineTextCount = numInlines + 1; - const inlineFieldKey = 'inline' + numInlines; // which field on the text document this annotation will write to - const inlineLayoutKey = 'layout_' + inlineFieldKey; // the field holding the layout string that will render the inline annotation + const numInlines = NumCast(this.Document.$inlineTextCount); + this.Document.$inlineTextCount = numInlines + 1; + const inlineFieldKey = '$inline' + numInlines; // which field on the text document this annotation will write to + const inlineLayoutKey = '$layout_' + inlineFieldKey; // the field holding the layout string that will render the inline annotation const textDocInline = Docs.Create.TextDocument('', { _layout_fieldKey: inlineLayoutKey, _width: 75, _height: 35, - annotationOn: textDoc, + annotationOn: this.Document[DocData], _layout_fitWidth: true, _layout_autoHeight: true, text_fontSize: '9px', @@ -128,9 +126,9 @@ export class RichTextRules { textDocInline.title_custom = 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.isDataDoc = true; - textDocInline.proto = textDoc; // make the annotation inherit from the outer text doc so that it can resolve any nested field references, e.g., [[field]] - 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 + textDocInline.proto = this.Document[DocData]; // make the annotation inherit from the outer text doc so that it can resolve any nested field references, e.g., [[field]] + this.Document[inlineLayoutKey] = FormattedTextBox.LayoutString(inlineFieldKey); // create a layout string for the layout key that will render the annotation text + this.Document[inlineFieldKey] = ''; // set a default value for the annotation const node = state.doc.resolve(start).nodeAfter; const newNode = schema.nodes.dashComment.create({ docId: textDocInline[Id], reflow: true }); const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 35, title: 'dashDoc', docId: textDocInline[Id], float: 'right' }); @@ -334,18 +332,14 @@ export class RichTextRules { if (value?.includes(',') && !value.startsWith('((')) { const values = value.split(','); const strs = values.some(v => !v.match(/^[-]?[0-9.]$/)); - this.Document[DocData][fieldKey] = strs ? new List(values) : new List(values.map(v => Number(v))); + this.Document['$' + fieldKey] = strs ? new List(values) : new List(values.map(v => Number(v))); } else if (value) { Doc.SetField( this.Document, fieldKey, assign + value, Doc.IsDataProto(this.Document) ? true : undefined, - assign.includes(':=') - ? undefined - : (gptval: FieldResult) => { - (dataDoc ? this.Document[DocData] : this.Document)[fieldKey] = gptval as string; - } + assign.includes(':=') ? undefined : (gptval: FieldResult) => (this.Document[(dataDoc ? '$' : '_') + fieldKey] = gptval as string) ); if (fieldKey === this.TextBox.fieldKey) return this.TextBox.EditorView!.state.tr; } @@ -399,11 +393,11 @@ export class RichTextRules { new InputRule(/#(@?[a-zA-Z_-]+[a-zA-Z_\-0-9]*)\s$/, (state, match, start, end) => { const tag = match[1]; if (!tag) return state.tr; - // this.Document[DocData]['#' + tag] = '#' + tag; - const tags = StrListCast(this.Document[DocData].tags); + // this.Document[['$#' + tag] = '#' + tag; + const tags = StrListCast(this.Document.$tags); if (!tags.includes(tag)) { tags.push(tag); - this.Document[DocData].tags = new List(tags); + this.Document.$tags = new List(tags); this.Document._layout_showTags = true; } const fieldView = state.schema.nodes.dashField.create({ fieldKey: tag.startsWith('@') ? tag.replace(/^@/, '') : '#' + tag }); diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index f818c6e20..ec97e067a 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -596,11 +596,11 @@ export class PresBox extends ViewBoxBaseComponent() { } if (pinDataTypes?.inkable || (!pinDataTypes && (activeItem.config_fillColor !== undefined || activeItem.color !== undefined))) { if (bestTarget.fillColor !== activeItem.config_fillColor) { - bestTarget[DocData].fillColor = StrCast(activeItem.config_fillColor, StrCast(bestTarget.fillColor)); + bestTarget.$fillColor = StrCast(activeItem.config_fillColor, StrCast(bestTarget.fillColor)); changed = true; } if (bestTarget.color !== activeItem.config_color) { - bestTarget[DocData].color = StrCast(activeItem.config_color, StrCast(bestTarget.color)); + bestTarget.$color = StrCast(activeItem.config_color, StrCast(bestTarget.color)); changed = true; } if (bestTarget.width !== activeItem.width) { @@ -669,7 +669,7 @@ export class PresBox extends ViewBoxBaseComponent() { return doc; }); const newList = new List([...oldItems, ...hiddenItems, ...newItems]); - bestTarget[DocData][fkey + '_annotations'] = newList; + bestTarget['$' + fkey + '_annotations'] = newList; } if (pinDataTypes?.poslayoutview || (!pinDataTypes && activeItem.config_pinLayoutData !== undefined)) { changed = true; @@ -690,8 +690,8 @@ export class PresBox extends ViewBoxBaseComponent() { data.fill && (doc._fillColor = data.fill); doc._width = data.w; doc._height = data.h; - data.data && (doc[DocData].data = field); - data.text && (doc[DocData].text = tfield); + data.data && (doc.$data = field); + data.text && (doc.$text = tfield); Doc.AddDocToList(bestTarget[DocData], layoutField, doc); } }); diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index dc7524bcd..2142adac8 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -431,7 +431,7 @@ export class PDFViewer extends ObservableReactComponent { }; addDrawingAnnotation = (drawing: Doc) => { - // drawing[DocData].x = this._props.pdfBox.ScreenToLocalBoxXf().TranslateX + // drawing.x = this._props.pdfBox.ScreenToLocalBoxXf().TranslateX // const scaleX = this._mainCont.current.offsetWidth / boundingRect.width; drawing.y = NumCast(drawing.y) + NumCast(this._props.Document.layout_scrollTop); this._props.addDocument?.(drawing); diff --git a/src/client/views/search/FaceRecognitionHandler.tsx b/src/client/views/search/FaceRecognitionHandler.tsx index 6f70e96ab..841546a04 100644 --- a/src/client/views/search/FaceRecognitionHandler.tsx +++ b/src/client/views/search/FaceRecognitionHandler.tsx @@ -66,7 +66,7 @@ export class FaceRecognitionHandler { * returns a list of all face collection Docs on the current dashboard * @returns face collection Doc list */ - public static UniqueFaces = () => DocListCast(Doc.ActiveDashboard?.[DocData].myUniqueFaces); + public static UniqueFaces = () => DocListCast(Doc.ActiveDashboard?.$myUniqueFaces); /** * Find a unique face from its name @@ -87,22 +87,22 @@ export class FaceRecognitionHandler { * @param faceDoc unique face Doc * @returns label string */ - public static UniqueFaceLabel = (faceDoc: Doc) => StrCast(faceDoc[DocData].face); + public static UniqueFaceLabel = (faceDoc: Doc) => StrCast(faceDoc.$face); - public static SetUniqueFaceLabel = (faceDoc: Doc, value: string) => (faceDoc[DocData].face = value); + public static SetUniqueFaceLabel = (faceDoc: Doc, value: string) => (faceDoc.$face = value); /** * Returns all the face descriptors associated with a unique face Doc * @param faceDoc unique face Doc * @returns face descriptors */ - public static UniqueFaceDescriptors = (faceDoc: Doc) => DocListCast(faceDoc[DocData].face_annos).map(face => face.faceDescriptor as List); + public static UniqueFaceDescriptors = (faceDoc: Doc) => DocListCast(faceDoc.$face_annos).map(face => face.faceDescriptor as List); /** * Returns a list of all face image Docs associated with a unique face Doc * @param faceDoc unique face Doc * @returns image Docs */ - public static UniqueFaceImages = (faceDoc: Doc) => DocListCast(faceDoc[DocData].face_annos).map(face => DocCast(face.annotationOn, face)); + public static UniqueFaceImages = (faceDoc: Doc) => DocListCast(faceDoc.$face_annos).map(face => DocCast(face.annotationOn, face)); /** * Adds a face image to a unique face Doc, adds the unique face Doc to the images list of reognized faces, @@ -145,8 +145,8 @@ export class FaceRecognitionHandler { * @returns a unique face Doc */ private createUniqueFaceDoc = (dashboard: Doc) => { - const faceDocNum = NumCast(dashboard[DocData].myUniqueFaces_count) + 1; - dashboard[DocData].myUniqueFaces_count = faceDocNum; // TODO: improve to a better name + const faceDocNum = NumCast(dashboard.$myUniqueFaces_count) + 1; + dashboard.$myUniqueFaces_count = faceDocNum; // TODO: improve to a better name const uniqueFaceDoc = Docs.Create.UniqeFaceDocument({ title: ComputedField.MakeFunction('this.face', undefined, undefined, 'this.face = value') as unknown as string, @@ -160,9 +160,8 @@ export class FaceRecognitionHandler { _width: 400, _height: 100, }); - const uface = uniqueFaceDoc[DocData]; - uface.face = `Face${faceDocNum}`; - uface.face_annos = new List(); + uniqueFaceDoc.$face = `Face${faceDocNum}`; + uniqueFaceDoc.$face_annos = new List(); Doc.SetContainer(uniqueFaceDoc, Doc.MyFaceCollection); Doc.ActiveDashboard && Doc.AddDocToList(Doc.ActiveDashboard[DocData], 'myUniqueFaces', uniqueFaceDoc); @@ -241,7 +240,7 @@ export class FaceRecognitionHandler { annos.push(faceAnno); }); - imgDoc[DocData].data_annotations = new List(annos); + imgDoc.$data_annotations = new List(annos); imgDoc._layout_showTags = annos.length > 0; return imgDocFaceDescriptions; }) diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index af98355d1..8b7e77fba 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -465,7 +465,6 @@ export class SearchBox extends ViewBoxBaseComponent() { } }); - // eslint-disable-next-line react/jsx-props-no-spreading const recommendationsJSX: JSX.Element[] = []; // this._recommendations.map(props => ); return ( diff --git a/src/client/views/smartdraw/DrawingFillHandler.tsx b/src/client/views/smartdraw/DrawingFillHandler.tsx index c672bc718..f1d5f2cfe 100644 --- a/src/client/views/smartdraw/DrawingFillHandler.tsx +++ b/src/client/views/smartdraw/DrawingFillHandler.tsx @@ -1,6 +1,5 @@ import { imageUrlToBase64 } from '../../../ClientUtils'; import { Doc, StrListCast } from '../../../fields/Doc'; -import { DocData } from '../../../fields/DocSymbols'; import { List } from '../../../fields/List'; import { DocCast, ImageCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; @@ -15,8 +14,7 @@ import { AspectRatioLimits, FireflyDimensionsMap, FireflyImageDimensions, Firefl const DashDropboxId = '2m86iveqdr9vzsa'; export class DrawingFillHandler { static drawingToImage = async (drawing: Doc, strength: number, user_prompt: string, styleDoc?: Doc) => { - const docData = drawing[DocData]; - const tags = StrListCast(docData.tags).map(tag => tag.slice(1)); + const tags = StrListCast(drawing.$tags).map(tag => tag.slice(1)); const styles = tags.filter(tag => FireflyStylePresets.has(tag)); const styleDocs = !Doc.Links(drawing).length ? styleDoc && !tags.length @@ -47,7 +45,7 @@ export class DrawingFillHandler { Networking.PostToServer('/queryFireflyImageFromStructure', { prompt: `${newPrompt}`, width: dims.width, height: dims.height, structureUrl, strength, presets: styles, styleUrl }) .then(res => { const genratedDocs = DocCast(drawing.ai_firefly_generatedDocs) ?? Docs.Create.MasonryDocument([], { _width: 400, _height: 400 }); - drawing[DocData].ai_firefly_generatedDocs = genratedDocs; + drawing.$ai_firefly_generatedDocs = genratedDocs; (res as Upload.ImageInformation[]).map(info => Doc.AddDocToList( genratedDocs, diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index fc89dcbe7..f5bd4f44c 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -320,10 +320,11 @@ export class Doc extends RefField { UpdatingFromServer, Width, '__LAYOUT__', + '__DATA__', ]; }, getOwnPropertyDescriptor: (target, prop) => { - if (prop.toString() === '__LAYOUT__' || !(prop in target[FieldKeys])) { + if (prop.toString() === '__DATA__' || prop.toString() === '__LAYOUT__' || !(prop in target[FieldKeys])) { return Reflect.getOwnPropertyDescriptor(target, prop); } return { @@ -400,6 +401,9 @@ export class Doc extends RefField { public [ToString] = () => `Doc(${GetEffectiveAcl(this[SelfProxy]) === AclPrivate ? '-inaccessible-' : this[SelfProxy].title})`; public get [DocLayout]() { return this[SelfProxy].__LAYOUT__; } // prettier-ignore public get [DocData](): Doc { + return this[SelfProxy].__DATA__; + } + @computed get __DATA__(): Doc { const self = this[SelfProxy]; return self.resolvedDataDoc && !self.isTemplateForField ? self : Doc.GetProto(Cast(Doc.Layout(self).resolvedDataDoc, Doc, null) || self); } @@ -414,7 +418,7 @@ export class Doc extends RefField { } else { return Cast(layoutField, Doc, null); } - return Cast(self[renderFieldKey + '_layout[' + templateLayoutDoc[Id] + ']'], Doc, null) || templateLayoutDoc; + return Cast(self['layout_' + templateLayoutDoc.title + '(' + renderFieldKey + ')'], Doc, null) || templateLayoutDoc; } return undefined; } @@ -865,7 +869,7 @@ export namespace Doc { // If it doesn't find the expanded layout, then it makes a delegate of the template layout and // saves it on the data doc indexed by the template layout's id. // - const expandedLayoutFieldKey = templateField + '_layout[' + templateLayoutDoc[Id] + ']'; + const expandedLayoutFieldKey = 'layout_' + templateLayoutDoc.title + '(' + templateField + ')'; let expandedTemplateLayout = targetDoc?.[expandedLayoutFieldKey]; if (templateLayoutDoc.resolvedDataDoc instanceof Promise) { @@ -1152,7 +1156,9 @@ export namespace Doc { // the document containing the view layout information - will be the Document itself unless the Document has // a layout field or 'layout' is given. export function Layout(doc: Doc, layout?: Doc): Doc { - const overrideLayout = layout && Cast(doc[`${StrCast(layout.isTemplateForField, 'data')}_layout[` + layout[Id] + ']'], Doc, null); + const templateField = layout && StrCast(layout.isTemplateForField, Doc.LayoutFieldKey(layout)); // the field that the template renders + const overrideLayout = layout && Cast(doc[layout.title + '(' + templateField + ')'], Doc, null); + // [`${StrCast(layout.isTemplateForField, 'data')}_layout[` + layout[Id] + ']'], Doc, null); return overrideLayout || doc[DocLayout] || doc; } export function SetLayout(doc: Doc, layout: Doc | string) { diff --git a/src/fields/util.ts b/src/fields/util.ts index 33764aca5..abbe543e8 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -314,6 +314,13 @@ export function setter(target: ListImpl | Doc, inProp: string | symbo // if you're trying to change an acl but don't have Admin access / you're trying to change it to something that isn't an acceptable acl, you can't if (typeof prop === 'string' && prop.startsWith('acl_') && (effectiveAcl !== AclAdmin || ![...Object.values(SharingPermissions), undefined].includes(value as SharingPermissions))) return true; + if (typeof prop === 'string' && prop !== '__id' && prop !== '__fieldTuples' && prop.startsWith('$')) { + prop = prop.substring(1); + if (target.__DATA__ instanceof Doc) { + target.__DATA__[prop] = value as FieldResult; + return true; + } + } if (typeof prop === 'string' && prop !== '__id' && prop !== '__fieldTuples' && prop.startsWith('_')) { if (!prop.startsWith('__')) prop = prop.substring(1); if (target.__LAYOUT__ instanceof Doc) { @@ -351,6 +358,7 @@ export function getter(target: Doc | ListImpl, prop: string | symbol, case DocAcl : return target[DocAcl]; case $mobx: return target.__fieldTuples[prop]; case DocLayout: return target.__LAYOUT__; + case DocData: return target.__DATA__; case Height: case Width: if (GetEffectiveAcl(target) === AclPrivate) return returnZero; // eslint-disable-next-line no-fallthrough default : @@ -362,6 +370,8 @@ export function getter(target: Doc | ListImpl, prop: string | symbol, const layoutProp = prop.startsWith('_') ? prop.substring(1) : undefined; if (layoutProp && target.__LAYOUT__) return (target.__LAYOUT__ as Doc)[layoutProp]; + const dataProp = prop.startsWith('$') ? prop.substring(1) : undefined; + if (dataProp && target.__DATA__) return (target.__DATA__ as Doc)[dataProp]; return getFieldImpl(target, layoutProp ?? prop, proxy); } -- cgit v1.2.3-70-g09d2 From d0fccd1050f5d6ccc24c1e4d2b7d1c0ed94fb2a7 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 23 Mar 2025 10:27:28 -0400 Subject: updated more [DocData] to .$ things --- src/client/util/CalendarManager.tsx | 5 +-- src/client/util/LinkManager.ts | 6 +-- src/client/views/DocComponent.tsx | 9 ++-- src/client/views/PropertiesDocContextSelector.tsx | 2 +- src/client/views/PropertiesView.tsx | 8 +--- src/client/views/SidebarAnnos.tsx | 9 ++-- src/client/views/StyleProviderQuiz.tsx | 8 ++-- src/client/views/TagsView.tsx | 33 +++++++-------- .../views/collections/CollectionDockingView.tsx | 6 +-- .../collections/CollectionMasonryViewFieldRow.tsx | 3 +- src/client/views/collections/CollectionMenu.tsx | 3 +- .../views/collections/CollectionNoteTakingView.tsx | 2 +- .../collections/CollectionNoteTakingViewColumn.tsx | 2 +- .../collections/CollectionStackedTimeline.tsx | 8 ++-- .../views/collections/CollectionStackingView.tsx | 5 +-- src/client/views/collections/CollectionSubView.tsx | 12 +++++- src/client/views/collections/TabDocView.tsx | 2 +- src/client/views/collections/TreeView.tsx | 5 +-- .../CollectionFreeFormInfoUI.tsx | 11 +++-- .../collectionFreeForm/CollectionFreeFormView.tsx | 25 ++++++----- .../collectionFreeForm/FaceCollectionBox.tsx | 4 +- .../collectionFreeForm/ImageLabelBox.tsx | 19 ++++----- .../collections/collectionFreeForm/MarqueeView.tsx | 19 ++++----- src/client/views/global/globalScripts.ts | 49 +++++++++------------- src/client/views/nodes/AudioBox.tsx | 2 +- src/client/views/nodes/ComparisonBox.tsx | 10 ++--- .../views/nodes/DataVizBox/components/TableBox.tsx | 4 +- src/client/views/nodes/DiagramBox.tsx | 5 +-- src/client/views/nodes/DocumentView.tsx | 14 +++---- src/client/views/nodes/ImageBox.tsx | 42 +++++++++---------- src/client/views/nodes/KeyValueBox.tsx | 2 +- src/client/views/nodes/LinkBox.tsx | 6 +-- src/client/views/nodes/LinkDescriptionPopup.tsx | 3 +- src/client/views/nodes/PDFBox.tsx | 17 ++++---- .../views/nodes/RecordingBox/RecordingBox.tsx | 3 +- src/client/views/nodes/VideoBox.tsx | 48 ++++++++++----------- src/client/views/nodes/calendarBox/CalendarBox.tsx | 2 +- .../nodes/chatbot/chatboxcomponents/ChatBox.tsx | 6 +-- .../views/nodes/formattedText/EquationView.tsx | 5 +-- src/client/views/nodes/imageEditor/ImageEditor.tsx | 9 ++-- src/client/views/nodes/trails/PresBox.tsx | 9 ++-- src/client/views/smartdraw/SmartDrawHandler.tsx | 21 +++++----- src/client/views/smartdraw/StickerPalette.tsx | 28 ++++++------- src/fields/Doc.ts | 25 ++++++----- src/fields/ScriptField.ts | 3 +- 45 files changed, 243 insertions(+), 276 deletions(-) (limited to 'src/client/views/nodes/trails') diff --git a/src/client/util/CalendarManager.tsx b/src/client/util/CalendarManager.tsx index 3357e5d59..1a5a5f889 100644 --- a/src/client/util/CalendarManager.tsx +++ b/src/client/util/CalendarManager.tsx @@ -17,7 +17,6 @@ import { TaskCompletionBox } from '../views/nodes/TaskCompletedBox'; import './CalendarManager.scss'; import { SnappingManager } from './SnappingManager'; import { CalendarDate, DateValue } from '@internationalized/date'; -import { DocData } from '../../fields/DocSymbols'; // import 'react-date-range/dist/styles.css'; // import 'react-date-range/dist/theme/default.css'; @@ -119,7 +118,7 @@ export class CalendarManager extends ObservableReactComponent { // TODO: Make undoable private addToCalendar = () => { const docs = DocumentView.Selected().length < 2 ? [this.targetDoc] : DocumentView.Selected().map(docView => docView.Document); - const targetDoc = docs[0]?.[DocData]; + const targetDoc = docs[0]; if (targetDoc) { let calendar: Doc; @@ -230,7 +229,7 @@ export class CalendarManager extends ObservableReactComponent { @computed get calendarInterface() { const docs = DocumentView.Selected().length < 2 ? [this.targetDoc] : DocumentView.Selected().map(docView => docView.Document); - const targetDoc = docs[0]?.[DocData]; + const targetDoc = docs[0]; return (
!Doc.IsSystem(doc)); + // const strings = isFiltered.map(doc => StrCast(doc.title) + ' ' + (Doc.IsDataProto(doc) ? '(data)' : '(embedding)')); //Doc.MyDockedBtns.linearView_IsOpen && strings.sort().forEach((str, i) => console.log(i.toString() + ' ' + str)); rp.post(ClientUtils.prepend('/setCacheDocumentIds'), { diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 79a0cc602..a311f6436 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -49,7 +49,7 @@ export function DocComponent

() { * This is the unique data repository for a dcoument that stores the intrinsic document data */ @computed get dataDoc() { - return this.Document[DocData]; + return this._props.Document[DocData]; } } return Component; @@ -93,7 +93,7 @@ export function ViewBoxBaseComponent

() { * This is the unique data repository for a dcoument that stores the intrinsic document data */ @computed get dataDoc() { - return this.Document.isTemplateForField || this.Document.isTemplateDoc ? (this._props.TemplateDataDocument ?? this.Document[DocData]) : this.Document[DocData]; + return this._props.Document.isTemplateForField || this._props.Document.isTemplateDoc ? (this._props.TemplateDataDocument ?? this._props.Document[DocData]) : this._props.Document[DocData]; } /** @@ -151,7 +151,7 @@ export function ViewBoxAnnotatableComponent

() { * This is the unique data repository for a dcoument that stores the intrinsic document data */ @computed get dataDoc() { - return this.Document.isTemplateForField || this.Document.isTemplateDoc ? (this._props.TemplateDataDocument ?? this.Document[DocData]) : this.Document[DocData]; + return this._props.Document.isTemplateForField || this._props.Document.isTemplateDoc ? (this._props.TemplateDataDocument ?? this._props.Document[DocData]) : this._props.Document[DocData]; } /** @@ -225,8 +225,7 @@ export function ViewBoxAnnotatableComponent

() { if ([AclAugment, AclEdit, AclAdmin].includes(effectiveAcl)) { added.forEach(adoc => { adoc._dragOnlyWithinContainer = undefined; - if (annotationKey ?? this._annotationKeySuffix()) adoc[DocData].annotationOn = this.Document; - else adoc[DocData].annotationOn = undefined; + adoc.$annotationOn = (annotationKey ?? this._annotationKeySuffix()) ? this.Document : undefined; Doc.SetContainer(adoc, this.Document); inheritParentAcls(targetDataDoc, adoc, true); }); diff --git a/src/client/views/PropertiesDocContextSelector.tsx b/src/client/views/PropertiesDocContextSelector.tsx index f494ff16a..ee6486a9c 100644 --- a/src/client/views/PropertiesDocContextSelector.tsx +++ b/src/client/views/PropertiesDocContextSelector.tsx @@ -26,7 +26,7 @@ export class PropertiesDocContextSelector extends ObservableReactComponent embedding.embedContainer && embedding.embedContainer instanceof Doc).reduce((set, embedding) => set.add(Cast(embedding.embedContainer, Doc, null)), new Set()); diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index b95553c4e..7e9cd002b 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -181,7 +181,7 @@ export class PropertiesView extends ObservableReactComponent { const layoutDoc = this.selectedLayoutDoc; - if (layoutDoc && this.dataDoc) { + if (layoutDoc) { return Math.max( 70, Math.min( @@ -308,11 +308,7 @@ export class PropertiesView extends ObservableReactComponent data.split(':')[0]) .filter(data => !filterExlusions?.includes(data.split(':')[0])) .map(data => { - const key = data.split(':')[0]; + const key = '$'+data.split(':')[0]; const val = Field.Copy(this.allMetadata.get(key)); - target[DocData][key] = val; + target[key] = val; return { type: 'dashField', attrs: { fieldKey: key, docId: '', hideKey: false, hideValue: false, editable: true }, @@ -98,7 +97,7 @@ export class SidebarAnnos extends ObservableReactComponent { - const input = StrCast(doc[DocData].title); + const input = StrCast(doc.$title); if (imgQuizMode(img) == quizMode.SMART && input) { const questionText = 'Question: What was labeled in this image?'; const rubricText = ' Rubric: ' + StrCast(doc.quiz); @@ -275,8 +275,8 @@ export namespace styleProviderQuiz { function redo(img: ImageBox) { imgQuizBoxes(img).forEach(doc => { - doc[DocData].title = ''; - doc.backgroundColor = '#e4e4e4'; + doc.$title = ''; + doc.$backgroundColor = '#e4e4e4'; }); } diff --git a/src/client/views/TagsView.tsx b/src/client/views/TagsView.tsx index 93d6fb684..7d2a6be5e 100644 --- a/src/client/views/TagsView.tsx +++ b/src/client/views/TagsView.tsx @@ -72,7 +72,7 @@ export class TagItem extends ObservableReactComponent { const newTagCol = new Doc(); newTagCol.title = tag; newTagCol.collections = new List(); - newTagCol[DocData].docs = new List(); + newTagCol.$docs = new List(); Doc.ActiveDashboard && Doc.AddDocToList(Doc.ActiveDashboard, 'myTagCollections', newTagCol); return newTagCol; @@ -82,7 +82,7 @@ export class TagItem extends ObservableReactComponent { * @param tag tag string * @returns An array of documents that contain the tag. */ - public static allDocsWithTag = (tag: string) => DocListCast(TagItem.findTagCollectionDoc(tag)?.[DocData].docs); + public static allDocsWithTag = (tag: string) => DocListCast(TagItem.findTagCollectionDoc(tag)?.$docs); public static docHasTag = (doc: Doc, tag: string) => StrListCast(doc?.tags).includes(tag); /** @@ -95,11 +95,11 @@ export class TagItem extends ObservableReactComponent { // If the document is of type COLLECTION, make it a smart collection, otherwise, add the tag to the document. if (doc.type === DocumentType.COL && !doc.annotationOn) { - Doc.AddDocToList(tagCollection[DocData], 'collections', doc); + Doc.AddDocToList(tagCollection, 'collections', doc); // Iterate through the tag Doc collections and add a copy of the document to each collection - for (const cdoc of DocListCast(tagCollection[DocData].docs)) { - if (!DocListCast(doc[DocData].data).find(d => Doc.AreProtosEqual(d, cdoc))) { + for (const cdoc of DocListCast(tagCollection.$docs)) { + if (!DocListCast(doc.$data).find(d => Doc.AreProtosEqual(d, cdoc))) { const newEmbedding = Doc.MakeEmbedding(cdoc); Doc.AddDocToList(doc[DocData], 'data', newEmbedding); Doc.SetContainer(newEmbedding, doc); @@ -111,7 +111,7 @@ export class TagItem extends ObservableReactComponent { // Iterate through the tag document's collections and add a copy of the document to each collection for (const collection of DocListCast(tagCollection.collections)) { - if (!DocListCast(collection[DocData].data).find(d => Doc.AreProtosEqual(d, doc))) { + if (!DocListCast(collection.$data).find(d => Doc.AreProtosEqual(d, doc))) { const newEmbedding = Doc.MakeEmbedding(doc); Doc.AddDocToList(collection[DocData], 'data', newEmbedding); Doc.SetContainer(newEmbedding, collection); @@ -119,8 +119,8 @@ export class TagItem extends ObservableReactComponent { } } - if (!doc[DocData].tags) doc[DocData].tags = new List(); - const tagList = doc[DocData].tags as List; + if (!doc.$tags) doc.$tags = new List(); + const tagList = doc.$tags as List; if (!tagList.includes(tag)) tagList.push(tag); }; @@ -131,22 +131,22 @@ export class TagItem extends ObservableReactComponent { * @param tagDoc doc that collections the Docs with the tag */ public static removeTagFromDoc = (doc: Doc, tag: string, tagDoc?: Doc) => { - if (doc[DocData].tags) { + if (doc.$tags) { if (doc.type === DocumentType.COL) { tagDoc && Doc.RemoveDocFromList(tagDoc[DocData], 'collections', doc); for (const cur_doc of TagItem.allDocsWithTag(tag)) { - doc[DocData].data = new List(DocListCast(doc[DocData].data).filter(d => !Doc.AreProtosEqual(cur_doc, d))); + doc.$data = new List(DocListCast(doc.$data).filter(d => !Doc.AreProtosEqual(cur_doc, d))); } } else { tagDoc && Doc.RemoveDocFromList(tagDoc[DocData], 'docs', doc); for (const collection of DocListCast(tagDoc?.collections)) { - collection[DocData].data = new List(DocListCast(collection[DocData].data).filter(d => !Doc.AreProtosEqual(doc, d))); + collection.$data = new List(DocListCast(collection.$data).filter(d => !Doc.AreProtosEqual(doc, d))); } } } - doc[DocData].tags = new List(StrListCast(doc[DocData].tags).filter(label => label !== tag)); + doc.$tags = new List(StrListCast(doc.$tags).filter(label => label !== tag)); }; private _ref: React.RefObject; @@ -171,11 +171,10 @@ export class TagItem extends ObservableReactComponent { // Create a new collection and set up configurations. const newCollection = ((doc: Doc) => { - const docData = doc[DocData]; - docData.data = new List(newEmbeddings); - docData.title = this._props.tag; - docData.tags = new List([this._props.tag]); - docData.freeform_fitContentsToBox = true; + doc.$data = new List(newEmbeddings); + doc.$title = this._props.tag; + doc.$tags = new List([this._props.tag]); + doc.$freeform_fitContentsToBox = true; doc._freeform_panX = doc._freeform_panY = 0; doc._width = 900; doc._height = 900; diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index a45b37f43..12a131deb 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -5,7 +5,7 @@ import * as ReactDOM from 'react-dom/client'; import ResizeObserver from 'resize-observer-polyfill'; import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, DivHeight, DivWidth, incrementTitleCopy, returnTrue, UpdateIcon } from '../../../ClientUtils'; import { Doc, DocListCast, Field, Opt } from '../../../fields/Doc'; -import { AclAdmin, AclEdit, DocData } from '../../../fields/DocSymbols'; +import { AclAdmin, AclEdit } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { InkTool } from '../../../fields/InkField'; import { List } from '../../../fields/List'; @@ -481,7 +481,7 @@ export class CollectionDockingView extends CollectionSubView() { Array.from(cloned.map.entries()).forEach(entry => { json = json.replace(entry[0], entry[1][Id]); }); - cloned.clone[DocData].dockingConfig = json; + cloned.clone.$dockingConfig = json; return DashboardView.openDashboard(cloned.clone); } const matches = json.match(/"documentId":"[a-z0-9-]+"/g); @@ -495,7 +495,7 @@ export class CollectionDockingView extends CollectionSubView() { const newtab = origtabdocs.length ? Doc.MakeCopy(origtab, true, undefined, true) : Doc.MakeEmbedding(origtab); const newtabdocs = origtabdocs.map(origtabdoc => Doc.MakeEmbedding(origtabdoc)); if (newtabdocs.length) { - newtab[DocData].data = new List(newtabdocs); + newtab.$data = new List(newtabdocs); newtabdocs.forEach(ntab => Doc.SetContainer(ntab, newtab)); } json = json.replace(origtab[Id], newtab[Id]); diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx index 996626575..4fe73895e 100644 --- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx +++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx @@ -5,7 +5,6 @@ import * as React from 'react'; import { returnEmptyString, returnFalse, setupMoveUpEvents } from '../../../ClientUtils'; import { emptyFunction, numberRange } from '../../../Utils'; import { Doc } from '../../../fields/Doc'; -import { DocData } from '../../../fields/DocSymbols'; import { PastelSchemaPalette, SchemaHeaderField } from '../../../fields/SchemaHeaderField'; import { ScriptField } from '../../../fields/ScriptField'; import { Docs } from '../../documents/Documents'; @@ -164,7 +163,7 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent { - this.target[DocData].data = new List(source); + this.target.$data = new List(source); }, ''), initialize: emptyFunction, }; diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx index c499bd288..4650727eb 100644 --- a/src/client/views/collections/CollectionNoteTakingView.tsx +++ b/src/client/views/collections/CollectionNoteTakingView.tsx @@ -441,7 +441,7 @@ export class CollectionNoteTakingView extends CollectionSubView() { if ((e.ctrlKey || fieldProps.Document._createDocOnCR) && ['Enter'].includes(e.key)) { e.stopPropagation?.(); const newDoc = Doc.MakeCopy(fieldProps.Document, true); - newDoc[DocData].text = undefined; + newDoc.$text = undefined; DocumentView.SetSelectOnLoad(newDoc); return this.addDocument?.(newDoc); } diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx index 40b3f9ef2..df9b5a1eb 100644 --- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx +++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx @@ -157,7 +157,7 @@ export class CollectionNoteTakingViewColumn extends ObservableReactComponent { const colHdrData = Array.from(Cast(this._props.Document[this._props.fieldKey + '_columnHeaders'], listSpec(SchemaHeaderField), null)); if (this._props.headingObject) { - // this._props.docList.forEach(d => (d[DocData][this._props.pivotField] = undefined)); + // this._props.docList.forEach(d => (d['$'+this._props.pivotField] = undefined)); colHdrData.splice(colHdrData.indexOf(this._props.headingObject), 1); this._props.resizeColumns(colHdrData); } diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx index a7a9f2114..0836cce38 100644 --- a/src/client/views/collections/CollectionStackedTimeline.tsx +++ b/src/client/views/collections/CollectionStackedTimeline.tsx @@ -432,8 +432,8 @@ export class CollectionStackedTimeline extends CollectionSubView { - this._props.mark[DocData].title = ComputedField.MakeFunction( - `["${this._props.endTag}"] ? "#" + formatToTime(this["${this._props.startTag}"]) + "-" + formatToTime(this["${this._props.endTag}"]) : "#" + formatToTime(this["${this._props.startTag}"]` - ); + this._props.mark.$title = ComputedField.MakeFunction(`["${this._props.endTag}"] ? "#" + formatToTime(this["${this._props.startTag}"]) + "-" + formatToTime(this["${this._props.endTag}"]) : "#" + formatToTime(this["${this._props.startTag}"]`); }; // context menu contextMenuItems = () => { diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 392d85af3..9972fe03d 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -5,7 +5,6 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import { ClientUtils, DivHeight, returnNone, returnZero, setupMoveUpEvents, smoothScroll } from '../../../ClientUtils'; import { Doc, Opt } from '../../../fields/Doc'; -import { DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; import { listSpec } from '../../../fields/Schema'; @@ -316,11 +315,11 @@ export class CollectionStackingView extends CollectionSubView([]) : undefined; + newDoc['$' + Doc.LayoutFieldKey(newDoc)] = dataField === undefined || Cast(dataField, listSpec(Doc), null)?.length !== undefined ? new List([]) : undefined; if (layoutFieldKey !== 'layout' && fieldProps.Document[layoutFieldKey] instanceof Doc) { newDoc[layoutFieldKey] = fieldProps.Document[layoutFieldKey]; } - newDoc[DocData].text = undefined; + newDoc.$text = undefined; DocumentView.SetSelectOnLoad(newDoc); return this.addDocument?.(newDoc); } diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 655894e40..29caead5b 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -9,7 +9,7 @@ import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; import { listSpec } from '../../../fields/Schema'; import { ScriptField } from '../../../fields/ScriptField'; -import { BoolCast, Cast, DateCast, NumCast, ScriptCast, StrCast, toList } from '../../../fields/Types'; +import { BoolCast, Cast, DateCast, DocCast, NumCast, ScriptCast, StrCast, toList } from '../../../fields/Types'; import { WebField } from '../../../fields/URLField'; import { GetEffectiveAcl, TraceMobx } from '../../../fields/util'; import { GestureUtils } from '../../../pen-gestures/GestureUtils'; @@ -85,6 +85,9 @@ export function CollectionSubView() { constructor(props: X & SubCollectionViewProps) { super(props); makeObservable(this); + console.log(`propsTitle: ${this._props.Document.title} DocTitle: ${this.Document.title} LayoutTitle:${this.layoutDoc.title} DataTitle:${this.dataDoc.title}`); + console.log(`tempTitle: ${this._props.TemplateDataDocument?.title} LayouTResolve: ${DocCast(this.layoutDoc.resolvedDataDoc)?.title} propDocResolve: ${DocCast(this._props.Document.resolvedDataDoc)?.title}`); + console.log('Children:', this.childDocs, this.childLayoutPairs); } @observable _focusFilters: Opt = undefined; // childFilters that are overridden when previewing a link to an anchor which has childFilters set on it @@ -108,7 +111,12 @@ export function CollectionSubView() { } get dataDoc() { - return this._props.TemplateDataDocument instanceof Doc && this.Document.isTemplateForField ? Doc.GetProto(this._props.TemplateDataDocument) : this.Document.resolvedDataDoc ? this.Document : this.Document[DocData]; // if the layout document has a resolvedDataDoc, then we don't want to get its parent which would be the unexpanded template + console.log(this._props.Document.title + ' isTemplate: ' + this.layoutDoc.isTemplateForField); + return this._props.TemplateDataDocument instanceof Doc && this.layoutDoc.isTemplateForField // + ? this._props.TemplateDataDocument[DocData] + : this.layoutDoc.resolvedDataDoc + ? this._props.Document + : this.Document[DocData]; // if the layout document has a resolvedDataDoc, then we don't want to get its parent which would be the unexpanded template } get childContainerViewPath() { diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx index cc56a8ff9..2d2c0fce5 100644 --- a/src/client/views/collections/TabDocView.tsx +++ b/src/client/views/collections/TabDocView.tsx @@ -347,7 +347,7 @@ export class TabDocView extends ObservableReactComponent { undoable(() => { const target = e.currentTarget as unknown as { value: string }; titleEle.size = target?.value.length + 3; - doc[DocData].title = target?.value ?? ''; + doc.$title = target?.value ?? ''; }, 'edit tab title')(); }; diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 6208905fe..d6a19e88e 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -372,9 +372,8 @@ export class TreeView extends ObservableReactComponent { _width: 1000, _height: 10, }); - const bulletData = bullet[DocData]; - bulletData.title = ComputedField.MakeFunction('this.text?.Text'); - bulletData.data = new List([]); + bullet.$title = ComputedField.MakeFunction('this.text?.Text'); + bullet.$data = new List([]); DocumentView.addViewRenderedCb(bullet, dv => dv.ComponentView?.setFocus?.()); return bullet; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx index 8b9a3e0ec..35c6d30fe 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoUI.tsx @@ -1,16 +1,15 @@ import { makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { Doc, DocListCast, FieldType, FieldResult } from '../../../../fields/Doc'; +import { Doc, DocListCast, FieldResult, FieldType } from '../../../../fields/Doc'; import { InkTool } from '../../../../fields/InkField'; import { StrCast } from '../../../../fields/Types'; import { ObservableReactComponent } from '../../ObservableReactComponent'; import { DocButtonState, DocumentLinksButton } from '../../nodes/DocumentLinksButton'; import { TopBar } from '../../topbar/TopBar'; import { CollectionFreeFormInfoState, InfoState, StateEntryFunc, infoState } from './CollectionFreeFormInfoState'; -import './CollectionFreeFormView.scss'; -import { DocData } from '../../../../fields/DocSymbols'; import { CollectionFreeFormView } from './CollectionFreeFormView'; +import './CollectionFreeFormView.scss'; export interface CollectionFreeFormInfoUIProps { Document: Doc; @@ -41,7 +40,7 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent {this._currState = val;}); } // prettier-ignore componentWillUnmount(): void { - this._props.Document[DocData].backgroundColor = this._originalbackground; + this._props.Document.$backgroundColor = this._originalbackground; } setCurrState = (state: infoState) => { @@ -52,9 +51,9 @@ export class CollectionFreeFormInfoUI extends ObservableReactComponent { - this._originalbackground = StrCast(this._props.Document[DocData].backgroundColor); + this._originalbackground = StrCast(this._props.Document.$backgroundColor); // state entry functions - // const setBackground = (colour: string) => () => {this._props.Document[DocData].backgroundColor = colour;} // prettier-ignore + // const setBackground = (colour: string) => () => {this._props.Document.$backgroundColor = colour;} // prettier-ignore // const setOpacity = (opacity: number) => () => {this._props.LayoutDoc.opacity = opacity;} // prettier-ignore // arc transition trigger conditions const firstDoc = () => (this._props.childDocs().length ? this._props.childDocs()[0] : undefined); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 89aa53c35..6030e146c 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -561,7 +561,7 @@ export class CollectionFreeFormView extends CollectionSubView { - inkDoc[DocData][field] = stroke.dataDoc[field]; + inkDoc['$' + field] = stroke.dataDoc[field]; }); this.addDocument(inkDoc); }); @@ -1260,15 +1260,14 @@ export class CollectionFreeFormView extends CollectionSubView { - const docData = doc[DocData]; - docData.title = opts.text; - docData._width = opts.size; - docData.ai_drawing_input = opts.text; - docData.ai_drawing_complexity = opts.complexity; - docData.ai_drawing_colored = opts.autoColor; - docData.ai_drawing_size = opts.size; - docData.ai_drawing_data = gptRes; - docData.ai = 'gpt'; + doc.$title = opts.text; + doc.$width = opts.size; + doc.$ai_drawing_input = opts.text; + doc.$ai_drawing_complexity = opts.complexity; + doc.$ai_drawing_colored = opts.autoColor; + doc.$ai_drawing_size = opts.size; + doc.$ai_drawing_data = gptRes; + doc.$ai = 'gpt'; this._drawingContainer = doc; if (x !== undefined && y !== undefined) { [doc.x, doc.y] = this.screenToFreeformContentsXf.transformPoint(x, y); @@ -1493,7 +1492,7 @@ export class CollectionFreeFormView extends CollectionSubView { const textDoc = DocCast(fieldProps.Document.rootDocument, fieldProps.Document); const newDoc = Doc.MakeCopy(textDoc, true); - newDoc[DocData][Doc.LayoutFieldKey(newDoc, fieldProps.LayoutTemplateString)] = undefined; // the copy should not copy the text contents of it source, just the render style + newDoc['$' + Doc.LayoutFieldKey(newDoc, fieldProps.LayoutTemplateString)] = undefined; // the copy should not copy the text contents of it source, just the render style newDoc.x = NumCast(textDoc.x) + (below ? 0 : NumCast(textDoc._width) + 10); newDoc.y = NumCast(textDoc.y) + (below ? NumCast(textDoc._height) + 10 : 0); DocumentView.SetSelectOnLoad(newDoc); @@ -1686,7 +1685,7 @@ export class CollectionFreeFormView extends CollectionSubView (this.Document.isTemplateDoc || this.Document.isTemplateForField ? false : !this._renderCutoffData.get(doc[Id] + ''))); + renderCutoffProvider = computedFn((doc: Doc) => (this._props.Document.isTemplateDoc || this._props.Document.isTemplateForField ? false : !this._renderCutoffData.get(doc[Id] + ''))); doEngineLayout( poolData: Map, diff --git a/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx b/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx index b9f8b13a7..b40189d76 100644 --- a/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx +++ b/src/client/views/collections/collectionFreeForm/FaceCollectionBox.tsx @@ -108,7 +108,7 @@ export class UniqueFaceBox extends ViewBoxBaseComponent() { if (faceAnno) { faceAnno.face && FaceRecognitionHandler.UniqueFaceRemoveFaceImage(faceAnno, DocCast(faceAnno.face)); FaceRecognitionHandler.UniqueFaceAddFaceImage(faceAnno, this.Document); - faceAnno[DocData].face = this.Document[DocData]; + faceAnno.$face = this.Document[DocData]; } } }); @@ -118,7 +118,7 @@ export class UniqueFaceBox extends ViewBoxBaseComponent() { const imgDoc = faceAnno; faceAnno.face && FaceRecognitionHandler.UniqueFaceRemoveFaceImage(imgDoc, DocCast(faceAnno.face)); FaceRecognitionHandler.UniqueFaceAddFaceImage(faceAnno, this.Document); - faceAnno[DocData].face = this.Document[DocData]; + faceAnno.$face = this.Document[DocData]; }); e.stopPropagation(); return true; diff --git a/src/client/views/collections/collectionFreeForm/ImageLabelBox.tsx b/src/client/views/collections/collectionFreeForm/ImageLabelBox.tsx index a3d9641da..c983d7c26 100644 --- a/src/client/views/collections/collectionFreeForm/ImageLabelBox.tsx +++ b/src/client/views/collections/collectionFreeForm/ImageLabelBox.tsx @@ -9,7 +9,6 @@ import React from 'react'; import { imageUrlToBase64 } from '../../../../ClientUtils'; import { Utils, numberRange } from '../../../../Utils'; import { Doc, NumListCast, Opt } from '../../../../fields/Doc'; -import { DocData } from '../../../../fields/DocSymbols'; import { List } from '../../../../fields/List'; import { ImageCast } from '../../../../fields/Types'; import { gptGetEmbedding, gptImageLabel } from '../../../apis/gpt/GPT'; @@ -165,7 +164,7 @@ export class ImageLabelBox extends ViewBoxBaseComponent() { // Converts the images into a Base64 format, afterwhich the information is sent to GPT to label them. const imageInfos = this._selectedImages.map(async doc => { - if (!doc[DocData].tags_chat) { + if (!doc.$tags_chat) { const [name, type] = ImageCast(doc[Doc.LayoutFieldKey(doc)]).url.href.split('.'); return imageUrlToBase64(`${name}_o.${type}`).then(hrefBase64 => !hrefBase64 ? undefined : @@ -176,7 +175,7 @@ export class ImageLabelBox extends ViewBoxBaseComponent() { (await Promise.all(imageInfos)).forEach(imageInfo => { if (imageInfo) { - imageInfo.doc[DocData].tags_chat = (imageInfo.doc[DocData].tags_chat as List) ?? new List(); + imageInfo.doc.$tags_chat = (imageInfo.doc.$tags_chat as List) ?? new List(); const labels = imageInfo.labels.split('\n'); labels.forEach(label => { @@ -186,7 +185,7 @@ export class ImageLabelBox extends ViewBoxBaseComponent() { .replace(/^\d+\.\s*|-|f\*/, '') .replace(/^#/, '') .trim(); - (imageInfo.doc[DocData].tags_chat as List).push(hashLabel); + (imageInfo.doc.$tags_chat as List).push(hashLabel); }); } }); @@ -201,10 +200,10 @@ export class ImageLabelBox extends ViewBoxBaseComponent() { this.startLoading(); for (const doc of this._selectedImages) { - for (let index = 0; index < (doc[DocData].tags_chat as List).length; index++) { - const label = (doc[DocData].tags_chat as List)[index]; + for (let index = 0; index < (doc.$tags_chat as List).length; index++) { + const label = (doc.$tags_chat as List)[index]; const embedding = await gptGetEmbedding(label); - doc[DocData][`tags_embedding_${index + 1}`] = new List(embedding); + doc[`$tags_embedding_${index + 1}`] = new List(embedding); } } @@ -215,13 +214,13 @@ export class ImageLabelBox extends ViewBoxBaseComponent() { // For each image, loop through the labels, and calculate similarity. Associate it with the // most similar one. this._selectedImages.forEach(doc => { - const embedLists = numberRange((doc[DocData].tags_chat as List).length).map(n => Array.from(NumListCast(doc[DocData][`tags_embedding_${n + 1}`]))); + const embedLists = numberRange((doc.$tags_chat as List).length).map(n => Array.from(NumListCast(doc[`$tags_embedding_${n + 1}`]))); const bestEmbedScore = (embedding: Opt) => Math.max(...embedLists.map(l => (embedding && similarity(Array.from(embedding), l)!) || 0)); const {label: mostSimilarLabelCollect} = this._labelGroups.map(label => ({ label, similarityScore: bestEmbedScore(labelToEmbedding.get(label)) })) .reduce((prev, cur) => cur.similarityScore < 0.3 || cur.similarityScore <= prev.similarityScore ? prev: cur, { label: '', similarityScore: 0, }); // prettier-ignore - doc[DocData].data_label = mostSimilarLabelCollect; // The label most similar to the image's contents. + doc.$data_label = mostSimilarLabelCollect; // The label most similar to the image's contents. }); this.endLoading(); @@ -322,7 +321,7 @@ export class ImageLabelBox extends ViewBoxBaseComponent() { await DocumentView.showDocument(doc, { willZoomCentered: true }); }}>

this._props.addDocTab(doc, OpenWhere.addRightKeyvalue)}> - {(doc[DocData].tags_chat as List).map(label => { + {(doc.$tags_chat as List).map(label => { return (
{label} diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index ad52db496..e3f4c6605 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -165,7 +165,7 @@ export class MarqueeView extends ObservableReactComponent { - this._props.Document[DocData].icon = new ImageField(returnedfilename); + this._props.Document.$icon = new ImageField(returnedfilename); }); }) ); @@ -371,10 +371,9 @@ export class MarqueeView extends ObservableReactComponent { - const docData = doc[DocData]; - docData.data = new List(selected); - docData.isGroup = makeGroup; - docData.title = makeGroup ? 'grouping' : 'nested freeform'; + doc.$data = new List(selected); + doc.$isGroup = makeGroup; + doc.$title = makeGroup ? 'grouping' : 'nested freeform'; doc._freeform_panX = doc._freeform_panY = 0; return doc; })(Doc.MakeCopy(Doc.UserDoc().emptyCollection as Doc, true)); @@ -462,9 +461,9 @@ export class MarqueeView extends ObservableReactComponent { - doc[DocData].borderColor = color; - }); + else selected.forEach(doc => (doc.$borderColor = color)); } return ''; }); @@ -114,7 +108,7 @@ ScriptingGlobals.add(function setBorderColor(color?: string, checkResult?: boole ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: boolean) { const selectedViews = DocumentView.Selected(); const selectedDoc = selectedViews.lastElement()?.Document; - const defaultFill = selectedDoc?._layout_isSvg ? () => StrCast(selectedDoc[DocData].fillColor) : !Doc.ActiveTool || Doc.ActiveTool === InkTool.None ? () => StrCast(Doc.UserDoc().textBackgroundColor, 'transparent') : () => ActiveInkFillColor(); + const defaultFill = selectedDoc?._layout_isSvg ? () => StrCast(selectedDoc.$fillColor) : !Doc.ActiveTool || Doc.ActiveTool === InkTool.None ? () => StrCast(Doc.UserDoc().textBackgroundColor, 'transparent') : () => ActiveInkFillColor(); const setDefaultFill = !Doc.ActiveTool || Doc.ActiveTool === InkTool.None ? (c: string) => { Doc.UserDoc().textBackgroundColor = c; }: SetActiveInkFillColor; // prettier-ignore if (Doc.ActiveTool !== InkTool.None && !selectedViews.lastElement()?.Document._layout_isSvg) { if (checkResult) return defaultFill(); @@ -149,10 +143,7 @@ ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: b return selected.lastElement()?._backgroundColor ?? defaultFill(); } if (!selected.length) setDefaultFill(color ?? 'transparent'); - else - selected.forEach(doc => { - doc[DocData][doc._layout_isSvg ? 'fillColor' : 'backgroundColor'] = color; - }); + else selected.forEach(doc => (doc[doc._layout_isSvg ? '$fillColor' : '$backgroundColor'] = color)); } return ''; }); @@ -170,7 +161,7 @@ ScriptingGlobals.add(function setHeaderColor(color?: string, checkResult?: boole } if (DocumentView.Selected().length) { DocumentView.SelectedDocs().forEach(doc => { - doc[DocData].layout_headingColor = color === 'transparent' ? undefined : color; + doc.$layout_headingColor = color === 'transparent' ? undefined : color; doc.layout_showTitle = color === 'transparent' ? undefined : StrCast(doc.layout_showTitle, 'title'); }); } else { @@ -470,23 +461,23 @@ ScriptingGlobals.add(function setInkProperty(option: InkProperty, value: string // prettier-ignore const map: Map number|boolean|string|undefined; setInk: (doc: Doc) => void; setMode: () => void }> = new Map([ [InkProperty.Mask, { - checkResult: () => ((selected?._layout_isSvg ? BoolCast(selected[DocData].stroke_isInkMask) : ActiveIsInkMask())), - setInk: (doc: Doc) => { doc[DocData].stroke_isInkMask = !doc.stroke_isInkMask; }, + checkResult: () => ((selected?._layout_isSvg ? BoolCast(selected.$stroke_isInkMask) : ActiveIsInkMask())), + setInk: (doc: Doc) => { doc.$stroke_isInkMask = !doc.stroke_isInkMask; }, setMode: () => SetActiveIsInkMask(value ? true : false) }], [InkProperty.Labels, { - checkResult: () => ((selected?._layout_isSvg ? BoolCast(selected[DocData].stroke_showLabel) : !ActiveHideTextLabels())), - setInk: (doc: Doc) => { doc[DocData].stroke_showLabel = value; }, + checkResult: () => ((selected?._layout_isSvg ? BoolCast(selected.$stroke_showLabel) : !ActiveHideTextLabels())), + setInk: (doc: Doc) => { doc.$stroke_showLabel = value; }, setMode: () => SetactiveHideTextLabels(value? false : true), }], [ InkProperty.StrokeWidth, { - checkResult: () => (selected?._layout_isSvg ? NumCast(selected[DocData].stroke_width, 1) : ActiveInkWidth()), - setInk: (doc: Doc) => { doc[DocData].stroke_width = NumCast(value); }, + checkResult: () => (selected?._layout_isSvg ? NumCast(selected.$stroke_width, 1) : ActiveInkWidth()), + setInk: (doc: Doc) => { doc.$stroke_width = NumCast(value); }, setMode: () => SetActiveInkWidth(value.toString()), }], [InkProperty.StrokeColor, { - checkResult: () => (selected?._layout_isSvg? StrCast(selected[DocData].color) : ActiveInkColor()), - setInk: (doc: Doc) => { doc[DocData].color = String(value); }, + checkResult: () => (selected?._layout_isSvg? StrCast(selected.$color) : ActiveInkColor()), + setInk: (doc: Doc) => { doc.$color = String(value); }, setMode: () => SetActiveInkColor(StrCast(value)) }], [ InkProperty.EraserWidth, { diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx index 25e76e2a6..e0d59cc9d 100644 --- a/src/client/views/nodes/AudioBox.tsx +++ b/src/client/views/nodes/AudioBox.tsx @@ -296,7 +296,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent() { 'Content-Type': 'application/json', }, }); - this.Document[DocData].phoneticTranscription = response.data['transcription']; + this.Document.$phoneticTranscription = response.data['transcription']; }; // context menu diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index c0c6db4d3..992fbba66 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -80,8 +80,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent() const front = Docs.Create.CenteredTextCreator('question', question, {}, img); const back = Docs.Create.CenteredTextCreator('answer', answer, {}); if (useDoc) { - useDoc[DocData][frontKey] = front; - useDoc[DocData][backKey] = back; + useDoc['$' + frontKey] = front; + useDoc['$' + backKey] = back; return useDoc; } return Docs.Create.FlashcardDocument(title, front, back, { _width: 300, _height: 300 }); @@ -475,7 +475,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent() axios .post( 'http://localhost:105/recognize/', // - { file: DocCast(this.Document.audio)[DocData].url }, + { file: DocCast(this.Document.audio).$url }, { headers: { 'Content-Type': 'application/json' } } ) .then(response => { @@ -520,7 +520,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent() action(resp => { switch (resp && callType) { case GPTCallType.CHATCARD: - DocCast(this.dataDoc[this.backKey])[DocData].text = resp; + DocCast(this.dataDoc[this.backKey]).$text = resp; break; case GPTCallType.QUIZDOC: this._renderSide = this.backKey; @@ -618,7 +618,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent() const hrefBase64 = await imageUrlToBase64(u); const response = await gptImageLabel(hrefBase64, 'Answer the following question as a short flashcard response. Do not include a label.' + (this.dataDoc.text as RichTextField)?.Text); - DocCast(this.dataDoc[this.backKey])[DocData].text = response; + DocCast(this.dataDoc[this.backKey]).$text = response; } catch (error) { console.log('Error', error); } diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx index 7ef4bca6b..b31a0ec1e 100644 --- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx +++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx @@ -160,8 +160,8 @@ export class TableBox extends ObservableReactComponent { DragManager.StartAnchorAnnoDrag(moveEv.target instanceof HTMLElement ? [moveEv.target] : [], new DragManager.AnchorAnnoDragData(this._props.docView()!, sourceAnchorCreator, targetCreator), downX, downY, { dragComplete: completeEv => { if (!completeEv.aborted && completeEv.annoDragData && completeEv.annoDragData.linkSourceDoc && completeEv.annoDragData.dropDocument && completeEv.linkDocument) { - completeEv.linkDocument[DocData].link_matchEmbeddings = true; - completeEv.linkDocument[DocData].stroke_startMarker = true; + completeEv.linkDocument.$link_matchEmbeddings = true; + completeEv.linkDocument.$stroke_startMarker = true; this._props.docView?.()?._props.addDocument?.(completeEv.linkDocument); } }, diff --git a/src/client/views/nodes/DiagramBox.tsx b/src/client/views/nodes/DiagramBox.tsx index a49c69be3..3b666bad5 100644 --- a/src/client/views/nodes/DiagramBox.tsx +++ b/src/client/views/nodes/DiagramBox.tsx @@ -3,7 +3,6 @@ import { action, computed, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast } from '../../../fields/Doc'; -import { DocData } from '../../../fields/DocSymbols'; import { RichTextField } from '../../../fields/RichTextField'; import { Cast, DocCast, NumCast, RTFCast, StrCast } from '../../../fields/Types'; import { Gestures } from '../../../pen-gestures/GestureTypes'; @@ -46,7 +45,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent() { @observable _errorMessage = ''; @computed get mermaidcode() { - return StrCast(this.Document[DocData].text, RTFCast(this.Document[DocData].text)?.Text); + return StrCast(this.Document.$text, RTFCast(this.Document.$text)?.Text); } componentDidMount() { @@ -89,7 +88,7 @@ export class DiagramBox extends ViewBoxAnnotatableComponent() { }; setMermaidCode = undoable((res: string) => { - this.Document[DocData].text = new RichTextField( + this.Document.$text = new RichTextField( JSON.stringify({ doc: { type: 'doc', diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 46bd076d4..e9353b001 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -9,7 +9,7 @@ import { Fade, JackInTheBox } from 'react-awesome-reveal'; import { ClientUtils, DivWidth, isTargetChildOf as isParentOf, lightOrDark, returnFalse, returnVal, simMouseEvent, simulateMouseClick } from '../../../ClientUtils'; import { Utils, emptyFunction } from '../../../Utils'; import { Doc, DocListCast, Field, FieldType, Opt, StrListCast } from '../../../fields/Doc'; -import { AclAdmin, AclEdit, AclPrivate, Animation, AudioPlay, DocData, DocViews } from '../../../fields/DocSymbols'; +import { AclAdmin, AclEdit, AclPrivate, Animation, AudioPlay, DocViews } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { InkTool } from '../../../fields/InkField'; import { List } from '../../../fields/List'; @@ -40,6 +40,7 @@ import { FieldsDropdown } from '../FieldsDropdown'; import { ObserverJsxParser } from '../ObservableReactComponent'; import { PinProps } from '../PinFuncs'; import { StyleProp } from '../StyleProp'; +import { TagsView } from '../TagsView'; import { ViewBoxInterface } from '../ViewBoxInterface'; import { GroupActive } from './CollectionFreeFormDocumentView'; import { DocumentContentsView } from './DocumentContentsView'; @@ -52,7 +53,6 @@ import { FormattedTextBox } from './formattedText/FormattedTextBox'; import { PresEffect, PresEffectDirection } from './trails/PresEnums'; import SpringAnimation from './trails/SlideEffect'; import { SpringType, springMappings } from './trails/SpringUtils'; -import { TagsView } from '../TagsView'; export interface DocumentViewProps extends FieldViewSharedProps { hideDecorations?: boolean; // whether to suppress all DocumentDecorations when doc is selected @@ -426,7 +426,7 @@ export class DocumentViewInternal extends DocComponent { this.Document.ignoreClick = false; - this.Document.onClick = this.Document[DocData].onClick = undefined; + this.Document.onClick = this.Document.$onClick = undefined; }, 'default on click'); deleteClicked = undoable(() => this._props.removeDocument?.(this.Document), 'delete doc'); @@ -758,7 +758,7 @@ export class DocumentViewInternal extends DocComponent ')[1]; const matchedTags = Array.from(SearchUtil.SearchCollection(Doc.MyFilesystem, tag, false, ['tags']).keys()); - const collectionDocs = DocListCast(collection[DocData].data).concat(collection); + const collectionDocs = DocListCast(collection.$data).concat(collection); let wid = 100; let created = false; const matchedDocs = matchedTags @@ -1749,6 +1749,6 @@ ScriptingGlobals.add(function updateTagsCollection(collection: Doc) { return aset; }, new Set()); - created && (collection[DocData].data = new List(Array.from(matchedDocs))); + created && (collection.$data = new List(Array.from(matchedDocs))); return true; }); diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 5b06e9fc5..5d9718760 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -284,10 +284,9 @@ export class ImageBox extends ViewBoxAnnotatableComponent() { crop = (region: Doc | undefined, addCrop?: boolean) => { if (!region) return undefined; const cropping = Doc.MakeCopy(region, true); - const regionData = region[DocData]; - regionData.lockedPosition = true; - regionData.title = 'region:' + this.Document.title; - regionData.followLinkToggle = true; + region.$lockedPosition = true; + region.$title = 'region:' + this.Document.title; + region.$followLinkToggle = true; this.addDocument(region); const anchx = NumCast(cropping.x); const anchy = NumCast(cropping.y); @@ -300,24 +299,23 @@ export class ImageBox extends ViewBoxAnnotatableComponent() { cropping._width = anchw * (this._props.NativeDimScaling?.() || 1); cropping._height = anchh * (this._props.NativeDimScaling?.() || 1); cropping.onClick = undefined; - const croppingProto = cropping[DocData]; - croppingProto.annotationOn = undefined; - croppingProto.isDataDoc = true; - croppingProto.backgroundColor = undefined; - croppingProto.proto = Cast(this.Document.proto, Doc, null)?.proto; // set proto of cropping's data doc to be IMAGE_PROTO - croppingProto.type = DocumentType.IMG; - croppingProto.layout = ImageBox.LayoutString('data'); - croppingProto.data = ObjectField.MakeCopy(this.dataDoc[this.fieldKey] as ObjectField); - croppingProto.data_nativeWidth = anchw; - croppingProto.data_nativeHeight = anchh; - croppingProto.freeform_scale = viewScale; - croppingProto.freeform_panX = anchx / viewScale; - croppingProto.freeform_panY = anchy / viewScale; - croppingProto.freeform_scale_min = viewScale; - croppingProto.freeform_panX_min = anchx / viewScale; - croppingProto.freeform_panX_max = anchw / viewScale; - croppingProto.freeform_panY_min = anchy / viewScale; - croppingProto.freeform_panY_max = anchh / viewScale; + cropping.$annotationOn = undefined; + cropping.$isDataDoc = true; + cropping.$backgroundColor = undefined; + cropping.$proto = Cast(this.Document.proto, Doc, null)?.proto; // set proto of cropping's data doc to be IMAGE_PROTO + cropping.$type = DocumentType.IMG; + cropping.$layout = ImageBox.LayoutString('data'); + cropping.$data = ObjectField.MakeCopy(this.dataDoc[this.fieldKey] as ObjectField); + cropping.$data_nativeWidth = anchw; + cropping.$data_nativeHeight = anchh; + cropping.$freeform_scale = viewScale; + cropping.$reeform_panX = anchx / viewScale; + cropping.$freeform_panY = anchy / viewScale; + cropping.$freeform_scale_min = viewScale; + cropping.$freeform_panX_min = anchx / viewScale; + cropping.$freeform_panX_max = anchw / viewScale; + cropping.$freeform_panY_min = anchy / viewScale; + cropping.$freeform_panY_max = anchh / viewScale; if (addCrop) { DocUtils.MakeLink(region, cropping, { link_relationship: 'cropped image' }); cropping.x = NumCast(this.Document.x) + NumCast(this.layoutDoc._width); diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx index 9795febbe..32c9efbd9 100644 --- a/src/client/views/nodes/KeyValueBox.tsx +++ b/src/client/views/nodes/KeyValueBox.tsx @@ -105,7 +105,7 @@ export class KeyValueBox extends ViewBoxBaseComponent() { if (setResult) setResult?.(value); else target[key] = field; }; - const res = script.run({ this: Doc.Layout(doc), _setCacheResult_ }, console.log); + const res = script.run({ this: doc, _setCacheResult_ }, console.log); if (!res.success) { if (key) target[key] = script.originalScript; return false; diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx index d5dc256d9..8bf65b637 100644 --- a/src/client/views/nodes/LinkBox.tsx +++ b/src/client/views/nodes/LinkBox.tsx @@ -252,7 +252,7 @@ export class LinkBox extends ViewBoxBaseComponent() { fontSize={fontSize} GetValue={() => linkDesc} SetValue={action(val => { - this.Document[DocData].link_description = val; + this.Document.$link_description = val; return true; })} /> @@ -262,8 +262,8 @@ export class LinkBox extends ViewBoxBaseComponent() { background={color} color={fontColor || lightOrDark(DashColor(color).fade(0.5).toString())} type={Type.PRIM} - val={StrCast(this.Document[DocData].link_description)} - setVal={action(val => (this.Document[DocData].link_description = val))} + val={StrCast(this.Document.$link_description)} + setVal={action(val => (this.Document.$link_description = val))} fillWidth /> */}
diff --git a/src/client/views/nodes/LinkDescriptionPopup.tsx b/src/client/views/nodes/LinkDescriptionPopup.tsx index ff95f8547..6bec9c53d 100644 --- a/src/client/views/nodes/LinkDescriptionPopup.tsx +++ b/src/client/views/nodes/LinkDescriptionPopup.tsx @@ -1,7 +1,6 @@ import { action, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { DocData } from '../../../fields/DocSymbols'; import { StrCast } from '../../../fields/Types'; import { LinkManager } from '../../util/LinkManager'; import './LinkDescriptionPopup.scss'; @@ -48,7 +47,7 @@ export class LinkDescriptionPopup extends React.Component<{}> { onDismiss = (add: boolean) => { this.display = false; if (add) { - LinkManager.Instance.currentLink && (LinkManager.Instance.currentLink[DocData].link_description = this.description); + LinkManager.Instance.currentLink && (LinkManager.Instance.currentLink.$link_description = this.description); } this.description = ''; }; diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 06b75e243..1f72206fc 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -129,15 +129,14 @@ export class PDFBox extends ViewBoxAnnotatableComponent() { cropping._width = anchw; cropping._height = anchh; cropping.onClick = undefined; - const croppingProto = cropping[DocData]; - croppingProto.annotationOn = undefined; - croppingProto.isDataDoc = true; - croppingProto.proto = Cast(this.Document.proto, Doc, null)?.proto; // set proto of cropping's data doc to be IMAGE_PROTO - croppingProto.type = DocumentType.IMG; - croppingProto.layout = ImageBox.LayoutString('data'); - croppingProto.data = new ImageField(ClientUtils.CorsProxy('http://www.cs.brown.edu/~bcz/noImage.png')); - croppingProto.data_nativeWidth = anchw; - croppingProto.data_nativeHeight = anchh; + cropping.$annotationOn = undefined; + cropping.$isDataDoc = true; + cropping.$proto = Cast(this.Document.proto, Doc, null)?.proto; // set proto of cropping's data doc to be IMAGE_PROTO + cropping.$type = DocumentType.IMG; + cropping.$layout = ImageBox.LayoutString('data'); + cropping.$data = new ImageField(ClientUtils.CorsProxy('http://www.cs.brown.edu/~bcz/noImage.png')); + cropping.$data_nativeWidth = anchw; + cropping.$data_nativeHeight = anchh; if (addCrop) { DocUtils.MakeLink(region, cropping, { link_relationship: 'cropped image' }); } diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx index 7ba313e92..53783e8a3 100644 --- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx +++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx @@ -3,7 +3,6 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import { DateField } from '../../../../fields/DateField'; import { Doc, DocListCast } from '../../../../fields/Doc'; -import { DocData } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; import { List } from '../../../../fields/List'; import { BoolCast, DocCast } from '../../../../fields/Types'; @@ -99,7 +98,7 @@ export class RecordingBox extends ViewBoxBaseComponent() { }); screengrabber.overlayX = 70; // was -400 screengrabber.overlayY = 590; // was 0 - screengrabber[DocData][Doc.LayoutFieldKey(screengrabber) + '_trackScreen'] = true; + screengrabber['$' + Doc.LayoutFieldKey(screengrabber) + '_trackScreen'] = true; Doc.AddToMyOverlay(screengrabber); // just adds doc to overlay DocumentView.addViewRenderedCb(screengrabber, docView => { RecordingBox.screengrabber = docView.ComponentView as RecordingBox; diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 9adee53e8..fa099178c 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -331,7 +331,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent() { Doc.SetNativeHeight(imageSnapshot[DocData], Doc.NativeHeight(this.layoutDoc)); this._props.addDocument?.(imageSnapshot); DocUtils.MakeLink(imageSnapshot, this.getAnchor(true), { link_relationship: 'video snapshot' }); - // link && (DocCast(link.link_anchor_2)[DocData].timecodeToHide = NumCast(DocCast(link.link_anchor_2).timecodeToShow) + 3); // do we need to set an end time? should default to +0.1 + // link && (DocCast(link.link_anchor_2).$timecodeToHide = NumCast(DocCast(link.link_anchor_2).timecodeToShow) + 3); // do we need to set an end time? should default to +0.1 setTimeout(() => downX !== undefined && downY !== undefined && DocumentView.getFirstDocumentView(imageSnapshot)?.startDragging(downX, downY, dropActionType.move, true)); }; @@ -918,11 +918,10 @@ export class VideoBox extends ViewBoxAnnotatableComponent() { crop = (region: Doc | undefined, addCrop?: boolean) => { if (!region) return undefined; const cropping = Doc.MakeCopy(region, true); - const regionData = region[DocData]; - regionData.backgroundColor = 'transparent'; - regionData.lockedPosition = true; - regionData.title = 'region:' + this.Document.title; - regionData.followLinkToggle = true; + region.$backgroundColor = 'transparent'; + region.$lockedPosition = true; + region.$title = 'region:' + this.Document.title; + region.$followLinkToggle = true; region._timecodeToHide = NumCast(region._timecodeToShow) + 0.0001; this.addDocument(region); const anchx = NumCast(cropping.x); @@ -938,25 +937,24 @@ export class VideoBox extends ViewBoxAnnotatableComponent() { cropping.timecodeToHide = undefined; cropping.timecodeToShow = undefined; cropping.onClick = undefined; - const croppingProto = cropping[DocData]; - croppingProto.annotationOn = undefined; - croppingProto.isDataDoc = true; - croppingProto.proto = Cast(this.Document.proto, Doc, null)?.proto; // set proto of cropping's data doc to be IMAGE_PROTO - croppingProto.type = DocumentType.VID; - croppingProto.layout = VideoBox.LayoutString('data'); - croppingProto.data = ObjectField.MakeCopy(this.dataDoc[this.fieldKey] as ObjectField); - croppingProto.data_nativeWidth = anchw; - croppingProto.data_nativeHeight = anchh; - croppingProto.videoCrop = true; - croppingProto.layout_currentTimecode = this.layoutDoc._layout_currentTimecode; - croppingProto.freeform_scale = viewScale; - croppingProto.freeform_scale_min = viewScale; - croppingProto.freeform_ = anchx / viewScale; - croppingProto.freeform_panY = anchy / viewScale; - croppingProto.freeform_panX_min = anchx / viewScale; - croppingProto.freeform_panX_max = anchw / viewScale; - croppingProto.freeform_panY_min = anchy / viewScale; - croppingProto.freeform_panY_max = anchh / viewScale; + cropping.$annotationOn = undefined; + cropping.$isDataDoc = true; + cropping.$proto = Cast(this.Document.proto, Doc, null)?.proto; // set proto of cropping's data doc to be IMAGE_PROTO + cropping.$type = DocumentType.VID; + cropping.$layout = VideoBox.LayoutString('data'); + cropping.$data = ObjectField.MakeCopy(this.dataDoc[this.fieldKey] as ObjectField); + cropping.$data_nativeWidth = anchw; + cropping.$data_nativeHeight = anchh; + cropping.$videoCrop = true; + cropping.$layout_currentTimecode = this.layoutDoc._layout_currentTimecode; + cropping.$freeform_scale = viewScale; + cropping.$freeform_scale_min = viewScale; + cropping.$freeform_ = anchx / viewScale; + cropping.$freeform_panY = anchy / viewScale; + cropping.$freeform_panX_min = anchx / viewScale; + cropping.$freeform_panX_max = anchw / viewScale; + cropping.$freeform_panY_min = anchy / viewScale; + cropping.$freeform_panY_max = anchh / viewScale; if (addCrop) { DocUtils.MakeLink(region, cropping, { link_relationship: 'cropped image' }); } diff --git a/src/client/views/nodes/calendarBox/CalendarBox.tsx b/src/client/views/nodes/calendarBox/CalendarBox.tsx index 1cbfd5fba..e3408696b 100644 --- a/src/client/views/nodes/calendarBox/CalendarBox.tsx +++ b/src/client/views/nodes/calendarBox/CalendarBox.tsx @@ -113,7 +113,7 @@ export class CalendarBox extends CollectionSubView() { if (!super.onInternalDrop(e, de)) return false; de.complete.docDragData?.droppedDocuments.forEach(doc => { const today = new Date().toISOString(); - if (!doc.date_range) doc[DocData].date_range = `${today}|${today}`; + if (!doc.date_range) doc.$date_range = `${today}|${today}`; }); return true; }; diff --git a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx index 6e9307d37..b023b1de6 100644 --- a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx +++ b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx @@ -733,9 +733,9 @@ export class ChatBox extends ViewBoxAnnotatableComponent() { const x2 = parseFloat(values[2]) * Doc.NativeWidth(doc); const y2 = parseFloat(values[3]) * Doc.NativeHeight(doc) + foundChunk.startPage * Doc.NativeHeight(doc); - const annotationKey = Doc.LayoutFieldKey(doc) + '_annotations'; + const annotationKey = '$' + Doc.LayoutFieldKey(doc) + '_annotations'; - const existingDoc = DocListCast(doc[DocData][annotationKey]).find(d => d.citation_id === citation.citation_id); + const existingDoc = DocListCast(doc[annotationKey]).find(d => d.citation_id === citation.citation_id); const highlightDoc = existingDoc ?? this.createImageCitationHighlight(x1, y1, x2, y2, citation, annotationKey, doc); DocumentManager.Instance.showDocument(highlightDoc, { willZoomCentered: true }, () => {}); @@ -779,7 +779,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent() { _height: y2 - y1, backgroundColor: 'rgba(255, 255, 0, 0.5)', }); - highlight_doc[DocData].citation_id = citation.citation_id; + highlight_doc.$citation_id = citation.citation_id; Doc.AddDocToList(pdfDoc[DocData], annotationKey, highlight_doc); highlight_doc.annotationOn = pdfDoc; Doc.SetContainer(highlight_doc, pdfDoc); diff --git a/src/client/views/nodes/formattedText/EquationView.tsx b/src/client/views/nodes/formattedText/EquationView.tsx index e0450b202..827db190a 100644 --- a/src/client/views/nodes/formattedText/EquationView.tsx +++ b/src/client/views/nodes/formattedText/EquationView.tsx @@ -6,7 +6,6 @@ import { EditorView } from 'prosemirror-view'; import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import { Doc } from '../../../../fields/Doc'; -import { DocData } from '../../../../fields/DocSymbols'; import { StrCast } from '../../../../fields/Types'; import './DashFieldView.scss'; import EquationEditor from './EquationEditor'; @@ -63,9 +62,9 @@ export class EquationViewInternal extends React.Component }}> { - this._textBoxDoc[DocData][this._fieldKey] = str; + this._textBoxDoc['$' + this._fieldKey] = str; }} autoCommands="pi theta sqrt sum prod alpha beta gamma rho" autoOperatorNames="sin cos tan" diff --git a/src/client/views/nodes/imageEditor/ImageEditor.tsx b/src/client/views/nodes/imageEditor/ImageEditor.tsx index 657e689bb..85bd95d15 100644 --- a/src/client/views/nodes/imageEditor/ImageEditor.tsx +++ b/src/client/views/nodes/imageEditor/ImageEditor.tsx @@ -24,8 +24,8 @@ import { PointerHandler } from './imageEditorUtils/PointerHandler'; import { activeColor, bgColor, brushWidthOffset, canvasSize, eraserColor, freeformRenderSize, newCollectionSize, offsetDistanceY, offsetX } from './imageEditorUtils/imageEditorConstants'; import { CutMode, CursorData, ImageDimensions, ImageEditTool, ImageToolType, Point } from './imageEditorUtils/imageEditorInterfaces'; import { DocumentView } from '../DocumentView'; -import { DocData } from '../../../../fields/DocSymbols'; import { SettingsManager } from '../../../util/SettingsManager'; +import { Upload } from '../../../../server/SharedMediaTypes'; interface GenerativeFillProps { imageEditorOpen: boolean; @@ -397,9 +397,8 @@ const ImageEditor = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addDoc const newImgDoc = await createNewImgDoc(finalImg, firstDoc); if (newImgDoc) { // set the image to transparent to remove the background / brushstrokes - const docData = newImgDoc[DocData]; - docData.backgroundColor = 'transparent'; - docData.disableMixBlend = true; + newImgDoc.$backgroundColor = 'transparent'; + newImgDoc.$disableMixBlend = true; if (firstDoc) setIsFirstDoc(false); setEdits([...prevEdits, { url: finalImgURL, saveRes: undefined }]); } @@ -476,7 +475,7 @@ const ImageEditor = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addDoc const createNewImgDoc = async (img: HTMLImageElement, firstDoc: boolean /*, parent?: Doc */): Promise => { if (!imageRootDoc) return undefined; const { src } = img; - const [result] = await Networking.PostToServer('/uploadRemoteImage', { sources: [src] }); + const [result] = (await Networking.PostToServer('/uploadRemoteImage', { sources: [src] })) as Upload.ImageInformation[]; const source = ClientUtils.prepend(result.accessPaths.agnostic.client); if (firstDoc) { diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index ec97e067a..23155ebf3 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -532,11 +532,10 @@ export class PresBox extends ViewBoxBaseComponent() { const setData = bestTargetView?.ComponentView?.setData; if (setData) setData(activeItem.config_data); else { - const bestTargetData = bestTarget[DocData]; - const current = bestTargetData[fkey]; - const hash = bestTargetData[fkey] ? stringHash(Field.toString(bestTargetData[fkey] as FieldType)) : undefined; - if (hash) bestTargetData[fkey + '_' + hash] = current instanceof ObjectField ? current[Copy]() : current; - bestTargetData[fkey] = activeItem.config_data instanceof ObjectField ? activeItem.config_data[Copy]() : activeItem.config_data; + const current = bestTarget['$' + fkey]; + const hash = bestTarget['$' + fkey] ? stringHash(Field.toString(bestTarget['$' + fkey] as FieldType)) : undefined; + if (hash) bestTarget['$' + fkey + '_' + hash] = current instanceof ObjectField ? current[Copy]() : current; + bestTarget['$' + fkey] = activeItem.config_data instanceof ObjectField ? activeItem.config_data[Copy]() : activeItem.config_data; } bestTarget[fkey + '_usePath'] = activeItem.config_usePath; setTimeout(() => { diff --git a/src/client/views/smartdraw/SmartDrawHandler.tsx b/src/client/views/smartdraw/SmartDrawHandler.tsx index 1cceabed3..2283ef965 100644 --- a/src/client/views/smartdraw/SmartDrawHandler.tsx +++ b/src/client/views/smartdraw/SmartDrawHandler.tsx @@ -10,9 +10,11 @@ import { INode, parse } from 'svgson'; import { imageUrlToBase64, setupMoveUpEvents } from '../../../ClientUtils'; import { unimplementedFunction } from '../../../Utils'; import { Doc, DocListCast } from '../../../fields/Doc'; -import { DocData } from '../../../fields/DocSymbols'; import { InkData, InkField, InkTool } from '../../../fields/InkField'; +import { List } from '../../../fields/List'; import { BoolCast, ImageCast, NumCast, StrCast } from '../../../fields/Types'; +import { PointData } from '../../../pen-gestures/GestureTypes'; +import { Upload } from '../../../server/SharedMediaTypes'; import { Networking } from '../../Network'; import { GPTCallType, gptAPICall, gptDrawingColor } from '../../apis/gpt/GPT'; import { DocumentType } from '../../documents/DocumentTypes'; @@ -26,9 +28,6 @@ import { MarqueeView } from '../collections/collectionFreeForm'; import { ActiveInkArrowEnd, ActiveInkArrowStart, ActiveInkBezierApprox, ActiveInkColor, ActiveInkDash, ActiveInkFillColor, ActiveInkWidth, ActiveIsInkMask, DocumentView } from '../nodes/DocumentView'; import { FireflyDimensionsMap, FireflyImageData, FireflyImageDimensions } from './FireflyConstants'; import './SmartDrawHandler.scss'; -import { Upload } from '../../../server/SharedMediaTypes'; -import { PointData } from '../../../pen-gestures/GestureTypes'; -import { List } from '../../../fields/List'; export interface DrawingOptions { text?: string; @@ -153,9 +152,9 @@ export class SmartDrawHandler extends ObservableReactComponent { this._display = false; this.ShowRegenerate = true; this._showEditBox = false; - const docData = this._selectedDocs[0][DocData]; - this._lastResponse = StrCast(docData.drawingData); - this._lastInput = { text: StrCast(docData.ai_drawing_input), complexity: NumCast(docData.ai_drawing_complexity), size: NumCast(docData.ai_drawing_size), autoColor: BoolCast(docData.ai_drawing_colored), x: this._pageX, y: this._pageY }; + const docData = this._selectedDocs[0]; + this._lastResponse = StrCast(docData.$drawingData); + this._lastInput = { text: StrCast(docData.$ai_drawing_input), complexity: NumCast(docData.$ai_drawing_complexity), size: NumCast(docData.$ai_drawing_size), autoColor: BoolCast(docData.$ai_drawing_colored), x: this._pageX, y: this._pageY }; }; /** @@ -404,7 +403,7 @@ export class SmartDrawHandler extends ObservableReactComponent { const hrefComplete = `${hrefParts[0]}_o.${hrefParts[1]}`; try { const hrefBase64 = await imageUrlToBase64(hrefComplete); - const strokes = DocListCast(drawing[DocData].data); + const strokes = DocListCast(drawing.$data); const coords: string[] = []; strokes.forEach((stroke, i) => { const inkingStroke = DocumentView.getDocumentView(stroke)?.ComponentView as InkingStroke; @@ -423,14 +422,14 @@ export class SmartDrawHandler extends ObservableReactComponent { */ colorStrokes = undoable((res: string, drawing: Doc) => { const colorList = res.match(/\{.*?\}/g); - const strokes = DocListCast(drawing[DocData].data); + const strokes = DocListCast(drawing.$data); colorList?.forEach((colors, index) => { const strokeAndFill = colors.match(/#[0-9A-Fa-f]{6}/g); if (strokeAndFill && strokeAndFill.length == 2) { - strokes[index][DocData].color = strokeAndFill[0]; + strokes[index].$color = strokeAndFill[0]; const inkStroke = DocumentView.getDocumentView(strokes[index])?.ComponentView as InkingStroke; const { inkData } = inkStroke.inkScaledData(); - InkingStroke.IsClosed(inkData) ? (strokes[index][DocData].fillColor = strokeAndFill[1]) : (strokes[index][DocData].fillColor = undefined); + InkingStroke.IsClosed(inkData) ? (strokes[index].$fillColor = strokeAndFill[1]) : (strokes[index].$fillColor = undefined); } }); }, 'color strokes'); diff --git a/src/client/views/smartdraw/StickerPalette.tsx b/src/client/views/smartdraw/StickerPalette.tsx index e3305851a..080a05d42 100644 --- a/src/client/views/smartdraw/StickerPalette.tsx +++ b/src/client/views/smartdraw/StickerPalette.tsx @@ -9,7 +9,6 @@ import ReactLoading from 'react-loading'; import { returnEmptyFilter, returnFalse, returnTrue } from '../../../ClientUtils'; import { emptyFunction, numberRange } from '../../../Utils'; import { Doc, DocListCast, returnEmptyDoclist } from '../../../fields/Doc'; -import { DocData } from '../../../fields/DocSymbols'; import { ImageCast, NumCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; import { DocumentType } from '../../documents/DocumentTypes'; @@ -133,7 +132,7 @@ export class StickerPalette extends ObservableReactComponent { this._isLoading = true; - const prevDrawings = DocListCast(this._props.Document[DocData].data); - this._props.Document[DocData].data = undefined; + const prevDrawings = DocListCast(this._props.Document.$data); + this._props.Document.$data = undefined; SmartDrawHandler.Instance.AddDrawing = this.addDrawing; this._canInteract = false; Promise.all( @@ -164,7 +163,7 @@ export class StickerPalette extends ObservableReactComponent { this._gptRes.push(gptRes); - drawing[DocData].freeform_fitContentsToBox = true; + drawing.$freeform_fitContentsToBox = true; Doc.AddDocToList(this._props.Document, 'data', drawing); }; @@ -176,17 +175,16 @@ export class StickerPalette extends ObservableReactComponent { const cIndex = NumCast(this._props.Document.carousel_index); const focusedDrawing = DocListCast(this._props.Document.data)[cIndex]; - const docData = focusedDrawing[DocData]; - docData.title = this._opts.text?.match(/^(.*?)~~~.*$/)?.[1] || this._opts.text; - docData.ai_drawing_input = this._opts.text; - docData.ai_drawing_complexity = this._opts.complexity; - docData.ai_drawing_colored = this._opts.autoColor; - docData.ai_drawing_size = this._opts.size; - docData.ai_drawing_data = this._gptRes[cIndex]; - docData.ai = 'gpt'; + focusedDrawing.$title = this._opts.text?.match(/^(.*?)~~~.*$/)?.[1] || this._opts.text; + focusedDrawing.$ai_drawing_input = this._opts.text; + focusedDrawing.$ai_drawing_complexity = this._opts.complexity; + focusedDrawing.$ai_drawing_colored = this._opts.autoColor; + focusedDrawing.$ai_drawing_size = this._opts.size; + focusedDrawing.$ai_drawing_data = this._gptRes[cIndex]; + focusedDrawing.$ai = 'gpt'; focusedDrawing.width = this._opts.size; - docData.x = this._opts.x; - docData.y = this._opts.y; + focusedDrawing.x = this._opts.x; + focusedDrawing.y = this._opts.y; StickerPalette.addToPalette(focusedDrawing).then(() => this.resetPalette(true)); }; diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index e2f708700..4bf04da5c 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -273,12 +273,12 @@ export class Doc extends RefField { public static AddToMyOverlay(doc: Doc) { return Doc.ActiveDashboard ? Doc.AddDocToList(Doc.ActiveDashboard, 'myOverlayDocs', doc) : Doc.AddDocToList(DocCast(Doc.UserDoc().myOverlayDocs), undefined, doc); } // prettier-ignore public static RemFromMyOverlay(doc: Doc) { return Doc.ActiveDashboard ? Doc.RemoveDocFromList(Doc.ActiveDashboard,'myOverlayDocs', doc) : Doc.RemoveDocFromList(DocCast(Doc.UserDoc().myOverlayDocs), undefined, doc); } // prettier-ignore public static AddToMyPublished(doc: Doc) { - doc[DocData].title_custom = true; - doc[DocData].layout_showTitle = 'title'; + doc.$title_custom = true; + doc.$layout_showTitle = 'title'; Doc.ActiveDashboard ? Doc.AddDocToList(Doc.ActiveDashboard, 'myPublishedDocs', doc) : Doc.AddDocToList(DocCast(Doc.UserDoc().myPublishedDocs), undefined, doc); } // prettier-ignore public static RemFromMyPublished(doc: Doc){ - doc[DocData].title_custom = false; - doc[DocData].layout_showTitle = undefined; + doc.$title_custom = false; + doc.$layout_showTitle = undefined; Doc.ActiveDashboard ? Doc.RemoveDocFromList(Doc.ActiveDashboard,'myPublishedDocs', doc) : Doc.RemoveDocFromList(DocCast(Doc.UserDoc().myPublishedDocs), undefined, doc); } // prettier-ignore public static IsComicStyle(doc?: Doc) { return doc && Doc.ActiveDashboard && !Doc.IsSystem(doc) && Doc.UserDoc().renderStyle === 'comic' ; } // prettier-ignore @@ -629,7 +629,7 @@ export namespace Doc { */ export function RemoveDocFromList(listDoc: Doc, fieldKey: string | undefined, doc: Doc, ignoreProto = false) { const key = fieldKey || Doc.LayoutFieldKey(listDoc); - const list = Doc.Get(listDoc, key, ignoreProto) === undefined ? (listDoc[DocData][key] = new List()) : Cast(listDoc[key], listSpec(Doc)); + const list = Doc.Get(listDoc, key, ignoreProto) === undefined ? (listDoc['$' + key] = new List()) : Cast(listDoc[key], listSpec(Doc)); if (list) { const ind = list.indexOf(doc); if (ind !== -1) { @@ -646,7 +646,7 @@ export namespace Doc { */ export function AddDocToList(listDoc: Doc, fieldKey: string | undefined, doc: Doc, relativeTo?: Doc, before?: boolean, first?: boolean, allowDuplicates?: boolean, reversed?: boolean, ignoreProto?: boolean) { const key = fieldKey || Doc.LayoutFieldKey(listDoc); - const list = Doc.Get(listDoc, key, ignoreProto) === undefined ? (listDoc[DocData][key] = new List()) : Cast(listDoc[key], listSpec(Doc)); + const list = Doc.Get(listDoc, key, ignoreProto) === undefined ? (listDoc['$' + key] = new List()) : Cast(listDoc[key], listSpec(Doc)); if (list) { if (!allowDuplicates) { const pind = list.findIndex(d => d instanceof Doc && d[Id] === doc[Id]); @@ -691,7 +691,7 @@ export namespace Doc { Doc.SetLayout(embedding, Doc.MakeEmbedding(layout)); } embedding.createdFrom = doc; - embedding.proto_embeddingId = doc[DocData].proto_embeddingId = Doc.GetEmbeddings(doc).length - 1; + embedding.proto_embeddingId = doc.$proto_embeddingId = Doc.GetEmbeddings(doc).length - 1; !Doc.GetT(embedding, 'title', 'string', true) && (embedding.title = ComputedField.MakeFunction(`renameEmbedding(this)`)); embedding.author = ClientUtils.CurrentUserEmail(); @@ -699,9 +699,8 @@ export namespace Doc { } export function BestEmbedding(doc: Doc) { - const dataDoc = doc[DocData]; - const availableEmbeddings = Doc.GetEmbeddings(dataDoc); - const bestEmbedding = [...(dataDoc !== doc ? [doc] : []), ...availableEmbeddings].find(d => !d.embedContainer && d.author === ClientUtils.CurrentUserEmail()); + const availableEmbeddings = Doc.GetEmbeddings(doc); + const bestEmbedding = [...(doc[DocData] !== doc ? [doc] : []), ...availableEmbeddings].find(d => !d.embedContainer && d.author === ClientUtils.CurrentUserEmail()); bestEmbedding && Doc.AddEmbedding(doc, doc); return bestEmbedding ?? Doc.MakeEmbedding(doc); } @@ -1475,7 +1474,7 @@ export namespace Doc { * @returns */ export function getDescription(doc: Doc) { - const curDescription = StrCast(doc[DocData][Doc.LayoutFieldKey(doc) + '_description']); + const curDescription = StrCast(doc['$' + Doc.LayoutFieldKey(doc) + '_description']); const docText = (async (tdoc:Doc) => { switch (tdoc.type) { case DocumentType.PDF: return curDescription || StrCast(tdoc.text).split(/\s+/).slice(0, 50).join(' '); // first 50 words of pdf text @@ -1484,7 +1483,7 @@ export namespace Doc { case DocumentType.RTF: return RTFCast(tdoc[Doc.LayoutFieldKey(tdoc)]).Text; default: return StrCast(tdoc.title).startsWith("Untitled") ? "" : StrCast(tdoc.title); }}); // prettier-ignore - return docText(doc).then(text => (doc[DocData][Doc.LayoutFieldKey(doc) + '_description'] = text)); + return docText(doc).then(text => (doc['$' + Doc.LayoutFieldKey(doc) + '_description'] = text)); } // prettier-ignore @@ -1737,7 +1736,7 @@ ScriptingGlobals.add(function idToDoc(id: string): Doc { }); // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function renameEmbedding(doc: Doc) { - return StrCast(doc[DocData].title).replace(/\([0-9]*\)/, '') + `(${doc.proto_embeddingId})`; + return StrCast(doc.$title).replace(/\([0-9]*\)/, '') + `(${doc.proto_embeddingId})`; }); // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function getProto(doc: Doc) { diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts index b294ee8c6..6e2d7eb78 100644 --- a/src/fields/ScriptField.ts +++ b/src/fields/ScriptField.ts @@ -210,6 +210,7 @@ export class ComputedField extends ScriptField { this._lastComputedResult = this._cachedResult ?? computedFn(() => + ((val) => val instanceof Array ? new List(val) : val)( this.script.compiled && this.script.run( { @@ -220,7 +221,7 @@ export class ComputedField extends ScriptField { _readOnly_: true, }, console.log - ).result as FieldResult + ).result as FieldResult) )(); // prettier-ignore return this._lastComputedResult; }; -- cgit v1.2.3-70-g09d2 From b0bb28202fa77556768d1da93bf9ea879c6ba2e5 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 10 Apr 2025 12:05:55 -0400 Subject: performance fixes for text boxes to not call screenToLocal unnecessarily. simplifications to template data docs --- src/client/views/DocumentDecorations.scss | 2 +- src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/StyleProvider.tsx | 24 +++-- src/client/views/TagsView.scss | 3 + .../views/collections/CollectionCarouselView.scss | 2 + .../views/collections/CollectionCarouselView.tsx | 14 ++- .../views/collections/CollectionNoteTakingView.tsx | 6 +- .../views/collections/CollectionStackingView.tsx | 13 ++- src/client/views/collections/CollectionSubView.tsx | 7 +- .../views/collections/CollectionTreeView.tsx | 14 +-- .../collectionGrid/CollectionGridView.tsx | 11 +-- .../CollectionMulticolumnView.tsx | 106 ++++++++++----------- .../CollectionMultirowView.tsx | 106 ++++++++++----------- src/client/views/nodes/DocumentView.scss | 6 ++ src/client/views/nodes/DocumentView.tsx | 87 ++++++++++------- src/client/views/nodes/FieldView.tsx | 2 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 16 ++-- .../formattedText/ProsemirrorExampleTransfer.ts | 3 +- src/client/views/nodes/trails/PresElementBox.tsx | 2 +- 19 files changed, 229 insertions(+), 197 deletions(-) (limited to 'src/client/views/nodes/trails') diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index 28cebe23c..09a13634f 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -40,10 +40,10 @@ $resizeHandler: 8px; } .documentDecorations-tagsView { position: absolute; - height: 100%; width: 100%; pointer-events: all; border-radius: 50%; + top: 30; // offset by height of documentButtonBar so that items can be clicked without overlap interference color: black; } } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 452dd60ee..0756d3d9e 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -863,7 +863,7 @@ export class DocumentDecorations extends ObservableReactComponent 1 || !seldocview.showTags ? 'none' : undefined, transform: `translate(${-this._resizeBorderWidth + 10}px, ${2 * this._resizeBorderWidth + bounds.b - bounds.y + this._titleHeight}px) `, }}> {DocumentView.Selected().length > 1 ? : null} diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index a3067907d..e8876f96f 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -327,7 +327,7 @@ export function DefaultStyleProvider(doc: Opt, props: Opt, props: Opt doc?.pointerEvents !== 'none' ? null : ( + const showLock = doc?.pointerEvents === 'none' + const lock = () => !showLock ? null : (
toggleLockedPosition(doc)}>
); - const paint = () => !doc?.onPaint ? null : ( + const showPaint = doc?.onPaint; + const paint = () => !showPaint ? null : (
togglePaintView(e, doc, props)}>
); + const showFilterIcon = + StrListCast(doc?._childFilters).length || StrListCast(doc?._childFiltersByRanges).length + ? 'green' // #18c718bd' //'hasFilter' + : childFilters?.().filter(f => ClientUtils.IsRecursiveFilter(f) && f !== ClientUtils.noDragDocsFilter).length || childFiltersByRanges?.().length + ? 'orange' // 'inheritsFilter' + : undefined; + const showFilter = showFilterIcon && !hideFilterStatus; const filter = () => { const dashView = untracked(() => DocumentView.getDocumentView(Doc.ActiveDashboard)); - const showFilterIcon = - StrListCast(doc?._childFilters).length || StrListCast(doc?._childFiltersByRanges).length - ? 'green' // #18c718bd' //'hasFilter' - : childFilters?.().filter(f => ClientUtils.IsRecursiveFilter(f) && f !== ClientUtils.noDragDocsFilter).length || childFiltersByRanges?.().length - ? 'orange' // 'inheritsFilter' - : undefined; - return !showFilterIcon || hideFilterStatus ? null : ( + return !showFilter ? null : (
, props: Opt {paint()} {lock()} diff --git a/src/client/views/TagsView.scss b/src/client/views/TagsView.scss index d58b55ab5..a940502d4 100644 --- a/src/client/views/TagsView.scss +++ b/src/client/views/TagsView.scss @@ -16,6 +16,9 @@ min-height: unset !important; } } + .tagsView-editing-box { + pointer-events: all; + } } } diff --git a/src/client/views/collections/CollectionCarouselView.scss b/src/client/views/collections/CollectionCarouselView.scss index 1080aa703..962b590c8 100644 --- a/src/client/views/collections/CollectionCarouselView.scss +++ b/src/client/views/collections/CollectionCarouselView.scss @@ -9,6 +9,8 @@ height: 50; display: inline-block; width: 100%; + bottom: 0; + position: absolute; } .collectionCarouselView-image { height: calc(100% - 50px); diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx index c80ac23eb..2d3f8cb0e 100644 --- a/src/client/views/collections/CollectionCarouselView.tsx +++ b/src/client/views/collections/CollectionCarouselView.tsx @@ -16,7 +16,6 @@ import { FocusViewOptions } from '../nodes/FocusViewOptions'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import './CollectionCarouselView.scss'; import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView'; -import { DocData } from '../../../fields/DocSymbols'; @observer export class CollectionCarouselView extends CollectionSubView() { @@ -116,12 +115,14 @@ export class CollectionCarouselView extends CollectionSubView() { ? false : undefined; // prettier-ignore onPassiveWheel = (e: WheelEvent) => e.stopPropagation(); + renderDoc = (doc: Doc, showCaptions: boolean, overlayFunc?: (r: DocumentView | null) => void) => { return ( diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx index 01695dbaf..173147f64 100644 --- a/src/client/views/collections/CollectionNoteTakingView.tsx +++ b/src/client/views/collections/CollectionNoteTakingView.tsx @@ -258,11 +258,9 @@ export class CollectionNoteTakingView extends CollectionSubView() { const noteTakingDocTransform = () => this.getDocTransform(doc, dref); return ( { - dref = r || undefined; - }} + ref={r => (dref = r || undefined)} Document={doc} - TemplateDataDocument={dataDoc ?? (!Doc.AreProtosEqual(doc[DocData], doc) ? doc[DocData] : undefined)} + TemplateDataDocument={doc.isTemplateDoc || doc.isTemplateForField ? this._props.TemplateDataDocument : undefined} pointerEvents={this.blockPointerEventsWhenDragging} renderDepth={this._props.renderDepth + 1} PanelWidth={width} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index d7cf0ffc2..4f60acb18 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -675,12 +675,12 @@ export class CollectionStackingView extends CollectionSubView 35; + @computed get menuBtnDoc() { return DocCast(this.layoutDoc.layout_headerButton); } // prettier-ignore @computed get buttonMenu() { - const menuDoc = DocCast(this.layoutDoc.layout_headerButton); - return !menuDoc ? null : ( -
+ return !this.menuBtnDoc ? null : ( +
- {buttonMenu || noviceExplainer ? ( + {this.menuBtnDoc || noviceExplainer ? (
- {buttonMenu ? this.buttonMenu : null} + {this.menuBtnDoc ? this.buttonMenu : null} {Doc.noviceMode && noviceExplainer ?
{StrCast(noviceExplainer)}
: null}
) : null} diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index a88707c6f..375c0fe53 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -603,7 +603,12 @@ export function CollectionSubView() { */ @computed get uiBtnScaling() { return this.maxWidgetSize / this._sideBtnWidth; } // prettier-ignore - screenXPadding = () => (this.uiBtnScaling * this._sideBtnWidth - NumCast(this.layoutDoc.xMargin)) / this._props.ScreenToLocalTransform().Scale; + screenXPadding = (docView?: DocumentView) => { + if (!docView) return 0; + const diff = this._props.PanelWidth() - docView.PanelWidth(); + const xpad1 = this.uiBtnScaling * (this._sideBtnWidth - NumCast(this.layoutDoc.xMargin)) - diff / 2; // this._sideBtnWidth; + return xpad1 / (docView.NativeDimScaling?.() || 1); + }; filteredChildDocs = () => this.childLayoutPairs.map(pair => pair.layout); childDocsFunc = () => this.childDocs; @action setFilterFunc = (func?: (doc: Doc) => boolean) => { this._filterFunc = func; }; // prettier-ignore diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 418c437d5..962fbdcd7 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -8,7 +8,7 @@ import { DocData } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { listSpec } from '../../../fields/Schema'; import { ScriptField } from '../../../fields/ScriptField'; -import { BoolCast, Cast, NumCast, ScriptCast, StrCast, toList } from '../../../fields/Types'; +import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast, toList } from '../../../fields/Types'; import { TraceMobx } from '../../../fields/util'; import { emptyFunction, Utils } from '../../../Utils'; import { Docs } from '../../documents/Documents'; @@ -200,7 +200,7 @@ export class CollectionTreeView extends CollectionSubView { // need to test if propagation has stopped because GoldenLayout forces a parallel react hierarchy to be created for its top-level layout const layoutItems: ContextMenuProps[] = []; - const menuDoc = ScriptCast(Cast(this.layoutDoc.layout_headerButton, Doc, null)?.onClick)?.script.originalScript === CollectionTreeView.AddTreeFunc; + const menuDoc = ScriptCast(this.menuBtnDoc?.onClick)?.script.originalScript === CollectionTreeView.AddTreeFunc; menuDoc && layoutItems.push({ description: 'Create new folder', event: () => CollectionTreeView.addTreeFolder(this.Document), icon: 'paint-brush' }); if (!Doc.noviceMode) { layoutItems.push({ @@ -347,14 +347,14 @@ export class CollectionTreeView extends CollectionSubView 35; + @computed get menuBtnDoc() { return DocCast(this.layoutDoc.layout_headerButton); } // prettier-ignore @computed get buttonMenu() { - const menuDoc = Cast(this.layoutDoc.layout_headerButton, Doc, null); // To create a multibutton menu add a CollectionLinearView - return !menuDoc ? null : ( -
+ return !this.menuBtnDoc ? null : ( +
(this._props.isDocumentActive?.() && (this._props.childDocumentsActive?.() || BoolCast(this.Document.childDocumentsActive)) ? true : undefined); /** * - * @param layout + * @param childLayout * @param dxf the x- and y-translations of the decorations box as a transform i.e. this.lookupIndividualTransform * @param width * @param height * @returns the `ContentFittingDocumentView` of the node */ - getDisplayDoc = (layout: Doc, dxf: () => Transform, width: () => number, height: () => number) => ( + getDisplayDoc = (childLayout: Doc, dxf: () => Transform, width: () => number, height: () => number) => ( { - if (this.columnUnitLength === undefined) { - return Transform.Identity(); // we're still waiting on promises to resolve - } - let offset = 0; - for (const { layout: candidate } of this.childLayoutPairs) { - if (candidate === layout) { - return this.ScreenToLocalBoxXf().translate(-offset / (this._props.NativeDimScaling?.() || 1), 0); + if (this.columnUnitLength !== undefined) { + let offset = 0; + for (const { layout: candidate } of this.childLayoutPairs) { + if (candidate === layout) { + return this.ScreenToLocalBoxXf().translate(-offset / (this._props.NativeDimScaling?.() || 1), 0); + } + offset += this.lookupPixels(candidate) + resizerWidth; } - offset += this.lookupPixels(candidate) + resizerWidth; } return Transform.Identity(); }; @@ -262,50 +261,51 @@ export class CollectionMulticolumnView extends CollectionSubView() { ? true : undefined; }; - getDisplayDoc = (childLayout: Doc) => { - const width = () => this.lookupPixels(childLayout); - const height = () => this._props.PanelHeight() - 2 * NumCast(this.layoutDoc._yMargin) - (BoolCast(this.layoutDoc.showWidthLabels) ? 20 : 0); - const dxf = () => - this.lookupIndividualTransform(childLayout) + childHeight = () => this._props.PanelHeight() - 2 * NumCast(this.layoutDoc._yMargin) - (BoolCast(this.layoutDoc.showWidthLabels) ? 20 : 0); + childWidth = computedFn((childDoc: Doc) => () => this.lookupPixels(childDoc)); + childXf = computedFn( + (childDoc: Doc) => () => + this.lookupIndividualTransform(childDoc) .translate(-NumCast(this.layoutDoc._xMargin), -NumCast(this.layoutDoc._yMargin)) - .scale(this._props.NativeDimScaling?.() || 1); - return ( - - ); - }; + .scale(this._props.NativeDimScaling?.() || 1) + ); + getDisplayDoc = (childLayout: Doc) => ( + + ); + /** * @returns the resolved list of rendered child documents, displayed * at their resolved pixel widths, each separated by a resizer. diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx index f95928cf6..6bbe55f54 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx @@ -2,7 +2,7 @@ import { action, computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc, DocListCast } from '../../../../fields/Doc'; -import { BoolCast, DocCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; +import { BoolCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types'; import { DragManager } from '../../../util/DragManager'; import { dropActionType } from '../../../util/DropActionTypes'; import { Transform } from '../../../util/Transform'; @@ -11,7 +11,7 @@ import { CollectionSubView, SubCollectionViewProps } from '../CollectionSubView' import './CollectionMultirowView.scss'; import HeightLabel from './MultirowHeightLabel'; import ResizeBar from './MultirowResizer'; -import { DocData } from '../../../../fields/DocSymbols'; +import { computedFn } from 'mobx-utils'; interface HeightSpecifier { magnitude: number; @@ -179,16 +179,14 @@ export class CollectionMultirowView extends CollectionSubView() { * documents before the target. */ private lookupIndividualTransform = (layout: Doc) => { - if (this.rowUnitLength === undefined) { - return Transform.Identity(); // we're still waiting on promises to resolve - } - let offset = 0; - // eslint-disable-next-line no-restricted-syntax - for (const { layout: candidate } of this.childLayoutPairs) { - if (candidate === layout) { - return this.ScreenToLocalBoxXf().translate(0, -offset / (this._props.NativeDimScaling?.() || 1)); + if (this.rowUnitLength !== undefined) { + let offset = 0; + for (const { layout: candidate } of this.childLayoutPairs) { + if (candidate === layout) { + return this.ScreenToLocalBoxXf().translate(0, -offset / (this._props.NativeDimScaling?.() || 1)); + } + offset += this.lookupPixels(candidate) + resizerHeight; } - offset += this.lookupPixels(candidate) + resizerHeight; } return Transform.Identity(); // type coersion, this case should never be hit }; @@ -244,49 +242,51 @@ export class CollectionMultirowView extends CollectionSubView() { ? true : undefined; }; - getDisplayDoc = (layout: Doc) => { - const height = () => this.lookupPixels(layout); - const width = () => this._props.PanelWidth() - 2 * NumCast(this.layoutDoc._xMargin) - (BoolCast(this.layoutDoc.showWidthLabels) ? 20 : 0); - const dxf = () => - this.lookupIndividualTransform(layout) + childHeight = computedFn((childDoc: Doc) => () => this.lookupPixels(childDoc)); + childWidth = () => this._props.PanelWidth() - 2 * NumCast(this.layoutDoc._xMargin) - (BoolCast(this.layoutDoc.showWidthLabels) ? 20 : 0); + childXf = computedFn( + (childDoc: Doc) => () => + this.lookupIndividualTransform(childDoc) .translate(-NumCast(this.layoutDoc._xMargin), -NumCast(this.layoutDoc._yMargin)) - .scale(this._props.NativeDimScaling?.() || 1); - return ( - - ); - }; + .scale(this._props.NativeDimScaling?.() || 1) + ); + + getDisplayDoc = (childLayout: Doc) => ( + + ); + /** * @returns the resolved list of rendered child documents, displayed * at their resolved pixel widths, each separated by a resizer. diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss index f60f33608..5ac66f2cd 100644 --- a/src/client/views/nodes/DocumentView.scss +++ b/src/client/views/nodes/DocumentView.scss @@ -277,6 +277,12 @@ bottom: 0; pointer-events: none; } +.documentView-widgetDecorations { + transform-origin: top right; + position: absolute; + top: 0; + right: 0; +} .documentView-editorView-history { position: absolute; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index b03dd3944..bec5ea5c1 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -712,6 +712,54 @@ export class DocumentViewInternal extends DocComponent (this.aiContentsHeight() * (this._props.NativeWidth?.() || 1)) / (this._props.NativeHeight?.() || 1); aiContentsHeight = () => Math.max(10, this._props.PanelHeight() - this._aiWinHeight * this.uiBtnScaling); + aiEditor = () => ( + <> +
this.historyRef(this._oldAiWheel, (this._oldAiWheel = r))} + style={{ + transform: `scale(${this.uiBtnScaling})`, + height: this.aiContentsHeight() / this.uiBtnScaling, + width: ((this._props.PanelWidth() - this.aiContentsWidth()) * 0.95) / this.uiBtnScaling, + }}> + {this._componentView?.componentAIViewHistory?.() ?? null} +
+
this.historyRef(this._oldHistoryWheel, (this._oldHistoryWheel = r))}> +
+ {this._componentView?.componentAIView?.() ?? null} + {this._props.DocumentView?.() ? : null} +
+ + ); + @computed get tagsOverlay() { + return ( +
+ {this._props.DocumentView?.() && !this._props.docViewPath().slice(-2)[0].ComponentView?.isUnstyledView?.() ? : null} +
+ ); + } + tagsOverlayFunc = () => (this._props.DocumentView?.().showTags ? this.tagsOverlay : null); + @computed get widgetOverlay() { + return ( +
+ {this.widgetDecorations} +
+ ); + } + widgetOverlayFunc = () => (this.widgetDecorations ? this.widgetOverlay : null); @computed get viewBoxContents() { TraceMobx(); const isInk = this.layoutDoc._layout_isSvg && !this._props.LayoutTemplateString; @@ -742,43 +790,8 @@ export class DocumentViewInternal extends DocComponent
- {!this._props.showAIEditor ? ( -
- {this._props.DocumentView?.() && !this._props.docViewPath().slice(-2)[0].ComponentView?.isUnstyledView?.() ? : null} -
- ) : ( - <> -
this.historyRef(this._oldAiWheel, (this._oldAiWheel = r))} - style={{ - transform: `scale(${this.uiBtnScaling})`, - height: this.aiContentsHeight() / this.uiBtnScaling, - width: ((this._props.PanelWidth() - this.aiContentsWidth()) * 0.95) / this.uiBtnScaling, - }}> - {this._componentView?.componentAIViewHistory?.() ?? null} -
-
this.historyRef(this._oldHistoryWheel, (this._oldHistoryWheel = r))}> -
- {this._componentView?.componentAIView?.() ?? null} - {this._props.DocumentView?.() ? : null} -
- - )} -
{this.widgetDecorations ?? null}
+ {this._props.showAIEditor ? this.aiEditor() : this.tagsOverlayFunc()} + {this.widgetOverlayFunc()} ); } diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 74059bd12..ad6d93d43 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -50,7 +50,7 @@ export interface FieldViewSharedProps { TemplateDataDocument?: Doc; renderDepth: number; scriptContext?: unknown; // can be assigned anything and will be passed as 'scriptContext' to any OnClick script that executes on this document - screenXPadding?: () => number; // padding in screen space coordinates (used by text box to reflow around UI buttons in carouselView) + screenXPadding?: (view: DocumentView | undefined) => number; // padding in screen space coordinates (used by text box to reflow around UI buttons in carouselView) xPadding?: number; yPadding?: number; dontRegisterView?: boolean; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 6fced76bd..a45b8a488 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -215,7 +215,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { - const rootDoc: Doc = Doc.isTemplateDoc(this._props.docViewPath().lastElement()?.Document) ? this.Document : DocCast(this.Document.rootDocument, this.Document); + const rootDoc = Doc.isTemplateDoc(this._props.docViewPath().lastElement()?.Document) ? this.Document : this.rootDoc; if (!pinProps && this.EditorView?.state.selection.empty) return rootDoc; const anchor = Docs.Create.ConfigDocument({ title: StrCast(rootDoc.title), annotationOn: rootDoc }); this.addDocument(anchor); @@ -308,7 +308,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { if (node.type === this.EditorView?.state.schema.nodes.dashField) { - const refDoc = !node.attrs.docId ? DocCast(this.Document.rootDocument, this.Document) : (DocServer.GetCachedRefField(node.attrs.docId as string) as Doc); + const refDoc = !node.attrs.docId ? this.rootDoc : (DocServer.GetCachedRefField(node.attrs.docId as string) as Doc); const fieldKey = StrCast(node.attrs.fieldKey); return ( (node.attrs.hideKey ? '' : fieldKey + ':') + // @@ -316,7 +316,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent !this._props.isContentActive() && FormattedTextBoxComment.textBox === this && FormattedTextBoxComment.Hide); - const scrSize = (which: number, view = this._props.docViewPath().slice(-which)[0]) => - [view?._props.PanelWidth() /(view?.screenToLocalScale()??1), view?._props.PanelHeight() / (view?.screenToLocalScale()??1)]; // prettier-ignore - const scrMargin = [Math.max(0, (scrSize(2)[0] - scrSize(1)[0]) / 2), Math.max(0, (scrSize(2)[1] - scrSize(1)[1]) / 2)]; - const paddingX = Math.max(NumCast(this.layoutDoc._xMargin), this._props.xPadding ?? 0, 0, ((this._props.screenXPadding?.() ?? 0) - scrMargin[0]) * this.ScreenToLocalBoxXf().Scale); - const paddingY = Math.max(NumCast(this.layoutDoc._yMargin), 0, ((this._props.yPadding ?? 0) - scrMargin[1]) * this.ScreenToLocalBoxXf().Scale); + const paddingX = Math.max(NumCast(this.layoutDoc._xMargin), 0, this._props.xPadding ?? 0, this._props.screenXPadding?.(this._props.DocumentView?.()) ?? 0); + const paddingY = Math.max(NumCast(this.layoutDoc._yMargin), 0, this._props.yPadding ?? 0); // prettier-ignore const styleFromLayout = styleFromLayoutString(this.Document, this._props, scale); // this converts any expressions in the format string to style props. e.g., return this.isLabel ? ( diff --git a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts index eabc6455f..7ae1fc202 100644 --- a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts +++ b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts @@ -50,8 +50,7 @@ export function buildKeymap>(schema: S, tbox?: Formatte const canEdit = (state: EditorState) => { if (!tbox) return true; - const permissions = GetEffectiveAcl(tbox._props.TemplateDataDocument ?? tbox.Document[DocData]); - switch (permissions) { + switch (GetEffectiveAcl(tbox.dataDoc)) { case AclAugment: { // previously used hack: (state.selection as any).$cursor.nodeBefore; diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index 31cd1603f..7e0375275 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -67,7 +67,7 @@ export class PresElementBox extends ViewBoxBaseComponent() { // Since this node is being rendered with a template, this method retrieves // the actual slide being rendered from the auto-generated rendering template @computed get slideDoc() { - return DocCast(this.Document.rootDocument, this.Document); + return this.rootDoc; } // this is the document in the workspaces that is targeted by the slide -- cgit v1.2.3-70-g09d2 From d818ef151ca65008e5c6bb5e92b709decb3026d8 Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 14 Apr 2025 18:35:49 -0400 Subject: fixed how templates are expanded to avoid template sub-component conflicts by changing how field keys are named. fixed various Cast functions to be more typesafe by including undefined as part of return type. overhaul of Doc.MakeClone, MakeCopy, FindRefernces - makeClone is no longer async. fixed inlined docs in text docs. --- src/client/documents/DocUtils.ts | 41 +- src/client/documents/DocumentTypes.ts | 2 +- src/client/documents/Documents.ts | 8 +- src/client/util/CurrentUserUtils.ts | 37 +- src/client/util/DictationManager.ts | 2 +- src/client/util/DocumentManager.ts | 2 +- src/client/util/DragManager.ts | 40 +- src/client/util/DropConverter.ts | 6 +- src/client/util/Import & Export/ImageUtils.ts | 2 +- src/client/util/LinkFollower.ts | 32 +- src/client/util/LinkManager.ts | 43 +- src/client/util/SearchUtil.ts | 6 +- src/client/util/SettingsManager.tsx | 2 +- src/client/views/DocComponent.tsx | 8 +- src/client/views/DocumentButtonBar.tsx | 8 +- src/client/views/FilterPanel.tsx | 4 +- src/client/views/GlobalKeyHandler.ts | 6 +- src/client/views/InkStrokeProperties.ts | 2 +- src/client/views/InkTranscription.tsx | 6 +- src/client/views/LightboxView.tsx | 4 +- src/client/views/Main.tsx | 4 +- src/client/views/MainView.tsx | 42 +- src/client/views/PinFuncs.ts | 8 +- src/client/views/PropertiesButtons.tsx | 2 +- src/client/views/PropertiesView.tsx | 8 +- src/client/views/StyleProvider.tsx | 12 +- src/client/views/StyleProviderQuiz.tsx | 2 +- src/client/views/TagsView.tsx | 6 +- src/client/views/animationtimeline/Timeline.tsx | 2 +- .../views/collections/CollectionCarouselView.tsx | 3 +- .../views/collections/CollectionDockingView.tsx | 16 +- .../views/collections/CollectionNoteTakingView.tsx | 11 +- .../views/collections/CollectionStackingView.tsx | 12 +- .../CollectionStackingViewFieldColumn.tsx | 4 +- src/client/views/collections/CollectionSubView.tsx | 37 +- src/client/views/collections/TabDocView.tsx | 14 +- src/client/views/collections/TreeView.tsx | 20 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 31 +- .../collectionFreeForm/FaceCollectionBox.tsx | 2 +- .../collectionFreeForm/ImageLabelBox.tsx | 4 +- .../collections/collectionFreeForm/MarqueeView.tsx | 6 +- .../collectionLinear/CollectionLinearView.tsx | 4 +- .../collectionSchema/CollectionSchemaView.tsx | 4 +- .../collectionSchema/SchemaTableCell.tsx | 2 +- src/client/views/global/globalScripts.ts | 37 +- src/client/views/newlightbox/NewLightboxView.tsx | 2 +- src/client/views/nodes/AudioBox.tsx | 2 +- .../views/nodes/CollectionFreeFormDocumentView.tsx | 4 +- src/client/views/nodes/DataVizBox/DataVizBox.tsx | 2 +- src/client/views/nodes/DocumentContentsView.tsx | 4 +- src/client/views/nodes/DocumentView.tsx | 100 ++-- src/client/views/nodes/FieldView.tsx | 2 +- src/client/views/nodes/IconTagBox.tsx | 2 +- src/client/views/nodes/ImageBox.tsx | 24 +- src/client/views/nodes/KeyValueBox.tsx | 8 +- src/client/views/nodes/KeyValuePair.tsx | 4 +- src/client/views/nodes/PDFBox.tsx | 2 +- .../views/nodes/RecordingBox/RecordingBox.tsx | 2 +- src/client/views/nodes/ScreenshotBox.tsx | 2 +- src/client/views/nodes/ScriptingBox.tsx | 13 +- src/client/views/nodes/WebBox.tsx | 18 +- .../nodes/chatbot/chatboxcomponents/ChatBox.tsx | 2 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 55 +- .../views/nodes/formattedText/RichTextMenu.tsx | 6 +- .../views/nodes/formattedText/RichTextRules.ts | 19 +- src/client/views/nodes/trails/PresBox.tsx | 187 +++--- src/client/views/nodes/trails/PresElementBox.scss | 308 ---------- src/client/views/nodes/trails/PresElementBox.tsx | 628 --------------------- src/client/views/nodes/trails/PresSlideBox.scss | 308 ++++++++++ src/client/views/nodes/trails/PresSlideBox.tsx | 628 +++++++++++++++++++++ src/client/views/nodes/trails/index.ts | 2 +- src/client/views/pdf/GPTPopup/GPTPopup.tsx | 2 +- src/client/views/search/FaceRecognitionHandler.tsx | 4 +- src/client/views/search/SearchBox.tsx | 2 +- src/client/views/smartdraw/StickerPalette.tsx | 13 +- src/debug/Repl.tsx | 6 +- src/fields/Doc.ts | 486 ++++++++-------- src/fields/List.ts | 6 +- src/fields/Proxy.ts | 64 +-- src/fields/Schema.ts | 21 +- src/fields/ScriptField.ts | 12 +- src/fields/Types.ts | 91 +-- src/fields/util.ts | 10 +- 83 files changed, 1799 insertions(+), 1806 deletions(-) delete mode 100644 src/client/views/nodes/trails/PresElementBox.scss delete mode 100644 src/client/views/nodes/trails/PresElementBox.tsx create mode 100644 src/client/views/nodes/trails/PresSlideBox.scss create mode 100644 src/client/views/nodes/trails/PresSlideBox.tsx (limited to 'src/client/views/nodes/trails') diff --git a/src/client/documents/DocUtils.ts b/src/client/documents/DocUtils.ts index 5a8230847..7845c80aa 100644 --- a/src/client/documents/DocUtils.ts +++ b/src/client/documents/DocUtils.ts @@ -55,13 +55,13 @@ export namespace DocUtils { const matchLink = (val: string, anchor: Doc) => { const linkedToExp = (val ?? '').split('='); if (linkedToExp.length === 1) return Field.toScriptString(anchor) === val; - return Field.toScriptString(DocCast(anchor[linkedToExp[0]])) === linkedToExp[1]; + return DocCast(anchor[linkedToExp[0]]) && Field.toScriptString(DocCast(anchor[linkedToExp[0]])!) === linkedToExp[1]; }; // prettier-ignore return (value === Doc.FilterNone && !allLinks.length) || (value === Doc.FilterAny && !!allLinks.length) || - (allLinks.some(link => matchLink(value as string, DocCast(link.link_anchor_1)) || - matchLink(value as string, DocCast(link.link_anchor_2)) )); + (allLinks.some(link => (DocCast(link.link_anchor_1) && matchLink(value as string, DocCast(link.link_anchor_1)!)) || + (DocCast(link.link_anchor_2) && matchLink(value as string, DocCast(link.link_anchor_2)!)) )); } if (typeof value === 'string') { value = value.replace(`,${ClientUtils.noRecursionHack}`, ''); @@ -266,7 +266,7 @@ export namespace DocUtils { Object.keys(funcs) .filter(key => !key.endsWith('-setter')) .forEach(key => { - const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key])); + const cfield = ComputedField.DisableCompute(() => FieldValue(doc[key])); const func = funcs[key]; if (ScriptCast(cfield)?.script.originalScript !== func) { const setFunc = Cast(funcs[key + '-setter'], 'string', null); @@ -375,12 +375,13 @@ export namespace DocUtils { const documentList: ContextMenuProps[] = foo .filter(btnDoc => !btnDoc.hidden) - .map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)) + .map(btnDoc => DocCast(btnDoc?.dragFactory)) .filter(doc => doc && doc !== Doc.UserDoc().emptyTrail && doc.title) + .map(doc => doc!) .map(dragDoc => ({ description: ':' + StrCast(dragDoc.title).replace('Untitled ', ''), event: undoable(() => { - const newDoc = (Doc.isTemplateDoc(dragDoc) ? DocUtils.delegateDragFactory : DocUtils.copyDragFactory)(dragDoc); + const newDoc = (dragDoc.isTemplateDoc ? DocUtils.delegateDragFactory : DocUtils.copyDragFactory)(dragDoc); if (newDoc) { newDoc._author = ClientUtils.CurrentUserEmail(); newDoc.x = x; @@ -437,6 +438,7 @@ export namespace DocUtils { .filter(btnDoc => !btnDoc.hidden) .map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)) .filter(doc => doc && doc !== Doc.UserDoc().emptyTrail && doc !== Doc.UserDoc().emptyNote && doc.title) + .map(doc => doc!) .map(dragDoc => ({ description: ':' + StrCast(dragDoc.title).replace('Untitled ', ''), event: undoable(() => { @@ -494,11 +496,11 @@ export namespace DocUtils { .map(btnDoc => (btnDoc.dragFactory as Doc) || btnDoc) .filter(d => d.isTemplateDoc); // bcz: this is hacky -- want to have different templates be applied depending on the "type" of a document. but type is not reliable and there could be other types of template searches so this should be generalized - // first try to find a template that matches the specific document type (_). otherwise, fallback to a general match on + // first try to find a template that matches the specific document type (). otherwise, fallback to a general match on !docLayoutTemplate && allTemplates.forEach(tempDoc => { const templateType = StrCast(doc[templateName + '_fieldKey'] || doc.type); - StrCast(tempDoc.title) === templateName + '_' + templateType && (docLayoutTemplate = tempDoc); + StrCast(tempDoc.title) === templateName + (templateType[0].toUpperCase() + templateType.slice(1)) && (docLayoutTemplate = tempDoc); }); !docLayoutTemplate && allTemplates.forEach(tempDoc => { @@ -522,18 +524,13 @@ export namespace DocUtils { Doc.ApplyTemplateTo(docLayoutTemplate, doc, customName, undefined); } } else { - let fieldTemplate: Opt; - if (doc.data instanceof RichTextField || typeof doc.data === 'string') { - fieldTemplate = Docs.Create.TextDocument('', options); - } else if (doc.data instanceof PdfField) { - fieldTemplate = Docs.Create.PdfDocument('http://www.msn.com', options); - } else if (doc.data instanceof VideoField) { - fieldTemplate = Docs.Create.VideoDocument('http://www.cs.brown.edu', options); - } else if (doc.data instanceof AudioField) { - fieldTemplate = Docs.Create.AudioDocument('http://www.cs.brown.edu', options); - } else if (doc.data instanceof ImageField) { - fieldTemplate = Docs.Create.ImageDocument('http://www.cs.brown.edu', options); - } + const fieldTemplate = (() => { + if (doc.data instanceof RichTextField || typeof doc.data === 'string') return Docs.Create.TextDocument('', options); + if (doc.data instanceof PdfField) return Docs.Create.PdfDocument('http://www.msn.com', options); + if (doc.data instanceof VideoField) return Docs.Create.VideoDocument('http://www.cs.brown.edu', options); + if (doc.data instanceof AudioField) return Docs.Create.AudioDocument('http://www.cs.brown.edu', options); + if (doc.data instanceof ImageField) return Docs.Create.ImageDocument('http://www.cs.brown.edu', options); + })(); const docTemplate = creator?.(fieldTemplate ? [fieldTemplate] : [], { title: customName + '(' + doc.title + ')', isTemplateDoc: true, _width: _width + 20, _height: Math.max(100, _height + 45) }); fieldTemplate && Doc.MakeMetadataFieldTemplate(fieldTemplate, docTemplate ? Doc.GetProto(docTemplate) : docTemplate); docTemplate && Doc.ApplyTemplateTo(docTemplate, doc, customName, undefined); @@ -904,8 +901,8 @@ export namespace DocUtils { return ndoc; } - export async function Zip(doc: Doc, zipFilename = 'dashExport.zip') { - const { clone, map, linkMap } = await Doc.MakeClone(doc); + export function Zip(doc: Doc, zipFilename = 'dashExport.zip') { + const { clone, map, linkMap } = Doc.MakeClone(doc); const proms = new Set(); function replacer(key: string, value: { url: string; [key: string]: unknown }) { if (key && ['branchOf', 'cloneOf', 'cursors'].includes(key)) return undefined; diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index dd0985182..5c6559836 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -36,7 +36,7 @@ export enum DocumentType { // special purpose wrappers that either take no data or are compositions of lower level types LINK = 'link', PRES = 'presentation', - PRESELEMENT = 'preselement', + PRESSLIDE = 'presslide', COMPARISON = 'comparison', PUSHPIN = 'pushpin', MAPROUTE = 'maproute', diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index d93a432d4..bf9cc5bd4 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -217,7 +217,7 @@ export class DocumentOptions { author?: string; // STRt = new StrInfo('creator of document'); // bcz: don't change this. Otherwise, the userDoc's field Infos will have a FieldInfo assigned to its author field which will render it unreadable author_date?: DATEt = new DateInfo('date the document was created', true); annotationOn?: DOCt = new DocInfo('document annotated by this document', false); - rootDocument?: DOCt = new DocInfo('document that supplies the information needed for a rendering template (eg, pres slide for PresElement)'); + rootDocument?: DOCt = new DocInfo('document that stores the data for compound template documents.'); color?: STRt = new StrInfo('foreground color data doc', false); hidden?: BOOLt = new BoolInfo('whether the document is not rendered by its collection', false); backgroundColor?: STRt = new StrInfo('background color for data doc', false); @@ -1139,8 +1139,8 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.FONTICON), undefined, { ...(options || {}) }); } - export function PresElementBoxDocument() { - return Prototypes.get(DocumentType.PRESELEMENT); + export function PresSlideDocument() { + return Prototypes.get(DocumentType.PRESSLIDE); } export function DataVizDocument(url: string, options?: DocumentOptions, overwriteDoc?: Doc) { @@ -1148,7 +1148,7 @@ export namespace Docs { } export function AnnoPaletteDocument(options?: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.ANNOPALETTE), new List([Doc.MyStickers]), { ...(options || {}) }); + return InstanceFromProto(Prototypes.get(DocumentType.ANNOPALETTE), new List([...(Doc.MyStickers ? [Doc.MyStickers] : [])]), { ...(options || {}) }); } export function DockDocument(documents: Array, config: string, options: DocumentOptions, id?: string) { diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 35dc5f1c7..1887c1716 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -148,12 +148,12 @@ export class CurrentUserUtils { { title: "Idea", backgroundColor: "pink", icon: "lightbulb" , _layout_showTitle: "title"}, { title: "Topic", backgroundColor: "lightblue", icon: "book-open" , _layout_showTitle: "title"}]; - + const metanote = DocCast(doc.emptyMetaNote); const reqdNoteList = [...reqdTempOpts.map(opts => { const reqdOpts = {...opts, isSystem:true, width:200, layout_autoHeight: true, layout_fitWidth: true}; const noteTemp = tempNotes ? DocListCast(tempNotes.data).find(fdoc => fdoc.title === opts.title): undefined; return DocUtils.AssignOpts(noteTemp, reqdOpts) ?? MakeTemplate(Docs.Create.TextDocument("",reqdOpts)); - }), DocCast(doc.emptyMetaNote), ... DocListCast(tempNotes?.data).filter(note => !reqdTempOpts.find(reqd => reqd.title === note.title))]; + }), ...(metanote ? [metanote]:[]), ... DocListCast(tempNotes?.data).filter(note => !reqdTempOpts.find(reqd => reqd.title === note.title))]; const reqdOpts:DocumentOptions = { title: "Note Layouts", _height: 75, isSystem: true }; return DocUtils.AssignOpts(tempNotes, reqdOpts, reqdNoteList) ?? (doc[field] = Docs.Create.TreeDocument(reqdNoteList, reqdOpts)); @@ -211,7 +211,7 @@ export class CurrentUserUtils { const fontBox = (opts:DocumentOptions, fieldKey:string) => Docs.Create.FontIconDocument({ layout:FontIconBox.LayoutString(fieldKey), _nativeHeight: 30, _nativeWidth: 30, _width: 30, _height: 30, ...opts }); const makeIconTemplate = (name: DocumentType | string | undefined, templateField: string, opts:DocumentOptions) => { - const title = "icon" + (name ? "_" + name : ""); + const title = "icon" + (name ? name[0].toUpperCase()+name.slice(1) : ""); const curIcon = DocCast(templateIconsDoc[title]); const creator = (() => { switch (opts.iconTemplate) { case DocumentType.IMG : return imageBox; @@ -424,7 +424,10 @@ pie title Minerals in my tap water const standardOps = (key:string) => ({ title : "Untitled "+ key, _layout_fitWidth: false, isSystem: true, "dragFactory_count": 0, cloneFieldFilter: new List(["isSystem"]) }); emptyThings.forEach( thing => DocUtils.AssignDocField(doc, "empty"+thing.key, (opts) => thing.creator(opts), {...standardOps(thing.key), ...thing.opts}, undefined, thing.scripts, thing.funcs)); - DocCast(Doc.UserDoc().emptyMetaNote).title = "MetaNote"; // hack: metanotes are used a template, so 'untitled metaNote' is an awkward name + const metanote = DocCast(Doc.UserDoc().emptyMetaNote); + if (metanote) { + metanote.title = "MetaNote"; // hack: metanotes are used a template, so 'untitled metaNote' is an awkward name + } return [ { toolTip: "Tap or drag to create a note", title: "Note", icon: "sticky-note", dragFactory: doc.emptyNote as Doc, clickFactory: DocCast(doc.emptyNote)}, @@ -490,7 +493,7 @@ pie title Minerals in my tap water { title: "Tools", toolTip: "Tools", target: this.setupToolsBtnPanel(doc, "myTools"), icon: "wrench", }, { title: "Imports", toolTip: "Imports ⌘I", target: this.setupImportSidebar(doc, "myImports"), icon: "upload", }, { title: "Closed", toolTip: "Recently Closed", target: this.setupRecentlyClosed(doc, "myRecentlyClosed"), icon: "archive", hidden: true }, // this doc is hidden from the Sidebar, but it's still being used in MyFilesystem which ignores the hidden field - { title: "Shared", toolTip: "Shared Docs", target: Doc.MySharedDocs, icon: "users", funcs: {badgeValue: badgeValue}}, + { title: "Shared", toolTip: "Shared Docs", target: Doc.MySharedDocs??Doc.UserDoc(), icon: "users", funcs: {badgeValue: badgeValue}}, { title: "Trails", toolTip: "Trails ⌘R", target: Doc.UserDoc(), icon: "pres-trail", funcs: {target: getActiveDashTrails}}, { title: "Image Grouper", toolTip: "Image Grouper", target: this.setupImageGrouper(doc, "myImageGrouper"), icon: "folder-open", hidden: false }, { title: "Faces", toolTip: "Unique Faces", target: this.setupFaceCollection(doc, "myFaceCollection"), icon: "face-smile", hidden: false }, @@ -551,7 +554,6 @@ pie title Minerals in my tap water const creatorBtns = CurrentUserUtils.setupCreatorButtons(doc, allTools?.length ? allTools[0]:undefined); const userTools = allTools && allTools?.length > 1 ? allTools[1]:undefined; const userBtns = CurrentUserUtils.setupUserDocumentCreatorButtons(doc, userTools); - // doc.myUserBtns = new PrefetchProxy(userBtns); const reqdToolOps:DocumentOptions = { title: "My Tools", isSystem: true, ignoreClick: true, layout_boxShadow: "0 0", layout_explainer: "This is a palette of documents that can be created.", _layout_dontCenter: "y", @@ -975,7 +977,10 @@ pie title Minerals in my tap water }; DocUtils.AssignDocField(doc, "mySharedDocs", opts => Docs.Create.TreeDocument([], opts, sharingDocumentId + "layout", sharingDocumentId), sharedDocOpts, undefined, sharedScripts); - if (!Doc.GetProto(DocCast(doc.mySharedDocs)).data_dashboards) Doc.GetProto(DocCast(doc.mySharedDocs)).data_dashboards = new List(); + const sharedDocs = DocCast(doc.mySharedDocs); + if (sharedDocs) { + if (!Doc.GetProto(sharedDocs).data_dashboards) Doc.GetProto(sharedDocs).data_dashboards = new List(); + } } /// Import option on the left side button panel @@ -1000,9 +1005,9 @@ pie title Minerals in my tap water static updateUserDocument(docIn: Doc, sharingDocumentId: string, linkDatabaseId: string) { const doc = docIn; DocUtils.AssignDocField(doc, "globalGroupDatabase", () => Docs.Prototypes.MainGroupDocument(), {}); - reaction(() => DateCast(DocCast(doc.globalGroupDatabase).data_modificationDate), + reaction(() => DateCast(DocCast(doc.globalGroupDatabase)?.data_modificationDate), async () => { - const groups = await DocListCastAsync(DocCast(doc.globalGroupDatabase).data); + const groups = await DocListCastAsync(DocCast(doc.globalGroupDatabase)?.data); const mygroups = groups?.filter(group => JSON.parse(StrCast(group.members)).includes(ClientUtils.CurrentUserEmail())) || []; SetCachedGroups(["Guest", ...(mygroups?.map(g => StrCast(g.title))??[])]); }, { fireImmediately: true }); @@ -1058,11 +1063,13 @@ pie title Minerals in my tap water SelectionManager.DeselectAll(); // this forces SelectionManager implementation to copy over to DocumentView's API. This also triggers the LinkManager to be created - Doc.AddDocToList(Doc.MyFilesystem, undefined, Doc.MyDashboards); - Doc.AddDocToList(Doc.MyFilesystem, undefined, Doc.MySharedDocs); - Doc.AddDocToList(Doc.MyFilesystem, undefined, Doc.MyRecentlyClosed); + if (Doc.MyFilesystem) { + Doc.MyDashboards && Doc.AddDocToList(Doc.MyFilesystem, undefined, Doc.MyDashboards); + Doc.MyDashboards && Doc.AddDocToList(Doc.MyFilesystem, undefined, Doc.MyDashboards); + Doc.MyRecentlyClosed && Doc.AddDocToList(Doc.MyFilesystem, undefined, Doc.MyRecentlyClosed); + } - Doc.GetProto(DocCast(Doc.UserDoc().emptyWebpage)).data = new WebField("https://www.wikipedia.org"); + DocCast(Doc.UserDoc().emptyWebpage) && (Doc.GetProto(DocCast(Doc.UserDoc().emptyWebpage)!).data = new WebField("https://www.wikipedia.org")); DocServer.CacheNeedsUpdate() && setTimeout(UPDATE_SERVER_CACHE, 2500); setInterval(UPDATE_SERVER_CACHE, 120000); @@ -1142,7 +1149,7 @@ pie title Minerals in my tap water const file = input.files?.[0]; if (file?.type === 'application/zip' || file?.type === 'application/x-zip-compressed') { const doc = await Doc.importDocument(file); - const list = Cast(Doc.MyImports.data, listSpec(Doc), null); + const list = Cast(Doc.MyImports?.data, listSpec(Doc), null); doc instanceof Doc && list?.splice(0, 0, doc); } else if (input.files && input.files.length !== 0) { const disposer = OverlayView.ShowSpinner(); @@ -1150,7 +1157,7 @@ pie title Minerals in my tap water if (results.length !== input.files?.length) { alert("Error uploading files - possibly due to unsupported file types"); } - const list = Cast(Doc.MyImports.data, listSpec(Doc), null); + const list = Cast(Doc.MyImports?.data, listSpec(Doc), null); list?.splice(0, 0, ...results); disposer(); } else { diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts index 2eef3da0e..dcef4a4fe 100644 --- a/src/client/util/DictationManager.ts +++ b/src/client/util/DictationManager.ts @@ -364,7 +364,7 @@ export namespace DictationManager { case 'nested collection':return Docs.Create.FreeformDocument([], {}); } // prettier-ignore })(); - created && Doc.AddDocToList(target.dataDoc, Doc.LayoutFieldKey(target.Document), created); + created && Doc.AddDocToList(target.dataDoc, Doc.LayoutDataKey(target.Document), created); } } }, diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 5ce005811..ad57c2a62 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -183,7 +183,7 @@ export class DocumentManager { static _howl: Howl; static playAudioAnno(doc: Doc) { - const anno = Cast(doc[Doc.LayoutFieldKey(doc) + '_audioAnnotations'], listSpec(AudioField), null)?.lastElement(); + const anno = Cast(doc[Doc.LayoutDataKey(doc) + '_audioAnnotations'], listSpec(AudioField), null)?.lastElement(); if (anno) { this._howl?.stop(); if (anno instanceof AudioField) { diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index e2e4c0fe4..a66e6998b 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -234,29 +234,27 @@ export namespace DragManager { dropDoc instanceof Doc && CreateLinkToActiveAudio(() => dropDoc); return dropDoc; }; - const finishDrag = async (e: DragCompleteEvent) => { + const finishDrag = (e: DragCompleteEvent) => { const { docDragData } = e; setTimeout(() => dragData.dragEnding?.()); onDropCompleted?.(e); // glr: optional additional function to be called - in this case with presentation trails if (docDragData && !docDragData.droppedDocuments.length) { docDragData.dropAction = dragData.userDropAction || dragData.dropAction; - docDragData.droppedDocuments = ( - await Promise.all( - dragData.draggedDocuments.map(async d => - !dragData.isDocDecorationMove && !dragData.userDropAction && ScriptCast(d.onDragStart) - ? addAudioTag(ScriptCast(d.onDragStart).script.run({ this: d }).result as Doc) - : docDragData.dropAction === dropActionType.embed - ? Doc.BestEmbedding(d) - : docDragData.dropAction === dropActionType.add - ? d - : docDragData.dropAction === dropActionType.proto - ? d[DocData] - : docDragData.dropAction === dropActionType.copy - ? (await Doc.MakeClone(d)).clone - : d - ) + docDragData.droppedDocuments = dragData.draggedDocuments + .map(d => + !dragData.isDocDecorationMove && !dragData.userDropAction && ScriptCast(d.onDragStart) + ? addAudioTag(ScriptCast(d.onDragStart)!.script.run({ this: d }).result as Doc) + : docDragData.dropAction === dropActionType.embed + ? Doc.BestEmbedding(d) + : docDragData.dropAction === dropActionType.add + ? d + : docDragData.dropAction === dropActionType.proto + ? d[DocData] + : docDragData.dropAction === dropActionType.copy + ? Doc.MakeClone(d).clone + : d ) - ).filter(d => d); + .filter(d => d); ![dropActionType.same, dropActionType.proto].includes(StrCast(docDragData.dropAction) as dropActionType) && docDragData.droppedDocuments // .filter(drop => !drop.dragOnlyWithinContainer || ['embed', 'copy'].includes(docDragData.dropAction as any)) @@ -364,7 +362,7 @@ export namespace DragManager { }; } - async function dispatchDrag(target: Element, e: PointerEvent, complete: DragCompleteEvent, pos: { x: number; y: number }, finishDrag?: (e: DragCompleteEvent) => void, options?: DragOptions, endDrag?: () => void) { + function dispatchDrag(target: Element, e: PointerEvent, complete: DragCompleteEvent, pos: { x: number; y: number }, finishDrag?: (e: DragCompleteEvent) => void, options?: DragOptions, endDrag?: () => void) { const dropArgs = { cancelable: true, // allows preventDefault() to be called to cancel the drop bubbles: true, @@ -380,7 +378,7 @@ export namespace DragManager { }; target.dispatchEvent(new CustomEvent('dashPreDrop', dropArgs)); UndoManager.StartTempBatch(); // run drag/drop in temp batch in case drop is not allowed (so we can undo any intermediate changes) - await finishDrag?.(complete); + finishDrag?.(complete); UndoManager.EndTempBatch(target.dispatchEvent(new CustomEvent('dashOnDrop', dropArgs))); // event return val is true unless the event preventDefault() is called options?.dragComplete?.(complete); endDrag?.(); @@ -566,11 +564,11 @@ export namespace DragManager { const targClassName = e.target instanceof HTMLElement && typeof e.target.className === 'string' ? e.target.className : ''; if (['lm_tab', 'lm_title_wrap', 'lm_tabs', 'lm_header'].includes(targClassName) && docDragData.draggedDocuments.length === 1) { if (!startWindowDragTimer) { - startWindowDragTimer = setTimeout(async () => { + startWindowDragTimer = setTimeout(() => { startWindowDragTimer = undefined; docDragData.dropAction = docDragData.userDropAction || dropActionType.same; AbortDrag(); - await finishDrag?.(new DragCompleteEvent(true, docDragData)); + finishDrag?.(new DragCompleteEvent(true, docDragData)); DragManager.StartWindowDrag?.(e, docDragData.droppedDocuments, aborted => { if (!aborted && (docDragData?.dropAction === dropActionType.move || docDragData?.dropAction === dropActionType.same)) { docDragData.removeDocument?.(docDragData?.draggedDocuments[0]); diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts index 7d3f63448..b6b111930 100644 --- a/src/client/util/DropConverter.ts +++ b/src/client/util/DropConverter.ts @@ -3,7 +3,7 @@ import { DocData, DocLayout } from '../../fields/DocSymbols'; import { ObjectField } from '../../fields/ObjectField'; import { RichTextField } from '../../fields/RichTextField'; import { ComputedField, ScriptField } from '../../fields/ScriptField'; -import { StrCast } from '../../fields/Types'; +import { DocCast, StrCast } from '../../fields/Types'; import { ImageField } from '../../fields/URLField'; import { Docs, DocumentOptions } from '../documents/Documents'; import { DocumentType } from '../documents/DocumentTypes'; @@ -23,7 +23,7 @@ import { ScriptingGlobals } from './ScriptingGlobals'; */ function makeTemplate(doc: Doc, first: boolean = true): boolean { const layoutDoc = doc.layout instanceof Doc && doc.layout.isTemplateForField ? doc.layout : doc; - if (layoutDoc.layout instanceof Doc) { + if (DocCast(layoutDoc.layout)) { return true; // its already a template } const layout = StrCast(layoutDoc.layout).match(/fieldKey={'[^']*'}/)?.[0]; @@ -68,7 +68,7 @@ export function MakeTemplate(doc: Doc) { * Makes a draggable button or image that will create a template doc Instance */ export function makeUserTemplateButtonOrImage(doc: Doc, image?: string) { - const layoutDoc = doc; // doc.layout instanceof Doc && doc.layout.isTemplateForField ? doc.layout : doc; + const layoutDoc = doc; if (layoutDoc.type !== DocumentType.FONTICON) { !layoutDoc.isTemplateDoc && makeTemplate(layoutDoc); } diff --git a/src/client/util/Import & Export/ImageUtils.ts b/src/client/util/Import & Export/ImageUtils.ts index 9c32ca25a..eae3460b3 100644 --- a/src/client/util/Import & Export/ImageUtils.ts +++ b/src/client/util/Import & Export/ImageUtils.ts @@ -15,7 +15,7 @@ export namespace ImageUtils { export const AssignImgInfo = (document: Doc, data?: Upload.InspectionResults) => { if (data) { data.nativeWidth && (document._height = (NumCast(document._width) * data.nativeHeight) / data.nativeWidth); - const field = '$' + Doc.LayoutFieldKey(document); + const field = '$' + Doc.LayoutDataKey(document); document[`${field}_nativeWidth`] = data.nativeWidth; document[`${field}_nativeHeight`] = data.nativeHeight; document[`${field}_path`] = data.source; diff --git a/src/client/util/LinkFollower.ts b/src/client/util/LinkFollower.ts index 0e67dcfaa..6081c3fae 100644 --- a/src/client/util/LinkFollower.ts +++ b/src/client/util/LinkFollower.ts @@ -43,13 +43,13 @@ export class LinkFollower { }; public static traverseLink(link: Opt, sourceDoc: Doc, finished?: () => void, traverseBacklink?: boolean) { - const getView = (doc: Doc) => DocumentView.getFirstDocumentView(DocCast(doc.layout_unrendered ? doc.annotationOn : doc)); - const isAnchor = (source: Doc, anchor: Doc) => Doc.AreProtosEqual(anchor, source) || Doc.AreProtosEqual(anchor.annotationOn as Doc, source); + const getView = (doc: Doc) => DocumentView.getFirstDocumentView(DocCast(doc.layout_unrendered ? doc.annotationOn : doc)!); + const isAnchor = (source?: Doc, anchor?: Doc) => Doc.AreProtosEqual(anchor, source) || Doc.AreProtosEqual(DocCast(anchor?.annotationOn), source); const linkDocs = link ? [link] : Doc.Links(sourceDoc); - const fwdLinks = linkDocs.filter(l => isAnchor(sourceDoc, l.link_anchor_1 as Doc)); // link docs where 'sourceDoc' is link_anchor_1 - const backLinks = linkDocs.filter(l => isAnchor(sourceDoc, l.link_anchor_2 as Doc)); // link docs where 'sourceDoc' is link_anchor_2 - const fwdLinkWithoutTargetView = fwdLinks.find(l => !getView(DocCast(l.link_anchor_2))); - const backLinkWithoutTargetView = backLinks.find(l => !getView(DocCast(l.link_anchor_1))); + const fwdLinks = linkDocs.filter(l => isAnchor(sourceDoc, DocCast(l.link_anchor_1))); // link docs where 'sourceDoc' is link_anchor_1 + const backLinks = linkDocs.filter(l => isAnchor(sourceDoc, DocCast(l.link_anchor_2))); // link docs where 'sourceDoc' is link_anchor_2 + const fwdLinkWithoutTargetView = fwdLinks.find(l => !DocCast(l.link_anchor_2) || !getView(DocCast(l.link_anchor_2)!)); + const backLinkWithoutTargetView = backLinks.find(l => !DocCast(l.link_anchor_1) || !getView(DocCast(l.link_anchor_1)!)); const linkWithoutTargetDoc = traverseBacklink === undefined ? (fwdLinkWithoutTargetView ?? backLinkWithoutTargetView) : traverseBacklink ? backLinkWithoutTargetView : fwdLinkWithoutTargetView; const linkDocList = linkWithoutTargetDoc && !sourceDoc.followAllLinks ? [linkWithoutTargetDoc] : traverseBacklink === undefined ? fwdLinks.concat(backLinks) : traverseBacklink ? backLinks : fwdLinks; const followLinks = sourceDoc.followLinkToggle || sourceDoc.followAllLinks ? linkDocList : linkDocList.slice(0, 1); @@ -60,17 +60,17 @@ export class LinkFollower { return false; } followLinks.forEach(async linkDoc => { - const target = ( + const target = DocCast( sourceDoc === linkDoc.link_anchor_1 ? linkDoc.link_anchor_2 : sourceDoc === linkDoc.link_anchor_2 ? linkDoc.link_anchor_1 - : Doc.AreProtosEqual(sourceDoc, linkDoc.link_anchor_1 as Doc) || Doc.AreProtosEqual((linkDoc.link_anchor_1 as Doc).annotationOn as Doc, sourceDoc) + : Doc.AreProtosEqual(sourceDoc, DocCast(linkDoc.link_anchor_1)) || Doc.AreProtosEqual(DocCast(DocCast(linkDoc.link_anchor_1)?.annotationOn), sourceDoc) ? linkDoc.link_anchor_2 : linkDoc.link_anchor_1 - ) as Doc; - const srcAnchor: Doc = Doc.getOppositeAnchor(linkDoc, target) ?? sourceDoc; + ); if (target) { + const srcAnchor = Doc.getOppositeAnchor(linkDoc, target) ?? sourceDoc; const doFollow = (canToggle?: boolean) => { const toggleTarget = canToggle && BoolCast(sourceDoc.followLinkToggle); const options: FocusViewOptions = { @@ -102,14 +102,16 @@ export class LinkFollower { if (srcAnchor.followLinkLocation === OpenWhere.inParent) { const sourceDocParent = DocCast(sourceDoc.embedContainer); if (target.embedContainer instanceof Doc && target.embedContainer !== sourceDocParent) { - Doc.RemoveDocFromList(target.embedContainer, Doc.LayoutFieldKey(target.embedContainer), target); + Doc.RemoveDocFromList(target.embedContainer, Doc.LayoutDataKey(target.embedContainer), target); movedTarget = true; } - if (!DocListCast(sourceDocParent[Doc.LayoutFieldKey(sourceDocParent)]).includes(target)) { - Doc.AddDocToList(sourceDocParent, Doc.LayoutFieldKey(sourceDocParent), target); - movedTarget = true; + if (sourceDocParent) { + if (!DocListCast(sourceDocParent[Doc.LayoutDataKey(sourceDocParent)]).includes(target)) { + Doc.AddDocToList(sourceDocParent, Doc.LayoutDataKey(sourceDocParent), target); + movedTarget = true; + } + Doc.SetContainer(target, sourceDocParent); } - Doc.SetContainer(target, sourceDocParent); } const moveTo = [NumCast(sourceDoc.x) + NumCast(sourceDoc.followLinkXoffset), NumCast(sourceDoc.y) + NumCast(sourceDoc.followLinkYoffset)]; if (srcAnchor.followLinkXoffset !== undefined && moveTo[0] !== target.x) { diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 3f98ab3c4..344e2e4c0 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -136,7 +136,7 @@ export class LinkManager { true ); FieldLoader.ServerLoadStatus.message = 'links'; - this.addLinkDB(Doc.LinkDBDoc()); + Doc.LinkDBDoc() && this.addLinkDB(Doc.LinkDBDoc()!); } public createlink_relationshipLists = () => { @@ -148,16 +148,21 @@ export class LinkManager { public addLink(linkDoc: Doc, checkExists = false) { Doc.AddDocToList(Doc.UserDoc(), 'links', linkDoc); - if (!checkExists || !DocListCast(Doc.LinkDBDoc().data).includes(linkDoc)) { - Doc.AddDocToList(Doc.LinkDBDoc(), 'data', linkDoc); - // eslint-disable-next-line no-use-before-define - setTimeout(UPDATE_SERVER_CACHE, 100); + if (Doc.LinkDBDoc()) { + if (!checkExists || !DocListCast(Doc.LinkDBDoc()!.data).includes(linkDoc)) { + Doc.AddDocToList(Doc.LinkDBDoc()!, 'data', linkDoc); + // eslint-disable-next-line no-use-before-define + setTimeout(UPDATE_SERVER_CACHE, 100); + } } } public deleteLink(linkDoc: Doc) { - const ret = Doc.RemoveDocFromList(Doc.LinkDBDoc(), 'data', linkDoc); - linkDoc.$link_anchor_1 = linkDoc.$link_anchor_2 = undefined; - return ret; + if (Doc.LinkDBDoc()) { + const ret = Doc.RemoveDocFromList(Doc.LinkDBDoc()!, 'data', linkDoc); + linkDoc.$link_anchor_1 = linkDoc.$link_anchor_2 = undefined; + return ret; + } + return false; } public deleteAllLinksOnAnchor(anchor: Doc) { LinkManager.Instance.relatedLinker(anchor).forEach(LinkManager.Instance.deleteLink); @@ -178,8 +183,8 @@ export class LinkManager { } const dirLinks = Array.from(anchor[DocData][DirectLinks]).filter(l => Doc.GetProto(anchor) === anchor[DocData] || ['1', '2'].includes(LinkManager.anchorIndex(l, anchor) as '0' | '1' | '2')); - const anchorRoot = DocCast(anchor.rootDocument, anchor); // template Doc fields store annotations on the topmost root of a template (not on themselves since the template layout items are only for layout) - const annos = DocListCast(anchorRoot[Doc.LayoutFieldKey(anchor) + '_annotations']); + const anchorRoot = DocCast(anchor.rootDocument, anchor)!; // template Doc fields store annotations on the topmost root of a template (not on themselves since the template layout items are only for layout) + const annos = DocListCast(anchorRoot[Doc.LayoutDataKey(anchor) + '_annotations']); return Array.from( annos.reduce((set, anno) => { if (!processed.includes(anno)) { @@ -242,11 +247,13 @@ export function UPDATE_SERVER_CACHE() { .filter(doc => doc instanceof Doc) .map(doc => doc as Doc); const references = new Set(prototypes); + DocCast(Doc.UserDoc().myLinkDatabase) && references.add(DocCast(Doc.UserDoc().myLinkDatabase)!); // prevent crawling through link database here -- see below Doc.FindReferences(Doc.UserDoc(), references, undefined); - DocListCast(DocCast(Doc.UserDoc().myLinkDatabase).data).forEach(link => { - if (!references.has(DocCast(link.link_anchor_1)) && !references.has(DocCast(link.link_anchor_2))) { - Doc.RemoveDocFromList(DocCast(Doc.UserDoc().myLinkDatabase), 'data', link); - Doc.AddDocToList(Doc.MyRecentlyClosed, undefined, link); + + DocListCast(DocCast(Doc.UserDoc().myLinkDatabase)?.data).forEach(link => { + if (DocCast(link.link_anchor_1) && !references.has(DocCast(link.link_anchor_1)!) && DocCast(link.link_anchor_2) && !references.has(DocCast(link.link_anchor_2)!)) { + DocCast(Doc.UserDoc().myLinkDatabase) && Doc.RemoveDocFromList(DocCast(Doc.UserDoc().myLinkDatabase)!, 'data', link); + Doc.MyRecentlyClosed && Doc.AddDocToList(Doc.MyRecentlyClosed, undefined, link); } }); LinkManager.Instance.userLinkDBs.forEach(linkDb => Doc.FindReferences(linkDb, references, undefined)); @@ -257,10 +264,10 @@ export function UPDATE_SERVER_CACHE() { cacheDocumentIds = newCacheUpdate; // print out cached docs - //Doc.MyDockedBtns.linearView_IsOpen && console.log('Set cached docs = '); - // const isFiltered = filtered.filter(doc => !Doc.IsSystem(doc)); - // const strings = isFiltered.map(doc => StrCast(doc.title) + ' ' + (Doc.IsDataProto(doc) ? '(data)' : '(embedding)')); - //Doc.MyDockedBtns.linearView_IsOpen && strings.sort().forEach((str, i) => console.log(i.toString() + ' ' + str)); + Doc.MyDockedBtns?.linearView_IsOpen && console.log('Set cached docs = '); + const isFiltered = filtered.filter(doc => !Doc.IsSystem(doc)); + const strings = isFiltered.map(doc => StrCast(doc.title) + ' ' + (Doc.IsDataProto(doc) ? '(data)' : '(embedding)')); + Doc.MyDockedBtns?.linearView_IsOpen && strings.sort().forEach((str, i) => console.log(i.toString() + ' ' + str)); rp.post(ClientUtils.prepend('/setCacheDocumentIds'), { body: { diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts index 733eae5f4..e4adcaa7e 100644 --- a/src/client/util/SearchUtil.ts +++ b/src/client/util/SearchUtil.ts @@ -9,7 +9,7 @@ export namespace SearchUtil { export type HighlightingResult = { [id: string]: { [key: string]: string[] } }; export function SearchCollection(collectionDoc: Opt, queryIn: string, matchKeyNames: boolean, onlyKeys?: string[]) { - const blockedTypes = [DocumentType.PRESELEMENT, DocumentType.CONFIG, DocumentType.KVP, DocumentType.FONTICON, DocumentType.BUTTON, DocumentType.SCRIPTING]; + const blockedTypes = [DocumentType.PRESSLIDE, DocumentType.CONFIG, DocumentType.KVP, DocumentType.FONTICON, DocumentType.BUTTON, DocumentType.SCRIPTING]; const blockedKeys = matchKeyNames ? [] : Object.entries(DocOptions) @@ -21,7 +21,7 @@ export namespace SearchUtil { const results = new ObservableMap(); if (collectionDoc) { - const docs = DocListCast(collectionDoc[Doc.LayoutFieldKey(collectionDoc)]); + const docs = DocListCast(collectionDoc[Doc.LayoutDataKey(collectionDoc)]); // eslint-disable-next-line @typescript-eslint/ban-types const docIDs: String[] = []; SearchUtil.foreachRecursiveDoc(docs, (depth: number, doc: Doc) => { @@ -77,7 +77,7 @@ export namespace SearchUtil { // eslint-disable-next-line no-loop-func docs.filter(d => d && !visited.includes(d)).forEach(d => { visited.push(d); - const fieldKey = Doc.LayoutFieldKey(d); + const fieldKey = Doc.LayoutDataKey(d); const annos = !Field.toString(Doc.LayoutField(d) as FieldType).includes('CollectionView'); const data = d[annos ? fieldKey + '_annotations' : fieldKey]; data && newarray.push(...DocListCast(data)); diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index 88f1f3260..9e79fd870 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -578,7 +578,7 @@ export class SettingsManager extends React.Component {
{ClientUtils.CurrentUserEmail()}
-