diff --git a/frontend/src/app/routes/view/view.component.html b/frontend/src/app/routes/view/view.component.html
index f172bfd..905b0a4 100644
--- a/frontend/src/app/routes/view/view.component.html
+++ b/frontend/src/app/routes/view/view.component.html
@@ -8,9 +8,28 @@
-
+
+
+
+
+ Image Format
+
+
+ {{ format.value }}
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/app/routes/view/view.component.scss b/frontend/src/app/routes/view/view.component.scss
index bd1ff2e..c89cb34 100644
--- a/frontend/src/app/routes/view/view.component.scss
+++ b/frontend/src/app/routes/view/view.component.scss
@@ -6,3 +6,7 @@
.content-border {
padding-block: 1rem;
}
+
+mat-form-field {
+ width: 100%;
+}
diff --git a/frontend/src/app/routes/view/view.component.ts b/frontend/src/app/routes/view/view.component.ts
index 3725adb..c04ade7 100644
--- a/frontend/src/app/routes/view/view.component.ts
+++ b/frontend/src/app/routes/view/view.component.ts
@@ -1,8 +1,18 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { ImageLinks } from 'picsur-shared/dist/dto/image-links.dto';
-import { HasFailed } from 'picsur-shared/dist/types';
+import {
+ AnimMime,
+ FullMime,
+ ImageMime,
+ Mime2Ext,
+ SupportedAnimMimes,
+ SupportedImageMimes,
+ SupportedMimeCategory
+} from 'picsur-shared/dist/dto/mimes.dto';
+import { HasFailed, HasSuccess } from 'picsur-shared/dist/types';
import { UUIDRegex } from 'picsur-shared/dist/util/common-regex';
+import { ParseMime } from 'picsur-shared/dist/util/parse-mime';
import { ImageService } from 'src/app/services/api/image.service';
import { UtilService } from 'src/app/util/util-module/util.service';
@@ -18,31 +28,72 @@ export class ViewComponent implements OnInit {
private utilService: UtilService
) {}
+ private id: string;
+ private hasOriginal: boolean = false;
+ private masterMime: FullMime = {
+ mime: ImageMime.JPEG,
+ type: SupportedMimeCategory.Image,
+ };
+
+ public formatOptions: {
+ value: string;
+ key: string;
+ }[] = [];
+
+ public setSelectedValue: string = ImageMime.JPEG;
+
public previewLink = '';
public imageLinks = new ImageLinks();
async ngOnInit() {
const params = this.route.snapshot.paramMap;
- const id = params.get('id') ?? '';
- if (!UUIDRegex.test(id)) {
+
+ this.id = params.get('id') ?? '';
+ if (!UUIDRegex.test(this.id)) {
return this.utilService.quitError('Invalid image link');
}
- const metadata = await this.imageService.GetImageMeta(id);
- if (HasFailed(metadata)) {
+ const metadata = await this.imageService.GetImageMeta(this.id);
+ if (HasFailed(metadata))
return this.utilService.quitError(metadata.getReason());
- }
- const hasOriginal = metadata.fileMimes.original !== undefined;
this.previewLink = this.imageService.GetImageURL(
- id,
+ this.id,
metadata.fileMimes.master
);
- this.imageLinks = this.imageService.CreateImageLinksFromID(
- id,
- hasOriginal ? null : metadata.fileMimes.master
- );
+ this.hasOriginal = metadata.fileMimes.original !== undefined;
+
+ const masterMime = ParseMime(metadata.fileMimes.master);
+ if (HasSuccess(masterMime)) {
+ this.masterMime = masterMime;
+ }
+
+ if (this.hasOriginal) {
+ this.setSelectedValue = 'original';
+ } else {
+ if (this.masterMime.type === SupportedMimeCategory.Image) {
+ this.setSelectedValue = ImageMime.JPEG;
+ } else if (this.masterMime.type === SupportedMimeCategory.Animation) {
+ this.setSelectedValue = AnimMime.GIF;
+ } else {
+ this.setSelectedValue = metadata.fileMimes.master;
+ }
+ }
+
+ this.selectedFormat(this.setSelectedValue);
+ this.updateFormatOptions();
+ }
+
+ selectedFormat(format: string) {
+ if (format === 'original') {
+ this.imageLinks = this.imageService.CreateImageLinksFromID(this.id, null);
+ } else {
+ this.imageLinks = this.imageService.CreateImageLinksFromID(
+ this.id,
+ format
+ );
+ }
}
download() {
@@ -56,4 +107,35 @@ export class ViewComponent implements OnInit {
goBackHome() {
this.router.navigate(['/']);
}
+
+ private updateFormatOptions() {
+ let newOptions: {
+ value: string;
+ key: string;
+ }[] = [];
+ if (this.hasOriginal) {
+ newOptions.push({
+ value: 'Original',
+ key: 'original',
+ });
+ }
+
+ if (this.masterMime.type === SupportedMimeCategory.Image) {
+ newOptions.push(
+ ...SupportedImageMimes.map((mime) => ({
+ value: Mime2Ext(mime)?.toUpperCase() ?? 'Error',
+ key: mime,
+ }))
+ );
+ } else if (this.masterMime.type === SupportedMimeCategory.Animation) {
+ newOptions.push(
+ ...SupportedAnimMimes.map((mime) => ({
+ value: Mime2Ext(mime)?.toUpperCase() ?? 'Error',
+ key: mime,
+ }))
+ );
+ }
+
+ this.formatOptions = newOptions;
+ }
}
diff --git a/frontend/src/app/routes/view/view.module.ts b/frontend/src/app/routes/view/view.module.ts
index 7f6e6d2..f875115 100644
--- a/frontend/src/app/routes/view/view.module.ts
+++ b/frontend/src/app/routes/view/view.module.ts
@@ -1,7 +1,9 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
+import { MatDividerModule } from '@angular/material/divider';
import { MatIconModule } from '@angular/material/icon';
+import { MatSelectModule } from '@angular/material/select';
import { CopyFieldModule } from 'src/app/components/copy-field/copy-field.module';
import { FabModule } from 'src/app/components/fab/fab.module';
import { PicsurImgModule } from 'src/app/components/picsur-img/picsur-img.module';
@@ -14,9 +16,11 @@ import { ViewRoutingModule } from './view.routing.module';
CopyFieldModule,
ViewRoutingModule,
MatButtonModule,
+ MatSelectModule,
+ MatDividerModule,
PicsurImgModule,
MatIconModule,
- FabModule
+ FabModule,
],
})
export class ViewRouteModule {}
diff --git a/frontend/src/app/services/api/image.service.ts b/frontend/src/app/services/api/image.service.ts
index 76f5e85..98efa80 100644
--- a/frontend/src/app/services/api/image.service.ts
+++ b/frontend/src/app/services/api/image.service.ts
@@ -46,7 +46,10 @@ export class ImageService {
};
}
- public CreateImageLinksFromID(imageID: string, mime: string | null): ImageLinks {
+ public CreateImageLinksFromID(
+ imageID: string,
+ mime: string | null
+ ): ImageLinks {
return this.CreateImageLinks(this.GetImageURL(imageID, mime));
}
}
diff --git a/frontend/src/app/util/util-module/util.service.ts b/frontend/src/app/util/util-module/util.service.ts
index 047bf83..1e0f7ed 100644
--- a/frontend/src/app/util/util-module/util.service.ts
+++ b/frontend/src/app/util/util-module/util.service.ts
@@ -121,6 +121,7 @@ export class UtilService {
new Blob([file.buffer], { type: file.mimeType })
);
a.download = file.name;
+ a.target = '_self';
a.click();
closeDialog();
diff --git a/shared/src/dto/mimes.dto.ts b/shared/src/dto/mimes.dto.ts
index 5dee088..e125ad6 100644
--- a/shared/src/dto/mimes.dto.ts
+++ b/shared/src/dto/mimes.dto.ts
@@ -35,20 +35,20 @@ export interface FullMime {
export const ImageMime2ExtMap: {
[key in ImageMime]: string;
} = {
+ [ImageMime.QOI]: 'qoi',
[ImageMime.JPEG]: 'jpg',
[ImageMime.PNG]: 'png',
[ImageMime.WEBP]: 'webp',
[ImageMime.TIFF]: 'tiff',
[ImageMime.BMP]: 'bmp',
// [ImageMime.ICO]: 'ico',
- [ImageMime.QOI]: 'qoi',
};
export const AnimMime2ExtMap: {
[key in AnimMime]: string;
} = {
- [AnimMime.APNG]: 'apng',
[AnimMime.GIF]: 'gif',
+ [AnimMime.APNG]: 'apng',
};
export const Mime2ExtMap: {