feat: save full image when cropping rectangle
This commit is contained in:
parent
a9d79dde46
commit
a55ca90ae6
14
README.md
14
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 ```<!--css-build:shady-->```.
|
||||
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)
|
|
@ -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<void> => {
|
||||
|
@ -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);
|
||||
|
|
|
@ -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<Promise<ObjSnapshotDto>> {
|
||||
|
@ -32,6 +33,9 @@ export class SnapshotCreateCommand implements ICommand<Promise<ObjSnapshotDto>>
|
|||
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 {
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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<Promise<number>> {
|
||||
constructor(private element: HTMLElement) {}
|
||||
|
||||
async execute(): Promise<number> {
|
||||
const id = await new ObjNextContentIdCommand().execute();
|
||||
const key = `${ObjectStoreKeys.CONTENT_ID}:${id}`;
|
||||
|
||||
const value = await HtmlImgFactory.computeImgValue(this.element as HTMLImageElement);
|
||||
|
||||
await BrowserStorageWrapper.set<ObjSnapshotContentDto>(key, {
|
||||
id,
|
||||
html: `<img src="${value}" />`,
|
||||
htmlAttr: '',
|
||||
css: {
|
||||
css: []
|
||||
},
|
||||
video: [],
|
||||
content: []
|
||||
});
|
||||
return id;
|
||||
}
|
||||
}
|
|
@ -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 = `<body>`;
|
||||
if (c) {
|
||||
html += `${c.snapshot.html}`;
|
||||
} else {
|
||||
html += `<img src="${s.screenshot || ''}" alt="screenshot" />`;
|
||||
}
|
||||
|
||||
const html = `<body><img src="${s.screenshot || ''}" alt="screenshot" /></body>`;
|
||||
html += `</body>`;
|
||||
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<void> => {
|
||||
fnConsoleLog('SHOW HTML !!!', s, c, c.snapshot.css.css.length);
|
||||
renderHeader(s, c.size);
|
||||
const renderSnapshot = async (s: ObjSnapshotDto, c?: ObjSnapshotData): Promise<void> => {
|
||||
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`;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue