diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/ContextMenuItem.tsx | 10 | ||||
-rw-r--r-- | src/client/views/PropertiesView.tsx | 4 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx | 3 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 4 | ||||
-rw-r--r-- | src/client/views/nodes/ImageBox.tsx | 3 | ||||
-rw-r--r-- | src/client/views/smartdraw/DrawingFillHandler.tsx | 70 | ||||
-rw-r--r-- | src/server/ApiManagers/FireflyManager.ts | 132 |
7 files changed, 82 insertions, 144 deletions
diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx index 6f8f41bdd..218718b18 100644 --- a/src/client/views/ContextMenuItem.tsx +++ b/src/client/views/ContextMenuItem.tsx @@ -1,6 +1,6 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, makeObservable, observable, runInAction } from 'mobx'; +import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { SnappingManager } from '../util/SnappingManager'; @@ -26,7 +26,7 @@ export class ContextMenuItem extends ObservableReactComponent<ContextMenuProps & _hoverTimeout?: NodeJS.Timeout; _overPosY = 0; _overPosX = 0; - @observable _items: ContextMenuProps[] = []; + @observable.shallow _items: ContextMenuProps[] = []; @observable _overItem = false; constructor(props: ContextMenuProps & { selected?: boolean }) { @@ -34,8 +34,8 @@ export class ContextMenuItem extends ObservableReactComponent<ContextMenuProps & makeObservable(this); } - componentDidMount() { - runInAction(() => this._items.push(...(this._props.subitems ?? []))); + @computed get items() { + return this._items.concat(this._props.subitems ?? []); } handleEvent = async (e: React.MouseEvent<HTMLDivElement>) => { @@ -91,7 +91,7 @@ export class ContextMenuItem extends ObservableReactComponent<ContextMenuProps & }; render() { - const submenu = this._items.map(prop => <ContextMenuItem {...prop} key={prop.description} closeMenu={this._props.closeMenu} />); + const submenu = this.items.map(prop => <ContextMenuItem {...prop} key={prop.description} closeMenu={this._props.closeMenu} />); return this.props.event || this._props.noexpand ? this.renderItem(submenu) : <div className="contextMenu-inlineMenu">{submenu}</div>; } } diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 4e12e0b2d..aefdeee17 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -995,9 +995,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps align="flex-start" fillWidth toggleType={ToggleType.BUTTON} - onClick={undoable(() => { - DrawingFillHandler.drawingToImage(targetDoc, 'fill in the details of this image'); - }, 'createImage')} + onClick={undoable(() => DrawingFillHandler.drawingToImage(targetDoc, 'fill in the details of this image'), 'createImage')} /> </div> <div className="color"> diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx index 79aad0ef2..272c13546 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx @@ -102,7 +102,6 @@ export function computePassLayout(poolData: Map<string, PoolData>, pivotDoc: Doc replica: '', }); }); - // eslint-disable-next-line no-use-before-define return normalizeResults(panelDim, 12, docMap, poolData, viewDefsToJSX, [], 0, []); } @@ -272,7 +271,6 @@ export function computePivotLayout(poolData: Map<string, PoolData>, pivotDoc: Do payload: pivotColumnGroups.get(key)?.filters, })); groupNames.push(...dividers); - // eslint-disable-next-line no-use-before-define return normalizeResults(panelDim, maxText, docMap, poolData, viewDefsToJSX, groupNames, 0, []); } @@ -347,7 +345,6 @@ export function computeTimelineLayout(poolData: Map<string, PoolData>, pivotDoc: if (!stack && (curTime === undefined || Math.abs(x - (curTime - minTime) * scaling) > pivotAxisWidth)) { groupNames.push({ type: 'text', text: toLabel(key), x: x, y: stack * 25, height: fontHeight, fontSize, payload: undefined }); } - // eslint-disable-next-line no-use-before-define layoutDocsAtTime(keyDocs, key); }); if (sortedKeys.length && curTime !== undefined && curTime > sortedKeys[sortedKeys.length - 1]) { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 4bfa7fc92..8519cda3c 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -52,6 +52,7 @@ import { FormattedTextBox } from './formattedText/FormattedTextBox'; import { PresEffect, PresEffectDirection } from './trails/PresEnums'; import SpringAnimation from './trails/SlideEffect'; import { SpringType, springMappings } from './trails/SpringUtils'; +import { DrawingFillHandler } from '../smartdraw/DrawingFillHandler'; export interface DocumentViewProps extends FieldViewSharedProps { hideDecorations?: boolean; // whether to suppress all DocumentDecorations when doc is selected @@ -551,6 +552,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document appearanceItems.splice(0, 0, { description: 'Open in Lightbox', event: () => DocumentView.SetLightboxDoc(this.Document), icon: 'external-link-alt' }); } appearanceItems.push({ description: 'Pin', event: () => this._props.pinToPres(this.Document, {}), icon: 'map-pin' }); + appearanceItems.push({ description: 'Make Image', event: () => DrawingFillHandler.drawingToImage(this.Document, StrCast(this.Document.title)), icon: 'map-pin' }); !Doc.noviceMode && templateDoc && appearanceItems.push({ description: 'Open Template ', event: () => this._props.addDocTab(templateDoc, OpenWhere.addRight), icon: 'eye' }); !appearance && appearanceItems.length && cm.addItem({ description: 'Appearance...', subitems: appearanceItems, icon: 'compass' }); @@ -1072,7 +1074,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() { public static GetDocImage(doc: Doc) { return DocumentView.getDocumentView(doc) ?.ComponentView?.updateIcon?.() - .then(() => ImageCast(DocCast(doc).icon)); + .then(() => ImageCast(doc?.icon, ImageCast(doc[Doc.LayoutFieldKey(doc)]))); } public get displayName() { return 'DocumentView(' + (this.Document?.title??"") + ')'; } // prettier-ignore diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index d847b7940..03d417e4e 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -40,7 +40,6 @@ import { FocusViewOptions } from './FocusViewOptions'; import './ImageBox.scss'; import { OpenWhere } from './OpenWhere'; import { Upload } from '../../../server/SharedMediaTypes'; -import { ImageUtils } from '../../util/Import & Export/ImageUtils'; export class ImageEditorData { // eslint-disable-next-line no-use-before-define @@ -361,6 +360,8 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { } }; + updateIcon = () => new Promise<void>(res => res()); + choosePath = (url: URL) => { if (!url?.href) return ''; const lower = url.href.toLowerCase(); diff --git a/src/client/views/smartdraw/DrawingFillHandler.tsx b/src/client/views/smartdraw/DrawingFillHandler.tsx index 6f111e95b..32416cec5 100644 --- a/src/client/views/smartdraw/DrawingFillHandler.tsx +++ b/src/client/views/smartdraw/DrawingFillHandler.tsx @@ -1,50 +1,22 @@ -// import { action, makeObservable } from 'mobx'; -// import { observer } from 'mobx-react'; -// import React from 'react'; -// import { Doc } from '../../../fields/Doc'; -// import { ImageCast } from '../../../fields/Types'; -// import { ImageField } from '../../../fields/URLField'; -// import { Docs } from '../../documents/Documents'; -// import { Networking } from '../../Network'; -// import { makeUserTemplateButtonOrImage } from '../../util/DropConverter'; -// import { DocumentView, DocumentViewInternal } from '../nodes/DocumentView'; -// import { ImageUtility } from '../nodes/imageEditor/imageEditorUtils/ImageHandler'; -// import { OpenWhere } from '../nodes/OpenWhere'; -// import { ObservableReactComponent } from '../ObservableReactComponent'; +import { Doc } from '../../../fields/Doc'; +import { ImageCast } from '../../../fields/Types'; +import { Upload } from '../../../server/SharedMediaTypes'; +import { Docs } from '../../documents/Documents'; +import { Networking } from '../../Network'; +import { DocumentView, DocumentViewInternal } from '../nodes/DocumentView'; +import { OpenWhere } from '../nodes/OpenWhere'; -// export class DrawingFillHandler { -// static drawingToImage = async (drawing: Doc, prompt: string) => { -// const imageField = await DocumentView.GetDocImage(drawing); -// if (!imageField) return; -// const { href } = ImageCast(imageField).url; -// const hrefParts = href.split('.'); -// const hrefComplete = `${hrefParts[0]}_o.${hrefParts[1]}`; -// try { -// const response = await fetch(hrefComplete); -// const blob: Blob = await response.blob(); -// const strength: number = 100; -// const img = await Networking.PostToServer('/oldQueryFireflyImage', { prompt, blob, strength }); -// DocumentViewInternal.addDocTabFunc(Docs.Create.ImageDocument(img, {}), OpenWhere.addRight); -// // Networking.PostToServer('/oldQueryFireflyImage', { prompt, blob, strength }).then(img => DocumentViewInternal.addDocTabFunc(Docs.Create.ImageDocument(img, {}), OpenWhere.addRight)); -// } catch (error) { -// console.error('Error fetching image:', error); -// return; -// } - -// // const image = new Image(); -// // image.src = imageField.url?.href; -// // // image.onload = async () => { -// // const canvas = document.createElement('canvas'); -// // canvas.width = image.width; -// // canvas.height = image.height; -// // const ctx = canvas.getContext('2d'); -// // if (!ctx) return; -// // ctx.globalCompositeOperation = 'source-over'; -// // ctx.clearRect(0, 0, image.width, image.height); -// // ctx.drawImage(image, 0, 0); -// // const blob: Blob = await ImageUtility.canvasToBlob(canvas); -// // const strength: number = 100; -// // Networking.PostToServer('/oldQueryFireflyImage', { prompt, blob, strength }).then(img => DocumentViewInternal.addDocTabFunc(Docs.Create.ImageDocument(img, {}), OpenWhere.addRight)); -// // }; -// }; -// } +export class DrawingFillHandler { + static drawingToImage = (drawing: Doc, prompt: string) => + DocumentView.GetDocImage(drawing)?.then(imageField => { + if (imageField) { + const { href } = ImageCast(imageField).url; + const hrefParts = href.split('.'); + const structureUrl = `${hrefParts[0]}_o.${hrefParts[1]}`; + const strength: number = 100; + Networking.PostToServer('/queryFireflyImageFromStructure', { prompt, structureUrl, strength }).then((info: Upload.ImageInformation) => + DocumentViewInternal.addDocTabFunc(Docs.Create.ImageDocument(info.accessPaths.agnostic.client, {}), OpenWhere.addRight)) // prettier-ignore + } + return false; + }); +} diff --git a/src/server/ApiManagers/FireflyManager.ts b/src/server/ApiManagers/FireflyManager.ts index 73cf94206..c84e9e8fa 100644 --- a/src/server/ApiManagers/FireflyManager.ts +++ b/src/server/ApiManagers/FireflyManager.ts @@ -20,21 +20,10 @@ export default class FireflyManager extends ApiManager { return undefined; }); - askFireflyOld = (prompt: string = 'a realistic illustration of a cat coding', uploadId: string, strength: number) => { - const fetched = this.getBearerToken().then(response => - response?.json().then((data: { access_token: string }) => { - const body: any = { - prompt: prompt, - structure: { - strength: strength, - imageReference: { - source: { - uploadId: uploadId, - }, - }, - }, - }; - return fetch('https://firefly-api.adobe.io/v3/images/generate', { + generateImageFromStructure = (prompt: string = 'a realistic illustration of a cat coding', structureUrl: string, strength: number) => + this.getBearerToken().then(response => + response?.json().then((data: { access_token: string }) => + fetch('https://firefly-api.adobe.io/v3/images/generate', { method: 'POST', headers: [ ['Content-Type', 'application/json'], @@ -42,40 +31,40 @@ export default class FireflyManager extends ApiManager { ['x-api-key', process.env._CLIENT_FIREFLY_CLIENT_ID ?? ''], ['Authorization', `Bearer ${data.access_token}`], ], - body: JSON.stringify(body), + body: JSON.stringify({ + prompt, + structure: !structureUrl + ? undefined + : { + strength, + imageReference: { + source: { url: structureUrl }, + }, + }, + }), }) - .then(response => response.json().then(json => JSON.stringify((json.outputs?.[0] as { image: { url: string } })?.image))) + .then(response2 => response2.json().then(json => JSON.stringify((json.outputs?.[0] as { image: { url: string } })?.image))) .catch(error => { console.error('Error:', error); return ''; + }) + ) + ); + + uploadImageToDropbox = (fileUrl: string, dbx = new Dropbox({ accessToken: process.env.DROPBOX_TOKEN })) => + new Promise<string>((res, rej) => + fs.readFile(path.join(filesDirectory, `${Directory.images}/${path.basename(fileUrl)}`), undefined, (err, contents) => { + if (err) { + console.log('Error: ', err); + rej(); + } else { + dbx.filesUpload({ path: `/Apps/browndash/${path.basename(fileUrl)}`, contents }).then(response => { + dbx.filesGetTemporaryLink({ path: response.result.path_display ?? '' }).then(link => res(link.result.link)); }); + } }) ); - return fetched; - }; - uploadImageToFirefly = (image: Blob) => { - const fetched = this.getBearerToken().then(response => - response?.json().then((data: { access_token: string }) => - fetch('https://firefly-api.adobe.io/v3/uploads', { - method: 'POST', - headers: [ - ['Content-Type', image.type], - ['x-api-key', process.env._CLIENT_FIREFLY_CLIENT_ID ?? ''], - ['Authorization', `Bearer ${data.access_token}`], - ], - body: image, - }) - .then(response => response.json()) - .then(data => data.uploadId) // Extract the uploadId from the response - .catch(error => { - console.error('Error:', error); - return ''; - }) - ) - ); - return fetched; - }; generateImage = (prompt: string = 'a realistic illustration of a cat coding') => { const fetched = this.getBearerToken().then(response => response?.json().then((data: { access_token: string }) => @@ -222,17 +211,16 @@ export default class FireflyManager extends ApiManager { protected initialize(register: Registration): void { register({ method: Method.POST, - subscription: '/oldQueryFireflyImage', - secureHandler: async ({ req, res }) => { - const { prompt, imageBlob, strength = 0.5 } = req.body; - const uploadId = imageBlob ? await this.uploadImageToFirefly(imageBlob) : null; - this.askFireflyOld(prompt, uploadId, strength).then(fire => - DashUploadUtils.UploadImage(JSON.parse(fire ?? '').url).then(info => { - if (info instanceof Error) _invalid(res, info.message); - else _success(res, info); - }) - ); - }, + subscription: '/queryFireflyImageFromStructure', + secureHandler: async ({ req, res }) => + this.uploadImageToDropbox(req.body.structureUrl).then(uploadUrl => + this.generateImageFromStructure(req.body.prompt, uploadUrl, req.body.strength).then(fire => + DashUploadUtils.UploadImage(JSON.parse(fire ?? '').url).then(info => { + if (info instanceof Error) _invalid(res, info.message); + else _success(res, info); + }) + ) + ), }); register({ method: Method.POST, @@ -263,36 +251,16 @@ export default class FireflyManager extends ApiManager { method: Method.POST, subscription: '/expandImage', secureHandler: ({ req, res }) => - new Promise<void>((resolve, reject) => { - const dbx = new Dropbox({ accessToken: process.env.DROPBOX_TOKEN }); - fs.readFile(path.join(filesDirectory, `${Directory.images}/${path.basename(req.body.file)}`), undefined, (err, contents) => { - if (err) { - console.log('Error: ', err); - reject(); - } else { - dbx.filesUpload({ path: `/Apps/browndash/${path.basename(req.body.file)}`, contents }) - .then(response => { - dbx.filesGetTemporaryLink({ path: response.result.path_display ?? '' }).then(link => { - console.log(link.result); - this.expandImage(link.result.link, req.body.prompt).then(text => { - if (text.error_code) _error(res, text.message); - else - DashUploadUtils.UploadImage(text.outputs[0].image.url).then(info => { - if (info instanceof Error) _invalid(res, info.message); - else _success(res, info); - resolve(); - }); - }); - }); - }) - .catch(uploadErr => { - console.log(uploadErr); - _error(res, 'upload to dropbox failed'); - reject(); - }); - } - }); - }), + this.uploadImageToDropbox(req.body.file).then(uploadUrl => + this.expandImage(uploadUrl, req.body.prompt).then(text => { + if (text.error_code) _error(res, text.message); + else + DashUploadUtils.UploadImage(text.outputs[0].image.url).then(info => { + if (info instanceof Error) _invalid(res, info.message); + else _success(res, info); + }); + }) + ), }); } } |