aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2024-05-19 02:08:43 -0400
committerbobzel <zzzman@gmail.com>2024-05-19 02:08:43 -0400
commit6841dc0fd2aecf31eda2102e660c58905d1e6f44 (patch)
tree821b79178aa07001274759c716badb2a8a170056 /src/client/views/collections/collectionFreeForm/MarqueeView.tsx
parent2fc1fb7d322ab0950afb0d334c17aa93bd16f6c0 (diff)
parent13dc6de0e0099f699ad0d2bb54401e6a0aa25018 (diff)
merged with soon-to-be-master
Diffstat (limited to 'src/client/views/collections/collectionFreeForm/MarqueeView.tsx')
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx138
1 files changed, 73 insertions, 65 deletions
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 887fa17a8..768270c09 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -1,8 +1,10 @@
+/* eslint-disable jsx-a11y/no-static-element-interactions */
import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Utils, intersectRect, lightOrDark, returnFalse, convertImageToBase64 } from '../../../../Utils';
-import { Doc, FieldResult, NumListCast, Opt } from '../../../../fields/Doc';
+import { ClientUtils, lightOrDark, returnFalse } from '../../../../ClientUtils';
+import { intersectRect } from '../../../../Utils';
+import { Doc, NumListCast, Opt } from '../../../../fields/Doc';
import { AclAdmin, AclAugment, AclEdit, DocData } from '../../../../fields/DocSymbols';
import { Id } from '../../../../fields/FieldSymbols';
import { InkData, InkField, InkTool } from '../../../../fields/InkField';
@@ -11,27 +13,27 @@ import { RichTextField } from '../../../../fields/RichTextField';
import { Cast, FieldValue, NumCast, StrCast } from '../../../../fields/Types';
import { ImageField, URLField } from '../../../../fields/URLField';
import { GetEffectiveAcl } from '../../../../fields/util';
+import { gptGetEmbedding, gptImageLabel } from '../../../apis/gpt/GPT';
import { CognitiveServices } from '../../../cognitive_services/CognitiveServices';
+import { DocUtils } from '../../../documents/DocUtils';
import { DocumentType } from '../../../documents/DocumentTypes';
-import { DocUtils, Docs, DocumentOptions } from '../../../documents/Documents';
-import { SelectionManager } from '../../../util/SelectionManager';
-import { freeformScrollMode } from '../../../util/SettingsManager';
-import { SnappingManager } from '../../../util/SnappingManager';
+import { Docs, DocumentOptions } from '../../../documents/Documents';
+import { SnappingManager, freeformScrollMode } from '../../../util/SnappingManager';
import { Transform } from '../../../util/Transform';
import { UndoManager, undoBatch } from '../../../util/UndoManager';
import { ContextMenu } from '../../ContextMenu';
import { ObservableReactComponent } from '../../ObservableReactComponent';
+import { MarqueeViewBounds } from '../../PinFuncs';
import { PreviewCursor } from '../../PreviewCursor';
-import { OpenWhere } from '../../nodes/DocumentView';
+import { DocumentView } from '../../nodes/DocumentView';
+import { OpenWhere } from '../../nodes/OpenWhere';
import { pasteImageBitmap } from '../../nodes/WebBoxRenderer';
import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
import { SubCollectionViewProps } from '../CollectionSubView';
+import { ImageLabelHandler } from './ImageLabelHandler';
import { MarqueeOptionsMenu } from './MarqueeOptionsMenu';
import './MarqueeView.scss';
-import { ObjectField } from '../../../../fields/ObjectField';
-import { gptGetEmbedding, gptImageLabel } from '../../../apis/gpt/GPT';
-import { ImageLabelHandler } from './ImageLabelHandler';
-import { listSpec } from '../../../../fields/Schema';
+import { ImageUtility } from '../../nodes/generativeFill/generativeFillUtils/ImageHandler';
interface MarqueeViewProps {
getContainerTransform: () => Transform;
getTransform: () => Transform;
@@ -48,13 +50,6 @@ interface MarqueeViewProps {
slowLoadDocuments: (files: File[] | string, options: DocumentOptions, generatedDocuments: Doc[], text: string, completed: ((doc: Doc[]) => void) | undefined, addDocument: (doc: Doc | Doc[]) => boolean) => Promise<void>;
}
-export interface MarqueeViewBounds {
- left: number;
- top: number;
- width: number;
- height: number;
-}
-
@observer
export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps & MarqueeViewProps> {
public static CurViewBounds(pinDoc: Doc, panelWidth: number, panelHeight: number) {
@@ -108,7 +103,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
@action
onKeyDown = (e: KeyboardEvent) => {
- //make textbox and add it to this collection
+ // make textbox and add it to this collection
// tslint:disable-next-line:prefer-const
const cm = ContextMenu.Instance;
const [x, y] = this.Transform.transformPoint(this._downX, this._downY);
@@ -147,7 +142,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
}
}
let ypos = y;
- ns.map(line => {
+ ns.forEach(line => {
const indent = line.search(/\S|$/);
const newBox = Docs.Create.TextDocument(line, { _width: 200, _height: 35, x: x + (indent / 3) * 10, y: ypos, title: line });
this._props.addDocument?.(newBox);
@@ -161,7 +156,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
pasteImageBitmap((data: any, error: any) => {
error && console.log(error);
data &&
- Utils.convertDataUri(data, this._props.Document[Id] + '-thumb-frozen').then(returnedfilename => {
+ ClientUtils.convertDataUri(data, this._props.Document[Id] + '-thumb-frozen').then(returnedfilename => {
this._props.Document['thumb-frozen'] = new ImageField(returnedfilename);
});
})
@@ -171,11 +166,11 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
const slide = DocUtils.copyDragFactory(DocCast(Doc.UserDoc().emptySlide))!;
slide.x = x;
slide.y = y;
- FormattedTextBox.SelectOnLoad = slide[Id];
+ Doc.SetSelectOnLoad(slide);
TreeView._editTitleOnLoad = { id: slide[Id], parent: undefined };
this._props.addDocument?.(slide);
e.stopPropagation();
- }*/ else if (e.key === 'p' && e.ctrlKey) {
+ } */ else if (e.key === 'p' && e.ctrlKey) {
e.preventDefault();
(async () => {
const text: string = await navigator.clipboard.readText();
@@ -183,14 +178,14 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
this.pasteTable(ns, x, y);
})();
e.stopPropagation();
- } else if (!e.ctrlKey && !e.metaKey && SelectionManager.Views.length < 2) {
+ } else if (!e.ctrlKey && !e.metaKey && DocumentView.Selected().length < 2) {
FormattedTextBox.SelectOnLoadChar = Doc.UserDoc().defaultTextLayout && !this._props.childLayoutString ? e.key : '';
FormattedTextBox.LiveTextUndo = UndoManager.StartBatch('type new note');
this._props.addLiveTextDocument(DocUtils.GetNewTextDoc('-typed text-', x, y, 200, 100));
e.stopPropagation();
}
};
- //heuristically converts pasted text into a table.
+ // heuristically converts pasted text into a table.
// assumes each entry is separated by a tab
// skips all rows until it gets to a row with more than one entry
// assumes that 1st row has header entry for each column
@@ -198,15 +193,15 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
// any row that has only one column is a section header-- this header is then added as a column to subsequent rows until the next header
// assumes each cell is a string or a number
pasteTable(ns: string[], x: number, y: number) {
- let csvRows = [];
+ const csvRows = [];
const headers = ns[0].split('\t');
csvRows.push(headers.join(','));
ns[0] = '';
const eachCell = ns.join('\t').split('\t');
let eachRow = [];
for (let i = 1; i < eachCell.length; i++) {
- eachRow.push(eachCell[i].replace(/\,/g, ''));
- if (i % headers.length == 0) {
+ eachRow.push(eachCell[i].replace(/,/g, ''));
+ if (i % headers.length === 0) {
csvRows.push(eachRow);
eachRow = [];
}
@@ -239,7 +234,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
this._lastY = e.pageY;
this._lassoPts.push([e.clientX, e.clientY]);
if (!e.cancelBubble) {
- if (!Utils.isClick(this._lastX, this._lastY, this._downX, this._downY, Date.now())) {
+ if (!ClientUtils.isClick(this._lastX, this._lastY, this._downX, this._downY, Date.now())) {
if (!this._commandExecuted) {
this.showMarquee();
}
@@ -257,7 +252,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
if (this._visible) {
const mselect = this.marqueeSelect();
if (!e.shiftKey) {
- SelectionManager.DeselectAll(mselect.length ? undefined : this._props.Document);
+ DocumentView.DeselectAll(mselect.length ? undefined : this._props.Document);
}
const docs = mselect.length ? mselect : [this._props.Document];
this._props.selectDocuments(docs);
@@ -328,7 +323,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
@action
onClick = (e: React.MouseEvent): void => {
if (this._props.pointerEvents?.() === 'none') return;
- if (Utils.isClick(e.clientX, e.clientY, this._downX, this._downY, Date.now())) {
+ if (ClientUtils.isClick(e.clientX, e.clientY, this._downX, this._downY, Date.now())) {
if (Doc.ActiveTool === InkTool.None) {
if (!this._props.trySelectCluster(e.shiftKey)) {
!SnappingManager.ExploreMode && this.setPreviewCursor(e.clientX, e.clientY, false, false, this._props.Document);
@@ -343,15 +338,21 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
};
@action
- showMarquee = () => (this._visible = true);
+ showMarquee = () => {
+ this._visible = true;
+ };
@action
- hideMarquee = () => (this._visible = false);
+ hideMarquee = () => {
+ this._visible = false;
+ };
@undoBatch
delete = action((e?: React.PointerEvent<Element> | KeyboardEvent | undefined, hide?: boolean) => {
const selected = this.marqueeSelect(false);
- SelectionManager.DeselectAll();
- selected.forEach(doc => (hide ? (doc.hidden = true) : this._props.removeDocument?.(doc)));
+ DocumentView.DeselectAll();
+ selected.forEach(doc => {
+ hide ? (doc.hidden = true) : this._props.removeDocument?.(doc);
+ });
this.cleanupInteractions(false);
MarqueeOptionsMenu.Instance.fadeOut(true);
@@ -382,9 +383,9 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
});
@undoBatch
- pileup = action((e: KeyboardEvent | React.PointerEvent | undefined) => {
+ pileup = action(() => {
const selected = this.marqueeSelect(false);
- SelectionManager.DeselectAll();
+ DocumentView.DeselectAll();
selected.forEach(d => this._props.removeDocument?.(d));
const newCollection = DocUtils.pileup(selected, this.Bounds.left + this.Bounds.width / 2, this.Bounds.top + this.Bounds.height / 2)!;
this._props.addDocument?.(newCollection);
@@ -394,7 +395,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
});
/**
- * This triggers the TabDocView.PinDoc method which is the universal method
+ * This triggers the DocumentView.PinDoc method which is the universal method
* used to pin documents to the currently active presentation trail.
*
* This one is unique in that it includes the bounds associated with marquee view.
@@ -434,32 +435,34 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
this._selectedDocs = selected;
const imagePromises = selected.map(doc => {
- let href = (doc['data'] as URLField).url.href;
- let hrefParts = href.split('.');
- let hrefComplete = `${hrefParts[0]}_o.${hrefParts[1]}`;
- return convertImageToBase64(hrefComplete).then(hrefBase64 => {
- return gptImageLabel(hrefBase64).then(response => {
- console.log(response);
- const labels = response.split('\n');
- console.log(labels);
- doc.image_labels = new List<string>(Array.from(labels!));
- return Promise.all(labels!.map(label => gptGetEmbedding(label))).then(embeddings => {
- return { doc, embeddings };
- });
- });
- });
+ const href = (doc['data'] as URLField).url.href;
+ const hrefParts = href.split('.');
+ const hrefComplete = `${hrefParts[0]}_o.${hrefParts[1]}`;
+ return ImageUtility.urlToBase64(hrefComplete).then(hrefBase64 =>
+ !hrefBase64
+ ? undefined
+ : gptImageLabel(hrefBase64).then(response => {
+ const labels = response.split('\n');
+ doc.image_labels = new List<string>(Array.from(labels!));
+ return Promise.all(labels!.map(label => gptGetEmbedding(label))).then(embeddings => {
+ return { doc, embeddings };
+ });
+ })
+ );
});
- let docsAndEmbeddings = await Promise.all(imagePromises);
-
- for (const docAndEmbedding of docsAndEmbeddings) {
- if (Array.isArray(docAndEmbedding.embeddings)) {
- let doc = docAndEmbedding.doc;
- for (let i = 0; i < 3; i++) {
- doc[`label_embedding_${i + 1}`] = new List<number>(docAndEmbedding.embeddings[i]);
+ const docsAndEmbeddings = await Promise.all(imagePromises);
+ docsAndEmbeddings
+ .filter(d => d)
+ .map(d => d!)
+ .forEach(docAndEmbedding => {
+ if (Array.isArray(docAndEmbedding.embeddings)) {
+ let doc = docAndEmbedding.doc;
+ for (let i = 0; i < 3; i++) {
+ doc[`label_embedding_${i + 1}`] = new List<number>(docAndEmbedding.embeddings[i]);
+ }
}
- }
- }
+ });
if (e) {
ImageLabelHandler.Instance.displayLabelHandler(e.pageX, e.pageY);
@@ -584,7 +587,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
});
@undoBatch
- summary = action((e: KeyboardEvent | React.PointerEvent | undefined) => {
+ summary = action(() => {
const selected = this.marqueeSelect(false).map(d => {
this._props.removeDocument?.(d);
d.x = NumCast(d.x) - this.Bounds.left;
@@ -629,8 +632,8 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
(e as any).propagationIsStopped = true;
if (e.key === 'g') this.collection(e, true);
if (e.key === 'c' || e.key === 't') this.collection(e);
- if (e.key === 's' || e.key === 'S') this.summary(e);
- if (e.key === 'p') this.pileup(e);
+ if (e.key === 's' || e.key === 'S') this.summary();
+ if (e.key === 'p') this.pileup();
this.cleanupInteractions(false);
}
if (e.key === 'r' || e.key === ' ') {
@@ -642,6 +645,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
};
touchesLine(r1: { left: number; top: number; width: number; height: number }) {
+ // eslint-disable-next-line no-restricted-syntax
for (const lassoPt of this._lassoPts) {
const topLeft = this.Transform.transformPoint(lassoPt[0], lassoPt[1]);
if (r1.left < topLeft[0] && topLeft[0] < r1.left + r1.width && r1.top < topLeft[1] && topLeft[1] < r1.top + r1.height) {
@@ -662,6 +666,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
let hasLeft = false;
let hasBottom = false;
let hasRight = false;
+ // eslint-disable-next-line no-restricted-syntax
for (const lassoPt of this._lassoPts) {
const truePoint = this.Transform.transformPoint(lassoPt[0], lassoPt[1]);
hasLeft = hasLeft || (truePoint[0] > tl[0] && truePoint[0] < r1.left && truePoint[1] > r1.top && truePoint[1] < r1.top + r1.height);
@@ -775,6 +780,7 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
};
render() {
return (
+ // eslint-disable-next-line jsx-a11y/click-events-have-key-events
<div
className="marqueeView"
ref={r => {
@@ -786,7 +792,9 @@ export class MarqueeView extends ObservableReactComponent<SubCollectionViewProps
cursor: [InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool) || this._visible ? 'crosshair' : 'pointer',
}}
onDragOver={e => e.preventDefault()}
- onScroll={e => (e.currentTarget.scrollTop = e.currentTarget.scrollLeft = 0)}
+ onScroll={e => {
+ e.currentTarget.scrollTop = e.currentTarget.scrollLeft = 0;
+ }}
onClick={this.onClick}
onPointerDown={this.onPointerDown}>
{this._visible ? this.marqueeDiv : null}