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.tsx75
1 files changed, 59 insertions, 16 deletions
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index c156c80e4..0dfc0ec28 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -1,10 +1,12 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@mui/material';
+import axios from 'axios';
import { Colors } from 'browndash-components';
import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction } from 'mobx';
import { observer } from 'mobx-react';
import { extname } from 'path';
import * as React from 'react';
+import ReactLoading from 'react-loading';
import { ClientUtils, DashColor, returnEmptyString, returnFalse, returnOne, returnZero, setupMoveUpEvents } from '../../../ClientUtils';
import { Doc, DocListCast, Opt } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
@@ -17,11 +19,11 @@ import { TraceMobx } from '../../../fields/util';
import { emptyFunction } from '../../../Utils';
import { Docs } from '../../documents/Documents';
import { DocumentType } from '../../documents/DocumentTypes';
-import { DocUtils } from '../../documents/DocUtils';
+import { DocUtils, FollowLinkScript } from '../../documents/DocUtils';
import { Networking } from '../../Network';
import { DragManager } from '../../util/DragManager';
import { SnappingManager } from '../../util/SnappingManager';
-import { undoBatch } from '../../util/UndoManager';
+import { undoable, undoBatch } from '../../util/UndoManager';
import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView';
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
@@ -60,25 +62,31 @@ export class ImageEditorData {
public static get AddDoc() { return ImageEditorData.imageData.addDoc; } // prettier-ignore
public static set AddDoc(addDoc: Opt<(doc: Doc | Doc[], annotationKey?: string) => boolean>) { ImageEditorData.set(this.imageData.open, this.imageData.rootDoc, this.imageData.source, addDoc); } // prettier-ignore
}
+
+const API_URL = 'https://api.unsplash.com/search/photos';
@observer
export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
public static LayoutString(fieldKey: string) {
return FieldView.LayoutString(ImageBox, fieldKey);
}
+ _ffref = React.createRef<CollectionFreeFormView>();
private _ignoreScroll = false;
private _forcedScroll = false;
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>();
- private _marqueeref = React.createRef<MarqueeAnnotator>();
private _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef();
- @observable _savedAnnotations = new ObservableMap<number, (HTMLDivElement & { marqueeing?: boolean })[]>();
- @observable _curSuffix = '';
- @observable _error = '';
- @observable _isHovering = false; // flag to switch between primary and alternate images on hover
- _ffref = React.createRef<CollectionFreeFormView>();
+ imageRef: HTMLImageElement | null = null; // <video> ref
+ marqueeref = React.createRef<MarqueeAnnotator>();
+ @observable Loading = false; // bcz: this should be migrated into StylProviderQuiz since it's not fundamental to the imageBox
+
+ @observable private _searchInput = '';
+ @observable private _savedAnnotations = new ObservableMap<number, (HTMLDivElement & { marqueeing?: boolean })[]>();
+ @observable private _curSuffix = '';
+ @observable private _error = '';
+ @observable private _isHovering = false; // flag to switch between primary and alternate images on hover
constructor(props: FieldViewProps) {
super(props);
@@ -90,7 +98,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this._dropDisposer?.();
ele && (this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this), this.Document));
};
-
getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => {
const visibleAnchor = this._getAnchor?.(this._savedAnnotations, true); // use marquee anchor, otherwise, save zoom/pan as anchor
const anchor =
@@ -149,8 +156,33 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
Object.values(this._disposers).forEach(disposer => disposer?.());
}
- @undoBatch
- drop = (e: Event, de: DragManager.DropEvent) => {
+ /**
+ * Find images from the unsplash api to add to flashcards.
+ */
+ fetchImages = async () => {
+ try {
+ const { data } = await axios.get(`${API_URL}?query=${this._searchInput}&page=1&per_page=${1}&client_id=${process.env.VITE_API_KEY}`);
+ const imageSnapshot = Docs.Create.ImageDocument(data.results[0].urls.small, {
+ _nativeWidth: Doc.NativeWidth(this.layoutDoc),
+ _nativeHeight: Doc.NativeHeight(this.layoutDoc),
+ x: NumCast(this.layoutDoc.x),
+ y: NumCast(this.layoutDoc.y),
+ onClick: FollowLinkScript(),
+ _width: 150,
+ _height: 150,
+ title: '--snapshot' + NumCast(this.layoutDoc._layout_currentTimecode) + ' image-',
+ });
+ this._props.addDocument?.(imageSnapshot);
+ } catch (error) {
+ console.log(error);
+ }
+ };
+
+ handleSelection = async (selection: string) => {
+ this._searchInput = selection;
+ };
+
+ drop = undoable((e: Event, de: DragManager.DropEvent) => {
if (de.complete.docDragData) {
let added: boolean | undefined;
const targetIsBullseye = (ele: HTMLElement): boolean => {
@@ -179,7 +211,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
return added;
}
return false;
- };
+ }, 'image drop');
@undoBatch
resolution = () => {
@@ -404,6 +436,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
<div className="imageBox-fader" style={{ opacity: backAlpha }}>
<img
alt=""
+ ref={action((r: HTMLImageElement | null) => (this.imageRef = r))}
key="paths"
src={srcpath}
style={{ transform, transformOrigin, objectFit: 'fill', height: '100%' }}
@@ -444,7 +477,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
e,
action(moveEv => {
MarqueeAnnotator.clearAnnotations(this._savedAnnotations);
- this._marqueeref.current?.onInitiateSelection([moveEv.clientX, moveEv.clientY]);
+ this.marqueeref.current?.onInitiateSelection([moveEv.clientX, moveEv.clientY]);
return true;
}),
returnFalse,
@@ -456,7 +489,11 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@action
finishMarquee = () => {
this._getAnchor = AnchorMenu.Instance?.GetAnchor;
- this._marqueeref.current?.onTerminateSelection();
+ this._props.styleProvider?.(this.Document, this._props, StyleProp.AnchorMenuItems);
+ AnchorMenu.Instance.addToCollection = this._props.DocumentView?.()._props.addDocument;
+ AnchorMenu.Instance.marqueeWidth = this.marqueeref.current?.Width ?? 0;
+ AnchorMenu.Instance.marqueeHeight = this.marqueeref.current?.Height ?? 0;
+ this.marqueeref.current?.onTerminateSelection();
this._props.select(false);
};
focus = (anchor: Doc, options: FocusViewOptions) => (anchor.type === DocumentType.CONFIG ? undefined : this._ffref.current?.focus(anchor, options));
@@ -490,7 +527,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
height: this._props.PanelHeight() ? undefined : `100%`,
pointerEvents: this.layoutDoc._lockedPosition ? 'none' : undefined,
borderRadius,
- overflow: this.layoutDoc.layout_fitWidth || this._props.fitWidth?.(this.Document) ? 'auto' : undefined,
+ overflow: this.layoutDoc.layout_fitWidth || this._props.fitWidth?.(this.Document) ? 'auto' : 'hidden',
}}>
<CollectionFreeFormView
ref={this._ffref}
@@ -517,11 +554,16 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
addDocument={this.addDocument}>
{this.content}
</CollectionFreeFormView>
+ {this.Loading ? (
+ <div className="loading-spinner" style={{ position: 'absolute' }}>
+ <ReactLoading type="spin" height={50} width={50} color={'blue'} />
+ </div>
+ ) : null}
{this.annotationLayer}
{!this._mainCont.current || !this.DocumentView || !this._annotationLayer.current ? null : (
<MarqueeAnnotator
Document={this.Document}
- ref={this._marqueeref}
+ ref={this.marqueeref}
scrollTop={0}
annotationLayerScrollTop={0}
scaling={returnOne}
@@ -535,6 +577,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
marqueeContainer={this._mainCont.current}
highlightDragSrcColor=""
anchorMenuCrop={this.crop}
+ // anchorMenuFlashcard={() => this.getImageDesc()}
/>
)}
</div>