import { Colors } from 'browndash-components'; import { action, runInAction } from 'mobx'; import { aggregateBounds } from '../../../Utils'; import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { DocData } from '../../../fields/DocSymbols'; import { InkTool } from '../../../fields/InkField'; import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types'; import { WebField } from '../../../fields/URLField'; import { Gestures } from '../../../pen-gestures/GestureTypes'; import { DocumentType } from '../../documents/DocumentTypes'; import { LinkManager } from '../../util/LinkManager'; import { ScriptingGlobals } from '../../util/ScriptingGlobals'; import { UndoManager, undoable } from '../../util/UndoManager'; import { GestureOverlay } from '../GestureOverlay'; import { InkingStroke } from '../InkingStroke'; import { CollectionFreeFormView } from '../collections/collectionFreeForm'; import { CollectionFreeFormDocumentView } from '../nodes/CollectionFreeFormDocumentView'; import { ActiveEraserWidth, ActiveFillColor, ActiveInkColor, ActiveInkHideTextLabels, ActiveInkWidth, ActiveIsInkMask, DocumentView, SetActiveFillColor, SetActiveInkColor, SetActiveInkHideTextLabels, SetActiveInkWidth, SetActiveIsInkMask, SetEraserWidth, } from '../nodes/DocumentView'; import { ImageBox } from '../nodes/ImageBox'; import { VideoBox } from '../nodes/VideoBox'; import { WebBox } from '../nodes/WebBox'; import { RichTextMenu } from '../nodes/formattedText/RichTextMenu'; import { NumListCast, StrListCast } from '../../../fields/Doc'; import { List } from '../../../fields/List'; import { CollectionViewType } from '../../documents/DocumentTypes'; // import { InkTranscription } from '../InkTranscription'; import { Docs } from '../../documents/Documents'; import { CollectionSubView } from '../collections/CollectionSubView'; import { GPTPopup, GPTPopupMode } from '../pdf/GPTPopup/GPTPopup'; import { PropertiesView } from '../PropertiesView'; import { MainView } from '../MainView'; import { SnappingManager } from '../../util/SnappingManager'; // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function IsNoneSelected() { return DocumentView.Selected().length <= 0; }, 'are no document selected'); // toggle: Set overlay status of selected document // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function setView(view: string, getSelected: boolean) { if (getSelected) return DocumentView.SelectedDocs(); const selected = DocumentView.SelectedDocs().lastElement(); selected ? (selected._type_collection = view) : console.log('[FontIconBox.tsx] changeView failed'); return undefined; }); // toggle: Set overlay status of selected document // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: boolean) { const selectedViews = DocumentView.Selected(); if (Doc.ActiveTool !== InkTool.None && !selectedViews.lastElement()?.Document._layout_isSvg) { if (checkResult) { return ActiveFillColor(); } SetActiveFillColor(color ?? 'transparent'); } else if (selectedViews.length) { if (checkResult) { const selView = selectedViews.lastElement(); const fieldKey = selView.Document._layout_isSvg ? 'fillColor' : 'backgroundColor'; const layoutFrameNumber = Cast(selView.containerViewPath?.().lastElement()?.Document?._currentFrame, 'number'); // frame number that container is at which determines layout frame values const contentFrameNumber = Cast(selView.Document?._currentFrame, 'number', layoutFrameNumber ?? null); // frame number that content is at which determines what content is displayed return CollectionFreeFormDocumentView.getStringValues(selView?.Document, contentFrameNumber)[fieldKey] ?? 'transparent'; } selectedViews.some(dv => dv.ComponentView instanceof InkingStroke) && SetActiveFillColor(color ?? 'transparent'); selectedViews.forEach(dv => { const fieldKey = dv.Document._layout_isSvg ? 'fillColor' : 'backgroundColor'; const layoutFrameNumber = Cast(dv.containerViewPath?.().lastElement()?.Document?._currentFrame, 'number'); // frame number that container is at which determines layout frame values const contentFrameNumber = Cast(dv.Document?._currentFrame, 'number', layoutFrameNumber ?? null); // frame number that content is at which determines what content is displayed if (contentFrameNumber !== undefined) { const obj: { [key: string]: Opt } = {}; obj[fieldKey] = color; CollectionFreeFormDocumentView.setStringValues(contentFrameNumber, dv.Document, obj); } else { const dataKey = Doc.LayoutFieldKey(dv.Document); const alternate = (dv.layoutDoc[dataKey + '_usePath'] ? '_' + dv.layoutDoc[dataKey + '_usePath'] : '').replace(':hover', ''); dv.dataDoc[fieldKey + alternate] = color; } }); } else { const selected = DocumentView.SelectedDocs().length ? DocumentView.SelectedDocs() : LinkManager.Instance.currentLink ? [LinkManager.Instance.currentLink] : []; if (checkResult) { return selected.lastElement()?._backgroundColor ?? 'transparent'; } SetActiveFillColor(color ?? 'transparent'); selected.forEach(doc => { doc[DocData].backgroundColor = color; }); // prettier-ignore } return ''; }); // toggle: Set overlay status of selected document // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function setDefaultTemplate(checkResult?: boolean) { return DocumentView.setDefaultTemplate(checkResult); }); // toggle: Set overlay status of selected document // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function setHeaderColor(color?: string, checkResult?: boolean) { if (checkResult) { return DocumentView.Selected().length ? StrCast(DocumentView.SelectedDocs().lastElement().layout_headingColor) : Doc.SharingDoc().headingColor; } if (DocumentView.Selected().length) { DocumentView.SelectedDocs().forEach(doc => { doc[DocData].layout_headingColor = color === 'transparent' ? undefined : color; doc.layout_showTitle = color === 'transparent' ? undefined : StrCast(doc.layout_showTitle, 'title'); }); } else { Doc.SharingDoc().headingColor = undefined; Doc.GetProto(Doc.SharingDoc()).headingColor = color === 'transparent' ? undefined : color; Doc.UserDoc().layout_showTitle = color === 'transparent' ? undefined : StrCast(Doc.UserDoc().layout_showTitle, 'title'); } return undefined; }); // toggle: Set overlay status of selected document // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) { const selected = DocumentView.Selected().length ? DocumentView.Selected()[0] : undefined; if (checkResult) { if (NumCast(selected?.Document.z) >= 1) return true; return false; } selected ? CollectionFreeFormDocumentView.from(selected)?.float() : console.log('[FontIconBox.tsx] toggleOverlay failed'); return undefined; }); // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines' | 'clusters' | 'viewAll' | 'fitOnce', checkResult?: boolean, persist?: boolean) { const selected = DocumentView.SelectedDocs().lastElement(); function isAttrFiltered(attr: string) { return StrListCast(selected._childFilters).some(filter => filter.includes(attr)); } // prettier-ignore const map: Map<'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'chat' | 'up' | 'down' | 'pile' | 'toggle-chat' | 'tag', { waitForRender?: boolean; checkResult: (doc: Doc) => any; setDoc: (doc: Doc, dv: DocumentView) => void; }> = new Map([ ['grid', { checkResult: (doc: Doc) => BoolCast(doc?._freeform_backgroundGrid, false), setDoc: (doc: Doc) => { doc._freeform_backgroundGrid = !doc._freeform_backgroundGrid; }, }], ['snaplines', { checkResult: (doc: Doc) => BoolCast(doc?._freeform_snapLines, false), setDoc: (doc: Doc) => { doc._freeform_snapLines = !doc._freeform_snapLines; }, }], ['viewAll', { checkResult: (doc: Doc) => BoolCast(doc?._freeform_fitContentsToBox, false), setDoc: (doc: Doc, dv: DocumentView) => { if (persist) doc._freeform_fitContentsToBox = !doc._freeform_fitContentsToBox; else if (doc._freeform_fitContentsToBox) doc._freeform_fitContentsToBox = undefined; else (dv.ComponentView as CollectionFreeFormView)?.fitContentOnce(); }, }], ['center', { checkResult: (doc: Doc) => BoolCast(doc?._stacking_alignCenter, false), setDoc: (doc: Doc) => { doc._stacking_alignCenter = !doc._stacking_alignCenter; }, }], ['clusters', { waitForRender: true, // flags that undo batch should terminate after a re-render giving the script the chance to fire checkResult: (doc: Doc) => BoolCast(doc?._freeform_useClusters, false), setDoc: (doc: Doc) => { doc._freeform_useClusters = !doc._freeform_useClusters; }, }], ['flashcards', { checkResult: (doc: Doc) => BoolCast(Doc.UserDoc().defaultToFlashcards, false), setDoc: (doc: Doc, dv: DocumentView) => Doc.UserDoc().defaultToFlashcards = !Doc.UserDoc().defaultToFlashcards, }], ['time', { checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "time", setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort === "time" ? doc.cardSort = '' : doc.cardSort = 'time', }], ['docType', { checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "type", setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort === "type" ? doc.cardSort = '' : doc.cardSort = 'type', }], ['color', { checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "color", setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort === "color" ? doc.cardSort = '' : doc.cardSort = 'color', }], ['tag', { checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "tag", setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort === "tag" ? doc.cardSort = '' : doc.cardSort = 'tag', }], // ['heart', { // checkResult: (doc: Doc) => isAttrFiltered('heart'), // setDoc: (doc: Doc, dv: DocumentView) => { // isAttrFiltered('heart') ? Doc.setDocFilter(doc, 'heart', true, 'remove') : Doc.setDocFilter(doc, 'heart', true, 'match'); // } // }], // ['star', { // checkResult: (doc: Doc) => isAttrFiltered('star'), // setDoc: (doc: Doc, dv: DocumentView) => { // isAttrFiltered('star') ? Doc.setDocFilter(doc, 'star', true, 'remove') : Doc.setDocFilter(doc, 'star', true, 'match'); // } // }], // ['bolt', { // checkResult: (doc: Doc) => isAttrFiltered('bolt'), // setDoc: (doc: Doc, dv: DocumentView) => { // isAttrFiltered('bolt') ? Doc.setDocFilter(doc, 'bolt', true, 'remove') : Doc.setDocFilter(doc, 'bolt', true, 'match'); // } // }], // ['cloud', { // checkResult: (doc: Doc) => isAttrFiltered('cloud'), // setDoc: (doc: Doc, dv: DocumentView) => { // isAttrFiltered('cloud') ? Doc.setDocFilter(doc, 'cloud', true, 'remove') : Doc.setDocFilter(doc, 'cloud', true, 'match'); // } // }], // ['chat', { // checkResult: (doc: Doc) => { // if (StrCast(doc?.cardSort) === "chat"){ // return true // }} , // setDoc: (doc: Doc, dv: DocumentView) => { // doc.cardSort === "chat" ? doc.cardSort = '' : doc.cardSort = 'chat'; // }, // }], ['up', { checkResult: (doc: Doc) => BoolCast(!doc?.cardSort_isDesc), setDoc: (doc: Doc, dv: DocumentView) => { doc.cardSort_isDesc = false; }, }], ['down', { checkResult: (doc: Doc) => BoolCast(doc?.cardSort_isDesc), setDoc: (doc: Doc, dv: DocumentView) => { doc.cardSort_isDesc = true; }, }], ['toggle-chat', { checkResult: (doc: Doc) => GPTPopup.Instance.visible, setDoc: (doc: Doc, dv: DocumentView) => { GPTPopup.Instance.setVisible(!GPTPopup.Instance.visible); GPTPopup.Instance.setMode(GPTPopupMode.SORT); doc.cardSort === "chat" ? doc.cardSort = '' : doc.cardSort = 'chat'; }, }], ['pile', { checkResult: (doc: Doc) => doc._type_collection == CollectionViewType.Freeform, setDoc: (doc: Doc, dv: DocumentView) => { doc._type_collection = CollectionViewType.Freeform; const newCol = Docs.Create.CarouselDocument(DocListCast(doc[Doc.LayoutFieldKey(doc)]), { _width: 250, _height: 200, _layout_fitWidth: false, _layout_autoHeight: true, }); const iconMap: { [key: number]: any } = { 0: 'star', 1: 'heart', 2: 'cloud', 3: 'bolt' }; for (let i=0; i<4; i++){ if (isAttrFiltered(iconMap[i])){ newCol[iconMap[i]] = true } } newCol && dv.ComponentView?.addDocument?.(newCol); DocumentView.showDocument(newCol, { willZoomCentered: true }) }, }], ]); if (checkResult) { return map.get(attr)?.checkResult(selected); } const filters = StrListCast(selected._childFilters).concat(StrListCast(selected?._childFiltersByRanges).filter((filter, i) => !(i % 3))); // console.log(filters.some(filter => filter.includes('star'))+ "SUOOOOPPP") const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} }; DocumentView.Selected().map(dv => map.get(attr)?.setDoc(dv.layoutDoc, dv)); setTimeout(() => batch.end(), 100); return undefined; }); ScriptingGlobals.add(function handleTags(value?: any, checkResult?: boolean) { const selected = DocumentView.SelectedDocs().lastElement(); function isAttrFiltered(attr: string) { return StrListCast(selected._childFilters).some(filter => filter.includes(attr)); } if (checkResult) { return value=== 'opts' ? PropertiesView.Instance.openFilters : isAttrFiltered(value) } if (value != 'opts'){ isAttrFiltered(value) ? Doc.setDocFilter(selected, value, true, 'remove') : Doc.setDocFilter(selected, value, true, 'match'); } else { SnappingManager.PropertiesWidth < 5 && SnappingManager.SetPropertiesWidth(0); SnappingManager.SetPropertiesWidth(MainView.Instance.propertiesWidth() < 15 ? Math.min(MainView.Instance._dashUIWidth - 50, 250) : 0); PropertiesView.Instance.CloseAll() PropertiesView.Instance.openFilters = true } return undefined; }, ''); // ScriptingGlobals.add(function cardHasLabel(label: string) { // const selected = DocumentView.SelectedDocs().lastElement(); // const labelNum = Number(label) - 1; // return labelNum < 4 || (selected && DocListCast(selected[Doc.LayoutFieldKey(selected)]).some(doc => doc[StrCast(selected.cardSort_customField)] == labelNum)); // }, ''); // ScriptingGlobals.add(function setCardSort(attr: "Time" | "Type"| "Color"| "ChatGPT"| "Custom 1"| "Custom 2"| "Custom 3", value?: any, checkResult?: boolean) { // // const editorView = RichTextMenu.Instance?.TextView?.EditorView; // const selected = DocumentView.SelectedDocs().lastElement(); // // prettier-ignore // const map: Map<"Time" | "Type"| "Color"| "ChatGPT"| "Custom 1"| "Custom 2"| "Custom 3", { checkResult: (doc: Doc) => any; setDoc: (doc: Doc) => void;}> = new Map([ // ['Time', { // checkResult: (doc: Doc) => {StrCast(doc?.cardSort); // console.log(StrCast(doc?.cardSort + "card sort"))}, // setDoc: (doc: Doc) => {doc.cardSort = "time" // console.log("hewwo")} // , // }], // ['Type', { // checkResult: (doc: Doc) => StrCast(doc?.cardSort), // setDoc: (doc: Doc) => doc.cardSort = "type", // }], // ['Color', { // checkResult: (doc: Doc) => StrCast(doc?.cardSort), // setDoc: (doc: Doc) => doc.cardSort = "color", // }], // // ['links', { // // checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "links", // // setDoc: (doc: Doc) => doc.cardSort = "links", // // }], // ['Custom 1', { // checkResult: (doc: Doc) => StrCast(doc?.cardSort) + " 1", // setDoc: (doc: Doc) => { // doc.cardSort = "custom"; // doc.cardSort_customField = "like"; // doc.cardSort_visibleSortGroups = new List(); // } // }], // ['Custom 2', { // checkResult: (doc: Doc) => StrCast(doc?.cardSort) + " 2", // setDoc: (doc: Doc) => { // doc.cardSort = "custom"; // doc.cardSort_customField = "star"; // doc.cardSort_visibleSortGroups = new List(); // } // }], // ['Custom 3', { // checkResult: (doc: Doc) => StrCast(doc?.cardSort) + " 3", // setDoc: (doc: Doc) => { // doc.cardSort = "custom"; // doc.cardSort_customField = "idea"; // doc.cardSort_visibleSortGroups = new List(); // } // }], // ['ChatGPT', { // checkResult: (doc: Doc) => StrCast(doc?.cardSort_customField), // setDoc: (doc: Doc) => { // doc.cardSort = "custom"; // doc.cardSort_customField = "chat"; // doc.cardSort_visibleSortGroups = new List(); // }, // }], // ]); // for (let i = 0; i < 8; i++) { // map.set((i + 1 + '') as any, { // checkResult: (doc: Doc) => NumListCast(doc?.cardSort_visibleSortGroups).includes(i), // setDoc: (doc: Doc) => { // const list = NumListCast(doc.cardSort_visibleSortGroups); // doc.cardSort_visibleSortGroups = new List(list.includes(i) ? list.filter(d => d !== i) : [...list, i]); // }, // }); // } // if (checkResult) { // console.log(attr + "attricute") // console.log(map.get(attr)?.checkResult(selected) + "check result") // return map.get(attr)?.checkResult(selected); // } // console.log(attr + "attricute lol") // // const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} }; // DocumentView.Selected().map(dv => map.get(attr)?.setDoc(dv.layoutDoc)); // // setTimeout(() => batch.end(), 100); // return undefined; // // map.get(attr)?.setDoc?.(); // // return undefined; // }); // ScriptingGlobals.add(function setCardSort(value?: any, checkResult?: boolean) { // // const editorView = RichTextMenu.Instance?.TextView?.EditorView; // const selected = DocumentView.SelectedDocs().lastElement(); // if (checkResult) { // // console.log(attr + "attricute") // // console.log(map.get(attr)?.checkResult(selected) + "check result") // console.log(StrCast(selected?.cardSort) + 'check'); // const hi = StrCast(selected?.cardSort); // return StrCast(selected?.cardSortForDropDown) ?? 'Time'; // } // function docFields(doc: Doc): void { // switch (value) { // case 'Custom 1': // doc.cardSort_customField = 'like'; // break; // case 'Custom 2': // doc.cardSort_customField = 'star'; // break; // case 'Custom 3': // doc.cardSort_customField = 'idea'; // break; // case 'Chat GPT': // doc.cardSort = 'custom'; // doc.cardSort_customField = 'chat'; // break; // default: // break; // } // doc.cardSort_visibleSortGroups = new List(); // } // // const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} }; // DocumentView.Selected().map(dv => { // dv.Document.cardSortForDropDown = value; // if (value != 'Chat GPT') { // dv.Document.cardSort = value.trim().split(/\s+/)[0].toLowerCase(); // } // docFields(dv.Document); // }); // return undefined; // // map.get(attr)?.setDoc?.(); // // return undefined; // }); // ScriptingGlobals.add(function setCardSortAttr(attr: 'time' | 'docType' | 'color', value: any, checkResult?: boolean) { // // const editorView = RichTextMenu.Instance?.TextView?.EditorView; // const selected = SelectionManager.Docs.lastElement(); // // prettier-ignore // const map: Map<'time' | 'docType' | 'color', { waitForRender?: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc, dv:DocumentView) => void;}> = new Map([ // ['time', { // checkResult: (doc:Doc) => StrCast(doc?.cardSort), // setDoc: (doc:Doc,dv:DocumentView) => doc.cardSort = "time", // }], // ['docType', { // checkResult: (doc:Doc) => StrCast(doc?.cardSort), // setDoc: (doc:Doc,dv:DocumentView) => doc.cardSort = "type", // }], // ['color', { // checkResult: (doc:Doc) => StrCast(doc?.cardSort), // setDoc: (doc:Doc,dv:DocumentView) => doc.cardSort = "color", // }], // // ['custom', { // // checkResult: () => RichTextMenu.Instance.textAlign, // // setDoc: () => value && editorView?.state ? RichTextMenu.Instance.align(editorView, editorView.dispatch, value):(Doc.UserDoc().textAlign = value), // // }] // // , // ]); // if (checkResult) { // return map.get(attr)?.checkResult(selected); // } // console.log('hey') // SelectionManager.Views.map(dv => map.get(attr)?.setDoc(dv.layoutDoc, dv)); // console.log('success') // }); // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highlight' | 'fontSize' | 'alignment', value: any, checkResult?: boolean) { const editorView = RichTextMenu.Instance?.TextView?.EditorView; // prettier-ignore const map: Map<'font'|'fontColor'|'highlight'|'fontSize'|'alignment', { checkResult: () => any; setDoc: () => void;}> = new Map([ ['font', { checkResult: () => RichTextMenu.Instance?.fontFamily, setDoc: () => value && RichTextMenu.Instance?.setFontField(value, 'fontFamily'), }], ['highlight', { checkResult: () => RichTextMenu.Instance?.fontHighlight, setDoc: () => value && RichTextMenu.Instance?.setFontField(value, 'fontHighlight'), }], ['fontColor', { checkResult: () => RichTextMenu.Instance?.fontColor, setDoc: () => value && RichTextMenu.Instance?.setFontField(value, 'fontColor'), }], ['alignment', { checkResult: () => RichTextMenu.Instance?.textAlign, setDoc: () => { value && editorView?.state ? RichTextMenu.Instance?.align(editorView, editorView.dispatch, value):(Doc.UserDoc().textAlign = value); }, }], ['fontSize', { checkResult: () => RichTextMenu.Instance?.fontSize.replace('px', ''), setDoc: () => { let fsize = value; if (typeof fsize === 'number') fsize = fsize.toString(); if (fsize && Number(fsize).toString() === fsize) fsize += 'px'; RichTextMenu.Instance?.setFontField(fsize, 'fontSize'); }, }], ]); if (checkResult) { // console.log(map.get(attr)?.checkResult() + "font check result") return map.get(attr)?.checkResult(); } map.get(attr)?.setDoc?.(); return undefined; }); type attrname = 'noAutoLink' | 'dictation' | 'bold' | 'italics' | 'elide' | 'underline' | 'left' | 'center' | 'right' | 'vcent' | 'bullet' | 'decimal'; type attrfuncs = [attrname, { checkResult: () => boolean; toggle?: () => any }]; // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function toggleCharStyle(charStyle: attrname, checkResult?: boolean) { const textView = RichTextMenu.Instance?.TextView; const editorView = textView?.EditorView; // prettier-ignore const alignments:attrfuncs[] = (['left','right','center','vcent'] as ("left"|"center"|"right"|"vcent")[]).map((where) => [ where, { checkResult: () => editorView ? (where === 'vcent' ? RichTextMenu.Instance?.textVcenter ?? false: (RichTextMenu.Instance?.textAlign === where)): where === 'vcent' ? BoolCast(Doc.UserDoc()._layout_centered): (Doc.UserDoc().textAlign === where), toggle: () => { editorView?.state ? (where === 'vcent' ? RichTextMenu.Instance?.vcenterToggle(): RichTextMenu.Instance?.align(editorView, editorView.dispatch, where)): where === 'vcent' ? Doc.UserDoc()._layout_centered = !Doc.UserDoc()._layout_centered: (Doc.UserDoc().textAlign = where); } }]); // prettier-ignore // prettier-ignore const listings:attrfuncs[] = (['bullet','decimal'] as attrname[]).map(list => [ list, { checkResult: () => (editorView ? RichTextMenu.Instance?.listStyle === list:false), toggle: () => editorView?.state && RichTextMenu.Instance?.changeListType(list) }]); // prettier-ignore const attrs:attrfuncs[] = [ ['dictation', { checkResult: () => !!textView?._recordingDictation, toggle: () => textView && runInAction(() => { textView._recordingDictation = !textView._recordingDictation;} ) }], ['elide', { checkResult: () => false, toggle: () => editorView ? RichTextMenu.Instance?.elideSelection(): 0}], ['noAutoLink',{ checkResult: () => ((editorView && RichTextMenu.Instance?.noAutoLink) ?? false), toggle: () => editorView && RichTextMenu.Instance?.toggleNoAutoLinkAnchor()}], ['bold', { checkResult: () => (editorView ? RichTextMenu.Instance?.bold??false : (Doc.UserDoc().fontWeight === 'bold')), toggle: editorView ? RichTextMenu.Instance?.toggleBold : () => { Doc.UserDoc().fontWeight = Doc.UserDoc().fontWeight === 'bold' ? undefined : 'bold'; }}], ['italics', { checkResult: () => (editorView ? RichTextMenu.Instance?.italics ?? false : (Doc.UserDoc().fontStyle === 'italics')), toggle: editorView ? RichTextMenu.Instance?.toggleItalics : () => { Doc.UserDoc().fontStyle = Doc.UserDoc().fontStyle === 'italics' ? undefined : 'italics'; }}], ['underline', { checkResult: () => (editorView ? RichTextMenu.Instance?.underline ?? false: (Doc.UserDoc().textDecoration === 'underline')), toggle: editorView ? RichTextMenu.Instance?.toggleUnderline : () => { Doc.UserDoc().textDecoration = Doc.UserDoc().textDecoration === 'underline' ? undefined : 'underline'; } }]] const map = new Map(attrs.concat(alignments).concat(listings)); if (checkResult) { return map.get(charStyle)?.checkResult(); } undoable(() => map.get(charStyle)?.toggle?.(), 'toggle ' + charStyle)(); return undefined; }); export function createInkGroup(/* inksToGroup?: Doc[], isSubGroup?: boolean */) { // TODO nda - if document being added to is a inkGrouping then we can just add to that group if (Doc.ActiveTool === InkTool.Write) { CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => { // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those const selected = ffView.unprocessedDocs; // loop through selected an get the bound const bounds: { x: number; y: number; width?: number; height?: number }[] = []; selected.map( action(d => { const x = NumCast(d.x); const y = NumCast(d.y); const width = NumCast(d._width); const height = NumCast(d._height); bounds.push({ x, y, width, height }); }) ); const aggregBounds = aggregateBounds(bounds, 0, 0); const marqViewRef = ffView._marqueeViewRef.current; // set the vals for bounds in marqueeView if (marqViewRef) { marqViewRef._downX = aggregBounds.x; marqViewRef._downY = aggregBounds.y; marqViewRef._lastX = aggregBounds.r; marqViewRef._lastY = aggregBounds.b; } selected.map( action(d => { const dx = NumCast(d.x); const dy = NumCast(d.y); delete d.x; delete d.y; delete d.activeFrame; delete d._timecodeToShow; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection delete d._timecodeToHide; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection // calculate pos based on bounds if (marqViewRef?.Bounds) { d.x = dx - marqViewRef.Bounds.left - marqViewRef.Bounds.width / 2; d.y = dy - marqViewRef.Bounds.top - marqViewRef.Bounds.height / 2; } return d; }) ); ffView._props.removeDocument?.(selected); // TODO: nda - this is the code to actually get a new grouped collection const newCollection = marqViewRef?.getCollection(selected, undefined, true); if (newCollection) { newCollection.height = NumCast(newCollection._height); newCollection.width = NumCast(newCollection._width); } // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs newCollection && ffView._props.addDocument?.(newCollection); // TODO: nda - will probably need to go through and only remove the unprocessed selected docs ffView.unprocessedDocs = []; // InkTranscription.Instance.transcribeInk(newCollection, selected, false); }); } CollectionFreeFormView.collectionsWithUnprocessedInk.clear(); } function setActiveTool(tool: InkTool | Gestures, keepPrim: boolean, checkResult?: boolean) { // InkTranscription.Instance?.createInkGroup(); if (checkResult) { return (Doc.ActiveTool === tool && !GestureOverlay.Instance?.InkShape) || GestureOverlay.Instance?.InkShape === tool ? GestureOverlay.Instance?.KeepPrimitiveMode || ![Gestures.Circle, Gestures.Line, Gestures.Rectangle].includes(tool as Gestures) : false; } runInAction(() => { if (GestureOverlay.Instance) { GestureOverlay.Instance.KeepPrimitiveMode = keepPrim; } if (Object.values(Gestures).includes(tool as any)) { if (GestureOverlay.Instance.InkShape === tool && !keepPrim) { Doc.ActiveTool = InkTool.None; GestureOverlay.Instance.InkShape = undefined; } else { Doc.ActiveTool = InkTool.Pen; GestureOverlay.Instance.InkShape = tool as Gestures; } } else if (tool) { if (Doc.UserDoc().ActiveTool === tool) { Doc.ActiveTool = InkTool.None; } else { if ([InkTool.StrokeEraser, InkTool.RadiusEraser, InkTool.SegmentEraser].includes(tool as any)) { Doc.UserDoc().activeEraserTool = tool; } // pen or eraser if (Doc.ActiveTool === tool && !GestureOverlay.Instance.InkShape && !keepPrim) { Doc.ActiveTool = InkTool.None; } else { Doc.ActiveTool = tool as any; GestureOverlay.Instance.InkShape = undefined; } } } else { Doc.ActiveTool = InkTool.None; } }); return undefined; } ScriptingGlobals.add(setActiveTool, 'sets the active ink tool mode'); ScriptingGlobals.add(function activeEraserTool() { return StrCast(Doc.UserDoc().activeEraserTool, InkTool.StrokeEraser); }, 'returns the current eraser tool'); // toggle: Set overlay status of selected document // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function setInkProperty(option: 'inkMask' | 'labels' | 'fillColor' | 'strokeWidth' | 'strokeColor' | 'eraserWidth', value: any, checkResult?: boolean) { const selected = DocumentView.SelectedDocs().lastElement() ?? Doc.UserDoc(); // prettier-ignore const map: Map<'inkMask' | 'labels' | 'fillColor' | 'strokeWidth' | 'strokeColor' | 'eraserWidth', { checkResult: () => any; setInk: (doc: Doc) => void; setMode: () => void }> = new Map([ ['inkMask', { checkResult: () => ((selected?._layout_isSvg ? BoolCast(selected[DocData].stroke_isInkMask) : ActiveIsInkMask())), setInk: (doc: Doc) => { doc[DocData].stroke_isInkMask = !doc.stroke_isInkMask; }, setMode: () => selected?.type !== DocumentType.INK && SetActiveIsInkMask(!ActiveIsInkMask()), }], ['labels', { checkResult: () => ((selected?._stroke_showLabel ? BoolCast(selected[DocData].stroke_showLabel) : ActiveInkHideTextLabels())), setInk: (doc: Doc) => { doc[DocData].stroke_showLabel = !doc.stroke_showLabel; }, setMode: () => selected?.type !== DocumentType.INK && SetActiveInkHideTextLabels(!ActiveInkHideTextLabels()), }], ['fillColor', { checkResult: () => (selected?._layout_isSvg ? StrCast(selected[DocData].fillColor) : ActiveFillColor() ?? "transparent"), setInk: (doc: Doc) => { doc[DocData].fillColor = StrCast(value); }, setMode: () => SetActiveFillColor(StrCast(value)), }], [ 'strokeWidth', { checkResult: () => (selected?._layout_isSvg ? NumCast(selected[DocData].stroke_width) : ActiveInkWidth()), setInk: (doc: Doc) => { doc[DocData].stroke_width = NumCast(value); }, setMode: () => { SetActiveInkWidth(value.toString()); selected?.type === DocumentType.INK && setActiveTool( GestureOverlay.Instance.InkShape ?? InkTool.Pen, true, false);}, }], ['strokeColor', { checkResult: () => (selected?._layout_isSvg? StrCast(selected[DocData].color) : ActiveInkColor()), setInk: (doc: Doc) => { doc[DocData].color = String(value); }, setMode: () => { SetActiveInkColor(StrCast(value)); selected?.type === DocumentType.INK && setActiveTool(GestureOverlay.Instance.InkShape ?? InkTool.Pen, true, false);}, }], [ 'eraserWidth', { checkResult: () => ActiveEraserWidth(), setInk: (doc: Doc) => { }, setMode: () => { SetEraserWidth(value.toString());}, }] ]); if (checkResult) { return map.get(option)?.checkResult(); } map.get(option)?.setMode(); DocumentView.SelectedDocs() .filter(doc => doc._layout_isSvg) .map(doc => map.get(option)?.setInk(doc)); return undefined; }); // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function toggleRaiseOnDrag(readOnly?: boolean) { if (readOnly) { return DocumentView.Selected().some(dv => dv.Document.keepZWhenDragged); } DocumentView.Selected().forEach(dv => { dv.Document.keepZWhenDragged = !dv.Document.keepZWhenDragged; }); return undefined; }); /** WEB * webSetURL * */ // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function webSetURL(url: string, checkResult?: boolean) { const selected = DocumentView.Selected().lastElement(); if (selected?.Document.type === DocumentType.WEB) { if (checkResult) { return StrCast(selected.Document.data, Cast(selected.Document.data, WebField, null)?.url?.href); } selected.ComponentView?.setData?.(url); } return ''; }); // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function webForward(checkResult?: boolean) { const selected = DocumentView.Selected().lastElement()?.ComponentView as WebBox; if (checkResult) { return selected?.forward(checkResult) ? undefined : 'lightGray'; } selected?.forward(); return undefined; }); // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function webBack() { const selected = DocumentView.Selected().lastElement()?.ComponentView as WebBox; selected?.back(); }); // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function videoSnapshot() { const selected = DocumentView.Selected().lastElement()?.ComponentView as VideoBox; selected?.Snapshot(); }); // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function imageSetPixelSize() { const selected = DocumentView.Selected().lastElement()?.ComponentView as ImageBox; selected?.setNativeSize(); }); // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function imageRotate90() { const selected = DocumentView.Selected().lastElement()?.ComponentView as ImageBox; selected?.rotate(); }); /** Schema * toggleSchemaPreview * */ // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function toggleSchemaPreview(checkResult?: boolean) { const selected = DocumentView.SelectedDocs().lastElement(); if (checkResult && selected) { const result: boolean = NumCast(selected.schema_previewWidth) > 0; if (result) return Colors.MEDIUM_BLUE; return 'transparent'; } if (selected) { if (NumCast(selected.schema_previewWidth) > 0) { selected.schema_previewWidth = 0; } else { selected.schema_previewWidth = 200; } } return ''; }); // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function toggleSingleLineSchema(checkResult?: boolean) { const selected = DocumentView.SelectedDocs().lastElement(); if (checkResult && selected) { return NumCast(selected._schema_singleLine) > 0 ? Colors.MEDIUM_BLUE : 'transparent'; } if (selected) { selected._schema_singleLine = !selected._schema_singleLine; } return undefined; }); /** STACK * groupBy */ // eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function setGroupBy(key: string, checkResult?: boolean) { DocumentView.SelectedDocs().forEach(doc => { doc._text_fontFamily = key; }); // prettier-ignore const editorView = RichTextMenu.Instance?.TextView?.EditorView; if (checkResult) { return StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc())?.fontFamily); } if (editorView) RichTextMenu.Instance?.setFontField(key, 'fontFamily'); else Doc.UserDoc().fontFamily = key; return undefined; });