From a55ca90ae666434a6edf6262e8a0a7f9fba52c0c Mon Sep 17 00:00:00 2001 From: Michal Szczepanski Date: Sun, 23 Apr 2023 07:10:32 +0200 Subject: [PATCH] feat: save full image when cropping rectangle --- README.md | 14 ++++++ src/common/text/nlp/word.nlp.ts | 5 ++- .../snapshot/snapshot-create.command.ts | 4 ++ .../snapshot/snapshot-save-image.command.ts | 45 +++++++++++++++++++ .../html-preview/html-preview.component.tsx | 31 ++++++++----- 5 files changed, 86 insertions(+), 13 deletions(-) create mode 100644 src/content-script/command/snapshot/snapshot-save-image.command.ts diff --git a/README.md b/README.md index 445275f..5d0c87c 100644 --- a/README.md +++ b/README.md @@ -11,4 +11,18 @@ Browser extension nobody wants and nobody needs npm run dev ``` +### Website +[https://pinmenote.com](https://pinmenote.com) - subscribe to premium to move project further + ### Known issues + +#### Shadow root +Open shadow root is not always displayed or parsed correctly - but at least it matches mht quality. + +#### Youtube +Youtube use polymer dom with ``````. +It is some polymer polyfil for shadow root that messes with css. + +#### Twitter +Use style ```transform: translateY(4620.5px); position: absolute;``` for single tweets +(todo remove those style attributes from tweet when saving element) \ No newline at end of file diff --git a/src/common/text/nlp/word.nlp.ts b/src/common/text/nlp/word.nlp.ts index 9d5d559..8b3f59b 100644 --- a/src/common/text/nlp/word.nlp.ts +++ b/src/common/text/nlp/word.nlp.ts @@ -48,7 +48,7 @@ export class WordNlp { ch = word.charAt(i).toLowerCase(); flatPart += ch; if (flatPart.length % 2 === 0) { - await this.saveStorage(flatPart, id); + break; } } await this.saveStorage(flatPart, id); @@ -56,6 +56,7 @@ export class WordNlp { await this.saveWord(word); } fnConsoleLog('indexed', Array.from(this.flatSet), 'count', this.flatSet.size, 'in', Date.now() - a); + this.flatSet.clear(); }; static removeFlat = async (words: string[], id: number): Promise => { @@ -67,7 +68,7 @@ export class WordNlp { ch = word.charAt(i).toLowerCase(); flatPart += ch; if (flatPart.length % 2 === 0) { - await this.removeStorage(flatPart, id); + break; } } await this.removeStorage(flatPart, id); diff --git a/src/content-script/command/snapshot/snapshot-create.command.ts b/src/content-script/command/snapshot/snapshot-create.command.ts index bd7777e..2984c7f 100644 --- a/src/content-script/command/snapshot/snapshot-create.command.ts +++ b/src/content-script/command/snapshot/snapshot-create.command.ts @@ -19,6 +19,7 @@ import { ICommand } from '../../../common/model/shared/common.dto'; import { ObjUrlDto } from '../../../common/model/obj/obj.dto'; import { ScreenshotFactory } from '../../../common/factory/screenshot.factory'; import { SnapshotContentSaveCommand } from './snapshot-content-save.command'; +import { SnapshotSaveImageCommand } from './snapshot-save-image.command'; import { XpathFactory } from '../../../common/factory/xpath.factory'; export class SnapshotCreateCommand implements ICommand> { @@ -32,6 +33,9 @@ export class SnapshotCreateCommand implements ICommand> const res = await new SnapshotContentSaveCommand(this.element).execute(); contentId = res.id; words = res.words; + } else if (this.element instanceof HTMLImageElement) { + // TODO save image + contentId = await new SnapshotSaveImageCommand(this.element).execute(); } const screenshot = await ScreenshotFactory.takeScreenshot(rect, this.url); return { diff --git a/src/content-script/command/snapshot/snapshot-save-image.command.ts b/src/content-script/command/snapshot/snapshot-save-image.command.ts new file mode 100644 index 0000000..09f93b8 --- /dev/null +++ b/src/content-script/command/snapshot/snapshot-save-image.command.ts @@ -0,0 +1,45 @@ +/* + * This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension). + * Copyright (c) 2023 Michal Szczepanski. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +import { BrowserStorageWrapper } from '../../../common/service/browser.storage.wrapper'; +import { HtmlImgFactory } from '../../factory/html/html-img.factory'; +import { ICommand } from '../../../common/model/shared/common.dto'; +import { ObjNextContentIdCommand } from '../../../common/command/obj/content/obj-next-content-id.command'; +import { ObjSnapshotContentDto } from '../../../common/model/obj/obj-snapshot.dto'; +import { ObjectStoreKeys } from '../../../common/keys/object.store.keys'; + +export class SnapshotSaveImageCommand implements ICommand> { + constructor(private element: HTMLElement) {} + + async execute(): Promise { + const id = await new ObjNextContentIdCommand().execute(); + const key = `${ObjectStoreKeys.CONTENT_ID}:${id}`; + + const value = await HtmlImgFactory.computeImgValue(this.element as HTMLImageElement); + + await BrowserStorageWrapper.set(key, { + id, + html: ``, + htmlAttr: '', + css: { + css: [] + }, + video: [], + content: [] + }); + return id; + } +} diff --git a/src/options-ui/components/html-preview/html-preview.component.tsx b/src/options-ui/components/html-preview/html-preview.component.tsx index 4cfeed4..02f2366 100644 --- a/src/options-ui/components/html-preview/html-preview.component.tsx +++ b/src/options-ui/components/html-preview/html-preview.component.tsx @@ -60,11 +60,14 @@ export const HtmlPreviewComponent: FunctionComponent = () => { async (event, key, value) => { setIsPreLoading(true); setIsLoading(true); - if (value.canvas) { - renderCanvas(value); - } else { - const c = await new ObjGetSnapshotContentCommand(value.contentId).execute(); + let c: ObjSnapshotData | undefined = undefined; + if (value.contentId > 0) { + c = await new ObjGetSnapshotContentCommand(value.contentId).execute(); setContent(c); + } + if (value.canvas) { + renderCanvas(value, c); + } else { await renderSnapshot(value, c); } } @@ -75,8 +78,8 @@ export const HtmlPreviewComponent: FunctionComponent = () => { }; }); - const renderCanvas = (s: ObjSnapshotDto) => { - renderHeader(s, 0); + const renderCanvas = (s: ObjSnapshotDto, c?: ObjSnapshotData) => { + renderHeader(s, c?.size); if (!htmlRef.current) return; if (!containerRef.current) return; @@ -86,8 +89,14 @@ export const HtmlPreviewComponent: FunctionComponent = () => { iframe.height = '100%'; htmlRef.current.appendChild(iframe); if (!iframe.contentWindow) return; + let html = ``; + if (c) { + html += `${c.snapshot.html}`; + } else { + html += `screenshot`; + } - const html = `screenshot`; + html += ``; const doc = iframe.contentWindow.document; doc.write(html); doc.close(); @@ -96,9 +105,9 @@ export const HtmlPreviewComponent: FunctionComponent = () => { setIsLoading(false); }; - const renderSnapshot = async (s: ObjSnapshotDto, c: ObjSnapshotData): Promise => { - fnConsoleLog('SHOW HTML !!!', s, c, c.snapshot.css.css.length); - renderHeader(s, c.size); + const renderSnapshot = async (s: ObjSnapshotDto, c?: ObjSnapshotData): Promise => { + fnConsoleLog('SHOW HTML !!!', s, c, c?.snapshot.css.css.length); + renderHeader(s, c?.size); if (!htmlRef.current) return; if (!containerRef.current) return; if (!c) return; @@ -134,7 +143,7 @@ export const HtmlPreviewComponent: FunctionComponent = () => { setIsLoading(false); }; - const renderHeader = (s: ObjSnapshotDto, size: number): void => { + const renderHeader = (s: ObjSnapshotDto, size?: number): void => { if (sizeRef.current) { sizeRef.current.innerHTML = `${fnByteToMb(size)} MB`; }