Move gallery content viewer to separate component
Signed-off-by: trivernis <trivernis@protonmail.com>pull/4/head
parent
09f3225aa3
commit
47738b392d
@ -0,0 +1 @@
|
|||||||
|
<app-image-viewer *ngIf="getContentType() === 'image'" [imageUrl]="contentUrl"></app-image-viewer>
|
@ -0,0 +1,4 @@
|
|||||||
|
app-image-viewer {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ContentViewerComponent } from './content-viewer.component';
|
||||||
|
|
||||||
|
describe('ContentViewerComponent', () => {
|
||||||
|
let component: ContentViewerComponent;
|
||||||
|
let fixture: ComponentFixture<ContentViewerComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ ContentViewerComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ContentViewerComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,37 @@
|
|||||||
|
import {Component, Input, OnInit} from '@angular/core';
|
||||||
|
import {SafeResourceUrl} from "@angular/platform-browser";
|
||||||
|
|
||||||
|
type ContentType = "image" | "video" | "text" | "other";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-content-viewer',
|
||||||
|
templateUrl: './content-viewer.component.html',
|
||||||
|
styleUrls: ['./content-viewer.component.scss']
|
||||||
|
})
|
||||||
|
export class ContentViewerComponent {
|
||||||
|
|
||||||
|
@Input() contentUrl!: SafeResourceUrl | string;
|
||||||
|
@Input() mimeType: string | undefined;
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
public getContentType(): ContentType {
|
||||||
|
if (!this.mimeType) {
|
||||||
|
return "other";
|
||||||
|
}
|
||||||
|
let mimeParts = this.mimeType.split("/");
|
||||||
|
const type = mimeParts.shift() ?? "other";
|
||||||
|
const subtype = mimeParts.shift() ?? "*";
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case "image":
|
||||||
|
return "image";
|
||||||
|
case "video":
|
||||||
|
return "video";
|
||||||
|
case "text":
|
||||||
|
return "text";
|
||||||
|
default:
|
||||||
|
return "other";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
<div (mouseenter)="this.mouseInImageView = true" (mouseleave)="this.mouseInImageView = false"
|
||||||
|
class="image-full-view-inner">
|
||||||
|
<div class="zoom-slider">
|
||||||
|
<mat-slider (input)="this.imageZoom=$event.value ?? 1" [value]="this.imageZoom" max="4"
|
||||||
|
min="0.5" step="0.1" vertical></mat-slider>
|
||||||
|
<button (click)="this.resetImage()" mat-icon-button>
|
||||||
|
<mat-icon>refresh</mat-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div (cdkDragMoved)="this.onDragMoved($event)"
|
||||||
|
[cdkDragFreeDragPosition]="this.imagePosition" cdkDrag class="image-drag-container">
|
||||||
|
<div [style]="{scale: this.imageZoom}" class="image-scale-container">
|
||||||
|
<app-content-aware-image [imageSrc]="this.imageUrl" decoding="sync"></app-content-aware-image>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,35 @@
|
|||||||
|
|
||||||
|
.image-drag-container, .image-scale-container {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-scale-container {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zoom-slider {
|
||||||
|
position: absolute;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
right: 1em;
|
||||||
|
bottom: 1em;
|
||||||
|
z-index: 10;
|
||||||
|
opacity: 0.5;
|
||||||
|
padding: 1em 0.5em;
|
||||||
|
transition-duration: 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zoom-slider:hover {
|
||||||
|
opacity: 1;
|
||||||
|
background-color: rgba(0, 0, 0, 0.3);
|
||||||
|
border-radius: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.image-full-view-inner {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ImageViewerComponent } from './image-viewer.component';
|
||||||
|
|
||||||
|
describe('ImageViewerComponent', () => {
|
||||||
|
let component: ImageViewerComponent;
|
||||||
|
let fixture: ComponentFixture<ImageViewerComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ ImageViewerComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ImageViewerComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,63 @@
|
|||||||
|
import {
|
||||||
|
Component,
|
||||||
|
ElementRef,
|
||||||
|
HostListener,
|
||||||
|
Input,
|
||||||
|
OnInit,
|
||||||
|
ViewChild
|
||||||
|
} from '@angular/core';
|
||||||
|
import {CdkDragMove} from "@angular/cdk/drag-drop";
|
||||||
|
import {SafeResourceUrl} from "@angular/platform-browser";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-image-viewer',
|
||||||
|
templateUrl: './image-viewer.component.html',
|
||||||
|
styleUrls: ['./image-viewer.component.scss']
|
||||||
|
})
|
||||||
|
export class ImageViewerComponent {
|
||||||
|
|
||||||
|
@Input() imageUrl!: SafeResourceUrl | string;
|
||||||
|
public imageZoom = 1;
|
||||||
|
public imagePosition = {x: 0, y: 0};
|
||||||
|
public mouseInImageView = false;
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
public resetImage() {
|
||||||
|
this.imageZoom = 1;
|
||||||
|
this.imagePosition = {x: 0, y: 0};
|
||||||
|
}
|
||||||
|
|
||||||
|
public onDragMoved($event: CdkDragMove<HTMLDivElement>): void {
|
||||||
|
this.imagePosition.x += $event.delta.x;
|
||||||
|
this.imagePosition.y += $event.delta.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener("window:keydown", ["$event"])
|
||||||
|
private async handleKeydownEvent(event: KeyboardEvent) {
|
||||||
|
switch (event.key) {
|
||||||
|
case "Escape":
|
||||||
|
this.resetImage();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener("mousewheel", ["$event"])
|
||||||
|
private handleScroll(event: any) {
|
||||||
|
if (this.mouseInImageView) {
|
||||||
|
const delta = event.wheelDelta ?? event.detail;
|
||||||
|
|
||||||
|
if (delta > 0) {
|
||||||
|
this.imageZoom += 0.2
|
||||||
|
if (this.imageZoom > 4) {
|
||||||
|
this.imageZoom = 4;
|
||||||
|
}
|
||||||
|
} else if (delta < 0) {
|
||||||
|
this.imageZoom -= 0.2
|
||||||
|
if (this.imageZoom < 0.5) {
|
||||||
|
this.imageZoom = 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue