|
|
@@ -1,5 +1,6 @@
|
|
|
import {
|
|
|
ChangeDetectionStrategy,
|
|
|
+ ChangeDetectorRef,
|
|
|
Component,
|
|
|
ElementRef,
|
|
|
EventEmitter,
|
|
|
@@ -9,56 +10,78 @@ import {
|
|
|
Output,
|
|
|
ViewChild,
|
|
|
} from '@angular/core';
|
|
|
-import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
|
|
|
-import { Subscription } from 'rxjs';
|
|
|
+import { FormBuilder, FormGroup } from '@angular/forms';
|
|
|
+import { fromEvent, Subscription } from 'rxjs';
|
|
|
+import { debounceTime } from 'rxjs/operators';
|
|
|
|
|
|
import { Asset, UpdateAssetInput } from '../../../common/generated-types';
|
|
|
-import { Dialog } from '../../providers/modal/modal.service';
|
|
|
+import { _ } from '../../../core/providers/i18n/mark-for-extraction';
|
|
|
+import { NotificationService } from '../../../core/providers/notification/notification.service';
|
|
|
+import { DataService } from '../../../data/providers/data.service';
|
|
|
+import { Point } from '../focal-point-control/focal-point-control.component';
|
|
|
+
|
|
|
+export type PreviewPreset = 'tiny' | 'thumb' | 'small' | 'medium' | 'large' | '';
|
|
|
|
|
|
@Component({
|
|
|
selector: 'vdr-asset-preview',
|
|
|
templateUrl: './asset-preview.component.html',
|
|
|
styleUrls: ['./asset-preview.component.scss'],
|
|
|
- changeDetection: ChangeDetectionStrategy.Default,
|
|
|
+ changeDetection: ChangeDetectionStrategy.OnPush,
|
|
|
})
|
|
|
export class AssetPreviewComponent implements OnInit, OnDestroy {
|
|
|
@Input() asset: Asset;
|
|
|
- @Output() assetChange = new EventEmitter<UpdateAssetInput>();
|
|
|
+ @Input() editable = false;
|
|
|
+ @Output() assetChange = new EventEmitter<Omit<UpdateAssetInput, 'focalPoint'>>();
|
|
|
+ @Output() editClick = new EventEmitter();
|
|
|
|
|
|
form: FormGroup;
|
|
|
|
|
|
- size = 'medium';
|
|
|
- resolveWith: (result?: void) => void;
|
|
|
+ size: PreviewPreset = 'medium';
|
|
|
width = 0;
|
|
|
height = 0;
|
|
|
centered = true;
|
|
|
+ settingFocalPoint = false;
|
|
|
+ lastFocalPoint?: Point;
|
|
|
@ViewChild('imageElement', { static: true }) private imageElementRef: ElementRef<HTMLImageElement>;
|
|
|
@ViewChild('previewDiv', { static: true }) private previewDivRef: ElementRef<HTMLDivElement>;
|
|
|
private subscription: Subscription;
|
|
|
+ private sizePriorToSettingFocalPoint: PreviewPreset;
|
|
|
+
|
|
|
+ constructor(
|
|
|
+ private formBuilder: FormBuilder,
|
|
|
+ private dataService: DataService,
|
|
|
+ private notificationService: NotificationService,
|
|
|
+ private changeDetector: ChangeDetectorRef,
|
|
|
+ ) {}
|
|
|
+
|
|
|
+ get fpx(): number | null {
|
|
|
+ return this.asset.focalPoint ? this.asset.focalPoint.x : null;
|
|
|
+ }
|
|
|
|
|
|
- constructor(private formBuilder: FormBuilder) {}
|
|
|
+ get fpy(): number | null {
|
|
|
+ return this.asset.focalPoint ? this.asset.focalPoint.y : null;
|
|
|
+ }
|
|
|
|
|
|
ngOnInit() {
|
|
|
const { focalPoint } = this.asset;
|
|
|
this.form = this.formBuilder.group({
|
|
|
name: [this.asset.name],
|
|
|
- focalPointX: [focalPoint ? focalPoint.x : null],
|
|
|
- focalPointY: [focalPoint ? focalPoint.y : null],
|
|
|
});
|
|
|
this.subscription = this.form.valueChanges.subscribe(value => {
|
|
|
- const focalPointValue =
|
|
|
- value.focalPointX != null && value.focalPointY != null
|
|
|
- ? {
|
|
|
- x: value.focalPointX,
|
|
|
- y: value.focalPointY,
|
|
|
- }
|
|
|
- : null;
|
|
|
this.assetChange.emit({
|
|
|
id: this.asset.id,
|
|
|
name: value.name,
|
|
|
- focalPoint: focalPointValue,
|
|
|
});
|
|
|
});
|
|
|
+
|
|
|
+ this.subscription.add(
|
|
|
+ fromEvent(window, 'resize')
|
|
|
+ .pipe(debounceTime(50))
|
|
|
+ .subscribe(() => {
|
|
|
+ this.updateDimensions();
|
|
|
+ this.changeDetector.markForCheck();
|
|
|
+ }),
|
|
|
+ );
|
|
|
}
|
|
|
|
|
|
ngOnDestroy(): void {
|
|
|
@@ -72,11 +95,89 @@ export class AssetPreviewComponent implements OnInit, OnDestroy {
|
|
|
return parts[parts.length - 1];
|
|
|
}
|
|
|
|
|
|
- getDimensions() {
|
|
|
+ updateDimensions() {
|
|
|
const img = this.imageElementRef.nativeElement;
|
|
|
const container = this.previewDivRef.nativeElement;
|
|
|
- this.width = img.width;
|
|
|
- this.height = img.height;
|
|
|
- this.centered = img.width <= container.offsetWidth && img.height <= container.offsetHeight;
|
|
|
+ const imgWidth = img.naturalWidth;
|
|
|
+ const imgHeight = img.naturalHeight;
|
|
|
+ const containerWidth = container.offsetWidth;
|
|
|
+ const containerHeight = container.offsetHeight;
|
|
|
+
|
|
|
+ const constrainToContainer = this.settingFocalPoint;
|
|
|
+ if (constrainToContainer) {
|
|
|
+ const controlsMarginPx = 48 * 2;
|
|
|
+ const availableHeight = containerHeight - controlsMarginPx;
|
|
|
+ const availableWidth = containerWidth;
|
|
|
+ const hRatio = imgHeight / availableHeight;
|
|
|
+ const wRatio = imgWidth / availableWidth;
|
|
|
+
|
|
|
+ const imageExceedsAvailableDimensions = 1 < hRatio || 1 < wRatio;
|
|
|
+ if (imageExceedsAvailableDimensions) {
|
|
|
+ const factor = hRatio < wRatio ? wRatio : hRatio;
|
|
|
+ this.width = Math.round(imgWidth / factor);
|
|
|
+ this.height = Math.round(imgHeight / factor);
|
|
|
+ this.centered = true;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.width = imgWidth;
|
|
|
+ this.height = imgHeight;
|
|
|
+ this.centered = imgWidth <= containerWidth && imgHeight <= containerHeight;
|
|
|
+ }
|
|
|
+
|
|
|
+ setFocalPointStart() {
|
|
|
+ this.sizePriorToSettingFocalPoint = this.size;
|
|
|
+ this.size = 'medium';
|
|
|
+ this.settingFocalPoint = true;
|
|
|
+ this.lastFocalPoint = this.asset.focalPoint || { x: 0.5, y: 0.5 };
|
|
|
+ this.updateDimensions();
|
|
|
+ }
|
|
|
+
|
|
|
+ removeFocalPoint() {
|
|
|
+ this.dataService.product
|
|
|
+ .updateAsset({
|
|
|
+ id: this.asset.id,
|
|
|
+ focalPoint: null,
|
|
|
+ })
|
|
|
+ .subscribe(
|
|
|
+ () => {
|
|
|
+ this.notificationService.success(_('asset.update-focal-point-success'));
|
|
|
+ this.asset.focalPoint = null;
|
|
|
+ this.changeDetector.markForCheck();
|
|
|
+ },
|
|
|
+ () => this.notificationService.error(_('asset.update-focal-point-error')),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ onFocalPointChange(point: Point) {
|
|
|
+ this.lastFocalPoint = point;
|
|
|
+ }
|
|
|
+
|
|
|
+ setFocalPointCancel() {
|
|
|
+ this.settingFocalPoint = false;
|
|
|
+ this.lastFocalPoint = undefined;
|
|
|
+ this.size = this.sizePriorToSettingFocalPoint;
|
|
|
+ }
|
|
|
+
|
|
|
+ setFocalPointEnd() {
|
|
|
+ this.settingFocalPoint = false;
|
|
|
+ this.size = this.sizePriorToSettingFocalPoint;
|
|
|
+ if (this.lastFocalPoint) {
|
|
|
+ const { x, y } = this.lastFocalPoint;
|
|
|
+ this.lastFocalPoint = undefined;
|
|
|
+ this.dataService.product
|
|
|
+ .updateAsset({
|
|
|
+ id: this.asset.id,
|
|
|
+ focalPoint: { x, y },
|
|
|
+ })
|
|
|
+ .subscribe(
|
|
|
+ () => {
|
|
|
+ this.notificationService.success(_('asset.update-focal-point-success'));
|
|
|
+ this.asset.focalPoint = { x, y };
|
|
|
+ this.changeDetector.markForCheck();
|
|
|
+ },
|
|
|
+ () => this.notificationService.error(_('asset.update-focal-point-error')),
|
|
|
+ );
|
|
|
+ }
|
|
|
}
|
|
|
}
|