aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/apis/gpt/GPT.ts5
-rw-r--r--src/client/views/nodes/DocumentView.tsx2
-rw-r--r--src/client/views/nodes/ImageBox.scss7
-rw-r--r--src/client/views/nodes/ImageBox.tsx23
-rw-r--r--src/client/views/smartdraw/DrawingFillHandler.tsx75
-rw-r--r--src/server/ApiManagers/FireflyManager.ts1
-rw-r--r--src/server/ApiManagers/UploadManager.ts7
-rw-r--r--src/server/DashUploadUtils.ts14
8 files changed, 62 insertions, 72 deletions
diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts
index 29b6ab989..140aebfe0 100644
--- a/src/client/apis/gpt/GPT.ts
+++ b/src/client/apis/gpt/GPT.ts
@@ -1,5 +1,6 @@
import { ChatCompletionMessageParam, Image } from 'openai/resources';
import { openai } from './setup';
+import { imageUrlToBase64 } from '../../../ClientUtils';
export enum GPTDocCommand {
AssignTags = 1,
@@ -310,7 +311,9 @@ const gptHandwriting = async (src: string): Promise<string> => {
}
};
-const gptDescribeImage = async (image: string): Promise<string> => {
+const gptDescribeImage = async (userPrompt: string, url: string): Promise<string> => {
+ if (userPrompt) return userPrompt;
+ const image = imageUrlToBase64(url);
try {
const response = await openai.chat.completions.create({
model: 'gpt-4o',
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 070a13103..37f888ddd 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -702,7 +702,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewProps & Field
*/
@computed get viewScaling() { return 1 / this.currentScale; } // prettier-ignore
/**
- * The maximum size a UI widget can be scaled so that it won't be bigger in screen pixels than its normal 35 pixel size.
+ * The maximum size a UI widget can be scaled so that it won't be bigger in screen pixels than its nominal pixel size.
*/
@computed get maxWidgetSize() { return Math.min(this.TagsBtnHeight * this.viewScaling, 0.25 * Math.min(NumCast(this.Document._width), NumCast(this.Document._height))); } // prettier-ignore
/**
diff --git a/src/client/views/nodes/ImageBox.scss b/src/client/views/nodes/ImageBox.scss
index 36abf707c..4a6e8eb49 100644
--- a/src/client/views/nodes/ImageBox.scss
+++ b/src/client/views/nodes/ImageBox.scss
@@ -142,11 +142,8 @@
}
}
.imageBox-regenerateDropTarget {
- right: 30;
- border-radius: 50%;
- svg {
- border-radius: 50%;
- }
+ right: 35;
+ transform-origin: 70px 35px;
}
.imageBox-fader img {
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 75c298dc6..2b9a78596 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -45,7 +45,6 @@ import { FieldView, FieldViewProps } from './FieldView';
import { FocusViewOptions } from './FocusViewOptions';
import './ImageBox.scss';
import { OpenWhere } from './OpenWhere';
-import { RichTextField } from '../../../fields/RichTextField';
import { ComputedField } from '../../../fields/ScriptField';
const DefaultPath = '/assets/unknown-file-icon-hi.png';
@@ -218,9 +217,10 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this._regenerateLoading = true;
const drag = de.complete.docDragData.draggedDocuments.lastElement();
const dragField = drag[Doc.LayoutFieldKey(drag)];
+ const descText = RTFCast(dragField)?.Text || StrCast(dragField) || RTFCast(drag.text)?.Text || StrCast(drag.text) || StrCast(this.Document.title);
const oldPrompt = StrCast(this.Document.ai_firefly_prompt, StrCast(this.Document.title));
const newPrompt = (text: string) => (oldPrompt ? `${oldPrompt} ~~~ ${text}` : text);
- DrawingFillHandler.drawingToImage(this.Document, 90, newPrompt(dragField instanceof RichTextField ? dragField.Text : ''), drag)?.then(action(() => (this._regenerateLoading = false)));
+ DrawingFillHandler.drawingToImage(this.Document, 90, newPrompt(descText), drag)?.then(action(() => (this._regenerateLoading = false)));
added = false;
} else if (de.altKey || !this.dataDoc[this.fieldKey]) {
const layoutDoc = de.complete.docDragData?.draggedDocuments[0];
@@ -401,13 +401,12 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
};
// updateIcon = () => new Promise<void>(res => res());
- updateIcon = (/* usePanelDimensions?: boolean */) => {
- const contentDiv = this._mainCont;
- return !contentDiv
+ updateIcon = (/* usePanelDimensions?: boolean */) =>
+ !this._mainCont || !DocListCast(this.dataDoc[this.annotationKey]).length
? new Promise<void>(res => res())
: UpdateIcon(
this.layoutDoc[Id] + '_icon_' + new Date().getTime(),
- contentDiv,
+ this._mainCont,
this._props.PanelWidth(), // usePanelDimensions ? this._props.PanelWidth() : NumCast(this.layoutDoc._width),
this._props.PanelHeight(), // usePanelDimensions ? this._props.PanelHeight() : NumCast(this.layoutDoc._height),
this._props.PanelWidth(),
@@ -422,7 +421,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this.dataDoc.icon_nativeHeight = nativeHeight;
}
);
- };
choosePath = (url: URL) => {
if (!url?.href) return '';
@@ -453,15 +451,15 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
/**
* How much the content of the view is being scaled based on its nesting and its fit-to-width settings
*/
- @computed get viewScaling() { return this.ScreenToLocalBoxXf().Scale * ( this._props.NativeDimScaling?.() || 1); } // prettier-ignore
+ @computed get viewScaling() { return this.ScreenToLocalBoxXf().Scale * (this._props.NativeDimScaling?.()??1); } // prettier-ignore
/**
* The maximum size a UI widget can be scaled so that it won't be bigger in screen pixels than its normal 35 pixel size.
*/
- @computed get maxWidgetSize() { return Math.min(this._sideBtnWidth, 0.5 * Math.min(NumCast(this.Document.width)))* this.viewScaling; } // prettier-ignore
+ @computed get maxWidgetSize() { return Math.min(this._sideBtnWidth, 0.2 * this._props.PanelWidth())*this.viewScaling; } // prettier-ignore
/**
* How much to reactively scale a UI element so that it is as big as it can be (up to its normal 35pixel size) without being too big for the Doc content
*/
- @computed get uiBtnScaling() { return Math.min(this.maxWidgetSize / this._sideBtnWidth, 1); } // prettier-ignore
+ @computed get uiBtnScaling() { return Math.min(1/(this._props.NativeDimScaling?.()??1), this.maxWidgetSize / this._sideBtnWidth); } // prettier-ignore
@computed get overlayImageIcon() {
const usePath = this.layoutDoc[`_${this.fieldKey}_usePath`];
@@ -518,10 +516,11 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
transform: `scale(${this.uiBtnScaling})`,
width: this._sideBtnWidth,
height: this._sideBtnWidth,
- background: 'transparent',
+ background: 'black',
+ color: 'white',
// color: SettingsManager.userBackgroundColor,
}}>
- {this._regenerateLoading ? <ReactLoading type="spin" color={SettingsManager.userVariantColor} width="100%" height="100%" /> : <FontAwesomeIcon icon="portrait" color={SettingsManager.userColor} size="lg" />}
+ {this._regenerateLoading ? <ReactLoading type="spin" width="100%" height="100%" /> : <FontAwesomeIcon icon="portrait" size="lg" />}
</div>
</Tooltip>
);
diff --git a/src/client/views/smartdraw/DrawingFillHandler.tsx b/src/client/views/smartdraw/DrawingFillHandler.tsx
index d8ef8308d..a91ec23b8 100644
--- a/src/client/views/smartdraw/DrawingFillHandler.tsx
+++ b/src/client/views/smartdraw/DrawingFillHandler.tsx
@@ -1,4 +1,3 @@
-import { imageUrlToBase64 } from '../../../ClientUtils';
import { Doc, StrListCast } from '../../../fields/Doc';
import { List } from '../../../fields/List';
import { DocCast, ImageCast, StrCast } from '../../../fields/Types';
@@ -42,44 +41,42 @@ export class DrawingFillHandler {
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 error = ('error' in res && (res.error as string)) || '';
- if (error.includes('Dropbox') && confirm('Create image failed. Try authorizing DropBox?\r\n' + error.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();
- return;
- }
- 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
+ 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(/^[^"]*/, ''))) {
+ 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();
+ return;
+ }
+ 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/server/ApiManagers/FireflyManager.ts b/src/server/ApiManagers/FireflyManager.ts
index e75ede9df..07428798c 100644
--- a/src/server/ApiManagers/FireflyManager.ts
+++ b/src/server/ApiManagers/FireflyManager.ts
@@ -117,7 +117,6 @@ export default class FireflyManager extends ApiManager {
generateImage = (prompt: string = 'a realistic illustration of a cat coding', width: number = 2048, height: number = 2048, seed?: number) => {
let body = `{ "prompt": "${prompt}", "size": { "width": ${width}, "height": ${height}} }`;
if (seed) {
- console.log('RECEIVED SEED', seed);
body = `{ "prompt": "${prompt}", "size": { "width": ${width}, "height": ${height}}, "seeds": [${seed}]}`;
}
const fetched = this.getBearerToken().then(response =>
diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts
index c9d5df547..7c55e4a42 100644
--- a/src/server/ApiManagers/UploadManager.ts
+++ b/src/server/ApiManagers/UploadManager.ts
@@ -126,11 +126,8 @@ export default class UploadManager extends ApiManager {
secureHandler: async ({ req, res }) => {
const { sources } = req.body;
if (Array.isArray(sources)) {
- const results = await Promise.all(sources.map(source => DashUploadUtils.UploadImage(source)));
- res.send(results);
- return;
- }
- res.send();
+ res.send(await Promise.all(sources.map(source => DashUploadUtils.UploadImage(source))));
+ } else res.send();
},
});
diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts
index a2747257a..ed109d8f7 100644
--- a/src/server/DashUploadUtils.ts
+++ b/src/server/DashUploadUtils.ts
@@ -450,14 +450,12 @@ export namespace DashUploadUtils {
* 3) the size of the image, in bytes (4432130)
* 4) the content type of the image, i.e. image/(jpeg | png | ...)
*/
- export const UploadImage = async (source: string, filename?: string, prefix: string = ''): Promise<Upload.ImageInformation | Error> => {
- const result = await InspectImage(source);
- if (result instanceof Error) {
- return { name: result.name, message: result.message };
- }
- const outputFile = filename || result.filename || '';
- return UploadInspectedImage(result, outputFile, prefix, isLocal().exec(source) || source.startsWith('data:') ? true : false);
- };
+ export const UploadImage = (source: string, filename?: string, prefix: string = ''): Promise<Upload.ImageInformation | Error> =>
+ InspectImage(source).then(async result =>
+ result instanceof Error
+ ? ({ name: result.name, message: result.message } as Error) //
+ : UploadInspectedImage(result, filename || result.filename || '', prefix, isLocal().exec(source) || source.startsWith('data:') ? true : false)
+ );
type md5 = 'md5';
type falsetype = false;