aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/smartdraw
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/smartdraw')
-rw-r--r--src/client/views/smartdraw/DrawingFillHandler.tsx109
-rw-r--r--src/client/views/smartdraw/SmartDrawHandler.tsx22
-rw-r--r--src/client/views/smartdraw/StickerPalette.tsx53
3 files changed, 93 insertions, 91 deletions
diff --git a/src/client/views/smartdraw/DrawingFillHandler.tsx b/src/client/views/smartdraw/DrawingFillHandler.tsx
index c672bc718..2c69284db 100644
--- a/src/client/views/smartdraw/DrawingFillHandler.tsx
+++ b/src/client/views/smartdraw/DrawingFillHandler.tsx
@@ -1,8 +1,6 @@
-import { imageUrlToBase64 } from '../../../ClientUtils';
import { Doc, StrListCast } from '../../../fields/Doc';
-import { DocData } from '../../../fields/DocSymbols';
import { List } from '../../../fields/List';
-import { DocCast, ImageCast } from '../../../fields/Types';
+import { DocCast, ImageCast, StrCast } from '../../../fields/Types';
import { ImageField } from '../../../fields/URLField';
import { Upload } from '../../../server/SharedMediaTypes';
import { gptDescribeImage } from '../../apis/gpt/GPT';
@@ -14,23 +12,29 @@ import { AspectRatioLimits, FireflyDimensionsMap, FireflyImageDimensions, Firefl
const DashDropboxId = '2m86iveqdr9vzsa';
export class DrawingFillHandler {
+ static authorizeDropbox = () => {
+ window.open(`https://www.dropbox.com/oauth2/authorize?client_id=${DashDropboxId}&response_type=code&token_access_type=offline&redirect_uri=http://localhost:1050/refreshDropbox`, '_blank')?.focus();
+ };
static drawingToImage = async (drawing: Doc, strength: number, user_prompt: string, styleDoc?: Doc) => {
- const docData = drawing[DocData];
- const tags = StrListCast(docData.tags).map(tag => tag.slice(1));
+ const tags = StrListCast(drawing.$tags).map(tag => tag.slice(1));
const styles = tags.filter(tag => FireflyStylePresets.has(tag));
- const styleDocs = !Doc.Links(drawing).length
- ? styleDoc && !tags.length
- ? [styleDoc]
- : []
- : Doc.Links(drawing)
- .map(link => Doc.getOppositeAnchor(link, drawing))
- .map(anchor => anchor && DocCast(anchor.embedContainer));
- const styleUrl = await DocumentView.GetDocImage(styleDocs.filter(doc => doc?.data instanceof ImageField).lastElement())?.then(styleImg => {
- const hrefParts = ImageCast(styleImg).url.href.split('.');
- return `${hrefParts.slice(0, -1).join('.')}_o.${hrefParts.lastElement()}`;
- });
+ const styleDocs = [drawing].concat(
+ drawing,
+ ...Doc.Links(drawing)
+ .map(link => Doc.getOppositeAnchor(link, drawing))
+ .map(anchor => DocCast(anchor?.annotationOn, anchor))
+ .map(anchor => anchor!),
+ ...(styleDoc ? [styleDoc] : [])
+ );
+ const styleUrl = tags.length
+ ? undefined
+ : await DocumentView.GetDocImage(styleDocs.filter(doc => doc?.data instanceof ImageField).lastElement())?.then(styleImg => {
+ const hrefParts = ImageCast(styleImg)?.url.href.split('.');
+ return !hrefParts ? undefined : `${hrefParts.slice(0, -1).join('.')}_o.${hrefParts.lastElement()}`;
+ });
return DocumentView.GetDocImage(drawing)?.then(imageField => {
- if (imageField) {
+ const href = ImageCast(imageField)?.url.href;
+ if (href) {
const aspectRatio = (drawing.width as number) / (drawing.height as number);
const dims = (() => {
if (aspectRatio > AspectRatioLimits[FireflyImageDimensions.Widescreen]) return FireflyDimensionsMap[FireflyImageDimensions.Widescreen];
@@ -38,44 +42,43 @@ export class DrawingFillHandler {
if (aspectRatio < AspectRatioLimits[FireflyImageDimensions.Portrait]) return FireflyDimensionsMap[FireflyImageDimensions.Portrait];
return FireflyDimensionsMap[FireflyImageDimensions.Square];
})();
- const { href } = ImageCast(imageField).url;
const hrefParts = href.split('.');
const structureUrl = `${hrefParts.slice(0, -1).join('.')}_o.${hrefParts.lastElement()}`;
- return imageUrlToBase64(structureUrl)
- .then(gptDescribeImage)
- .then((prompt, newPrompt = user_prompt || prompt) =>
- Networking.PostToServer('/queryFireflyImageFromStructure', { prompt: `${newPrompt}`, width: dims.width, height: dims.height, structureUrl, strength, presets: styles, styleUrl })
- .then(res => {
- const genratedDocs = DocCast(drawing.ai_firefly_generatedDocs) ?? Docs.Create.MasonryDocument([], { _width: 400, _height: 400 });
- drawing[DocData].ai_firefly_generatedDocs = genratedDocs;
- (res as Upload.ImageInformation[]).map(info =>
- Doc.AddDocToList(
- genratedDocs,
- undefined,
- Docs.Create.ImageDocument(info.accessPaths.agnostic.client, {
- ai: 'firefly',
- tags: new List<string>(['@ai']),
- title: newPrompt,
- _data_usePath: 'alternate:hover',
- data_alternates: new List<Doc>([drawing]),
- ai_firefly_prompt: newPrompt,
- _width: 500,
- data_nativeWidth: info.nativeWidth,
- data_nativeHeight: info.nativeHeight,
- }),
- undefined,
- undefined,
- true
- )
- );
- if (!DocumentView.getFirstDocumentView(genratedDocs)) DocumentViewInternal.addDocTabFunc(genratedDocs, OpenWhere.addRight);
- })
- .catch(e => {
- if (e.toString().includes('Dropbox') && confirm('Create image failed. Try authorizing DropBox?\r\n' + e.toString().replace(/^[^"]*/, ''))) {
- window.open(`https://www.dropbox.com/oauth2/authorize?client_id=${DashDropboxId}&response_type=code&token_access_type=offline&redirect_uri=http://localhost:1050/refreshDropbox`, '_blank')?.focus();
- } else alert(e.toString());
- })
- ); // prettier-ignore:q
+ return gptDescribeImage(user_prompt, structureUrl).then(newPrompt =>
+ Networking.PostToServer('/queryFireflyImageFromStructure', { prompt: `${newPrompt}`, width: dims.width, height: dims.height, structureUrl, strength, presets: styles, styleUrl })
+ .then(res => {
+ const error = ('error' in res && (res.error as string)) || '';
+ if (error.includes('Dropbox') && confirm('Create image failed. Try authorizing DropBox?\r\n' + error.replace(/^[^"]*/, ''))) {
+ return DrawingFillHandler.authorizeDropbox();
+ }
+ const genratedDocs = DocCast(drawing.ai_firefly_generatedDocs) ?? Docs.Create.MasonryDocument([], { title: StrCast(drawing.title) + ' AI Images', _width: 400, _height: 400 });
+ drawing.$ai_firefly_generatedDocs = genratedDocs;
+ (res as Upload.ImageInformation[]).map(info =>
+ Doc.AddDocToList(
+ genratedDocs,
+ undefined,
+ Docs.Create.ImageDocument(info.accessPaths.agnostic.client, {
+ ai: 'firefly',
+ tags: new List<string>(['@ai']),
+ title: newPrompt,
+ _data_usePath: 'alternate:hover',
+ data_alternates: new List<Doc>([drawing]),
+ ai_firefly_prompt: newPrompt,
+ _width: 500,
+ data_nativeWidth: info.nativeWidth,
+ data_nativeHeight: info.nativeHeight,
+ }),
+ undefined,
+ undefined,
+ true
+ )
+ );
+ if (!DocumentView.getFirstDocumentView(genratedDocs)) DocumentViewInternal.addDocTabFunc(genratedDocs, OpenWhere.addRight);
+ })
+ .catch(e => {
+ alert(e.toString());
+ })
+ ); // prettier-ignore:q
}
});
};
diff --git a/src/client/views/smartdraw/SmartDrawHandler.tsx b/src/client/views/smartdraw/SmartDrawHandler.tsx
index 1cceabed3..4f0cd3978 100644
--- a/src/client/views/smartdraw/SmartDrawHandler.tsx
+++ b/src/client/views/smartdraw/SmartDrawHandler.tsx
@@ -10,9 +10,11 @@ import { INode, parse } from 'svgson';
import { imageUrlToBase64, setupMoveUpEvents } from '../../../ClientUtils';
import { unimplementedFunction } from '../../../Utils';
import { Doc, DocListCast } from '../../../fields/Doc';
-import { DocData } from '../../../fields/DocSymbols';
import { InkData, InkField, InkTool } from '../../../fields/InkField';
+import { List } from '../../../fields/List';
import { BoolCast, ImageCast, NumCast, StrCast } from '../../../fields/Types';
+import { PointData } from '../../../pen-gestures/GestureTypes';
+import { Upload } from '../../../server/SharedMediaTypes';
import { Networking } from '../../Network';
import { GPTCallType, gptAPICall, gptDrawingColor } from '../../apis/gpt/GPT';
import { DocumentType } from '../../documents/DocumentTypes';
@@ -26,9 +28,6 @@ import { MarqueeView } from '../collections/collectionFreeForm';
import { ActiveInkArrowEnd, ActiveInkArrowStart, ActiveInkBezierApprox, ActiveInkColor, ActiveInkDash, ActiveInkFillColor, ActiveInkWidth, ActiveIsInkMask, DocumentView } from '../nodes/DocumentView';
import { FireflyDimensionsMap, FireflyImageData, FireflyImageDimensions } from './FireflyConstants';
import './SmartDrawHandler.scss';
-import { Upload } from '../../../server/SharedMediaTypes';
-import { PointData } from '../../../pen-gestures/GestureTypes';
-import { List } from '../../../fields/List';
export interface DrawingOptions {
text?: string;
@@ -153,9 +152,9 @@ export class SmartDrawHandler extends ObservableReactComponent<object> {
this._display = false;
this.ShowRegenerate = true;
this._showEditBox = false;
- const docData = this._selectedDocs[0][DocData];
- this._lastResponse = StrCast(docData.drawingData);
- this._lastInput = { text: StrCast(docData.ai_drawing_input), complexity: NumCast(docData.ai_drawing_complexity), size: NumCast(docData.ai_drawing_size), autoColor: BoolCast(docData.ai_drawing_colored), x: this._pageX, y: this._pageY };
+ const docData = this._selectedDocs[0];
+ this._lastResponse = StrCast(docData.$drawingData);
+ this._lastInput = { text: StrCast(docData.$ai_drawing_input), complexity: NumCast(docData.$ai_drawing_complexity), size: NumCast(docData.$ai_drawing_size), autoColor: BoolCast(docData.$ai_drawing_colored), x: this._pageX, y: this._pageY };
};
/**
@@ -404,7 +403,7 @@ export class SmartDrawHandler extends ObservableReactComponent<object> {
const hrefComplete = `${hrefParts[0]}_o.${hrefParts[1]}`;
try {
const hrefBase64 = await imageUrlToBase64(hrefComplete);
- const strokes = DocListCast(drawing[DocData].data);
+ const strokes = DocListCast(drawing.$data);
const coords: string[] = [];
strokes.forEach((stroke, i) => {
const inkingStroke = DocumentView.getDocumentView(stroke)?.ComponentView as InkingStroke;
@@ -423,14 +422,14 @@ export class SmartDrawHandler extends ObservableReactComponent<object> {
*/
colorStrokes = undoable((res: string, drawing: Doc) => {
const colorList = res.match(/\{.*?\}/g);
- const strokes = DocListCast(drawing[DocData].data);
+ const strokes = DocListCast(drawing.$data);
colorList?.forEach((colors, index) => {
const strokeAndFill = colors.match(/#[0-9A-Fa-f]{6}/g);
if (strokeAndFill && strokeAndFill.length == 2) {
- strokes[index][DocData].color = strokeAndFill[0];
+ strokes[index].$color = strokeAndFill[0];
const inkStroke = DocumentView.getDocumentView(strokes[index])?.ComponentView as InkingStroke;
const { inkData } = inkStroke.inkScaledData();
- InkingStroke.IsClosed(inkData) ? (strokes[index][DocData].fillColor = strokeAndFill[1]) : (strokes[index][DocData].fillColor = undefined);
+ InkingStroke.IsClosed(inkData) ? (strokes[index].$fillColor = strokeAndFill[1]) : (strokes[index].$fillColor = undefined);
}
});
}, 'color strokes');
@@ -577,6 +576,7 @@ export class SmartDrawHandler extends ObservableReactComponent<object> {
type="text"
autoFocus
value={this._userInput}
+ onPointerDown={e => e.stopPropagation()}
onChange={action(e => this._canInteract && (this._userInput = e.target.value))}
placeholder="Enter item to draw"
onKeyDown={this.handleKeyPress}
diff --git a/src/client/views/smartdraw/StickerPalette.tsx b/src/client/views/smartdraw/StickerPalette.tsx
index d5307974f..0e234e966 100644
--- a/src/client/views/smartdraw/StickerPalette.tsx
+++ b/src/client/views/smartdraw/StickerPalette.tsx
@@ -9,7 +9,6 @@ import ReactLoading from 'react-loading';
import { returnEmptyFilter, returnFalse, returnTrue } from '../../../ClientUtils';
import { emptyFunction, numberRange } from '../../../Utils';
import { Doc, DocListCast, returnEmptyDoclist } from '../../../fields/Doc';
-import { DocData } from '../../../fields/DocSymbols';
import { ImageCast, NumCast } from '../../../fields/Types';
import { ImageField } from '../../../fields/URLField';
import { DocumentType } from '../../documents/DocumentTypes';
@@ -26,7 +25,7 @@ import { DrawingOptions, SmartDrawHandler } from './SmartDrawHandler';
import './StickerPalette.scss';
interface StickerPaletteProps {
- Document: Doc;
+ Doc: Doc;
}
enum StickerPaletteMode {
@@ -57,10 +56,10 @@ export class StickerPalette extends ObservableReactComponent<StickerPaletteProps
if (!doc.savedAsSticker) {
const docView = DocumentView.getDocumentView(doc);
await docView?.ComponentView?.updateIcon?.(true);
- const { clone } = await Doc.MakeClone(doc);
+ const { clone } = Doc.MakeClone(doc);
clone.title = doc.title;
- const image = ImageCast(doc.icon, ImageCast(clone[Doc.LayoutFieldKey(clone)]))?.url?.href;
- Doc.AddDocToList(Doc.MyStickers, 'data', makeUserTemplateButtonOrImage(clone, image));
+ const image = ImageCast(doc.icon, ImageCast(clone[Doc.LayoutDataKey(clone)]))?.url?.href;
+ Doc.MyStickers && Doc.AddDocToList(Doc.MyStickers, 'data', makeUserTemplateButtonOrImage(clone, image));
doc.savedAsSticker = true;
}
};
@@ -133,7 +132,7 @@ export class StickerPalette extends ObservableReactComponent<StickerPaletteProps
this._canInteract = true;
this._opts = { text: '', complexity: 5, size: 200, autoColor: true, x: 0, y: 0 };
this._gptRes = [];
- this._props.Document[DocData].data = undefined;
+ this._props.Doc.$data = undefined;
});
/**
@@ -143,15 +142,15 @@ export class StickerPalette extends ObservableReactComponent<StickerPaletteProps
@undoBatch
generateDrawings = action(() => {
this._isLoading = true;
- const prevDrawings = DocListCast(this._props.Document[DocData].data);
- this._props.Document[DocData].data = undefined;
+ const prevDrawings = DocListCast(this._props.Doc.$data);
+ this._props.Doc.$data = undefined;
SmartDrawHandler.Instance.AddDrawing = this.addDrawing;
this._canInteract = false;
Promise.all(
numberRange(3).map(i => {
return this._showRegenerate
? SmartDrawHandler.Instance.regenerate(prevDrawings, this._opts, this._gptRes[i], this._userInput)
- : SmartDrawHandler.Instance.drawWithGPT({ X: 0, Y: 0 }, this._userInput, this._opts.complexity, this._opts.size, this._opts.autoColor);
+ : SmartDrawHandler.Instance.drawWithGPT({ X: 0, Y: 0 }, this._userInput, this._opts.complexity || 0, this._opts.size || 0, !!this._opts.autoColor);
})
).then(() => {
this._opts.text !== '' ? (this._opts.text = `${this._opts.text} ~~~ ${this._userInput}`) : (this._opts.text = this._userInput);
@@ -164,8 +163,8 @@ export class StickerPalette extends ObservableReactComponent<StickerPaletteProps
@action
addDrawing = (drawing: Doc, opts: DrawingOptions, gptRes: string) => {
this._gptRes.push(gptRes);
- drawing[DocData].freeform_fitContentsToBox = true;
- Doc.AddDocToList(this._props.Document, 'data', drawing);
+ drawing.$freeform_fitContentsToBox = true;
+ Doc.AddDocToList(this._props.Doc, 'data', drawing);
};
/**
@@ -174,19 +173,18 @@ export class StickerPalette extends ObservableReactComponent<StickerPaletteProps
* presses the "save drawing" button.
*/
saveDrawing = () => {
- const cIndex = NumCast(this._props.Document.carousel_index);
- const focusedDrawing = DocListCast(this._props.Document.data)[cIndex];
- const docData = focusedDrawing[DocData];
- docData.title = this._opts.text.match(/^(.*?)~~~.*$/)?.[1] || this._opts.text;
- docData.ai_drawing_input = this._opts.text;
- docData.ai_drawing_complexity = this._opts.complexity;
- docData.ai_drawing_colored = this._opts.autoColor;
- docData.ai_drawing_size = this._opts.size;
- docData.ai_drawing_data = this._gptRes[cIndex];
- docData.ai = 'gpt';
+ const cIndex = NumCast(this._props.Doc.carousel_index);
+ const focusedDrawing = DocListCast(this._props.Doc.data)[cIndex];
+ focusedDrawing.$title = this._opts.text?.match(/^(.*?)~~~.*$/)?.[1] || this._opts.text;
+ focusedDrawing.$ai_drawing_input = this._opts.text;
+ focusedDrawing.$ai_drawing_complexity = this._opts.complexity;
+ focusedDrawing.$ai_drawing_colored = this._opts.autoColor;
+ focusedDrawing.$ai_drawing_size = this._opts.size;
+ focusedDrawing.$ai_drawing_data = this._gptRes[cIndex];
+ focusedDrawing.$ai = 'gpt';
focusedDrawing.width = this._opts.size;
- docData.x = this._opts.x;
- docData.y = this._opts.y;
+ focusedDrawing.x = this._opts.x;
+ focusedDrawing.y = this._opts.y;
StickerPalette.addToPalette(focusedDrawing).then(() => this.resetPalette(true));
};
@@ -315,7 +313,7 @@ export class StickerPalette extends ObservableReactComponent<StickerPaletteProps
<>
{this.renderCreateInput()}
{this.renderCreateOptions()}
- {this.renderDoc(this._props.Document, (r: DocumentView) => {
+ {this.renderDoc(this._props.Doc, (r: DocumentView) => {
this._docCarouselView = r;
})}
<div className="palette-buttons">
@@ -329,9 +327,10 @@ export class StickerPalette extends ObservableReactComponent<StickerPaletteProps
);
renderPaletteView = () => (
<>
- {this.renderDoc(Doc.MyStickers, (r: DocumentView) => {
- this._docView = r;
- })}
+ {Doc.MyStickers &&
+ this.renderDoc(Doc.MyStickers, (r: DocumentView) => {
+ this._docView = r;
+ })}
<Button text="Add" icon={<FontAwesomeIcon icon="square-plus" />} color={SettingsManager.userColor} onClick={() => this.setPaletteMode(StickerPaletteMode.create)} />
</>
);