aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx130
1 files changed, 127 insertions, 3 deletions
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 791124f50..c5102070a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -10,7 +10,6 @@ import { DocData, Height, Width } from '../../../../fields/DocSymbols';
import { Id } from '../../../../fields/FieldSymbols';
import { InkData, InkField, InkTool, PointData, Segment } from '../../../../fields/InkField';
import { List } from '../../../../fields/List';
-import { RichTextField } from '../../../../fields/RichTextField';
import { listSpec } from '../../../../fields/Schema';
import { ScriptField } from '../../../../fields/ScriptField';
import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
@@ -27,7 +26,7 @@ import { ReplayMovements } from '../../../util/ReplayMovements';
import { CompileScript } from '../../../util/Scripting';
import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
import { SelectionManager } from '../../../util/SelectionManager';
-import { freeformScrollMode } from '../../../util/SettingsManager';
+import { freeformScrollMode, SettingsManager } from '../../../util/SettingsManager';
import { SnappingManager } from '../../../util/SnappingManager';
import { Transform } from '../../../util/Transform';
import { undoable, undoBatch, UndoManager } from '../../../util/UndoManager';
@@ -54,6 +53,11 @@ import { CollectionFreeFormPannableContents } from './CollectionFreeFormPannable
import { CollectionFreeFormRemoteCursors } from './CollectionFreeFormRemoteCursors';
import './CollectionFreeFormView.scss';
import { MarqueeView } from './MarqueeView';
+import { PropertiesView } from '../../PropertiesView';
+import { ExtractColors } from '../../ExtractColors';
+import { smartLayout, smartLayout2, StyleInputDocument } from '../../../apis/gpt/customization';
+import { extname } from 'path';
+import { RichTextField } from '../../../../fields/RichTextField';
export interface collectionFreeformViewProps {
NativeWidth?: () => number;
@@ -106,6 +110,13 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
private _brushtimer: any;
private _brushtimer1: any;
+ private _presEaseFunc: string = 'ease';
+
+ @action
+ setPresEaseFunc = (easeFunc: string) => {
+ this._presEaseFunc = easeFunc;
+ };
+
public get isAnnotationOverlay() {
return this._props.isAnnotationOverlay;
}
@@ -307,6 +318,12 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
};
focus = (anchor: Doc, options: FocusViewOptions) => {
+ // incorporate the easefunc here
+ if (options.easeFunc) {
+ this.setPresEaseFunc(options.easeFunc);
+ console.log('Ease func', options.easeFunc);
+ }
+
if (this._lightboxDoc) return;
if (anchor === this.Document) {
// if (options.willZoomCentered && options.zoomScale) {
@@ -1038,6 +1055,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
setTimeout(() => (this.layoutDoc.layout_scrollTop = relTop * maxScrollTop), 10);
newPanY = minPanY;
}
+ // updating pan state
!this.Document._verticalScroll && (this.Document[this.panXFieldKey] = this.isAnnotationOverlay ? newPanX : panX);
!this.Document._horizontalScroll && (this.Document[this.panYFieldKey] = this.isAnnotationOverlay ? newPanY : panY);
}
@@ -1638,6 +1656,107 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
}
};
+ printDoc = (doc: Doc) => {
+ console.log('Printing keys');
+ Object.keys(doc).forEach(key => {
+ console.log(key, ':', doc[key]);
+ });
+ };
+
+ @action
+ openProperties = () => {
+ SettingsManager.Instance.propertiesWidth = 300;
+ };
+
+ choosePath(url: URL) {
+ if (!url?.href) return '';
+ const lower = url.href.toLowerCase();
+ if (url.protocol === 'data') return url.href;
+ if (url.href.indexOf(window.location.origin) === -1 && url.href.indexOf('dashblobstore') === -1) return Utils.CorsProxy(url.href);
+ if (!/\.(png|jpg|jpeg|gif|webp)$/.test(lower)) return `/assets/unknown-file-icon-hi.png`;
+
+ const ext = extname(url.href);
+ return url.href.replace(ext, '_m' + ext);
+ }
+
+ @action
+ smartLayout = async () => {};
+
+ roundToRoundNumber = (num: number) => {
+ return Math.round(num / 10) * 10;
+ };
+
+ // gpt layout
+ @action
+ gptLayout = async () => {
+ const docLayouts = this.childDocs.map(doc => ({
+ width: this.roundToRoundNumber(NumCast(doc.width)),
+ height: this.roundToRoundNumber(NumCast(doc.height)),
+ // content: StrCast(doc.title),
+ }));
+ console.log('Doc layouts', docLayouts);
+
+ const res = await smartLayout2(docLayouts);
+ console.log('Smart layout result', res);
+ // make type-safe
+ const resObj = JSON.parse(res) as any[];
+ resObj.forEach((elem, i) => {
+ this.childDocs[i].x = elem.x;
+ this.childDocs[i].y = elem.y;
+ });
+
+ // refit collection
+ setTimeout(() => {
+ this.fitContentOnce();
+ }, 500);
+ };
+
+ // gpt styling
+ @action
+ gptStyling = async () => {
+ // clear it in properties instead
+ if (!PropertiesView.Instance) return;
+ this.openProperties();
+ PropertiesView.Instance.setGeneratedStyles([]);
+ PropertiesView.Instance.selectedStyle = -1;
+ PropertiesView.Instance.useImageData = false;
+
+ console.log('Title', this.Document.title);
+ console.log('bgcolor', this.layoutDoc._backgroundColor);
+ // doc.backgroundColor
+ const inputDocs = this.childDocs.filter(doc => doc.type == 'rich text');
+ const imgDocs = this.childDocs.filter(doc => doc.type == 'image');
+ const imgUrls = imgDocs.map(doc => this.choosePath((doc.data as ImageField).url));
+
+ const imageElements = await ExtractColors.loadImagesUrl(imgUrls);
+ const colors = await Promise.all(imageElements.map(elem => ExtractColors.getImgColors(elem)));
+ let colorHexes = colors
+ .reduce((acc, curr) => acc.concat(curr), [])
+ .map(color => color.hex)
+ .slice(0, 10);
+ console.log('Hexes', colorHexes);
+
+ PropertiesView.Instance?.setInputDocs(inputDocs);
+
+ // also pass it colors
+ const gptInput: StyleInputDocument[] = inputDocs.map((doc, i) => ({
+ id: i,
+ textContent: (doc.text as RichTextField)?.Text,
+ textSize: 16,
+ }));
+
+ const collectionDescription = StrCast(this.Document.title);
+
+ const styleInput = {
+ collectionDescription,
+ documents: gptInput,
+ imageColors: colorHexes,
+ };
+
+ PropertiesView.Instance.styleInput = styleInput;
+ PropertiesView.Instance.gptStyling();
+ };
+
onContextMenu = (e: React.MouseEvent) => {
if (this._props.isAnnotationOverlay || !ContextMenu.Instance) return;
@@ -1667,6 +1786,10 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
optionItems.push({ description: (this._showAnimTimeline ? 'Close' : 'Open') + ' Animation Timeline', event: action(() => (this._showAnimTimeline = !this._showAnimTimeline)), icon: 'eye' });
this._props.renderDepth && optionItems.push({ description: 'Use Background Color as Default', event: () => (Cast(Doc.UserDoc().emptyCollection, Doc, null).backgroundColor = StrCast(this.layoutDoc.backgroundColor)), icon: 'palette' });
this._props.renderDepth && optionItems.push({ description: 'Fit Content Once', event: this.fitContentOnce, icon: 'object-group' });
+ // Want to condense into a Smart Organize button
+ this._props.renderDepth && optionItems.push({ description: 'Style with AI', event: this.gptStyling, icon: 'paint-brush' });
+ this._props.renderDepth && optionItems.push({ description: 'Smart Layout', event: this.gptLayout, icon: 'object-group' });
+ // this._props.renderDepth && optionItems.push({ description: 'Smart Organize', event: this.smartOrganize, icon: 'object-group' });
if (!Doc.noviceMode) {
optionItems.push({ description: (!Doc.NativeWidth(this.layoutDoc) || !Doc.NativeHeight(this.layoutDoc) ? 'Freeze' : 'Unfreeze') + ' Aspect', event: this.toggleNativeDimensions, icon: 'snowflake' });
}
@@ -1777,7 +1900,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
brushedView={this.brushedView}
isAnnotationOverlay={this.isAnnotationOverlay}
transform={this.PanZoomCenterXf}
- transition={this._panZoomTransition ? `transform ${this._panZoomTransition}ms` : Cast(this.layoutDoc._viewTransition, 'string', Cast(this.Document._viewTransition, 'string', null))}
+ // Inject timing function here
+ transition={this._panZoomTransition ? `transform ${this._panZoomTransition}ms ${this._presEaseFunc}` : Cast(this.layoutDoc._viewTransition, 'string', Cast(this.Document._viewTransition, 'string', null))}
viewDefDivClick={this._props.viewDefDivClick}>
{this.props.children ?? null} {/* most likely case of children is document content that's being annoated: eg., an image */}
{this.contentViews}