aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/ImageBox.tsx
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2022-07-08 00:17:26 -0400
committerbobzel <zzzman@gmail.com>2022-07-08 00:17:26 -0400
commit146f8622d5bac2edc6b09f57c173bd057dfbcfad (patch)
treef871089c438a476543ca96bac163c0532b9557c7 /src/client/views/nodes/ImageBox.tsx
parentb7e66da6b23cdb41c127000dfe13843d35f7d0cc (diff)
restructured currentUserUtils to avoid having import cycles.
Diffstat (limited to 'src/client/views/nodes/ImageBox.tsx')
-rw-r--r--src/client/views/nodes/ImageBox.tsx362
1 files changed, 188 insertions, 174 deletions
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 60eb48114..ffa839fcb 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -1,5 +1,5 @@
import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from 'mobx';
-import { observer } from "mobx-react";
+import { observer } from 'mobx-react';
import { extname } from 'path';
import { DataSym, Doc, DocListCast, Opt, WidthSym } from '../../../fields/Doc';
import { Id } from '../../../fields/FieldSymbols';
@@ -14,13 +14,12 @@ import { TraceMobx } from '../../../fields/util';
import { emptyFunction, OmitKeys, returnFalse, returnOne, setupMoveUpEvents, Utils } from '../../../Utils';
import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils';
import { CognitiveServices, Confidence, Service, Tag } from '../../cognitive_services/CognitiveServices';
-import { Docs, DocUtils } from '../../documents/Documents';
+import { DocUtils } from '../../documents/Documents';
import { DocumentType } from '../../documents/DocumentTypes';
import { Networking } from '../../Network';
-import { CurrentUserUtils } from '../../util/CurrentUserUtils';
import { DragManager } from '../../util/DragManager';
import { undoBatch } from '../../util/UndoManager';
-import { ContextMenu } from "../../views/ContextMenu";
+import { ContextMenu } from '../../views/ContextMenu';
import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView';
import { ContextMenuProps } from '../ContextMenuItem';
import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComponent';
@@ -29,62 +28,64 @@ import { AnchorMenu } from '../pdf/AnchorMenu';
import { StyleProp } from '../StyleProvider';
import { FaceRectangles } from './FaceRectangles';
import { FieldView, FieldViewProps } from './FieldView';
-import "./ImageBox.scss";
-import React = require("react");
+import './ImageBox.scss';
+import React = require('react');
export const pageSchema = createSchema({
- googlePhotosUrl: "string",
- googlePhotosTags: "string"
+ googlePhotosUrl: 'string',
+ googlePhotosTags: 'string',
});
const uploadIcons = {
- idle: "downarrow.png",
- loading: "loading.gif",
- success: "greencheck.png",
- failure: "redx.png"
+ idle: 'downarrow.png',
+ loading: 'loading.gif',
+ success: 'greencheck.png',
+ failure: 'redx.png',
};
@observer
export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps & FieldViewProps>() {
- protected _multiTouchDisposer?: import("../../util/InteractionUtils").InteractionUtils.MultiTouchEventDisposer | undefined;
- public static LayoutString(fieldKey: string) { return FieldView.LayoutString(ImageBox, fieldKey); }
+ protected _multiTouchDisposer?: import('../../util/InteractionUtils').InteractionUtils.MultiTouchEventDisposer | undefined;
+ public static LayoutString(fieldKey: string) {
+ return FieldView.LayoutString(ImageBox, fieldKey);
+ }
private _dropDisposer?: DragManager.DragDropDisposer;
private _disposers: { [name: string]: IReactionDisposer } = {};
private _getAnchor: (savedAnnotations?: ObservableMap<number, HTMLDivElement[]>) => Opt<Doc> = () => undefined;
- @observable _curSuffix = "";
+ @observable _curSuffix = '';
@observable _uploadIcon = uploadIcons.idle;
protected createDropTarget = (ele: HTMLDivElement) => {
this._dropDisposer?.();
ele && (this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.props.Document));
- }
- setViewSpec = (anchor: Doc, preview: boolean) => {
-
- } // sets viewing information for a componentview, typically when following a link. 'preview' tells the view to use the values without writing to the document
-
+ };
+ setViewSpec = (anchor: Doc, preview: boolean) => {}; // sets viewing information for a componentview, typically when following a link. 'preview' tells the view to use the values without writing to the document
getAnchor = () => {
const anchor = this._getAnchor?.(this._savedAnnotations);
anchor && this.addDocument(anchor);
return anchor ?? this.rootDoc;
- }
+ };
componentDidMount() {
this.props.setContentView?.(this); // bcz: do not remove this. without it, stepping into an image in the lightbox causes an infinite loop....
- this._disposers.sizer = reaction(() => (
- {
+ this._disposers.sizer = reaction(
+ () => ({
forceFull: this.props.renderDepth < 1 || this.layoutDoc._showFullRes,
scrSize: this.props.ScreenToLocalTransform().inverse().transformDirection(this.nativeSize.nativeWidth, this.nativeSize.nativeHeight)[0] / this.nativeSize.nativeWidth,
- selected: this.props.isSelected()
+ selected: this.props.isSelected(),
}),
- ({ forceFull, scrSize, selected }) => this._curSuffix = this.fieldKey === "icon" ? "_m" : forceFull ? "_o" : scrSize < 0.25 ? "_s" : scrSize < 0.5 ? "_m" : scrSize < 0.8 || !selected ? "_l" : "_o",
- { fireImmediately: true, delay: 1000 });
- this._disposers.path = reaction(() => ({ nativeSize: this.nativeSize, width: this.layoutDoc[WidthSym]() }),
+ ({ forceFull, scrSize, selected }) => (this._curSuffix = this.fieldKey === 'icon' ? '_m' : forceFull ? '_o' : scrSize < 0.25 ? '_s' : scrSize < 0.5 ? '_m' : scrSize < 0.8 || !selected ? '_l' : '_o'),
+ { fireImmediately: true, delay: 1000 }
+ );
+ this._disposers.path = reaction(
+ () => ({ nativeSize: this.nativeSize, width: this.layoutDoc[WidthSym]() }),
({ nativeSize, width }) => {
if (true || !this.layoutDoc._height) {
- this.layoutDoc._height = width * nativeSize.nativeHeight / nativeSize.nativeWidth;
+ this.layoutDoc._height = (width * nativeSize.nativeHeight) / nativeSize.nativeWidth;
}
},
- { fireImmediately: true });
+ { fireImmediately: true }
+ );
}
componentWillUnmount() {
@@ -96,10 +97,12 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
drop = (e: Event, de: DragManager.DropEvent) => {
if (de.complete.docDragData) {
if (de.metaKey) {
- de.complete.docDragData.droppedDocuments.forEach(action((drop: Doc) => {
- Doc.AddDocToList(this.dataDoc, this.fieldKey + "-alternates", drop);
- e.stopPropagation();
- }));
+ de.complete.docDragData.droppedDocuments.forEach(
+ action((drop: Doc) => {
+ Doc.AddDocToList(this.dataDoc, this.fieldKey + '-alternates', drop);
+ e.stopPropagation();
+ })
+ );
} else if (de.altKey || !this.dataDoc[this.fieldKey]) {
const layoutDoc = de.complete.docDragData?.draggedDocuments[0];
const targetField = Doc.LayoutFieldKey(layoutDoc);
@@ -112,20 +115,20 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
}
}
}
- }
+ };
@undoBatch
- resolution = () => this.layoutDoc._showFullRes = !this.layoutDoc._showFullRes
+ resolution = () => (this.layoutDoc._showFullRes = !this.layoutDoc._showFullRes);
@undoBatch
rotate = action(() => {
- const nw = NumCast(this.dataDoc[this.fieldKey + "-nativeWidth"]);
- const nh = NumCast(this.dataDoc[this.fieldKey + "-nativeHeight"]);
+ const nw = NumCast(this.dataDoc[this.fieldKey + '-nativeWidth']);
+ const nh = NumCast(this.dataDoc[this.fieldKey + '-nativeHeight']);
const w = this.layoutDoc._width;
const h = this.layoutDoc._height;
- this.dataDoc[this.fieldKey + "-rotation"] = (NumCast(this.dataDoc[this.fieldKey + "-rotation"]) + 90) % 360;
- this.dataDoc[this.fieldKey + "-nativeWidth"] = nh;
- this.dataDoc[this.fieldKey + "-nativeHeight"] = nw;
+ this.dataDoc[this.fieldKey + '-rotation'] = (NumCast(this.dataDoc[this.fieldKey + '-rotation']) + 90) % 360;
+ this.dataDoc[this.fieldKey + '-nativeWidth'] = nh;
+ this.dataDoc[this.fieldKey + '-nativeHeight'] = nw;
this.layoutDoc._width = h;
this.layoutDoc._height = w;
});
@@ -134,15 +137,15 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
if (!region) return;
const cropping = Doc.MakeCopy(region, true);
Doc.GetProto(region).lockedPosition = true;
- Doc.GetProto(region).title = "region:" + this.rootDoc.title;
+ Doc.GetProto(region).title = 'region:' + this.rootDoc.title;
Doc.GetProto(region).isPushpin = true;
this.addDocument(region);
const anchx = NumCast(cropping.x);
const anchy = NumCast(cropping.y);
const anchw = NumCast(cropping._width);
const anchh = NumCast(cropping._height);
- const viewScale = NumCast(this.rootDoc[this.fieldKey + "-nativeWidth"]) / anchw;
- cropping.title = "crop: " + this.rootDoc.title;
+ const viewScale = NumCast(this.rootDoc[this.fieldKey + '-nativeWidth']) / anchw;
+ cropping.title = 'crop: ' + this.rootDoc.title;
cropping.x = NumCast(this.rootDoc.x) + NumCast(this.rootDoc._width);
cropping.y = NumCast(this.rootDoc.y);
cropping._width = anchw * (this.props.scaling?.() || 1);
@@ -153,70 +156,70 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
croppingProto.isPrototype = true;
croppingProto.proto = Cast(this.rootDoc.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.layout = ImageBox.LayoutString('data');
croppingProto.data = ObjectField.MakeCopy(this.rootDoc[this.fieldKey] as ObjectField);
- croppingProto["data-nativeWidth"] = anchw;
- croppingProto["data-nativeHeight"] = anchh;
+ croppingProto['data-nativeWidth'] = anchw;
+ croppingProto['data-nativeHeight'] = anchh;
croppingProto.viewScale = viewScale;
croppingProto.viewScaleMin = viewScale;
croppingProto.panX = anchx / viewScale;
croppingProto.panY = anchy / viewScale;
- croppingProto.panXMin = (anchx) / viewScale;
- croppingProto.panXMax = (anchw) / viewScale;
- croppingProto.panYMin = (anchy) / viewScale;
- croppingProto.panYMax = (anchh) / viewScale;
+ croppingProto.panXMin = anchx / viewScale;
+ croppingProto.panXMax = anchw / viewScale;
+ croppingProto.panYMin = anchy / viewScale;
+ croppingProto.panYMax = anchh / viewScale;
if (addCrop) {
- DocUtils.MakeLink({ doc: region }, { doc: cropping }, "cropped image", "");
+ DocUtils.MakeLink({ doc: region }, { doc: cropping }, 'cropped image', '');
}
this.props.bringToFront(cropping);
return cropping;
- }
+ };
specificContextMenu = (e: React.MouseEvent): void => {
const field = Cast(this.dataDoc[this.fieldKey], ImageField);
if (field) {
const funcs: ContextMenuProps[] = [];
- funcs.push({ description: "Rotate Clockwise 90", event: this.rotate, icon: "expand-arrows-alt" });
- funcs.push({ description: `Show ${this.layoutDoc._showFullRes ? "Dynamic Res" : "Full Res"}`, event: this.resolution, icon: "expand-arrows-alt" });
- funcs.push({ description: "Copy path", event: () => Utils.CopyText(this.choosePath(field.url)), icon: "expand-arrows-alt" });
+ funcs.push({ description: 'Rotate Clockwise 90', event: this.rotate, icon: 'expand-arrows-alt' });
+ funcs.push({ description: `Show ${this.layoutDoc._showFullRes ? 'Dynamic Res' : 'Full Res'}`, event: this.resolution, icon: 'expand-arrows-alt' });
+ funcs.push({ description: 'Copy path', event: () => Utils.CopyText(this.choosePath(field.url)), icon: 'expand-arrows-alt' });
if (!Doc.noviceMode) {
- funcs.push({ description: "Export to Google Photos", event: () => GooglePhotos.Transactions.UploadImages([this.props.Document]), icon: "caret-square-right" });
+ funcs.push({ description: 'Export to Google Photos', event: () => GooglePhotos.Transactions.UploadImages([this.props.Document]), icon: 'caret-square-right' });
- const existingAnalyze = ContextMenu.Instance?.findByDescription("Analyzers...");
- const modes: ContextMenuProps[] = existingAnalyze && "subitems" in existingAnalyze ? existingAnalyze.subitems : [];
- modes.push({ description: "Generate Tags", event: this.generateMetadata, icon: "tag" });
- modes.push({ description: "Find Faces", event: this.extractFaces, icon: "camera" });
+ const existingAnalyze = ContextMenu.Instance?.findByDescription('Analyzers...');
+ const modes: ContextMenuProps[] = existingAnalyze && 'subitems' in existingAnalyze ? existingAnalyze.subitems : [];
+ modes.push({ description: 'Generate Tags', event: this.generateMetadata, icon: 'tag' });
+ modes.push({ description: 'Find Faces', event: this.extractFaces, icon: 'camera' });
//modes.push({ description: "Recommend", event: this.extractText, icon: "brain" });
- !existingAnalyze && ContextMenu.Instance?.addItem({ description: "Analyzers...", subitems: modes, icon: "hand-point-right" });
+ !existingAnalyze && ContextMenu.Instance?.addItem({ description: 'Analyzers...', subitems: modes, icon: 'hand-point-right' });
}
- ContextMenu.Instance?.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" });
+ ContextMenu.Instance?.addItem({ description: 'Options...', subitems: funcs, icon: 'asterisk' });
}
- }
+ };
extractFaces = () => {
const converter = (results: any) => {
return results.map((face: CognitiveServices.Image.Face) => Doc.Get.FromJson({ data: face, title: `Face: ${face.faceId}` })!);
};
- this.url && CognitiveServices.Image.Appliers.ProcessImage(this.dataDoc, [this.fieldKey + "-faces"], this.url, Service.Face, converter);
- }
+ this.url && CognitiveServices.Image.Appliers.ProcessImage(this.dataDoc, [this.fieldKey + '-faces'], this.url, Service.Face, converter);
+ };
generateMetadata = (threshold: Confidence = Confidence.Excellent) => {
const converter = (results: any) => {
- const tagDoc = new Doc;
+ const tagDoc = new Doc();
const tagsList = new List();
results.tags.map((tag: Tag) => {
tagsList.push(tag.name);
- const sanitized = tag.name.replace(" ", "_");
+ const sanitized = tag.name.replace(' ', '_');
tagDoc[sanitized] = ComputedField.MakeFunction(`(${tag.confidence} >= this.confidence) ? ${tag.confidence} : "${ComputedField.undefined}"`);
});
- this.dataDoc[this.fieldKey + "-generatedTags"] = tagsList;
- tagDoc.title = "Generated Tags Doc";
+ this.dataDoc[this.fieldKey + '-generatedTags'] = tagsList;
+ tagDoc.title = 'Generated Tags Doc';
tagDoc.confidence = threshold;
return tagDoc;
};
- this.url && CognitiveServices.Image.Appliers.ProcessImage(this.dataDoc, [this.fieldKey + "-generatedTagsDoc"], this.url, Service.ComputerVision, converter);
- }
+ this.url && CognitiveServices.Image.Appliers.ProcessImage(this.dataDoc, [this.fieldKey + '-generatedTagsDoc'], this.url, Service.ComputerVision, converter);
+ };
@computed private get url() {
const data = Cast(this.dataDoc[this.fieldKey], ImageField);
@@ -225,9 +228,9 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
choosePath(url: URL) {
const lower = url.href.toLowerCase();
- if (url.protocol === "data") return url.href;
+ if (url.protocol === 'data') return url.href;
if (url.href.indexOf(window.location.origin) === -1) return Utils.CorsProxy(url.href);
- if (!/\.(png|jpg|jpeg|gif|webp)$/.test(lower)) return url.href; //Why is this here
+ if (!/\.(png|jpg|jpeg|gif|webp)$/.test(lower)) return url.href; //Why is this here
const ext = extname(url.href);
return url.href.replace(ext, this._curSuffix + ext);
@@ -235,40 +238,36 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
considerGooglePhotosLink = () => {
const remoteUrl = this.dataDoc.googlePhotosUrl;
- return !remoteUrl ? (null) : (<img draggable={false}
- style={{ transformOrigin: "bottom right" }}
- id={"google-photos"}
- src={"/assets/google_photos.png"}
- onClick={() => window.open(remoteUrl)}
- />);
- }
+ return !remoteUrl ? null : <img draggable={false} style={{ transformOrigin: 'bottom right' }} id={'google-photos'} src={'/assets/google_photos.png'} onClick={() => window.open(remoteUrl)} />;
+ };
considerGooglePhotosTags = () => {
const tags = this.dataDoc.googlePhotosTags;
- return !tags ? (null) : (<img id={"google-tags"} src={"/assets/google_tags.png"} />);
- }
+ return !tags ? null : <img id={'google-tags'} src={'/assets/google_tags.png'} />;
+ };
@computed
private get considerDownloadIcon() {
const data = this.dataDoc[this.fieldKey];
if (!(data instanceof ImageField)) {
- return (null);
+ return null;
}
const primary = data.url.href;
if (primary.includes(window.location.origin)) {
- return (null);
+ return null;
}
return (
<img
- id={"upload-icon"} draggable={false}
- style={{ transformOrigin: "bottom right" }}
+ id={'upload-icon'}
+ draggable={false}
+ style={{ transformOrigin: 'bottom right' }}
src={`/assets/${this._uploadIcon}`}
onClick={async () => {
const { dataDoc } = this;
const { success, failure, idle, loading } = uploadIcons;
- runInAction(() => this._uploadIcon = loading);
- const [{ accessPaths }] = await Networking.PostToServer("/uploadRemoteImage", { sources: [primary] });
- dataDoc[this.props.fieldKey + "-originalUrl"] = primary;
+ runInAction(() => (this._uploadIcon = loading));
+ const [{ accessPaths }] = await Networking.PostToServer('/uploadRemoteImage', { sources: [primary] });
+ dataDoc[this.props.fieldKey + '-originalUrl'] = primary;
let succeeded = true;
let data: ImageField | undefined;
try {
@@ -276,13 +275,16 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
} catch {
succeeded = false;
}
- runInAction(() => this._uploadIcon = succeeded ? success : failure);
- setTimeout(action(() => {
- this._uploadIcon = idle;
- if (data) {
- dataDoc[this.fieldKey] = data;
- }
- }), 2000);
+ runInAction(() => (this._uploadIcon = succeeded ? success : failure));
+ setTimeout(
+ action(() => {
+ this._uploadIcon = idle;
+ if (data) {
+ dataDoc[this.fieldKey] = data;
+ }
+ }),
+ 2000
+ );
}}
/>
);
@@ -290,18 +292,21 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
@computed get nativeSize() {
TraceMobx();
- const nativeWidth = NumCast(this.dataDoc[this.fieldKey + "-nativeWidth"], NumCast(this.layoutDoc[this.fieldKey + "-nativeWidth"], 500));
- const nativeHeight = NumCast(this.dataDoc[this.fieldKey + "-nativeHeight"], NumCast(this.layoutDoc[this.fieldKey + "-nativeHeight"], 1));
- const nativeOrientation = NumCast(this.dataDoc[this.fieldKey + "-nativeOrientation"], 1);
+ const nativeWidth = NumCast(this.dataDoc[this.fieldKey + '-nativeWidth'], NumCast(this.layoutDoc[this.fieldKey + '-nativeWidth'], 500));
+ const nativeHeight = NumCast(this.dataDoc[this.fieldKey + '-nativeHeight'], NumCast(this.layoutDoc[this.fieldKey + '-nativeHeight'], 1));
+ const nativeOrientation = NumCast(this.dataDoc[this.fieldKey + '-nativeOrientation'], 1);
return { nativeWidth, nativeHeight, nativeOrientation };
}
@computed get paths() {
const field = Cast(this.dataDoc[this.fieldKey], ImageField, null); // retrieve the primary image URL that is being rendered from the data doc
- const alts = DocListCast(this.dataDoc[this.fieldKey + "-alternates"]); // retrieve alternate documents that may be rendered as alternate images
- const altpaths = alts.map(doc => Cast(doc[Doc.LayoutFieldKey(doc)], ImageField, null)?.url).filter(url => url).map(url => this.choosePath(url)); // access the primary layout data of the alternate documents
+ const alts = DocListCast(this.dataDoc[this.fieldKey + '-alternates']); // retrieve alternate documents that may be rendered as alternate images
+ const altpaths = alts
+ .map(doc => Cast(doc[Doc.LayoutFieldKey(doc)], ImageField, null)?.url)
+ .filter(url => url)
+ .map(url => this.choosePath(url)); // access the primary layout data of the alternate documents
const paths = field ? [this.choosePath(field.url), ...altpaths] : altpaths;
- return paths.length ? paths : [Utils.CorsProxy("http://www.cs.brown.edu/~bcz/noImage.png")];
+ return paths.length ? paths : [Utils.CorsProxy('http://www.cs.brown.edu/~bcz/noImage.png')];
}
@computed get content() {
@@ -310,39 +315,35 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
const srcpath = this.paths[0];
const fadepath = this.paths[Math.min(1, this.paths.length - 1)];
const { nativeWidth, nativeHeight, nativeOrientation } = this.nativeSize;
- const rotation = NumCast(this.dataDoc[this.fieldKey + "-rotation"]);
+ const rotation = NumCast(this.dataDoc[this.fieldKey + '-rotation']);
const aspect = rotation % 180 ? nativeHeight / nativeWidth : 1;
- let transformOrigin = "center center";
+ let transformOrigin = 'center center';
let transform = `translate(0%, 0%) rotate(${rotation}deg) scale(${aspect})`;
if (rotation === 90 || rotation === -270) {
- transformOrigin = "top left";
+ transformOrigin = 'top left';
transform = `translate(100%, 0%) rotate(${rotation}deg) scale(${aspect})`;
} else if (rotation === 180) {
transform = `rotate(${rotation}deg) scale(${aspect})`;
} else if (rotation === 270 || rotation === -90) {
- transformOrigin = "right top";
+ transformOrigin = 'right top';
transform = `translate(-100%, 0%) rotate(${rotation}deg) scale(${aspect})`;
}
- return <div className="imageBox-cont" key={this.layoutDoc[Id]} ref={this.createDropTarget} onPointerDown={this.marqueeDown}>
- <div className="imageBox-fader" style={{ overflow: Array.from(this.props.docViewPath?.()).slice(-1)[0].fitWidth ? "auto" : undefined }} >
- <img key="paths"
- src={srcpath}
- style={{ transform, transformOrigin }}
- draggable={false}
- width={nativeWidth} />
- {fadepath === srcpath ? (null) :
- <div className={`imageBox-fadeBlocker${this.props.isHovering?.() ? "-hover" : ""}`}>
- <img className="imageBox-fadeaway" key={"fadeaway"}
- src={fadepath}
- style={{ transform, transformOrigin }} draggable={false}
- width={nativeWidth} />
- </div>}
+ return (
+ <div className="imageBox-cont" key={this.layoutDoc[Id]} ref={this.createDropTarget} onPointerDown={this.marqueeDown}>
+ <div className="imageBox-fader" style={{ overflow: Array.from(this.props.docViewPath?.()).slice(-1)[0].fitWidth ? 'auto' : undefined }}>
+ <img key="paths" src={srcpath} style={{ transform, transformOrigin }} draggable={false} width={nativeWidth} />
+ {fadepath === srcpath ? null : (
+ <div className={`imageBox-fadeBlocker${this.props.isHovering?.() ? '-hover' : ''}`}>
+ <img className="imageBox-fadeaway" key={'fadeaway'} src={fadepath} style={{ transform, transformOrigin }} draggable={false} width={nativeWidth} />
+ </div>
+ )}
+ </div>
+ {this.considerDownloadIcon}
+ {this.considerGooglePhotosLink()}
+ <FaceRectangles document={this.dataDoc} color={'#0000FF'} backgroundColor={'#0000FF'} />
</div>
- {this.considerDownloadIcon}
- {this.considerGooglePhotosLink()}
- <FaceRectangles document={this.dataDoc} color={"#0000FF"} backgroundColor={"#0000FF"} />
- </div>;
+ );
}
screenToLocalTransform = this.props.ScreenToLocalTransform;
@@ -357,66 +358,79 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
return <div className="imageBox-annotationLayer" style={{ height: this.props.PanelHeight() }} ref={this._annotationLayer} />;
}
marqueeDown = (e: React.PointerEvent) => {
- if (!e.altKey && e.button === 0 && NumCast(this.rootDoc._viewScale,1) <= NumCast(this.rootDoc.viewScaleMin,1) && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(CurrentUserUtils.ActiveTool)) {
- setupMoveUpEvents(this, e, action(e => {
- MarqueeAnnotator.clearAnnotations(this._savedAnnotations);
- this._marqueeing = [e.clientX, e.clientY];
- return true;
- }), returnFalse, () => MarqueeAnnotator.clearAnnotations(this._savedAnnotations), false);
+ if (!e.altKey && e.button === 0 && NumCast(this.rootDoc._viewScale, 1) <= NumCast(this.rootDoc.viewScaleMin, 1) && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) {
+ setupMoveUpEvents(
+ this,
+ e,
+ action(e => {
+ MarqueeAnnotator.clearAnnotations(this._savedAnnotations);
+ this._marqueeing = [e.clientX, e.clientY];
+ return true;
+ }),
+ returnFalse,
+ () => MarqueeAnnotator.clearAnnotations(this._savedAnnotations),
+ false
+ );
}
- }
+ };
@action
finishMarquee = () => {
this._getAnchor = AnchorMenu.Instance?.GetAnchor;
this._marqueeing = undefined;
this.props.select(false);
- }
+ };
savedAnnotations = () => this._savedAnnotations;
render() {
TraceMobx();
const borderRad = this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BorderRounding);
- const borderRadius = borderRad?.includes("px") ? `${Number(borderRad.split("px")[0]) / (this.props.scaling?.() || 1)}px` : borderRad;
- return (<div className="imageBox" onContextMenu={this.specificContextMenu} ref={this._mainCont}
- style={{
- width: this.props.PanelWidth() ? undefined : `100%`,
- height: this.props.PanelWidth() ? undefined : `100%`,
- pointerEvents: this.layoutDoc._lockedPosition ? "none" : undefined,
- borderRadius
- }} >
- <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight", "setContentView"]).omit}
- renderDepth={this.props.renderDepth + 1}
- fieldKey={this.annotationKey}
- CollectionView={undefined}
- isAnnotationOverlay={true}
- annotationLayerHostsContent={true}
- PanelWidth={this.props.PanelWidth}
- PanelHeight={this.props.PanelHeight}
- ScreenToLocalTransform={this.screenToLocalTransform}
- select={emptyFunction}
- scaling={returnOne}
- whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
- removeDocument={this.removeDocument}
- moveDocument={this.moveDocument}
- addDocument={this.addDocument}>
- {this.contentFunc}
- </CollectionFreeFormView>
- {this.annotationLayer}
- {!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? (null) :
- <MarqueeAnnotator
- rootDoc={this.rootDoc}
- scrollTop={0}
- down={this._marqueeing}
- scaling={this.props.scaling}
- docView={this.props.docViewPath().slice(-1)[0]}
- addDocument={this.addDocument}
- finishMarquee={this.finishMarquee}
- savedAnnotations={this.savedAnnotations}
- annotationLayer={this._annotationLayer.current}
- mainCont={this._mainCont.current}
- anchorMenuCrop={this.crop}
- />}
- </div >);
+ const borderRadius = borderRad?.includes('px') ? `${Number(borderRad.split('px')[0]) / (this.props.scaling?.() || 1)}px` : borderRad;
+ return (
+ <div
+ className="imageBox"
+ onContextMenu={this.specificContextMenu}
+ ref={this._mainCont}
+ style={{
+ width: this.props.PanelWidth() ? undefined : `100%`,
+ height: this.props.PanelWidth() ? undefined : `100%`,
+ pointerEvents: this.layoutDoc._lockedPosition ? 'none' : undefined,
+ borderRadius,
+ }}>
+ <CollectionFreeFormView
+ {...OmitKeys(this.props, ['NativeWidth', 'NativeHeight', 'setContentView']).omit}
+ renderDepth={this.props.renderDepth + 1}
+ fieldKey={this.annotationKey}
+ CollectionView={undefined}
+ isAnnotationOverlay={true}
+ annotationLayerHostsContent={true}
+ PanelWidth={this.props.PanelWidth}
+ PanelHeight={this.props.PanelHeight}
+ ScreenToLocalTransform={this.screenToLocalTransform}
+ select={emptyFunction}
+ scaling={returnOne}
+ whenChildContentsActiveChanged={this.whenChildContentsActiveChanged}
+ removeDocument={this.removeDocument}
+ moveDocument={this.moveDocument}
+ addDocument={this.addDocument}>
+ {this.contentFunc}
+ </CollectionFreeFormView>
+ {this.annotationLayer}
+ {!this._marqueeing || !this._mainCont.current || !this._annotationLayer.current ? null : (
+ <MarqueeAnnotator
+ rootDoc={this.rootDoc}
+ scrollTop={0}
+ down={this._marqueeing}
+ scaling={this.props.scaling}
+ docView={this.props.docViewPath().slice(-1)[0]}
+ addDocument={this.addDocument}
+ finishMarquee={this.finishMarquee}
+ savedAnnotations={this.savedAnnotations}
+ annotationLayer={this._annotationLayer.current}
+ mainCont={this._mainCont.current}
+ anchorMenuCrop={this.crop}
+ />
+ )}
+ </div>
+ );
}
-
}