aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/documents/Documents.ts2
-rw-r--r--src/client/views/DocumentDecorations.tsx106
-rw-r--r--src/client/views/nodes/ImageBox.tsx10
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx2
-rw-r--r--src/server/ApiManagers/FireflyManager.ts8
5 files changed, 39 insertions, 89 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index e694419a4..a4a668085 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -535,8 +535,6 @@ export class DocumentOptions {
* The list of embedded Doc instances in each Scrapbook slot
*/
scrapbookContents?: List<Doc>;
-
- _outpaintingMetadata?: STRt = new StrInfo('serialized JSON metadata needed for image outpainting', false);
}
export const DocOptions = new DocumentOptions();
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 3f11a4713..2d39b827d 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -445,6 +445,12 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
@action
onPointerDown = (e: React.PointerEvent): void => {
SnappingManager.SetIsResizing(DocumentView.Selected().lastElement()?.Document[Id]); // turns off pointer events on things like youtube videos and web pages so that dragging doesn't get "stuck" when cursor moves over them
+ DocumentView.Selected()
+ .filter(dv => e.shiftKey && dv.ComponentView instanceof ImageBox)
+ .forEach(dv => {
+ dv.Document._outpaintingOriginalWidth = NumCast(dv.Document._width);
+ dv.Document._outpaintingOriginalHeight = NumCast(dv.Document._height);
+ });
setupMoveUpEvents(this, e, this.onPointerMove, this.onPointerUp, emptyFunction);
e.stopPropagation();
const id = (this._resizeHdlId = e.currentTarget.className);
@@ -484,50 +490,31 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
const dragHdl = this._resizeHdlId.split(' ')[0].replace('documentDecorations-', '').replace('Resizer', '');
const thisPt = // do snapping of drag point
- fixedAspect && (dragHdl === 'bottomRight' || dragHdl === 'topLeft')
+ fixedAspect && (dragHdl === 'bottomRight' || dragHdl === 'topLeft') && e.ctrlKey
? DragManager.snapDragAspect(this.projectDragToAspect(e, first, fixedAspect), fixedAspect)
: DragManager.snapDrag(e, -this._offset.x, -this._offset.y, this._offset.x, this._offset.y);
const { scale, refPt } = this.getResizeVals(thisPt, dragHdl);
!this._interactionLock &&
- runInAction(async () => {
+ runInAction(() => {
// resize selected docs if we're not in the middle of a resize (ie, throttle input events to frame rate)
this._interactionLock = true;
this._snapPt = thisPt;
- // Special handling for shift+click (outpainting mode)
- if (e.shiftKey && DocumentView.Selected().some(dv => dv.ComponentView instanceof ImageBox)) {
- DocumentView.Selected().forEach(docView => {
- if (docView.ComponentView instanceof ImageBox) {
- // Set flag for outpainting mode
- docView.Document._outpaintingResize = true;
+ const notOutpainted = DocumentView.Selected().filter(dv => !e.shiftKey || !(dv.ComponentView instanceof ImageBox));
+ // Special handling for shift-drag resize (outpainting of Images)
+ DocumentView.Selected()
+ .filter(dv => !notOutpainted.includes(dv))
+ .forEach(dv => this.resizeViewForOutpainting(dv, refPt, scale, { dragHdl, shiftKey: e.shiftKey })); // Adjust only the document dimensions without scaling internal content
- // Adjust only the document dimensions without scaling internal content
- this.resizeViewForOutpainting(docView, refPt, scale, { dragHdl, shiftKey: e.shiftKey });
- } else {
- // Handle regular resize for non-image components
- e.ctrlKey && !Doc.NativeHeight(docView.Document) && docView.toggleNativeDimensions();
- const hasFixedAspect = this.hasFixedAspect(docView.Document);
- const scaleAspect = { x: scale.x === 1 && hasFixedAspect ? scale.y : scale.x, y: scale.x !== 1 && hasFixedAspect ? scale.x : scale.y };
- this.resizeView(docView, refPt, scaleAspect, { dragHdl, ctrlKey: e.ctrlKey });
- }
- });
- } else {
- // Regular resize behavior (existing code)
- e.ctrlKey && DocumentView.Selected().forEach(docView => !Doc.NativeHeight(docView.Document) && docView.toggleNativeDimensions());
- const hasFixedAspect = DocumentView.Selected()
- .map(dv => dv.Document)
- .some(this.hasFixedAspect);
- const scaleAspect = { x: scale.x === 1 && hasFixedAspect ? scale.y : scale.x, y: scale.x !== 1 && hasFixedAspect ? scale.x : scale.y };
- DocumentView.Selected().forEach(docView => this.resizeView(docView, refPt, scaleAspect, { dragHdl, ctrlKey: e.ctrlKey }));
- }
+ // Regular resize behavior for docs not being outpainted
+ e.ctrlKey && notOutpainted.forEach(docView => !Doc.NativeHeight(docView.Document) && docView.toggleNativeDimensions());
+ const hasFixedAspect = notOutpainted.map(dv => dv.Document).some(this.hasFixedAspect);
+ const scaleAspect = { x: scale.x === 1 && hasFixedAspect ? scale.y : scale.x, y: scale.x !== 1 && hasFixedAspect ? scale.x : scale.y };
+ notOutpainted.forEach(docView => this.resizeView(docView, refPt, scaleAspect, { dragHdl, freezeNativeDims: e.ctrlKey }));
- await new Promise<void>(res => {
- setTimeout(() => {
- res((this._interactionLock = undefined));
- });
- });
+ new Promise<void>(res => setTimeout(() => res((this._interactionLock = undefined))));
});
return false;
@@ -545,11 +532,6 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
return;
}
- if (!doc._outpaintingOriginalWidth || !doc._outpaintingOriginalHeight) {
- doc._outpaintingOriginalWidth = NumCast(doc._width);
- doc._outpaintingOriginalHeight = NumCast(doc._height);
- }
-
// Calculate new boundary dimensions
const originalWidth = NumCast(doc._width);
const originalHeight = NumCast(doc._height);
@@ -566,38 +548,17 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
doc.y = NumCast(doc.y) + deltaY;
doc._layout_modificationDate = new DateField();
-
- // Trigger outpainting
- doc._needsOutpainting = true;
-
- // Store metadata needed for outpainting
- doc._outpaintingMetadata = JSON.stringify({
- originalWidth: doc._outpaintingOriginalWidth,
- originalHeight: doc._outpaintingOriginalHeight,
- newWidth,
- newHeight,
- scaleX: scale.x,
- scaleY: scale.y,
- anchorHandle: opts.dragHdl,
- });
};
@action
- onPointerUp = (): void => {
+ onPointerUp = (e: PointerEvent): void => {
SnappingManager.SetIsResizing(undefined);
SnappingManager.clearSnapLines();
// Check if any outpainting needs to be processed
- DocumentView.Selected().forEach(view => {
- if (view.Document._needsOutpainting && view.ComponentView instanceof ImageBox) {
- // Trigger outpainting process in the ImageBox component
- (view.ComponentView as ImageBox).processOutpainting();
-
- // Clear flags
- view.Document._needsOutpainting = false;
- view.Document._outpaintingResize = false;
- }
- });
+ DocumentView.Selected()
+ .filter(dv => e.shiftKey && dv.ComponentView instanceof ImageBox)
+ .forEach(view => (view.ComponentView as ImageBox).processOutpainting());
this._resizeHdlId = '';
this._resizeUndo?.end();
@@ -647,7 +608,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
//
// resize a single DocumentView about the specified reference point, possibly setting/updating the native dimensions of the Doc
//
- resizeView = (docView: DocumentView, refPt: number[], scale: { x: number; y: number }, opts: { dragHdl: string; ctrlKey: boolean }) => {
+ resizeView = (docView: DocumentView, refPt: number[], scale: { x: number; y: number }, opts: { dragHdl: string; freezeNativeDims: boolean }) => {
const doc = docView.Document;
if (doc.isGroup) {
DocListCast(doc.data)
@@ -660,25 +621,24 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
const [nwidth, nheight] = [docView.nativeWidth, docView.nativeHeight];
const [initWidth, initHeight] = [NumCast(doc._width, 1), NumCast(doc._height)];
- const modifyNativeDim =
- (opts.ctrlKey && doc._layout_nativeDimEditable) || // e.g., PDF or web page
- (doc._layout_reflowHorizontal && opts.dragHdl !== 'bottom' && opts.dragHdl !== 'top') || // eg rtf or some web pages
- (doc._layout_reflowVertical && (opts.dragHdl === 'bottom' || opts.dragHdl === 'top' || opts.ctrlKey)); // eg rtf, web, pdf
- if (nwidth && nheight && !modifyNativeDim) {
- // eg., dragging right resizer on PDF -- enforce native dimensions because not expliclty overridden with ctrl or bottom resize drag
+ const cornerReflow = !opts.freezeNativeDims && doc._layout_reflowHorizontal && doc._layout_reflowVertical && ['topLeft', 'topRight', 'bottomLeft', 'bottomRight'].includes(opts.dragHdl);
+ const horizontalReflow = !opts.freezeNativeDims && doc._layout_reflowHorizontal && ['left', 'right'].includes(opts.dragHdl); // eg rtf or some web pages
+ const verticalReflow = !opts.freezeNativeDims && doc._layout_reflowVertical && ['bottom', 'top'].includes(opts.dragHdl); // eg rtf, web, pdf
+ // preserve aspect ratio if Doc has a native ize and drag won't cause reflow (eg, ctrl-dragging a Doc's corner doesn't allow reflow, or dragging right side of a PDF which isn't horizontally reflowable)
+ if (nwidth && nheight && !cornerReflow && !horizontalReflow && !verticalReflow) {
scale.x === 1 ? (scale.x = scale.y) : (scale.y = scale.x);
}
- if (['right', 'left', 'bottomRight'].includes(opts.dragHdl) && modifyNativeDim && Doc.NativeWidth(doc)) {
+ if ((horizontalReflow || cornerReflow) && Doc.NativeWidth(doc)) {
const setData = Doc.NativeWidth(doc[DocData]) === doc.nativeWidth;
- doc.nativeWidth = scale.x * Doc.NativeWidth(doc);
+ doc._nativeWidth = scale.x * Doc.NativeWidth(doc);
if (setData) Doc.SetNativeWidth(doc[DocData], NumCast(doc.nativeWidth));
if (doc._layout_reflowVertical && !NumCast(doc.nativeHeight)) {
doc._nativeHeight = (initHeight / initWidth) * nwidth; // initializes the nativeHeight for a PDF
}
}
- if (['bottom', 'top', 'bottomRight'].includes(opts.dragHdl) && modifyNativeDim && Doc.NativeHeight(doc)) {
- const setData = Doc.NativeHeight(doc[DocData]) === doc.nativeHeight && (!doc.layout_reflowVertical || opts.ctrlKey);
+ if ((verticalReflow || cornerReflow) && Doc.NativeHeight(doc)) {
+ const setData = Doc.NativeHeight(doc[DocData]) === doc.nativeHeight && !doc.layout_reflowVertical;
doc._nativeHeight = scale.y * Doc.NativeHeight(doc);
if (setData) Doc.SetNativeHeight(doc[DocData], NumCast(doc._nativeHeight));
}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 999d7089b..197ef0998 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -170,14 +170,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
},
{ fireImmediately: true }
);
- this._disposers.outpainting = reaction(
- () => this.Document?._needsOutpainting,
- needsOutpainting => {
- if (needsOutpainting && this.Document?._outpaintingResize) {
- this.processOutpainting();
- }
- }
- );
}
componentWillUnmount() {
@@ -421,7 +413,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
const response = await Networking.PostToServer('/outpaintImage', {
imageUrl: currentPath,
prompt: customPrompt,
- originalDimensions: { width: origWidth, height: origHeight },
+ originalDimensions: { width: Math.min(newWidth, origWidth), height: Math.min(newHeight, origHeight) },
newDimensions: { width: newWidth, height: newHeight },
});
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 164c64107..98e461a52 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1149,7 +1149,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
// Since we also monitor all component height changes, this will update the document's height.
resetNativeHeight = action((scrollHeight: number) => {
this.layoutDoc['_' + this.fieldKey + '_height'] = scrollHeight;
- if (!this.layoutDoc.isTemplateForField) this.layoutDoc._nativeHeight = scrollHeight;
+ if (!this.layoutDoc.isTemplateForField && NumCast(this.layoutDoc._nativeHeight)) this.layoutDoc._nativeHeight = scrollHeight;
});
addPlugin = (plugin: Plugin) => {
diff --git a/src/server/ApiManagers/FireflyManager.ts b/src/server/ApiManagers/FireflyManager.ts
index 5311ca643..63581d3b3 100644
--- a/src/server/ApiManagers/FireflyManager.ts
+++ b/src/server/ApiManagers/FireflyManager.ts
@@ -343,10 +343,10 @@ export default class FireflyManager extends ApiManager {
numVariations: 1,
placement: {
inset: {
- left: 0,
- top: 0,
- right: Math.round(req.body.newDimensions.width - req.body.originalDimensions.width),
- bottom: Math.round(req.body.newDimensions.height - req.body.originalDimensions.height),
+ left: Math.round(req.body.newDimensions.width - req.body.originalDimensions.width) / 2,
+ top: Math.round(req.body.newDimensions.height - req.body.originalDimensions.height) / 2,
+ right: Math.round(req.body.newDimensions.width - req.body.originalDimensions.width) / 2,
+ bottom: Math.round(req.body.newDimensions.height - req.body.originalDimensions.height) / 2,
},
alignment: {
horizontal: 'center',