feat: cleanup screenshot thubnail

This commit is contained in:
Michal Szczepanski 2023-09-19 20:21:21 +02:00
parent 5d0b5da2c6
commit 402b88f760
6 changed files with 66 additions and 33 deletions

@ -27,6 +27,7 @@ import { ObjectStoreKeys } from '../../keys/object.store.keys';
import { ScreenshotFactory } from '../../factory/screenshot.factory'; import { ScreenshotFactory } from '../../factory/screenshot.factory';
import { UrlFactory } from '../../factory/url.factory'; import { UrlFactory } from '../../factory/url.factory';
import { fnSha256 } from '../../fn/fn-hash'; import { fnSha256 } from '../../fn/fn-hash';
import { ImageResizeFactory } from '../../factory/image-resize.factory';
export class PdfAddCommand implements ICommand<Promise<void>> { export class PdfAddCommand implements ICommand<Promise<void>> {
constructor(private value: FetchResponse<string>) {} constructor(private value: FetchResponse<string>) {}
@ -35,11 +36,13 @@ export class PdfAddCommand implements ICommand<Promise<void>> {
const dt = Date.now(); const dt = Date.now();
const hash = fnSha256(this.value.data); const hash = fnSha256(this.value.data);
const screenshot = await ScreenshotFactory.takeScreenshot({ let screenshot = await ScreenshotFactory.takeScreenshot(document, window, ContentSettingsStore.settings);
screenshot = await ImageResizeFactory.resize2(
document, document,
window, ScreenshotFactory.THUMB_SETTINGS,
settings: ContentSettingsStore.settings ScreenshotFactory.THUMB_SIZE,
}); screenshot
);
const url = UrlFactory.newUrl(); const url = UrlFactory.newUrl();

@ -61,7 +61,12 @@ export class DownloadImageButton {
setTimeout(async () => { setTimeout(async () => {
let rect: ObjRectangleDto = this.model.ref.getBoundingClientRect(); let rect: ObjRectangleDto = this.model.ref.getBoundingClientRect();
if (this.model.canvas) rect = this.model.canvas.rect; if (this.model.canvas) rect = this.model.canvas.rect;
const screenshot = await ScreenshotFactory.takeScreenshot(this.model.doc, rect); const screenshot = await ScreenshotFactory.takeScreenshot(
this.model.doc.document,
this.model.doc.window,
this.model.doc.settings,
rect
);
await this.downloadScreenshot(screenshot); await this.downloadScreenshot(screenshot);
this.edit.showScreenshot(); this.edit.showScreenshot();

@ -17,23 +17,33 @@
import { ObjRectangleDto, ObjSizeDto } from '../model/obj/obj-utils.dto'; import { ObjRectangleDto, ObjSizeDto } from '../model/obj/obj-utils.dto';
import { PinDocument } from '../components/pin/model/pin-view.model'; import { PinDocument } from '../components/pin/model/pin-view.model';
import { fnConsoleLog } from '../fn/fn-console'; import { fnConsoleLog } from '../fn/fn-console';
import { ScreenshotFormat } from '../environment';
export interface ScreenshotSettings {
screenshotFormat: ScreenshotFormat;
screenshotQuality: number;
}
export class ImageResizeFactory { export class ImageResizeFactory {
static resize2 = (doc: PinDocument, size: ObjSizeDto, b64image: string): Promise<string> => { static resize2 = (
doc: Document,
settings: ScreenshotSettings,
size: ObjSizeDto,
b64image: string
): Promise<string> => {
return new Promise<string>((resolve, reject) => { return new Promise<string>((resolve, reject) => {
const img = new Image(); const img = new Image();
img.crossOrigin = 'anonymous'; img.crossOrigin = 'anonymous';
img.onload = () => { img.onload = () => {
try { try {
const can = doc.document.createElement('canvas'); const can = doc.createElement('canvas');
const wr = size.width / img.naturalWidth; const wr = size.width / img.naturalWidth;
const hr = size.height / img.naturalHeight; const hr = size.height / img.naturalHeight;
fnConsoleLog('AAAAAAAAAAAAAAAAAAAAAAAAAaa', wr, hr);
can.width = img.naturalWidth * wr; can.width = img.naturalWidth * wr;
can.height = img.naturalHeight * hr; can.height = img.naturalHeight * hr;
const ctx = can.getContext('2d'); const ctx = can.getContext('2d');
ctx?.drawImage(img, 0, 0, can.width, can.height); ctx?.drawImage(img, 0, 0, can.width, can.height);
b64image = can.toDataURL(`image/${doc.settings.screenshotFormat}`, doc.settings.screenshotQuality); b64image = can.toDataURL(`image/${settings.screenshotFormat}`, settings.screenshotQuality);
} finally { } finally {
window.URL.revokeObjectURL(b64image); window.URL.revokeObjectURL(b64image);
img.onerror = null; img.onerror = null;
@ -52,23 +62,29 @@ export class ImageResizeFactory {
img.src = b64image; img.src = b64image;
}); });
}; };
static resize = (doc: PinDocument, size: ObjRectangleDto, b64image: string): Promise<string> => { static resize = (
doc: Document,
win: Window,
settings: ScreenshotSettings,
size: ObjRectangleDto,
b64image: string
): Promise<string> => {
const rect = { const rect = {
x: size.x, x: size.x,
y: size.y, y: size.y,
width: size.width, width: size.width,
height: Math.min(size.height, doc.window.innerHeight - size.y) height: Math.min(size.height, win.innerHeight - size.y)
}; };
return new Promise<string>((resolve, reject) => { return new Promise<string>((resolve, reject) => {
const img = new Image(); const img = new Image();
img.crossOrigin = 'anonymous'; img.crossOrigin = 'anonymous';
img.onload = () => { img.onload = () => {
try { try {
const can = doc.document.createElement('canvas'); const can = doc.createElement('canvas');
can.width = rect.width; can.width = rect.width;
can.height = rect.height; can.height = rect.height;
const wr = img.naturalWidth / doc.window.innerWidth; const wr = img.naturalWidth / win.innerWidth;
const hr = img.naturalHeight / doc.window.innerHeight; const hr = img.naturalHeight / win.innerHeight;
const ctx = can.getContext('2d'); const ctx = can.getContext('2d');
ctx?.drawImage( ctx?.drawImage(
img, img,
@ -81,7 +97,7 @@ export class ImageResizeFactory {
rect.width, rect.width,
rect.height rect.height
); );
b64image = can.toDataURL(`image/${doc.settings.screenshotFormat}`, doc.settings.screenshotQuality); b64image = can.toDataURL(`image/${settings.screenshotFormat}`, settings.screenshotQuality);
} finally { } finally {
window.URL.revokeObjectURL(b64image); window.URL.revokeObjectURL(b64image);
img.onerror = null; img.onerror = null;

@ -16,22 +16,36 @@
*/ */
import { BrowserApi } from '@pinmenote/browser-api'; import { BrowserApi } from '@pinmenote/browser-api';
import { BusMessageType } from '../model/bus.model'; import { BusMessageType } from '../model/bus.model';
import { ImageResizeFactory } from './image-resize.factory'; import { ImageResizeFactory, ScreenshotSettings } from './image-resize.factory';
import { ObjRectangleDto } from '../model/obj/obj-utils.dto'; import { ObjRectangleDto, ObjSizeDto } from '../model/obj/obj-utils.dto';
import { ObjUrlDto } from '../model/obj/obj.dto'; import { ObjUrlDto } from '../model/obj/obj.dto';
import { PinDocument } from '../components/pin/model/pin-view.model';
import { TinyDispatcher } from '@pinmenote/tiny-dispatcher'; import { TinyDispatcher } from '@pinmenote/tiny-dispatcher';
import { fnConsoleLog } from '../fn/fn-console'; import { fnConsoleLog } from '../fn/fn-console';
export class ScreenshotFactory { export class ScreenshotFactory {
static takeScreenshot = async (doc: PinDocument, rect?: ObjRectangleDto, url?: ObjUrlDto): Promise<string> => { static readonly THUMB_SETTINGS: ScreenshotSettings = {
screenshotFormat: 'jpeg',
screenshotQuality: 80
};
static readonly THUMB_SIZE: ObjSizeDto = {
width: 640,
height: 360
};
static takeScreenshot = async (
doc: Document,
win: Window,
settings: ScreenshotSettings,
rect?: ObjRectangleDto,
url?: ObjUrlDto
): Promise<string> => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// Crop screenshot function // Crop screenshot function
TinyDispatcher.getInstance().addListener<string>( TinyDispatcher.getInstance().addListener<string>(
BusMessageType.CONTENT_TAKE_SCREENSHOT, BusMessageType.CONTENT_TAKE_SCREENSHOT,
async (event: string, key: string, screenshot: string) => { async (event: string, key: string, screenshot: string) => {
TinyDispatcher.getInstance().removeListener(event, key); TinyDispatcher.getInstance().removeListener(event, key);
if (rect) screenshot = await ImageResizeFactory.resize(doc, rect, screenshot); if (rect) screenshot = await ImageResizeFactory.resize(doc, win, settings, rect, screenshot);
resolve(screenshot); resolve(screenshot);
} }
); );
@ -47,7 +61,7 @@ export class ScreenshotFactory {
.then(() => { .then(() => {
// We handle it above, inside dispatcher // We handle it above, inside dispatcher
}) })
.catch((e) => { .catch((e: any) => {
fnConsoleLog('ScreenshotFactory->sendTakeScreenshot->error', e); fnConsoleLog('ScreenshotFactory->sendTakeScreenshot->error', e);
reject('PROBLEM !!!'); reject('PROBLEM !!!');
}); });

@ -61,15 +61,12 @@ export class ContentPageSnapshotCreateCommand implements ICommand<Promise<PageSn
isPartial = true; isPartial = true;
} }
let screenshot = await ScreenshotFactory.takeScreenshot( let screenshot = await ScreenshotFactory.takeScreenshot(document, window, this.settings, rect, this.url);
{ settings: this.settings, document, window },
rect,
this.url
);
if (rect.width > 640 || rect.height > 360) { if (rect.width > 640 || rect.height > 360) {
screenshot = await ImageResizeFactory.resize2( screenshot = await ImageResizeFactory.resize2(
{ settings: this.settings, document, window }, document,
{ width: 640, height: 360 }, ScreenshotFactory.THUMB_SETTINGS,
ScreenshotFactory.THUMB_SIZE,
screenshot screenshot
); );
} }

@ -35,11 +35,9 @@ export class PinFactory {
): Promise<ObjPinDto> => { ): Promise<ObjPinDto> => {
const rect = canvas ? canvas.rect : XpathFactory.computeRect(ref); const rect = canvas ? canvas.rect : XpathFactory.computeRect(ref);
const screenshot = await ScreenshotFactory.takeScreenshot( const screenshot = await ScreenshotFactory.takeScreenshot(
{ document,
settings: ContentSettingsStore.settings, window,
document, ContentSettingsStore.settings,
window
},
rect, rect,
url url
); );