diff options
Diffstat (limited to 'src/client/views/nodes/ImageBox.tsx')
-rw-r--r-- | src/client/views/nodes/ImageBox.tsx | 58 |
1 files changed, 50 insertions, 8 deletions
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index e8d4be1fd..98df777cb 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -1,3 +1,5 @@ +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Tooltip } from '@material-ui/core'; import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import { extname } from 'path'; @@ -8,7 +10,7 @@ import { List } from '../../../fields/List'; import { ObjectField } from '../../../fields/ObjectField'; import { createSchema } from '../../../fields/Schema'; import { ComputedField } from '../../../fields/ScriptField'; -import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types'; +import { Cast, NumCast, StrCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; import { TraceMobx } from '../../../fields/util'; import { DashColor, emptyFunction, returnEmptyString, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from '../../../Utils'; @@ -19,6 +21,7 @@ import { DocumentType } from '../../documents/DocumentTypes'; import { Networking } from '../../Network'; import { DocumentManager } from '../../util/DocumentManager'; import { DragManager } from '../../util/DragManager'; +import { SnappingManager } from '../../util/SnappingManager'; import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from '../../views/ContextMenu'; import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView'; @@ -57,6 +60,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp private _dropDisposer?: DragManager.DragDropDisposer; private _disposers: { [name: string]: IReactionDisposer } = {}; private _getAnchor: (savedAnnotations: Opt<ObservableMap<number, HTMLDivElement[]>>, addAsAnnotation: boolean) => Opt<Doc> = () => undefined; + private _overlayIconRef = React.createRef<HTMLDivElement>(); @observable _curSuffix = ''; @observable _uploadIcon = uploadIcons.idle; @@ -131,10 +135,16 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp @action drop = (e: Event, de: DragManager.DropEvent) => { if (de.complete.docDragData) { - if (de.metaKey) { + const targetIsBullseye = (ele: HTMLElement): boolean => { + if (!ele) return false; + if (ele === this._overlayIconRef.current) return true; + return targetIsBullseye(ele.parentElement as HTMLElement); + }; + if (de.metaKey || targetIsBullseye(e.target as HTMLElement)) { de.complete.docDragData.droppedDocuments.forEach( action((drop: Doc) => { Doc.AddDocToList(this.dataDoc, this.fieldKey + '-alternates', drop); + this.rootDoc[this.fieldKey + '-usePath'] = 'alternate:hover'; e.stopPropagation(); }) ); @@ -154,8 +164,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp @undoBatch resolution = () => (this.layoutDoc._showFullRes = !this.layoutDoc._showFullRes); - @undoBatch - setUseAlt = () => (this.layoutDoc[this.fieldKey + '-useAlt'] = !this.layoutDoc[this.fieldKey + '-useAlt']); @undoBatch setNativeSize = action(() => { @@ -239,7 +247,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp funcs.push({ description: 'Rotate Clockwise 90', event: this.rotate, icon: 'redo-alt' }); funcs.push({ description: `Show ${this.layoutDoc._showFullRes ? 'Dynamic Res' : 'Full Res'}`, event: this.resolution, icon: 'expand' }); funcs.push({ description: 'Set Native Pixel Size', event: this.setNativeSize, icon: 'expand-arrows-alt' }); - funcs.push({ description: `${this.layoutDoc[this.fieldKey + '-useAlt'] ? 'Show Alternate' : 'Show Primary'}`, event: this.setUseAlt, icon: 'image' }); funcs.push({ description: 'Copy path', event: () => Utils.CopyText(this.choosePath(field.url)), icon: 'copy' }); if (!Doc.noviceMode) { funcs.push({ description: 'Export to Google Photos', event: () => GooglePhotos.Transactions.UploadImages([this.props.Document]), icon: 'caret-square-right' }); @@ -356,6 +363,41 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp const nativeOrientation = NumCast(this.dataDoc[this.fieldKey + '-nativeOrientation'], 1); return { nativeWidth, nativeHeight, nativeOrientation }; } + @computed get overlayImageIcon() { + const usePath = this.rootDoc[`_${this.fieldKey}-usePath`]; + return ( + <Tooltip + title={ + <div className="dash-tooltip"> + toggle between + <span style={{ color: usePath === undefined ? 'black' : undefined }}> + <em> primary, </em> + </span> + <span style={{ color: usePath === 'alternate' ? 'black' : undefined }}> + <em>alternate, </em> + </span> + and show + <span style={{ color: usePath === 'alternate:hover' ? 'black' : undefined }}> + <em> alternate on hover</em> + </span> + </div> + }> + <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))} + style={{ + display: (SnappingManager.GetIsDragging() && DragManager.DocDragData?.canEmbed) || DocListCast(this.dataDoc[this.fieldKey + '-alternates']).length ? 'block' : 'none', + width: 'min(10%, 25px)', + height: 'min(10%, 25px)', + background: usePath === undefined ? 'white' : usePath === 'alternate' ? 'black' : 'gray', + color: usePath === undefined ? 'black' : 'white', + }}> + <FontAwesomeIcon icon="turn-up" size="lg" /> + </div> + </Tooltip> + ); + } @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 @@ -389,15 +431,14 @@ 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`]; 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} /> {fadepath === srcpath ? null : ( - <div - className={`imageBox-fadeBlocker${(this._isHovering && this.layoutDoc[this.fieldKey + '-useAlt'] === undefined) || BoolCast(this.layoutDoc[this.fieldKey + '-useAlt']) ? '-hover' : ''}`} - style={{ transition: StrCast(this.layoutDoc.viewTransition, 'opacity 1000ms') }}> + <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} /> </div> )} @@ -405,6 +446,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp {!Doc.noviceMode && this.considerDownloadIcon} {this.considerGooglePhotosLink()} <FaceRectangles document={this.dataDoc} color={'#0000FF'} backgroundColor={'#0000FF'} /> + {this.overlayImageIcon} </div> ); } |