From 67450b443b70099ce51a8db2872b2c04e09b4558 Mon Sep 17 00:00:00 2001 From: sharkiecodes Date: Sun, 11 May 2025 21:28:05 -0400 Subject: scrapbook backgrounds --- src/client/apis/gpt/GPT.ts | 1 + src/client/views/nodes/scrapbook/ScrapbookBox.tsx | 100 ++++++++++++++++++---- 2 files changed, 85 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 693b4f901..4dd30f8b3 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -30,6 +30,7 @@ enum GPTCallType { DRAW = 'draw', COLOR = 'color', TEMPLATE = 'template', + SCRAPBOOK = 'scrapbook', VIZSUM = 'vizsum', VIZSUM2 = 'vizsum2', FILL = 'fill', diff --git a/src/client/views/nodes/scrapbook/ScrapbookBox.tsx b/src/client/views/nodes/scrapbook/ScrapbookBox.tsx index 731715964..ced2df6c5 100644 --- a/src/client/views/nodes/scrapbook/ScrapbookBox.tsx +++ b/src/client/views/nodes/scrapbook/ScrapbookBox.tsx @@ -12,7 +12,13 @@ import { FieldView, FieldViewProps } from '../FieldView'; import { DragManager } from '../../../util/DragManager'; import { RTFCast, StrCast, toList } from '../../../../fields/Types'; import { undoable } from '../../../util/UndoManager'; +import ReactLoading from 'react-loading'; import { ScrapbookItemConfig, ScrapbookPreset } from './ScrapbookPreset'; +import { ImageBox } from '../ImageBox'; +import { FireflyImageDimensions } from '../../smartdraw/FireflyConstants'; +import { SmartDrawHandler } from '../../smartdraw/SmartDrawHandler'; +import { ImageCast } from '../../../../fields/Types'; +import { lengthToDegrees } from '@turf/turf'; enum ScrapbookPresetType { Classic = 'Classic', @@ -23,16 +29,24 @@ enum ScrapbookPresetType { // Scrapbook view: a container that lays out its child items in a grid/template export class ScrapbookBox extends ViewBoxAnnotatableComponent() { + + + state = { + loading: false, + src: '', + }; + + @observable createdDate: string; - @observable configs : ScrapbookItemConfig[] + // @observable configs : ScrapbookItemConfig[] constructor(props: FieldViewProps) { super(props); makeObservable(this); this.createdDate = this.getFormattedDate(); - this.configs = - ScrapbookPreset.createPreset(presetType); + //this.configs = + //ScrapbookPreset.createPreset(presetType); // ensure we always have a List in dataDoc['items'] if (!this.dataDoc[this.fieldKey]) { @@ -244,9 +258,9 @@ export class ScrapbookBox extends ViewBoxAnnotatableComponent() if (this.dataDoc.title !== title) { this.dataDoc.title = title; - const image = Docs.Create.TextDocument('image'); + const image = Docs.Create.TextDocument('person image'); image.accepts_docType = DocumentType.IMG; - image.accepts_tagType = 'LANDSCAPE' //should i be writing fields on this doc? clarify diff between this and proto, original + image.accepts_tagType = 'PERSON' //should i be writing fields on this doc? clarify diff between this and proto, original const placeholder = new Doc(); placeholder.proto = image; placeholder.original = image; @@ -256,9 +270,9 @@ export class ScrapbookBox extends ViewBoxAnnotatableComponent() placeholder.y = -100; //placeholder.overrideFields = new List(['x', 'y']); // shouldn't need to do this for layout fields since the placeholder already overrides its protos - const summary = Docs.Create.TextDocument('summary'); + const summary = Docs.Create.TextDocument('long summary'); summary.accepts_docType = DocumentType.RTF; - summary.accepts_tagType = 'caption'; + summary.accepts_tagType = 'lengthy description'; //summary.$tags_chat = new List(['lengthy description']); //we need to go back and set this const placeholder2 = new Doc(); placeholder2.proto = summary; @@ -268,9 +282,9 @@ export class ScrapbookBox extends ViewBoxAnnotatableComponent() placeholder2._width = 250; //placeholder2.overrideFields = new List(['x', 'y', '_width']); // shouldn't need to do this for layout fields since the placeholder already overrides its protos - const sidebar = Docs.Create.TextDocument('sidebar'); + const sidebar = Docs.Create.TextDocument('brief sidebar'); sidebar.accepts_docType = DocumentType.RTF; - sidebar.accepts_tagType = 'lengthy description'; //accepts_textType = 'lengthy description' + sidebar.accepts_tagType = 'title'; //accepts_textType = 'lengthy description' const placeholder3 = new Doc(); placeholder3.proto = sidebar; placeholder3.original = sidebar; @@ -281,9 +295,9 @@ export class ScrapbookBox extends ViewBoxAnnotatableComponent() - const internalImg = Docs.Create.TextDocument('image internal'); + const internalImg = Docs.Create.TextDocument('landscape internal'); internalImg.accepts_docType = DocumentType.IMG; - internalImg.accepts_tagType = 'PERSON' //should i be writing fields on this doc? clarify diff between this and proto, original + internalImg.accepts_tagType = 'LANDSCAPE' //should i be writing fields on this doc? clarify diff between this and proto, original const placeholder5 = new Doc(); placeholder5.proto = internalImg; placeholder5.original = internalImg; @@ -316,16 +330,43 @@ export class ScrapbookBox extends ViewBoxAnnotatableComponent() /*note-to-self difference between passing a new List versus just the raw array? */ + this.dataDoc[this.fieldKey] = new List([placeholder, placeholder2, placeholder3, placeholder4]); - this.dataDoc[this.fieldKey] = this.dataDoc[this.fieldKey] ?? new List([placeholder, placeholder2, placeholder3, placeholder4]); + //this.dataDoc[this.fieldKey] = this.dataDoc[this.fieldKey] ?? new List([placeholder, placeholder2, placeholder3, placeholder4]); } } + + async generateAiImage() { + this.setState({ loading: true }); + + const prompt = 'A serene mountain landscape at sunrise, ultra-wide, pastel sky, abstract, scrapbook background'; + //'A serene mountain landscape at sunrise, ultra-wide, pastel sky'; + const dimensions = FireflyImageDimensions.Square; // or whichever suits your scenario + + SmartDrawHandler.CreateWithFirefly(prompt, dimensions) + .then(action(doc => { + if (doc instanceof Doc) { + const imgField = ImageCast(doc.data); + this.setState({ src: imgField?.url.href }); + } else { + alert('Failed to generate the image.'); + } + })) + .catch(e => { + alert(`Image generation error: ${e}`); + }) + .finally(() => { + this.setState({ loading: false }); + }); + } componentDidMount() { //this.initScrapbook(ScrapbookPresetType.Default); this.setTitle(); + this.generateAiImage(); + } childRejectDrop = (de: DragManager.DropEvent, subView?: DocumentView) => { @@ -405,8 +446,33 @@ export class ScrapbookBox extends ViewBoxAnnotatableComponent() }; render() { + const { loading, src } = this.state; + return ( -
+
+ {loading && ( +
+ +
+ )} + {loading && ( +
+ +
+ )} + {/* Render AI-generated background */} + {src && ( + + )} + () -function extractScrapbookConfigs(docs: Doc[]): ScrapbookItemConfig[] { - return docs.map(doc => extractConfig(doc)); -} +//function extractScrapbookConfigs(docs: Doc[]): ScrapbookItemConfig[] { + //return docs.map(doc => extractConfig(doc)); +//} // function extractConfig(doc: Doc): ScrapbookItemConfig { // const layoutKey = Doc.LayoutDataKey(doc); @@ -452,6 +518,8 @@ function extractScrapbookConfigs(docs: Doc[]): ScrapbookItemConfig[] { // } // Register scrapbook + + Docs.Prototypes.TemplateMap.set(DocumentType.SCRAPBOOK, { layout: { view: ScrapbookBox, dataField: 'items' }, options: { -- cgit v1.2.3-70-g09d2