aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/ImageBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/ImageBox.tsx')
-rw-r--r--src/client/views/nodes/ImageBox.tsx58
1 files changed, 30 insertions, 28 deletions
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 19e393968..d28d71fe3 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -89,26 +89,26 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
const anchor =
visibleAnchor ??
Docs.Create.ConfigDocument({
- title: 'ImgAnchor:' + this.rootDoc.title,
+ title: 'ImgAnchor:' + this.Document.title,
config_panX: NumCast(this.layoutDoc._freeform_panX),
config_panY: NumCast(this.layoutDoc._freeform_panY),
config_viewScale: Cast(this.layoutDoc._freeform_scale, 'number', null),
- annotationOn: this.rootDoc,
+ annotationOn: this.Document,
});
if (anchor) {
if (!addAsAnnotation) anchor.backgroundColor = 'transparent';
addAsAnnotation && this.addDocument(anchor);
- PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), pannable: visibleAnchor ? false : true } }, this.rootDoc);
+ PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), pannable: visibleAnchor ? false : true } }, this.Document);
return anchor;
}
- return this.rootDoc;
+ return this.Document;
};
componentDidMount() {
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) * NumCast(this.rootDoc._freeform_scale, 1),
+ scrSize: (this.props.ScreenToLocalTransform().inverse().transformDirection(this.nativeSize.nativeWidth, this.nativeSize.nativeHeight)[0] / this.nativeSize.nativeWidth) * NumCast(this.layoutDoc._freeform_scale, 1),
selected: this.props.isSelected(),
}),
({ forceFull, scrSize, selected }) => (this._curSuffix = selected ? '_o' : this.fieldKey === 'icon' ? '_m' : forceFull ? '_o' : scrSize < 0.25 ? '_s' : scrSize < 0.5 ? '_m' : scrSize < 0.8 ? '_l' : '_o'),
@@ -152,7 +152,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
};
if (de.metaKey || targetIsBullseye(e.target as HTMLElement)) {
added = de.complete.docDragData.droppedDocuments.reduce((last: boolean, drop: Doc) => {
- this.rootDoc[this.fieldKey + '_usePath'] = 'alternate:hover';
+ this.layoutDoc[this.fieldKey + '_usePath'] = 'alternate:hover';
return last && Doc.AddDocToList(this.dataDoc, this.fieldKey + '-alternates', drop);
}, true);
} else if (de.altKey || !this.dataDoc[this.fieldKey]) {
@@ -177,13 +177,13 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
@undoBatch
setNativeSize = action(() => {
- const scaling = (this.props.DocumentView?.().props.ScreenToLocalTransform().Scale || 1) / NumCast(this.rootDoc._freeform_scale, 1);
+ const scaling = (this.props.DocumentView?.().props.ScreenToLocalTransform().Scale || 1) / NumCast(this.layoutDoc._freeform_scale, 1);
const nscale = NumCast(this.props.PanelWidth()) / scaling;
const nw = nscale / NumCast(this.dataDoc[this.fieldKey + '_nativeWidth']);
this.dataDoc[this.fieldKey + '_nativeHeight'] = NumCast(this.dataDoc[this.fieldKey + '_nativeHeight']) * nw;
this.dataDoc[this.fieldKey + '_nativeWidth'] = NumCast(this.dataDoc[this.fieldKey + '_nativeWidth']) * nw;
- this.rootDoc._freeform_panX = nw * NumCast(this.rootDoc._freeform_panX);
- this.rootDoc._freeform_panY = nw * NumCast(this.rootDoc._freeform_panY);
+ this.layoutDoc._freeform_panX = nw * NumCast(this.layoutDoc._freeform_panX);
+ this.layoutDoc._freeform_panY = nw * NumCast(this.layoutDoc._freeform_panY);
this.dataDoc._freeform_panXMax = this.dataDoc._freeform_panXMax ? nw * NumCast(this.dataDoc._freeform_panXMax) : undefined;
this.dataDoc._freeform_panXMin = this.dataDoc._freeform_panXMin ? nw * NumCast(this.dataDoc._freeform_panXMin) : undefined;
this.dataDoc._freeform_panYMax = this.dataDoc._freeform_panYMax ? nw * NumCast(this.dataDoc._freeform_panYMax) : undefined;
@@ -206,17 +206,17 @@ 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.Document.title;
Doc.GetProto(region).followLinkToggle = 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;
- cropping.x = NumCast(this.rootDoc.x) + NumCast(this.rootDoc._width);
- cropping.y = NumCast(this.rootDoc.y);
+ const viewScale = NumCast(this.dataDoc[this.fieldKey + '_nativeWidth']) / anchw;
+ cropping.title = 'crop: ' + this.Document.title;
+ cropping.x = NumCast(this.Document.x) + NumCast(this.layoutDoc._width);
+ cropping.y = NumCast(this.Document.y);
cropping._width = anchw * (this.props.NativeDimScaling?.() || 1);
cropping._height = anchh * (this.props.NativeDimScaling?.() || 1);
cropping.onClick = undefined;
@@ -224,10 +224,10 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
croppingProto.annotationOn = undefined;
croppingProto.isDataDoc = true;
croppingProto.backgroundColor = undefined;
- croppingProto.proto = Cast(this.rootDoc.proto, Doc, null)?.proto; // set proto of cropping's data doc to be IMAGE_PROTO
+ 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.rootDoc[this.fieldKey] as ObjectField);
+ croppingProto.data = ObjectField.MakeCopy(this.dataDoc[this.fieldKey] as ObjectField);
croppingProto['data_nativeWidth'] = anchw;
croppingProto['data_nativeHeight'] = anchh;
croppingProto.freeform_scale = viewScale;
@@ -240,8 +240,8 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
croppingProto.freeform_panY_max = anchh / viewScale;
if (addCrop) {
DocUtils.MakeLink(region, cropping, { link_relationship: 'cropped image' });
- cropping.x = NumCast(this.rootDoc.x) + NumCast(this.rootDoc._width);
- cropping.y = NumCast(this.rootDoc.y);
+ cropping.x = NumCast(this.Document.x) + NumCast(this.layoutDoc._width);
+ cropping.y = NumCast(this.Document.y);
this.props.addDocTab(cropping, OpenWhere.inParent);
}
DocumentManager.Instance.AddViewRenderedCb(cropping, dv => setTimeout(() => (dv.ComponentView as ImageBox).setNativeSize(), 200));
@@ -263,7 +263,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
ImageBox.setImageEditorOpen(true);
ImageBox.setImageEditorSource(this.choosePath(field.url));
ImageBox.addDoc = this.props.addDocument;
- ImageBox.imageRootDoc = this.rootDoc;
+ ImageBox.imageRootDoc = this.Document;
}),
icon: 'pencil-alt',
});
@@ -319,7 +319,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
if (!/\.(png|jpg|jpeg|gif|webp)$/.test(lower)) return `/assets/unknown-file-icon-hi.png`;
const ext = extname(url.href);
- return url.href.replace(ext, this._curSuffix + ext);
+ return url.href.replace(ext, (this._error ? '_o' : this._curSuffix) + ext);
}
considerGooglePhotosLink = () => {
@@ -332,7 +332,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
return !tags ? null : <img id={'google-tags'} src={'/assets/google_tags.png'} />;
};
- getScrollHeight = () => (this.props.layout_fitWidth?.(this.rootDoc) !== false && NumCast(this.rootDoc._freeform_scale, 1) === NumCast(this.rootDoc._freeform_scaleMin, 1) ? this.nativeSize.nativeHeight : undefined);
+ getScrollHeight = () => (this.props.layout_fitWidth?.(this.Document) !== false && NumCast(this.layoutDoc._freeform_scale, 1) === NumCast(this.dataDoc._freeform_scaleMin, 1) ? this.nativeSize.nativeHeight : undefined);
@computed
private get considerDownloadIcon() {
@@ -384,7 +384,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
return { nativeWidth, nativeHeight, nativeOrientation };
}
@computed get overlayImageIcon() {
- const usePath = this.rootDoc[`_${this.fieldKey}_usePath`];
+ const usePath = this.layoutDoc[`_${this.fieldKey}_usePath`];
return (
<Tooltip
title={
@@ -405,7 +405,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
<div
className="imageBox-alternateDropTarget"
ref={this._overlayIconRef}
- onPointerDown={e => setupMoveUpEvents(e.target, e, returnFalse, emptyFunction, e => (this.rootDoc[`_${this.fieldKey}_usePath`] = usePath === undefined ? 'alternate' : usePath === 'alternate' ? 'alternate:hover' : undefined))}
+ onPointerDown={e => setupMoveUpEvents(e.target, e, returnFalse, emptyFunction, e => (this.layoutDoc[`_${this.fieldKey}_usePath`] = usePath === undefined ? 'alternate' : usePath === 'alternate' ? 'alternate:hover' : undefined))}
style={{
display: (this.props.isContentActive() !== false && DragManager.DocDragData?.canEmbed) || DocListCast(this.dataDoc[this.fieldKey + '-alternates']).length ? 'block' : 'none',
width: 'min(10%, 25px)',
@@ -430,11 +430,13 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
return paths.length ? paths : [Utils.CorsProxy('https://cs.brown.edu/~bcz/noImage.png')];
}
+ @observable _error = '';
+
@observable _isHovering = false; // flag to switch between primary and alternate images on hover
@computed get content() {
TraceMobx();
- const backColor = DashColor(this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor));
+ const backColor = DashColor(this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor));
const backAlpha = backColor.red() === 0 && backColor.green() === 0 && backColor.blue() === 0 ? backColor.alpha() : 1;
const srcpath = this.layoutDoc.hideImage ? '' : this.paths[0];
const fadepath = this.layoutDoc.hideImage ? '' : this.paths.lastElement();
@@ -452,12 +454,12 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
transformOrigin = 'right top';
transform = `translate(-100%, 0%) rotate(${rotation}deg) scale(${aspect})`;
}
- const usePath = this.rootDoc[`_${this.fieldKey}_usePath`];
+ const usePath = this.layoutDoc[`_${this.fieldKey}_usePath`];
return (
<div className="imageBox-cont" onPointerEnter={action(() => (this._isHovering = true))} onPointerLeave={action(() => (this._isHovering = false))} key={this.layoutDoc[Id]} ref={this.createDropTarget} onPointerDown={this.marqueeDown}>
<div className="imageBox-fader" style={{ opacity: backAlpha }}>
- <img key="paths" src={srcpath} style={{ transform, transformOrigin }} draggable={false} width={nativeWidth} />
+ <img key="paths" src={srcpath} style={{ transform, transformOrigin }} onError={action(e => (this._error = e.toString()))} draggable={false} width={nativeWidth} />
{fadepath === srcpath ? null : (
<div className={`imageBox-fadeBlocker${(this._isHovering && usePath === 'alternate:hover') || usePath === 'alternate' ? '-hover' : ''}`} style={{ transition: StrCast(this.layoutDoc.viewTransition, 'opacity 1000ms') }}>
<img className="imageBox-fadeaway" key="fadeaway" src={fadepath} style={{ transform, transformOrigin }} draggable={false} width={nativeWidth} />
@@ -481,7 +483,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
}
screenToLocalTransform = () => this.props.ScreenToLocalTransform().translate(0, NumCast(this.layoutDoc._layout_scrollTop) * this.props.ScreenToLocalTransform().Scale);
marqueeDown = (e: React.PointerEvent) => {
- if (!e.altKey && e.button === 0 && NumCast(this.rootDoc._freeform_scale, 1) <= NumCast(this.rootDoc.freeform_scaleMin, 1) && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) {
+ if (!e.altKey && e.button === 0 && NumCast(this.layoutDoc._freeform_scale, 1) <= NumCast(this.dataDoc.freeform_scaleMin, 1) && this.props.isContentActive(true) && ![InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) {
setupMoveUpEvents(
this,
e,
@@ -529,7 +531,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
height: this.props.PanelWidth() ? undefined : `100%`,
pointerEvents: this.layoutDoc._lockedPosition ? 'none' : undefined,
borderRadius,
- overflow: this.layoutDoc.layout_fitWidth || this.props.layout_fitWidth?.(this.rootDoc) ? 'auto' : undefined,
+ overflow: this.layoutDoc.layout_fitWidth || this.props.layout_fitWidth?.(this.Document) ? 'auto' : undefined,
}}>
<CollectionFreeFormView
ref={this._ffref}