feat: show and manage pins on page snapshot

This commit is contained in:
Michal Szczepanski 2023-05-28 01:40:05 +02:00
parent 0830cdf945
commit 99368bf2e9
87 changed files with 648 additions and 467 deletions

@ -17,11 +17,12 @@
import { BrowserStorageWrapper } from '../../service/browser.storage.wrapper';
import { ICommand } from '../../model/shared/common.dto';
import { ObjDto } from '../../model/obj/obj.dto';
import { ObjPinDto } from '../../model/obj/obj-pin.dto';
import { ObjectStoreKeys } from '../../keys/object.store.keys';
export class ObjPinGetCommand<T> implements ICommand<Promise<ObjDto<T>>> {
export class ObjPinGetCommand implements ICommand<Promise<ObjDto<ObjPinDto>>> {
constructor(private id: number) {}
async execute(): Promise<ObjDto<T>> {
return await BrowserStorageWrapper.get<ObjDto<T>>(`${ObjectStoreKeys.PIN_ID}:${this.id}`);
async execute(): Promise<ObjDto<ObjPinDto>> {
return await BrowserStorageWrapper.get<ObjDto<ObjPinDto>>(`${ObjectStoreKeys.PIN_ID}:${this.id}`);
}
}

@ -27,7 +27,7 @@ export class ObjGetHrefCommand implements ICommand<Promise<ObjDto<ObjPageDataDto
const out: ObjDto<ObjPageDataDto>[] = [];
const pinIds = (await LinkHrefOriginStore.pinIds(this.data.href)).reverse();
for (const id of pinIds) {
const obj = await new ObjPinGetCommand<ObjPageDataDto>(id).execute();
const obj = await new ObjPinGetCommand(id).execute();
out.push(obj);
}
const ids = (await LinkHrefOriginStore.hrefIds(this.data.href)).reverse();

@ -30,7 +30,7 @@ export class PinGetHrefCommand implements ICommand<Promise<ObjDto<ObjPinDto>[]>>
const out: ObjDto<ObjPinDto>[] = [];
for (const id of pinIds) {
const obj = await new ObjPinGetCommand<ObjPinDto>(id).execute();
const obj = await new ObjPinGetCommand(id).execute();
// TODO revisit visible flag in pin.manager.ts in content scripts
if (!obj.local?.visible) continue;
out.push(obj);

@ -14,7 +14,8 @@
* 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 { applyStylesToElement } from '../../../common/style.utils';
import { PinDocument } from '../model/pin-view.model';
import { applyStylesToElement } from '../../../style.utils';
const elStyles = {
'background-color': '#ffffff',
@ -26,8 +27,9 @@ const elStyles = {
};
export class ContentButton {
private readonly btn = document.createElement('button');
constructor(private html: string, private clickCallback: () => void) {
private readonly btn: HTMLButtonElement;
constructor(private doc: PinDocument, private html: string, private clickCallback: () => void) {
this.btn = doc.document.createElement('button');
this.btn.innerHTML = html;
this.btn.addEventListener('click', clickCallback);
}

@ -14,12 +14,12 @@
* 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 { HtmlComponent, HtmlComponentFocusable } from '../../model/html.model';
import { HtmlComponent, HtmlComponentFocusable } from '../model/pin-view.model';
import { PinEditManager } from '../pin-edit.manager';
import { PinModel } from '../pin.model';
import { PinEditModel } from '../model/pin-edit.model';
import { ShowCommentButton } from './buttons/show-comment.button';
import { VideoTimeComponent } from './video-time/video-time.component';
import { applyStylesToElement } from '../../../common/style.utils';
import { applyStylesToElement } from '../../../style.utils';
const elStyles = {
height: '20px',
@ -30,14 +30,15 @@ const elStyles = {
};
export class BottomBarComponent implements HtmlComponent<HTMLElement>, HtmlComponentFocusable {
private el = document.createElement('div');
private el: HTMLDivElement;
private videoTime: VideoTimeComponent;
private addComment: ShowCommentButton;
constructor(edit: PinEditManager, private model: PinModel) {
constructor(edit: PinEditManager, private model: PinEditModel) {
this.el = model.doc.document.createElement('div');
this.videoTime = new VideoTimeComponent(model);
this.addComment = new ShowCommentButton(edit);
this.addComment = new ShowCommentButton(edit, model);
}
render(): HTMLDivElement {

@ -14,9 +14,10 @@
* 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 { HtmlComponent } from '../../../model/html.model';
import { HtmlComponent } from '../../model/pin-view.model';
import { PinEditManager } from '../../pin-edit.manager';
import { applyStylesToElement } from '../../../../common/style.utils';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
const elStyles = {
color: '#000000',
@ -28,11 +29,13 @@ const elStyles = {
};
export class ShowCommentButton implements HtmlComponent<HTMLElement> {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
private visible = false;
constructor(private edit: PinEditManager) {}
constructor(private edit: PinEditManager, model: PinEditModel) {
this.el = model.doc.document.createElement('div');
}
cleanup(): void {
this.el.removeEventListener('click', this.handleClick);

@ -14,11 +14,11 @@
* 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 { ObjVideoDataDto } from '../../../../common/model/obj/obj-snapshot.dto';
import { PinModel } from '../../pin.model';
import { XpathFactory } from '../../../../common/factory/xpath.factory';
import { applyStylesToElement } from '../../../../common/style.utils';
import { fnVideoSecondsTime } from '../../../../common/fn/fn-date-format';
import { ObjVideoDataDto } from '../../../../model/obj/obj-snapshot.dto';
import { PinEditModel } from '../../model/pin-edit.model';
import { XpathFactory } from '../../../../factory/xpath.factory';
import { applyStylesToElement } from '../../../../style.utils';
import { fnVideoSecondsTime } from '../../../../fn/fn-date-format';
const elStyles = {
display: 'flex',
@ -35,10 +35,11 @@ const titleStyle = {
};
export class VideoTimeComponent {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
private readonly video?: ObjVideoDataDto;
constructor(private model: PinModel) {
constructor(private model: PinEditModel) {
this.el = model.doc.document.createElement('div');
if (model.video) {
this.video = model.video[0];
}
@ -47,16 +48,16 @@ export class VideoTimeComponent {
renderVideo = () => {
if (!this.video) return;
this.el.innerHTML = '';
const title = document.createElement('div');
const title = this.model.doc.document.createElement('div');
applyStylesToElement(title, titleStyle);
title.innerText = 'video';
this.el.appendChild(title);
const from = document.createElement('div');
const from = this.model.doc.document.createElement('div');
from.innerText = fnVideoSecondsTime(this.video.currentTime);
this.el.appendChild(from);
const between = document.createElement('div');
const between = this.model.doc.document.createElement('div');
between.innerText = '-';
this.el.appendChild(between);
};
@ -75,7 +76,7 @@ export class VideoTimeComponent {
private handleNavigateClick = () => {
if (!this.video) return;
const value = XpathFactory.newXPathResult(this.video.xpath);
const value = XpathFactory.newXPathResult(document, this.video.xpath);
const node = value.singleNodeValue as HTMLVideoElement;
if (!node) return;
node.currentTime = this.video.currentTime;

@ -16,10 +16,10 @@
*/
import { DownloadCsvButton } from './download-buttons/download-csv.button';
import { DownloadImageButton } from './download-buttons/download-image.button';
import { HtmlComponent } from '../../model/html.model';
import { HtmlComponent } from '../model/pin-view.model';
import { PinEditManager } from '../pin-edit.manager';
import { PinModel } from '../pin.model';
import { applyStylesToElement } from '../../../common/style.utils';
import { PinEditModel } from '../model/pin-edit.model';
import { applyStylesToElement } from '../../../style.utils';
const downloadBarStyles = {
top: '-24px',
@ -34,14 +34,15 @@ const downloadBarStyles = {
};
export class DownloadBarComponent implements HtmlComponent<HTMLElement> {
private readonly el = document.createElement('div');
private readonly el: HTMLDivElement;
private visible = false;
private imageButton: DownloadImageButton;
private csvButton: DownloadCsvButton;
constructor(edit: PinEditManager, private model: PinModel) {
constructor(edit: PinEditManager, private model: PinEditModel) {
this.el = model.doc.document.createElement('div');
this.imageButton = new DownloadImageButton(edit, model);
this.csvButton = new DownloadCsvButton(model);
}

@ -14,11 +14,11 @@
* 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 { BusDownloadMessage, BusMessageType } from '../../../../common/model/bus.model';
import { BrowserApi } from '../../../../common/service/browser.api.wrapper';
import { PinModel } from '../../pin.model';
import { applyStylesToElement } from '../../../../common/style.utils';
import { fnUid } from '../../../../common/fn/fn-uid';
import { BusDownloadMessage, BusMessageType } from '../../../../model/bus.model';
import { BrowserApi } from '../../../../service/browser.api.wrapper';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
import { fnUid } from '../../../../fn/fn-uid';
const elStyles = {
'margin-right': '10px',
@ -28,9 +28,11 @@ const elStyles = {
};
export class DownloadCsvButton {
constructor(private model: PinModel) {}
private readonly el: HTMLDivElement;
private readonly el = document.createElement('div');
constructor(private model: PinEditModel) {
this.el = model.doc.document.createElement('div');
}
render(): HTMLElement {
this.el.innerText = 'csv';

@ -14,16 +14,15 @@
* 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 { BusDownloadMessage, BusMessageType } from '../../../../common/model/bus.model';
import { BrowserApi } from '../../../../common/service/browser.api.wrapper';
import { ContentSettingsStore } from '../../../store/content-settings.store';
import { ObjRectangleDto } from '../../../../common/model/obj/obj-utils.dto';
import { BusDownloadMessage, BusMessageType } from '../../../../model/bus.model';
import { BrowserApi } from '../../../../service/browser.api.wrapper';
import { ObjRectangleDto } from '../../../../model/obj/obj-utils.dto';
import { PinEditManager } from '../../pin-edit.manager';
import { PinModel } from '../../pin.model';
import { ScreenshotFactory } from '../../../../common/factory/screenshot.factory';
import { applyStylesToElement } from '../../../../common/style.utils';
import { fnB64toBlob } from '../../../../common/fn/fn-b64-to-blob';
import { fnUid } from '../../../../common/fn/fn-uid';
import { PinEditModel } from '../../model/pin-edit.model';
import { ScreenshotFactory } from '../../../../factory/screenshot.factory';
import { applyStylesToElement } from '../../../../style.utils';
import { fnB64toBlob } from '../../../../fn/fn-b64-to-blob';
import { fnUid } from '../../../../fn/fn-uid';
const elStyles = {
'margin-right': '10px',
@ -32,9 +31,11 @@ const elStyles = {
};
export class DownloadImageButton {
private readonly el = document.createElement('div');
private readonly el: HTMLDivElement;
constructor(private edit: PinEditManager, private model: PinModel) {}
constructor(private edit: PinEditManager, private model: PinEditModel) {
this.el = model.doc.document.createElement('div');
}
render(): HTMLElement {
this.el.innerText = 'image';
@ -62,20 +63,20 @@ export class DownloadImageButton {
if (this.model.canvas) {
rect = this.model.canvas.rect;
}
const screenshot = await ScreenshotFactory.takeScreenshot(rect);
const screenshot = await ScreenshotFactory.takeScreenshot(this.model.doc, rect);
await this.downloadScreenshot(screenshot);
this.edit.showScreenshot();
this.model.ref.style.border = ContentSettingsStore.borderStyle;
this.model.ref.style.borderRadius = ContentSettingsStore.borderRadius;
this.model.ref.style.border = this.model.doc.settings.borderStyle;
this.model.ref.style.borderRadius = this.model.doc.settings.borderRadius;
}, 0);
};
private downloadScreenshot = async (screenshot: string): Promise<void> => {
let url = '';
let filename = '';
if (ContentSettingsStore.screenshotFormat == 'jpeg') {
if (this.model.doc.settings.screenshotFormat == 'jpeg') {
url = window.URL.createObjectURL(fnB64toBlob(screenshot, 'image/jpeg'));
filename = `${fnUid()}.jpg`;
} else {

@ -14,7 +14,7 @@
* 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 { HtmlComponent, HtmlComponentFocusable } from '../../model/html.model';
import { HtmlComponent, HtmlComponentFocusable } from '../model/pin-view.model';
import { ContentButton } from '../base/content-button';
import { DrawBrushSizeButton } from './draw-buttons/draw-brush-size.button';
import { DrawColorPickerButton } from './draw-buttons/draw-color-picker.button';
@ -24,10 +24,10 @@ import { DrawLineButton } from './draw-buttons/draw-line.button';
import { DrawPencilButton } from './draw-buttons/draw-pencil.button';
import { DrawRedoButton } from './draw-buttons/draw-redo.button';
import { DrawTestButton } from './draw-buttons/draw-test.button';
import { DrawToolDto } from '../../../common/model/obj/obj-draw.dto';
import { DrawToolDto } from '../../../model/obj/obj-draw.dto';
import { DrawUndoButton } from './draw-buttons/draw-undo.button';
import { PinModel } from '../pin.model';
import { applyStylesToElement } from '../../../common/style.utils';
import { PinEditModel } from '../model/pin-edit.model';
import { applyStylesToElement } from '../../../style.utils';
const drawBarStyles = {
top: '-24px',
@ -44,7 +44,7 @@ const iconStyles = {
};
export class DrawBarComponent implements HtmlComponent<HTMLElement>, HtmlComponentFocusable {
private readonly el = document.createElement('div');
private readonly el: HTMLDivElement;
private visible = false;
@ -63,17 +63,18 @@ export class DrawBarComponent implements HtmlComponent<HTMLElement>, HtmlCompone
private readonly saveButton: ContentButton;
constructor(private model: PinModel) {
this.pencil = new DrawPencilButton(this);
this.line = new DrawLineButton(this);
this.fill = new DrawFillButton(this);
this.erase = new DrawEraseButton(this);
constructor(private model: PinEditModel) {
this.el = model.doc.document.createElement('div');
this.pencil = new DrawPencilButton(this, model);
this.line = new DrawLineButton(this, model);
this.fill = new DrawFillButton(this, model);
this.erase = new DrawEraseButton(this, model);
this.colorPicker = new DrawColorPickerButton(model);
this.sizeButton = new DrawBrushSizeButton(model);
this.undoButton = new DrawUndoButton(this);
this.redoButton = new DrawRedoButton(this);
this.undoButton = new DrawUndoButton(this, model);
this.redoButton = new DrawRedoButton(this, model);
// TODO move logic to model
this.model.draw.setUndoButton(this.undoButton);
@ -81,7 +82,7 @@ export class DrawBarComponent implements HtmlComponent<HTMLElement>, HtmlCompone
this.drawTest = new DrawTestButton(model);
this.saveButton = new ContentButton('save', this.handleSaveClick);
this.saveButton = new ContentButton(model.doc, 'save', this.handleSaveClick);
}
handleSaveClick = async (): Promise<void> => {

@ -14,20 +14,21 @@
* 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 { HtmlComponent, HtmlComponentFocusable } from '../../../model/html.model';
import { HtmlComponent, HtmlComponentFocusable } from '../../model/pin-view.model';
import { DrawBrushSize } from './draw-brush-size';
import { PinModel } from '../../pin.model';
import { applyStylesToElement } from '../../../../common/style.utils';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
import { iconButtonStyles } from '../../styles/icon-button.styles';
export class DrawBrushSizeButton implements HtmlComponent<HTMLElement>, HtmlComponentFocusable {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
private visible = false;
private sizeInput: DrawBrushSize;
constructor(private model: PinModel) {
constructor(private model: PinEditModel) {
this.el = model.doc.document.createElement('div');
this.sizeInput = new DrawBrushSize(model);
}

@ -14,9 +14,9 @@
* 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 { HtmlComponent } from '../../../model/html.model';
import { PinModel } from '../../pin.model';
import { applyStylesToElement } from '../../../../common/style.utils';
import { HtmlComponent } from '../../model/pin-view.model';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
const elStyles = {
width: '75px',
@ -37,11 +37,13 @@ const inputStyles = {
};
export class DrawBrushSize implements HtmlComponent<HTMLElement> {
private readonly el = document.createElement('div');
private readonly el: HTMLDivElement;
private readonly input: HTMLInputElement;
private input = document.createElement('input');
constructor(private model: PinModel) {}
constructor(private model: PinEditModel) {
this.el = model.doc.document.createElement('div');
this.input = model.doc.document.createElement('input');
}
render(): HTMLElement {
applyStylesToElement(this.el, elStyles);

@ -14,21 +14,22 @@
* 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 { HtmlComponent, HtmlComponentFocusable } from '../../../model/html.model';
import { HtmlComponent, HtmlComponentFocusable } from '../../model/pin-view.model';
import { DrawColorPicker } from './draw-color-picker';
import { PinModel } from '../../pin.model';
import { applyStylesToElement } from '../../../../common/style.utils';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
import { iconButtonStyles } from '../../styles/icon-button.styles';
export class DrawColorPickerButton implements HtmlComponent<HTMLElement>, HtmlComponentFocusable {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
private picker: DrawColorPicker;
private visible = false;
constructor(private model: PinModel) {
this.picker = new DrawColorPicker(model.rect, this);
constructor(private model: PinEditModel) {
this.el = model.doc.document.createElement('div');
this.picker = new DrawColorPicker(model, this);
}
render(): HTMLElement {

@ -16,9 +16,9 @@
*/
import { ColorUtils, RGBColor } from './draw-color.utils';
import { DrawColorPickerButton } from './draw-color-picker.button';
import { HtmlComponent } from '../../../model/html.model';
import { ObjRectangleDto } from '../../../../common/model/obj/obj-utils.dto';
import { applyStylesToElement } from '../../../../common/style.utils';
import { HtmlComponent } from '../../model/pin-view.model';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
const saturationStyles = {
background: 'linear-gradient(to right, #FFFFFF, #FF0000)',
@ -94,22 +94,30 @@ const colorInputStyles = {
};
export class DrawColorPicker implements HtmlComponent<HTMLElement> {
private readonly el = document.createElement('div');
private readonly saturation = document.createElement('div');
private readonly saturationSelector = document.createElement('div');
private readonly el: HTMLDivElement;
private readonly saturation: HTMLDivElement;
private readonly saturationSelector: HTMLDivElement;
private saturationMove = false;
private readonly brightness = document.createElement('div');
private readonly brightness: HTMLDivElement;
private readonly hue = document.createElement('div');
private readonly hueSelector = document.createElement('div');
private readonly hue: HTMLDivElement;
private readonly hueSelector: HTMLDivElement;
private hueMove = false;
private colorInput = document.createElement('input');
private readonly colorInput: HTMLInputElement;
private color: RGBColor = { r: 255, g: 0, b: 0 };
constructor(private rect: ObjRectangleDto, private colorDisplay: DrawColorPickerButton) {}
constructor(private model: PinEditModel, private colorDisplay: DrawColorPickerButton) {
this.el = model.doc.document.createElement('div');
this.saturation = model.doc.document.createElement('div');
this.saturationSelector = model.doc.document.createElement('div');
this.brightness = model.doc.document.createElement('div');
this.hue = model.doc.document.createElement('div');
this.hueSelector = model.doc.document.createElement('div');
this.colorInput = model.doc.document.createElement('input');
}
render(): HTMLElement {
applyStylesToElement(this.saturation, saturationStyles);

@ -15,17 +15,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { DrawBarComponent } from '../draw-bar.component';
import { DrawToolDto } from '../../../../common/model/obj/obj-draw.dto';
import { HtmlComponent } from '../../../model/html.model';
import { applyStylesToElement } from '../../../../common/style.utils';
import { DrawToolDto } from '../../../../model/obj/obj-draw.dto';
import { HtmlComponent } from '../../model/pin-view.model';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
import { iconButtonStyles } from '../../styles/icon-button.styles';
export class DrawEraseButton implements HtmlComponent<HTMLElement> {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
private selected = false;
constructor(private drawBar: DrawBarComponent) {}
constructor(private drawBar: DrawBarComponent, model: PinEditModel) {
this.el = model.doc.document.createElement('div');
}
render(): HTMLElement {
const stroke = this.selected ? '#ff0000' : '#000000';

@ -15,17 +15,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { DrawBarComponent } from '../draw-bar.component';
import { DrawToolDto } from '../../../../common/model/obj/obj-draw.dto';
import { HtmlComponent } from '../../../model/html.model';
import { applyStylesToElement } from '../../../../common/style.utils';
import { DrawToolDto } from '../../../../model/obj/obj-draw.dto';
import { HtmlComponent } from '../../model/pin-view.model';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
import { iconButtonStyles } from '../../styles/icon-button.styles';
export class DrawFillButton implements HtmlComponent<HTMLElement> {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
private selected = false;
constructor(private drawBar: DrawBarComponent) {}
constructor(private drawBar: DrawBarComponent, model: PinEditModel) {
this.el = model.doc.document.createElement('div');
}
render(): HTMLElement {
const fill = this.selected ? '#ff0000' : '#000000';

@ -15,17 +15,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { DrawBarComponent } from '../draw-bar.component';
import { DrawToolDto } from '../../../../common/model/obj/obj-draw.dto';
import { HtmlComponent } from '../../../model/html.model';
import { applyStylesToElement } from '../../../../common/style.utils';
import { DrawToolDto } from '../../../../model/obj/obj-draw.dto';
import { HtmlComponent } from '../../model/pin-view.model';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
import { iconButtonStyles } from '../../styles/icon-button.styles';
export class DrawLineButton implements HtmlComponent<HTMLElement> {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
private selected = false;
constructor(private drawBar: DrawBarComponent) {}
constructor(private drawBar: DrawBarComponent, model: PinEditModel) {
this.el = model.doc.document.createElement('div');
}
render(): HTMLElement {
const stroke = this.selected ? '#ff0000' : '#000000';

@ -15,17 +15,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { DrawBarComponent } from '../draw-bar.component';
import { DrawToolDto } from '../../../../common/model/obj/obj-draw.dto';
import { HtmlComponent } from '../../../model/html.model';
import { applyStylesToElement } from '../../../../common/style.utils';
import { DrawToolDto } from '../../../../model/obj/obj-draw.dto';
import { HtmlComponent } from '../../model/pin-view.model';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
import { iconButtonStyles } from '../../styles/icon-button.styles';
export class DrawPencilButton implements HtmlComponent<HTMLElement> {
private el = document.createElement('div');
private readonly el;
private selected = false;
constructor(private drawBar: DrawBarComponent) {}
constructor(private drawBar: DrawBarComponent, model: PinEditModel) {
this.el = model.doc.document.createElement('div');
}
render(): HTMLElement {
const fill = this.selected ? '#ff0000' : '#000000';

@ -15,16 +15,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { DrawBarComponent } from '../draw-bar.component';
import { HtmlComponent } from '../../../model/html.model';
import { applyStylesToElement } from '../../../../common/style.utils';
import { HtmlComponent } from '../../model/pin-view.model';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
import { iconButtonStyles } from '../../styles/icon-button.styles';
export class DrawRedoButton implements HtmlComponent<HTMLElement> {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
private canRedo = false;
constructor(private drawBar: DrawBarComponent) {}
constructor(private drawBar: DrawBarComponent, model: PinEditModel) {
this.el = model.doc.document.createElement('div');
}
render(): HTMLElement {
const fill = this.canRedo ? '#ff0000' : '#000000';

@ -14,15 +14,17 @@
* 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 { HtmlComponent } from '../../../model/html.model';
import { PinModel } from '../../pin.model';
import { applyStylesToElement } from '../../../../common/style.utils';
import { HtmlComponent } from '../../model/pin-view.model';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
import { iconButtonStyles } from '../../styles/icon-button.styles';
export class DrawTestButton implements HtmlComponent<HTMLElement> {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
constructor(private model: PinModel) {}
constructor(private model: PinEditModel) {
this.el = model.doc.document.createElement('div');
}
render(): HTMLElement {
this.el.innerText = 'test';

@ -15,16 +15,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { DrawBarComponent } from '../draw-bar.component';
import { HtmlComponent } from '../../../model/html.model';
import { applyStylesToElement } from '../../../../common/style.utils';
import { HtmlComponent } from '../../model/pin-view.model';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
import { iconButtonStyles } from '../../styles/icon-button.styles';
export class DrawUndoButton implements HtmlComponent<HTMLElement> {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
private canUndo = false;
constructor(private drawBar: DrawBarComponent) {}
constructor(private drawBar: DrawBarComponent, model: PinEditModel) {
this.el = model.doc.document.createElement('div');
}
render(): HTMLElement {
const fill = this.canUndo ? '#ff0000' : '#000000';

@ -14,19 +14,20 @@
* 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 { HtmlComponent, HtmlComponentFocusable } from '../model/html.model';
import { HtmlComponent, HtmlComponentFocusable } from './model/pin-view.model';
import { DrawAreaComponent } from './draw/draw-area.component';
import { ObjRectangleDto } from '../../common/model/obj/obj-utils.dto';
import { PinModel } from './pin.model';
import { applyStylesToElement } from '../../common/style.utils';
import { ObjRectangleDto } from '../../model/obj/obj-utils.dto';
import { PinEditModel } from './model/pin-edit.model';
import { applyStylesToElement } from '../../style.utils';
export class DrawContainerComponent implements HtmlComponent<HTMLElement>, HtmlComponentFocusable {
private readonly el = document.createElement('div');
private readonly el: HTMLDivElement;
readonly drawArea: DrawAreaComponent;
private rect: ObjRectangleDto;
constructor(private model: PinModel) {
constructor(private model: PinEditModel) {
this.el = model.doc.document.createElement('div');
this.rect = model.rect;
this.drawArea = new DrawAreaComponent(model);

@ -14,15 +14,15 @@
* 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 { DrawToolDto, ObjDrawDataDto } from '../../../common/model/obj/obj-draw.dto';
import { DrawToolDto, ObjDrawDataDto } from '../../../model/obj/obj-draw.dto';
import { EraserDraw } from './tool/eraser.draw';
import { FillDraw } from './tool/fill.draw';
import { LineDraw } from './tool/line.draw';
import { ObjPointDto } from '../../../common/model/obj/obj-utils.dto';
import { ObjPointDto } from '../../../model/obj/obj-utils.dto';
import { PencilDraw } from './tool/pencil.draw';
import { PinModel } from '../pin.model';
import { applyStylesToElement } from '../../../common/style.utils';
import { fnConsoleLog } from '../../../common/fn/fn-console';
import { PinEditModel } from '../model/pin-edit.model';
import { applyStylesToElement } from '../../../style.utils';
import { fnConsoleLog } from '../../../fn/fn-console';
const canvasStyles = {
position: 'absolute',
@ -31,8 +31,8 @@ const canvasStyles = {
};
export class DrawAreaComponent {
readonly rasterCanvas: HTMLCanvasElement = document.createElement('canvas');
readonly drawCanvas: HTMLCanvasElement = document.createElement('canvas');
readonly rasterCanvas: HTMLCanvasElement;
readonly drawCanvas: HTMLCanvasElement;
private readonly drawCtx: CanvasRenderingContext2D | null;
private readonly rasterCtx: CanvasRenderingContext2D | null;
@ -41,7 +41,9 @@ export class DrawAreaComponent {
private readonly drawData: ObjDrawDataDto[] = [];
private drawRedoData: ObjDrawDataDto[] = [];
constructor(private model: PinModel) {
constructor(private model: PinEditModel) {
this.rasterCanvas = model.doc.document.createElement('canvas');
this.drawCanvas = model.doc.document.createElement('canvas');
this.drawCtx = this.drawCanvas.getContext('2d');
this.rasterCtx = this.rasterCanvas.getContext('2d');
if (!model.drawData) {

@ -14,7 +14,7 @@
* 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 { ObjPointDto } from '../../../../common/model/obj/obj-utils.dto';
import { ObjPointDto } from '../../../../model/obj/obj-utils.dto';
export class EraserDraw {
private static points: ObjPointDto[];

@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { ColorUtils, RGBColor } from '../../draw-bar/draw-buttons/draw-color.utils';
import { ObjPointDto } from '../../../../common/model/obj/obj-utils.dto';
import { ObjPointDto } from '../../../../model/obj/obj-utils.dto';
export class FillDraw {
static fill(from: ObjPointDto, color: string, ctx: CanvasRenderingContext2D): ObjPointDto[] {

@ -14,7 +14,7 @@
* 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 { ObjPointDto } from '../../../../common/model/obj/obj-utils.dto';
import { ObjPointDto } from '../../../../model/obj/obj-utils.dto';
export class LineDraw {
private static color: string;

@ -14,7 +14,7 @@
* 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 { ObjPointDto } from '../../../../common/model/obj/obj-utils.dto';
import { ObjPointDto } from '../../../../model/obj/obj-utils.dto';
export class PencilDraw {
private static points: ObjPointDto[] = [];

@ -14,9 +14,9 @@
* 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 { HtmlComponent, HtmlComponentFocusable } from '../../model/html.model';
import { HtmlPrettifyFactory } from '../../factory/html-prettify.factory';
import { applyStylesToElement } from '../../../common/style.utils';
import { HtmlComponent, HtmlComponentFocusable, PinDocument } from '../model/pin-view.model';
import { HtmlPrettifyFactory } from '../../../factory/html-prettify.factory';
import { applyStylesToElement } from '../../../style.utils';
const elStyle = {
'margin-top': '48px',
@ -45,19 +45,24 @@ const btnStyle = {
};
export class HtmlEditComponent implements HtmlComponent<HTMLElement>, HtmlComponentFocusable {
private readonly el = document.createElement('div');
private readonly el: HTMLDivElement;
private text = document.createElement('textarea');
private action = document.createElement('div');
private saveButton = document.createElement('button');
private rollbackButton = document.createElement('button');
private text: HTMLTextAreaElement;
private action: HTMLDivElement;
private saveButton: HTMLButtonElement;
private rollbackButton: HTMLButtonElement;
public originalHtml: string;
private htmlValue = '';
constructor(private ref: HTMLElement) {
constructor(private ref: HTMLElement, doc: PinDocument) {
// TODO fix parent icon click
this.originalHtml = ref.innerHTML;
this.el = doc.document.createElement('div');
this.text = doc.document.createElement('textarea');
this.action = doc.document.createElement('div');
this.saveButton = doc.document.createElement('button');
this.rollbackButton = doc.document.createElement('button');
}
get value(): string | undefined {

@ -14,14 +14,14 @@
* 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 { DrawToolDto, ObjDrawDataDto, ObjDrawDto } from '../../common/model/obj/obj-draw.dto';
import { DrawAreaComponent } from './draw/draw-area.component';
import { DrawRedoButton } from './draw-bar/draw-buttons/draw-redo.button';
import { DrawUndoButton } from './draw-bar/draw-buttons/draw-undo.button';
import { ObjDrawListDto } from '../../common/model/obj/obj-pin.dto';
import { PinModel } from './pin.model';
import { PinUpdateCommand } from '../../common/command/pin/pin-update.command';
import { fnSha256 } from '../../common/fn/fn-sha256';
import { DrawToolDto, ObjDrawDataDto, ObjDrawDto } from '../../../model/obj/obj-draw.dto';
import { DrawAreaComponent } from '../draw/draw-area.component';
import { DrawRedoButton } from '../draw-bar/draw-buttons/draw-redo.button';
import { DrawUndoButton } from '../draw-bar/draw-buttons/draw-undo.button';
import { ObjDrawListDto } from '../../../model/obj/obj-pin.dto';
import { PinEditModel } from './pin-edit.model';
import { PinUpdateCommand } from '../../../command/pin/pin-update.command';
import { fnSha256 } from '../../../fn/fn-sha256';
export class DrawModel {
tool = DrawToolDto.Pencil;
@ -76,7 +76,7 @@ export class DrawModel {
this.draw.data[0].data = data;
}
async saveDraw(model: PinModel) {
async saveDraw(model: PinEditModel) {
this.draw.data[0].hash = fnSha256(JSON.stringify(this.draw.data[0].data));
await new PinUpdateCommand(model.object).execute();
}

@ -14,16 +14,18 @@
* 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 { ObjCanvasDto, ObjVideoDataDto } from '../../common/model/obj/obj-snapshot.dto';
import { ObjCommentListDto, ObjPinDto, PinBorderDataDto } from '../../common/model/obj/obj-pin.dto';
import { ObjDto, ObjLocalDto, ObjUrlDto } from '../../common/model/obj/obj.dto';
import { ObjCanvasDto, ObjVideoDataDto } from '../../../model/obj/obj-snapshot.dto';
import { ObjCommentListDto, ObjPinDto, PinBorderDataDto } from '../../../model/obj/obj-pin.dto';
import { ObjDto, ObjLocalDto, ObjUrlDto } from '../../../model/obj/obj.dto';
import { DrawModel } from './draw.model';
import { ObjDrawDto } from '../../common/model/obj/obj-draw.dto';
import { ObjRectangleDto } from '../../common/model/obj/obj-utils.dto';
import { PinMouseManager } from './pin-mouse.manager';
import { PinPointFactory } from '../factory/pin-point.factory';
import { ObjDrawDto } from '../../../model/obj/obj-draw.dto';
import { ObjRectangleDto } from '../../../model/obj/obj-utils.dto';
import { PinComponent } from '../pin.component';
import { PinDocument } from './pin-view.model';
import { PinMouseManager } from '../pin-mouse.manager';
import { PinPointFactory } from '../../../factory/pin-point.factory';
export class PinModel {
export class PinEditModel {
private readonly obj: ObjDto<ObjPinDto>;
private refValue: HTMLElement;
private rectValue: ObjRectangleDto;
@ -34,9 +36,9 @@ export class PinModel {
constructor(
object: ObjDto<ObjPinDto>,
refValue: HTMLElement,
readonly top: HTMLDivElement,
readonly bottom: HTMLDivElement,
private mouseManager: PinMouseManager
private component: PinComponent,
private mouseManager: PinMouseManager,
readonly doc: PinDocument
) {
this.obj = object;
this.refValue = refValue;
@ -44,6 +46,14 @@ export class PinModel {
this.draw = new DrawModel(this.obj.data.draw);
}
get top(): HTMLDivElement {
return this.component.top;
}
get bottom(): HTMLDivElement {
return this.component.bottom;
}
get rect(): ObjRectangleDto {
return this.rectValue;
}
@ -103,4 +113,8 @@ export class PinModel {
get object(): ObjDto<ObjPinDto> {
return this.obj;
}
remove() {
this.component.cleanup();
}
}

@ -0,0 +1,42 @@
/*
* 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 { PinEditModel } from './pin-edit.model';
import { SettingsConfig } from '../../../environment';
export interface PinDocument {
document: Document;
window: Window;
settings: SettingsConfig;
}
export interface HtmlComponentFocusable {
focusin(): void;
focusout(): void;
}
export interface PageComponent {
model: PinEditModel; // TODO REMOVE here
focus(goto: boolean): void;
cleanup(): void;
resize(): void;
render(): any;
isHidden(): boolean;
}
export interface HtmlComponent<T> {
render(): T;
}

@ -14,18 +14,20 @@
* 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 { HtmlComponent } from '../../../model/html.model';
import { PinModel } from '../../pin.model';
import { PinUpdateCommand } from '../../../../common/command/pin/pin-update.command';
import { XpathFactory } from '../../../../common/factory/xpath.factory';
import { applyStylesToElement } from '../../../../common/style.utils';
import { fnConsoleLog } from '../../../../common/fn/fn-console';
import { HtmlComponent } from '../../model/pin-view.model';
import { PinEditModel } from '../../model/pin-edit.model';
import { PinUpdateCommand } from '../../../../command/pin/pin-update.command';
import { XpathFactory } from '../../../../factory/xpath.factory';
import { applyStylesToElement } from '../../../../style.utils';
import { fnConsoleLog } from '../../../../fn/fn-console';
import { iconButtonStyles } from '../../styles/icon-button.styles';
export class EditBarParentButton implements HtmlComponent<HTMLElement> {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
constructor(private model: PinModel, private resizeCallback: () => void) {}
constructor(private model: PinEditModel, private resizeCallback: () => void) {
this.el = model.doc.document.createElement('div');
}
render(): HTMLElement {
this.el.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" fill="#000000" height="24" viewBox="0 0 24 24" width="24">

@ -14,21 +14,17 @@
* 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 { ObjDto, ObjTypeDto } from '../../../../common/model/obj/obj.dto';
import { BrowserStorageWrapper } from '../../../../common/service/browser.storage.wrapper';
import { HtmlComponent } from '../../../model/html.model';
import { LinkHrefOriginStore } from '../../../../common/store/link-href-origin.store';
import { ObjPageDto } from '../../../../common/model/obj/obj-pin.dto';
import { ObjectStoreKeys } from '../../../../common/keys/object.store.keys';
import { PinModel } from '../../pin.model';
import { PinStore } from '../../../store/pin.store';
import { applyStylesToElement } from '../../../../common/style.utils';
import { HtmlComponent } from '../../model/pin-view.model';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
import { iconButtonStyles } from '../../styles/icon-button.styles';
export class EditBarSnapshotButton implements HtmlComponent<HTMLElement> {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
constructor(private model: PinModel) {}
constructor(model: PinEditModel, private editCallback: () => void) {
this.el = model.doc.document.createElement('div');
}
render(): HTMLElement {
this.el.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" fill="#777777" height="24" viewBox="0 0 24 24" width="24">
@ -54,21 +50,8 @@ export class EditBarSnapshotButton implements HtmlComponent<HTMLElement> {
this.el.removeEventListener('click', this.handleClick);
}
private handleClick = async () => {
private handleClick = () => {
this.el.removeEventListener('click', this.handleClick);
const o = this.model.object;
const obj: ObjDto<ObjPageDto> = {
...o,
data: { snapshot: o.data.snapshot, draw: { data: [] }, comments: { data: [] } }
};
obj.type = ObjTypeDto.PageElementSnapshot;
await LinkHrefOriginStore.pinDel(obj.data.snapshot.url, obj.id);
const key = `${ObjectStoreKeys.OBJECT_ID}:${obj.id}`;
await BrowserStorageWrapper.set(key, obj);
// Remove from store
PinStore.delByUid(this.model.object.id);
this.editCallback();
};
}

@ -14,11 +14,11 @@
* 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 { HtmlComponent, HtmlComponentFocusable } from '../../model/html.model';
import { HtmlComponent, HtmlComponentFocusable } from '../model/pin-view.model';
import { EditBarParentButton } from './edit-bar-buttons/edit-bar-parent.button';
import { EditBarSnapshotButton } from './edit-bar-buttons/edit-bar-snapshot.button';
import { PinModel } from '../pin.model';
import { applyStylesToElement } from '../../../common/style.utils';
import { PinEditModel } from '../model/pin-edit.model';
import { applyStylesToElement } from '../../../style.utils';
const editBarStyles = {
top: '-24px',
@ -31,16 +31,17 @@ const editBarStyles = {
};
export class PinEditBarComponent implements HtmlComponent<HTMLElement>, HtmlComponentFocusable {
private readonly el = document.createElement('div');
private readonly el;
private visible = false;
private parentButton: EditBarParentButton;
private snapshotButton: EditBarSnapshotButton;
private readonly snapshotButton?: EditBarSnapshotButton;
constructor(private model: PinModel, resizeCallback: () => void) {
constructor(private model: PinEditModel, resizeCallback: () => void, editCallback?: () => void) {
this.el = model.doc.document.createElement('div');
this.parentButton = new EditBarParentButton(model, resizeCallback);
this.snapshotButton = new EditBarSnapshotButton(model);
if (editCallback) this.snapshotButton = new EditBarSnapshotButton(model, editCallback);
}
render(): HTMLElement {
@ -49,7 +50,7 @@ export class PinEditBarComponent implements HtmlComponent<HTMLElement>, HtmlComp
this.adjustTop();
this.el.appendChild(this.snapshotButton.render());
if (this.snapshotButton) this.el.appendChild(this.snapshotButton.render());
this.el.appendChild(this.parentButton.render());
return this.el;
@ -57,7 +58,7 @@ export class PinEditBarComponent implements HtmlComponent<HTMLElement>, HtmlComp
cleanup(): void {
this.parentButton.cleanup();
this.snapshotButton.cleanup();
if (this.snapshotButton) this.snapshotButton.cleanup();
}
focusin(): void {

@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { PinComponent } from './pin.component';
import { fnConsoleLog } from '../../common/fn/fn-console';
import { fnConsoleLog } from '../../fn/fn-console';
enum VisibleState {
None = 1,

@ -14,31 +14,30 @@
* 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 { HtmlComponent, PageComponent } from '../model/html.model';
import { HtmlComponent, PageComponent, PinDocument } from './model/pin-view.model';
import { BottomBarComponent } from './bottom-bar/bottom-bar.component';
import { ContentSettingsStore } from '../store/content-settings.store';
import { DownloadBarComponent } from './download-bar/download-bar.component';
import { DrawBarComponent } from './draw-bar/draw-bar.component';
import { DrawContainerComponent } from './draw-container.component';
import { DrawToolDto } from '../../common/model/obj/obj-draw.dto';
import { ObjDto } from '../../common/model/obj/obj.dto';
import { ObjPinDto } from '../../common/model/obj/obj-pin.dto';
import { DrawToolDto } from '../../model/obj/obj-draw.dto';
import { ObjDto } from '../../model/obj/obj.dto';
import { ObjPinDto } from '../../model/obj/obj-pin.dto';
import { PinEditBarComponent } from './pin-edit-bar/pin-edit-bar.component';
import { PinEditManager } from './pin-edit.manager';
import { PinModel } from './pin.model';
import { PinEditModel } from './model/pin-edit.model';
import { PinMouseManager } from './pin-mouse.manager';
import { PinPointFactory } from '../factory/pin-point.factory';
import { PinPointFactory } from '../../factory/pin-point.factory';
import { TextContainerComponent } from './text/text-container.component';
import { TopBarComponent } from './top-bar/top-bar.component';
import { applyStylesToElement } from '../../common/style.utils';
import { isElementHiddenFn } from '../fn/is-element-hidden.fn';
import { applyStylesToElement } from '../../style.utils';
import { fnIsElementHidden } from '../../fn/fn-is-element-hidden';
import { fnScrollToElement } from '../../fn/fn-scroll-to-element';
import { pinStyles } from './styles/pin.styles';
import { scrollToElementFn } from '../fn/scroll-to-element.fn';
export class PinComponent implements HtmlComponent<void>, PageComponent {
readonly top = document.createElement('div');
readonly bottom = document.createElement('div');
readonly border = document.createElement('div');
readonly top: HTMLDivElement;
readonly bottom: HTMLDivElement;
readonly border: HTMLDivElement;
private readonly mouseManager: PinMouseManager;
@ -55,11 +54,14 @@ export class PinComponent implements HtmlComponent<void>, PageComponent {
readonly edit: PinEditManager;
readonly model: PinModel;
readonly model: PinEditModel;
constructor(ref: HTMLElement, object: ObjDto<ObjPinDto>) {
constructor(ref: HTMLElement, object: ObjDto<ObjPinDto>, private doc: PinDocument, toSnapshotHandler?: () => void) {
this.top = this.doc.document.createElement('div');
this.bottom = this.doc.document.createElement('div');
this.border = this.doc.document.createElement('div');
this.mouseManager = new PinMouseManager(this.top, this.bottom, this.handleMouseOver, this.handleMouseOut);
this.model = new PinModel(object, ref, this.top, this.bottom, this.mouseManager);
this.model = new PinEditModel(object, ref, this, this.mouseManager, doc);
this.edit = new PinEditManager(this);
this.topBar = new TopBarComponent(this.edit, this.model);
@ -71,11 +73,11 @@ export class PinComponent implements HtmlComponent<void>, PageComponent {
this.downloadBar = new DownloadBarComponent(this.edit, this.model);
this.editBar = new PinEditBarComponent(this.model, this.resize);
this.editBar = new PinEditBarComponent(this.model, this.resize, toSnapshotHandler);
}
focus(): void {
scrollToElementFn(this.model.ref, this.model.ref.getBoundingClientRect().height / 2);
fnScrollToElement(this.model.ref, this.model.ref.getBoundingClientRect().height / 2);
this.handleMouseOver();
}
@ -117,8 +119,8 @@ export class PinComponent implements HtmlComponent<void>, PageComponent {
// Pin Edit
this.top.appendChild(this.editBar.render());
document.body.appendChild(this.top);
document.body.appendChild(this.bottom);
this.doc.document.body.appendChild(this.top);
this.doc.document.body.appendChild(this.bottom);
this.mouseManager.start(this.model.ref);
this.handleMouseOut();
@ -130,11 +132,11 @@ export class PinComponent implements HtmlComponent<void>, PageComponent {
this.border.style.pointerEvents = 'none';
this.border.style.top = `${this.model.rect.y}px`;
this.border.style.left = `${this.model.rect.x}px`;
this.border.style.border = ContentSettingsStore.newElementStyle;
document.body.appendChild(this.border);
this.border.style.border = this.doc.settings.newElementStyle;
this.doc.document.body.appendChild(this.border);
} else {
this.model.ref.style.border = ContentSettingsStore.borderStyle;
this.model.ref.style.borderRadius = ContentSettingsStore.borderRadius;
this.model.ref.style.border = this.doc.settings.borderStyle;
this.model.ref.style.borderRadius = this.doc.settings.borderRadius;
}
}
@ -178,7 +180,7 @@ export class PinComponent implements HtmlComponent<void>, PageComponent {
private timeoutId = -1;
private handleMouseOver = () => {
window.clearTimeout(this.timeoutId);
this.doc.window.clearTimeout(this.timeoutId);
if (!this.edit.isScreenshot) this.topBar.focusin();
if (!this.edit.isScreenshot) this.bottomBar.focusin();
@ -186,29 +188,29 @@ export class PinComponent implements HtmlComponent<void>, PageComponent {
this.drawBar.focusin();
this.downloadBar.focusin();
this.editBar.focusin();
if (ContentSettingsStore.borderStyle === ContentSettingsStore.borderNone) {
this.model.ref.style.border = ContentSettingsStore.newElementStyle;
if (this.doc.settings.borderStyle === 'none') {
this.model.ref.style.border = this.doc.settings.newElementStyle;
}
if (!this.model.canvas) this.timeoutId = window.setTimeout(this.handleMouseOut, 3000);
if (!this.model.canvas) this.timeoutId = this.doc.window.setTimeout(this.handleMouseOut, 3000);
};
private handleMouseOut = () => {
window.clearTimeout(this.timeoutId);
this.doc.window.clearTimeout(this.timeoutId);
if (this.model.canvas) return;
this.timeoutId = window.setTimeout(() => {
this.timeoutId = this.doc.window.setTimeout(() => {
this.topBar.focusout();
this.bottomBar.focusout();
this.drawBar.focusout();
this.downloadBar.focusout();
this.editBar.focusout();
if (ContentSettingsStore.borderStyle === ContentSettingsStore.borderNone) {
this.model.ref.style.border = ContentSettingsStore.borderNone;
if (this.doc.settings.borderStyle === 'none') {
this.model.ref.style.border = 'none';
}
this.model.ref.style.border = ContentSettingsStore.borderStyle;
this.model.ref.style.border = this.doc.settings.borderStyle;
}, 2000);
};
isHidden(): boolean {
return isElementHiddenFn(this.model.ref);
return fnIsElementHidden(this.model.ref);
}
}

@ -16,13 +16,14 @@
*/
import { Command } from 'prosemirror-state';
import { EditorView } from 'prosemirror-view';
import { applyStylesToElement } from '../../../../common/style.utils';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
import { editorBarButtonStyles } from './editor-bar-button.styles';
import { schema } from 'prosemirror-markdown';
import { toggleMark } from 'prosemirror-commands';
export class TextBoldButton {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
private boldCommand?: Command;
private clicked = false;
@ -30,6 +31,10 @@ export class TextBoldButton {
private editor?: EditorView;
constructor(model: PinEditModel) {
this.el = model.doc.document.createElement('div');
}
setEditor(editor: EditorView | undefined): void {
this.editor = editor;
}

@ -16,23 +16,28 @@
*/
import { Command } from 'prosemirror-state';
import { EditorView } from 'prosemirror-view';
import { applyStylesToElement } from '../../../../common/style.utils';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
import { editorBarButtonStyles } from './editor-bar-button.styles';
import { schema } from 'prosemirror-markdown';
import { wrapInList } from 'prosemirror-schema-list';
export class TextBulletListButton {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
private listCommand?: Command;
private editor?: EditorView;
constructor(private model: PinEditModel) {
this.el = model.doc.document.createElement('div');
}
setEditor(editor: EditorView | undefined): void {
this.editor = editor;
}
render(): HTMLDivElement {
const li = document.createElement('li');
const li = this.model.doc.document.createElement('li');
li.style.paddingLeft = '5px';
li.style.paddingBottom = '10px';
this.el.appendChild(li);

@ -16,13 +16,14 @@
*/
import { Command } from 'prosemirror-state';
import { EditorView } from 'prosemirror-view';
import { applyStylesToElement } from '../../../../common/style.utils';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
import { editorBarButtonStyles } from './editor-bar-button.styles';
import { schema } from 'prosemirror-markdown';
import { toggleMark } from 'prosemirror-commands';
export class TextItalicButton {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
private italicCommand?: Command;
private clicked = false;
@ -30,6 +31,10 @@ export class TextItalicButton {
private editor?: EditorView;
constructor(private model: PinEditModel) {
this.el = model.doc.document.createElement('div');
}
setEditor(editor: EditorView | undefined): void {
this.editor = editor;
}

@ -16,17 +16,22 @@
*/
import { Command } from 'prosemirror-state';
import { EditorView } from 'prosemirror-view';
import { applyStylesToElement } from '../../../../common/style.utils';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
import { editorBarButtonStyles } from './editor-bar-button.styles';
import { schema } from 'prosemirror-markdown';
import { wrapInList } from 'prosemirror-schema-list';
export class TextNumericListButton {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
private listCommand?: Command;
private editor?: EditorView;
constructor(model: PinEditModel) {
this.el = model.doc.document.createElement('div');
}
setEditor(editor: EditorView | undefined): void {
this.editor = editor;
}

@ -16,14 +16,15 @@
*/
import { EditorState } from 'prosemirror-state';
import { EditorView } from 'prosemirror-view';
import { HtmlComponent } from '../../model/html.model';
import { ObjRectangleDto } from '../../../common/model/obj/obj-utils.dto';
import { HtmlComponent } from '../model/pin-view.model';
import { ObjRectangleDto } from '../../../model/obj/obj-utils.dto';
import { PinEditModel } from '../model/pin-edit.model';
import { TextBoldButton } from './text-bar-buttons/text-bold.button';
import { TextBulletListButton } from './text-bar-buttons/text-bullet-list.button';
import { TextItalicButton } from './text-bar-buttons/text-italic.button';
import { TextNumericListButton } from './text-bar-buttons/text-numeric-list.button';
import { applyStylesToElement } from '../../../common/style.utils';
import { fnConsoleLog } from '../../../common/fn/fn-console';
import { applyStylesToElement } from '../../../style.utils';
import { fnConsoleLog } from '../../../fn/fn-console';
const elStyles = {
display: 'flex',
@ -35,7 +36,7 @@ const elStyles = {
};
export class TextBarComponent implements HtmlComponent<HTMLElement> {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
private bold: TextBoldButton;
private italic: TextItalicButton;
@ -49,11 +50,12 @@ export class TextBarComponent implements HtmlComponent<HTMLElement> {
private editor?: EditorView;
constructor() {
this.bold = new TextBoldButton();
this.italic = new TextItalicButton();
this.bulletList = new TextBulletListButton();
this.numericList = new TextNumericListButton();
constructor(model: PinEditModel) {
this.el = model.doc.document.createElement('div');
this.bold = new TextBoldButton(model);
this.italic = new TextItalicButton(model);
this.bulletList = new TextBulletListButton(model);
this.numericList = new TextNumericListButton(model);
}
setEditor(editor: EditorView | undefined): void {

@ -16,7 +16,8 @@
*/
import { CommentEditButton } from './comment-edit.button';
import { CommentRemoveButton } from './comment-remove.button';
import { applyStylesToElement } from '../../../../common/style.utils';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
const elStyles = {
margin: '10px',
@ -25,12 +26,14 @@ const elStyles = {
};
export class CommentActionBar {
private el = document.createElement('div');
constructor(private removeCallback: () => void, private editCallback: () => void) {}
private readonly el: HTMLDivElement;
constructor(private model: PinEditModel, private removeCallback: () => void, private editCallback: () => void) {
this.el = model.doc.document.createElement('div');
}
render(): HTMLElement {
const r = new CommentRemoveButton(this.removeCallback);
const e = new CommentEditButton(this.editCallback);
const r = new CommentRemoveButton(this.model, this.removeCallback);
const e = new CommentEditButton(this.model, this.editCallback);
this.el.appendChild(e.render());
this.el.appendChild(r.render());
applyStylesToElement(this.el, elStyles);

@ -14,12 +14,16 @@
* 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 { HtmlComponent } from '../../../model/html.model';
import { HtmlComponent } from '../../model/pin-view.model';
import { PinEditModel } from '../../model/pin-edit.model';
export class CommentEditButton implements HtmlComponent<HTMLElement> {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
constructor(private editCallback: () => void) {}
constructor(model: PinEditModel, private editCallback: () => void) {
this.el = model.doc.document.createElement('div');
}
render(): HTMLElement {
this.el.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" fill="#000000" height="16" viewBox="0 0 24 24" width="16">

@ -14,13 +14,16 @@
* 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 { ObjCommentDto } from '../../../../common/model/obj/obj-pin.dto';
import { fnDateFormat } from '../../../../common/fn/fn-date-format';
import { ObjCommentDto } from '../../../../model/obj/obj-pin.dto';
import { PinEditModel } from '../../model/pin-edit.model';
import { fnDateFormat } from '../../../../fn/fn-date-format';
export class CommentFooterComponent {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
constructor(private comment: ObjCommentDto) {}
constructor(private model: PinEditModel, private comment: ObjCommentDto) {
this.el = model.doc.document.createElement('div');
}
render(): HTMLElement {
this.el.style.fontSize = '0.7em';

@ -14,12 +14,16 @@
* 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 { HtmlComponent } from '../../../model/html.model';
import { HtmlComponent } from '../../model/pin-view.model';
import { PinEditModel } from '../../model/pin-edit.model';
export class CommentRemoveButton implements HtmlComponent<HTMLElement> {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
constructor(private removeCallback: () => void) {}
constructor(model: PinEditModel, private removeCallback: () => void) {
this.el = model.doc.document.createElement('div');
}
render(): HTMLElement {
this.el.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" fill="#000000" height="16" viewBox="0 0 24 24" width="16">

@ -16,15 +16,15 @@
*/
import { CommentActionBar } from './comment-action-bar';
import { CommentFooterComponent } from './comment-footer.component';
import { HashtagFindCommand } from '../../../../common/command/obj/hashtag/hashtag-find.command';
import { HtmlComponent } from '../../../model/html.model';
import { ObjCommentDto } from '../../../../common/model/obj/obj-pin.dto';
import { ObjRemoveHashtagsCommand } from '../../../../common/command/obj/hashtag/obj-remove-hashtags.command';
import { ObjUpdateHashtagsCommand } from '../../../../common/command/obj/hashtag/obj-update-hashtags.command';
import { PinModel } from '../../pin.model';
import { PinUpdateCommand } from '../../../../common/command/pin/pin-update.command';
import { HashtagFindCommand } from '../../../../command/obj/hashtag/hashtag-find.command';
import { HtmlComponent } from '../../model/pin-view.model';
import { ObjCommentDto } from '../../../../model/obj/obj-pin.dto';
import { ObjRemoveHashtagsCommand } from '../../../../command/obj/hashtag/obj-remove-hashtags.command';
import { ObjUpdateHashtagsCommand } from '../../../../command/obj/hashtag/obj-update-hashtags.command';
import { PinEditModel } from '../../model/pin-edit.model';
import { PinUpdateCommand } from '../../../../command/pin/pin-update.command';
import { TextCommentEditorComponent } from '../text-comment-editor.component';
import { applyStylesToElement } from '../../../../common/style.utils';
import { applyStylesToElement } from '../../../../style.utils';
import { marked } from 'marked';
const viewStyles = {
@ -37,17 +37,18 @@ const viewStyles = {
};
export class CommentComponent implements HtmlComponent<HTMLElement> {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
private view?: HTMLDivElement;
private footer: CommentFooterComponent;
constructor(
private model: PinModel,
private model: PinEditModel,
private comment: ObjCommentDto,
private index: number,
private renderCallback: () => void
) {
this.footer = new CommentFooterComponent(comment);
this.el = model.doc.document.createElement('div');
this.footer = new CommentFooterComponent(model, comment);
}
render(): HTMLElement {
this.renderRead();
@ -56,8 +57,8 @@ export class CommentComponent implements HtmlComponent<HTMLElement> {
renderRead = () => {
this.renderView();
const comment = document.createElement('div');
const value = document.createElement('div');
const comment = this.model.doc.document.createElement('div');
const value = this.model.doc.document.createElement('div');
value.innerHTML = marked(this.comment.value);
comment.appendChild(value);
comment.appendChild(this.footer.render());
@ -65,20 +66,20 @@ export class CommentComponent implements HtmlComponent<HTMLElement> {
comment.style.marginBottom = '5px';
if (!this.view) return;
this.view.appendChild(comment);
const actionBar = new CommentActionBar(this.removeCallback, this.editCallback);
const actionBar = new CommentActionBar(this.model, this.removeCallback, this.editCallback);
this.view.appendChild(actionBar.render());
this.el.appendChild(this.view);
};
renderView = () => {
this.view?.remove();
this.view = document.createElement('div');
this.view = this.model.doc.document.createElement('div');
applyStylesToElement(this.view, viewStyles);
};
editCallback = () => {
this.renderView();
const comment = document.createElement('div');
const comment = this.model.doc.document.createElement('div');
const txt = new TextCommentEditorComponent(
this.model,
'Save',

@ -15,28 +15,29 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { ContentButton } from '../base/content-button';
import { HtmlComponent } from '../../model/html.model';
import { PinModel } from '../pin.model';
import { HtmlComponent } from '../model/pin-view.model';
import { PinEditModel } from '../model/pin-edit.model';
import { TextEditorComponent } from './text-editor.component';
export class TextCommentEditorComponent implements HtmlComponent<HTMLElement> {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
private textEditor: TextEditorComponent;
private readonly saveButton: ContentButton;
private readonly cancelButton?: ContentButton;
constructor(
model: PinModel,
model: PinEditModel,
saveLabel: string,
private saveCallback: (value: string) => void,
cancelLabel?: string,
cancelCallback?: () => void,
initialValue = ''
) {
this.el = model.doc.document.createElement('div');
this.textEditor = new TextEditorComponent(initialValue, model);
this.saveButton = new ContentButton(saveLabel, this.handleSaveClick);
if (cancelLabel && cancelCallback) this.cancelButton = new ContentButton(cancelLabel, cancelCallback);
this.saveButton = new ContentButton(model.doc, saveLabel, this.handleSaveClick);
if (cancelLabel && cancelCallback) this.cancelButton = new ContentButton(model.doc, cancelLabel, cancelCallback);
}
render(): HTMLElement {

@ -15,18 +15,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { CommentComponent } from './comment/comment.component';
import { HtmlComponent } from '../../model/html.model';
import { PinModel } from '../pin.model';
import { applyStylesToElement } from '../../../common/style.utils';
import { HtmlComponent } from '../model/pin-view.model';
import { PinEditModel } from '../model/pin-edit.model';
import { applyStylesToElement } from '../../../style.utils';
const elStyles = {
'background-color': '#ffffff'
};
export class TextCommentListComponent implements HtmlComponent<HTMLElement> {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
constructor(private model: PinModel) {}
constructor(private model: PinEditModel) {
this.el = model.doc.document.createElement('div');
}
render(): HTMLElement {
applyStylesToElement(this.el, elStyles);

@ -14,14 +14,14 @@
* 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 { HtmlComponent } from '../../model/html.model';
import { ObjAddHashtagsCommand } from '../../../common/command/obj/hashtag/obj-add-hashtags.command';
import { PinModel } from '../pin.model';
import { PinUpdateCommand } from '../../../common/command/pin/pin-update.command';
import { HtmlComponent } from '../model/pin-view.model';
import { ObjAddHashtagsCommand } from '../../../command/obj/hashtag/obj-add-hashtags.command';
import { PinEditModel } from '../model/pin-edit.model';
import { PinUpdateCommand } from '../../../command/pin/pin-update.command';
import { TextCommentEditorComponent } from './text-comment-editor.component';
import { TextCommentListComponent } from './text-comment-list.component';
import { applyStylesToElement } from '../../../common/style.utils';
import { fnSha256 } from '../../../common/fn/fn-sha256';
import { applyStylesToElement } from '../../../style.utils';
import { fnSha256 } from '../../../fn/fn-sha256';
const elStyles = {
'min-height': '40px',
@ -29,12 +29,13 @@ const elStyles = {
};
export class TextContainerComponent implements HtmlComponent<HTMLElement> {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
private add: TextCommentEditorComponent;
private comments: TextCommentListComponent;
constructor(private model: PinModel) {
constructor(private model: PinEditModel) {
this.el = model.doc.document.createElement('div');
this.add = new TextCommentEditorComponent(model, 'Add', this.addCommentCallback);
this.comments = new TextCommentListComponent(model);
}

@ -15,17 +15,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { EditorView } from 'prosemirror-view';
import { HtmlComponent } from '../../model/html.model';
import { PinModel } from '../pin.model';
import { createTextEditorState } from '../../../common/components/text-editor/text.editor.state';
import { HtmlComponent } from '../model/pin-view.model';
import { PinEditModel } from '../model/pin-edit.model';
import { createTextEditorState } from '../../text-editor/text.editor.state';
import { defaultMarkdownSerializer } from 'prosemirror-markdown';
export class TextEditorComponent implements HtmlComponent<HTMLElement> {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
private editorView?: EditorView;
constructor(private initialValue: string, private model: PinModel) {}
constructor(private initialValue: string, private model: PinEditModel) {
this.el = model.doc.document.createElement('div');
}
get value(): string {
if (!this.editorView) return '';

@ -14,16 +14,18 @@
* 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 { HtmlComponent } from '../../../model/html.model';
import MathMLToLaTeX from '../../../../vendor/mathml-to-latex/src/index';
import { PinModel } from '../../pin.model';
import { applyStylesToElement } from '../../../../common/style.utils';
import { fnConsoleLog } from '../../../../common/fn/fn-console';
import { HtmlComponent } from '../../model/pin-view.model';
import MathMLToLaTeX from '../../../../../vendor/mathml-to-latex/src';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
import { fnConsoleLog } from '../../../../fn/fn-console';
import { iconButtonStyles } from '../../styles/icon-button.styles';
export class ActionCopyButton implements HtmlComponent<HTMLElement> {
private el = document.createElement('div');
constructor(private model: PinModel) {}
private readonly el: HTMLDivElement;
constructor(private model: PinEditModel) {
this.el = model.doc.document.createElement('div');
}
render(): HTMLElement {
this.el.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" fill="#000000" height="24" viewBox="0 0 24 24" width="24">

@ -14,18 +14,21 @@
* 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 { HtmlComponent } from '../../../model/html.model';
import { HtmlComponent } from '../../model/pin-view.model';
import { PinEditManager } from '../../pin-edit.manager';
import { applyStylesToElement } from '../../../../common/style.utils';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
import { iconButtonStyles } from '../../styles/icon-button.styles';
export class ActionDownloadButton implements HtmlComponent<HTMLElement> {
private el = document.createElement('div');
private readonly el: HTMLDivElement;
private visible = false;
private fillColor = '#000000';
constructor(private edit: PinEditManager) {}
constructor(private edit: PinEditManager, model: PinEditModel) {
this.el = model.doc.document.createElement('div');
}
render(): HTMLElement {
this.el.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" fill="${this.fillColor}" enable-background="new 0 0 24 24" height="24" viewBox="0 0 24 24" width="24">

@ -14,19 +14,20 @@
* 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 { HtmlComponent } from '../../../model/html.model';
import { HtmlComponent } from '../../model/pin-view.model';
import { PinEditManager } from '../../pin-edit.manager';
import { PinModel } from '../../pin.model';
import { PinUpdateCommand } from '../../../../common/command/pin/pin-update.command';
import { applyStylesToElement } from '../../../../common/style.utils';
import { PinEditModel } from '../../model/pin-edit.model';
import { PinUpdateCommand } from '../../../../command/pin/pin-update.command';
import { applyStylesToElement } from '../../../../style.utils';
import { iconButtonStyles } from '../../styles/icon-button.styles';
export class ActionDrawVisibleButton implements HtmlComponent<HTMLElement> {
private readonly el = document.createElement('div');
private readonly el: HTMLDivElement;
private fillColor: string;
constructor(private edit: PinEditManager, private model: PinModel) {
constructor(private edit: PinEditManager, private model: PinEditModel) {
this.el = model.doc.document.createElement('div');
this.fillColor = model.local.drawVisible ? '#ff0000' : '#000000';
}

@ -14,19 +14,22 @@
* 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 { HtmlComponent } from '../../../model/html.model';
import { HtmlComponent } from '../../model/pin-view.model';
import { PinEditManager } from '../../pin-edit.manager';
import { applyStylesToElement } from '../../../../common/style.utils';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
import { iconButtonStyles } from '../../styles/icon-button.styles';
export class ActionDrawButton implements HtmlComponent<HTMLElement> {
private readonly el = document.createElement('div');
private readonly el: HTMLDivElement;
private visible = false;
private fillColor = '#000000';
constructor(private edit: PinEditManager) {}
constructor(private edit: PinEditManager, model: PinEditModel) {
this.el = model.doc.document.createElement('div');
}
render(): HTMLElement {
this.el.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" fill="${this.fillColor}" height="24" viewBox="0 0 24 24" width="24">

@ -14,18 +14,21 @@
* 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 { HtmlComponent } from '../../../model/html.model';
import { HtmlComponent } from '../../model/pin-view.model';
import { PinEditManager } from '../../pin-edit.manager';
import { applyStylesToElement } from '../../../../common/style.utils';
import { PinEditModel } from '../../model/pin-edit.model';
import { applyStylesToElement } from '../../../../style.utils';
import { iconButtonStyles } from '../../styles/icon-button.styles';
export class ActionPinEditButton implements HtmlComponent<HTMLElement> {
private readonly el = document.createElement('div');
private readonly el;
private visible = false;
private fillColor = '#000000';
constructor(private edit: PinEditManager) {}
constructor(private edit: PinEditManager, model: PinEditModel) {
this.el = model.doc.document.createElement('div');
}
render() {
this.el.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" fill="${this.fillColor}" height="24" viewBox="0 0 24 24" width="24">

@ -14,16 +14,17 @@
* 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 { HtmlComponent } from '../../../model/html.model';
import { PinModel } from '../../pin.model';
import { PinRemoveCommand } from '../../../../common/command/pin/pin-remove.command';
import { PinStore } from '../../../store/pin.store';
import { applyStylesToElement } from '../../../../common/style.utils';
import { HtmlComponent } from '../../model/pin-view.model';
import { PinEditModel } from '../../model/pin-edit.model';
import { PinRemoveCommand } from '../../../../command/pin/pin-remove.command';
import { applyStylesToElement } from '../../../../style.utils';
import { iconButtonStyles } from '../../styles/icon-button.styles';
export class ActionRemoveButton implements HtmlComponent<HTMLElement> {
private el = document.createElement('div');
constructor(private model: PinModel) {}
private readonly el: HTMLDivElement;
constructor(private model: PinEditModel) {
this.el = model.doc.document.createElement('div');
}
render(): HTMLElement {
this.el.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" fill="#000000" height="24" viewBox="0 0 24 24" width="24">
@ -41,6 +42,7 @@ export class ActionRemoveButton implements HtmlComponent<HTMLElement> {
private handleClick = async () => {
this.el.removeEventListener('click', this.handleClick);
await new PinRemoveCommand(this.model.id, this.model.url).execute();
PinStore.delByUid(this.model.id);
this.model.remove();
// PinStore.delByUid(this.model.id);
};
}

@ -14,7 +14,7 @@
* 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 { HtmlComponent, HtmlComponentFocusable } from '../../model/html.model';
import { HtmlComponent, HtmlComponentFocusable } from '../model/pin-view.model';
import { ActionCopyButton } from './action-buttons/action-copy.button';
import { ActionDownloadButton } from './action-buttons/action-download.button';
import { ActionDrawButton } from './action-buttons/action-draw.button';
@ -22,8 +22,8 @@ import { ActionDrawVisibleButton } from './action-buttons/action-draw-visible.bu
import { ActionPinEditButton } from './action-buttons/action-pin-edit.button';
import { ActionRemoveButton } from './action-buttons/action-remove.button';
import { PinEditManager } from '../pin-edit.manager';
import { PinModel } from '../pin.model';
import { applyStylesToElement } from '../../../common/style.utils';
import { PinEditModel } from '../model/pin-edit.model';
import { applyStylesToElement } from '../../../style.utils';
const topBarStyles = {
height: '24px',
@ -68,7 +68,7 @@ const drawVisibleIconStyles = {
};
export class TopBarComponent implements HtmlComponent<HTMLElement>, HtmlComponentFocusable {
private readonly el = document.createElement('div');
private readonly el: HTMLDivElement;
private readonly editIcon: ActionPinEditButton;
private readonly removeIcon: ActionRemoveButton;
@ -80,13 +80,14 @@ export class TopBarComponent implements HtmlComponent<HTMLElement>, HtmlComponen
private topMargin = '-24px';
constructor(edit: PinEditManager, private model: PinModel) {
this.editIcon = new ActionPinEditButton(edit);
constructor(edit: PinEditManager, private model: PinEditModel) {
this.el = model.doc.document.createElement('div');
this.editIcon = new ActionPinEditButton(edit, model);
this.removeIcon = new ActionRemoveButton(model);
this.copyIcon = new ActionCopyButton(model);
this.downloadIcon = new ActionDownloadButton(edit);
this.downloadIcon = new ActionDownloadButton(edit, model);
this.drawIcon = new ActionDrawButton(edit);
this.drawIcon = new ActionDrawButton(edit, model);
this.drawVisibleIcon = new ActionDrawVisibleButton(edit, model);
}

@ -14,26 +14,26 @@
* 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 { ContentSettingsStore } from '../../content-script/store/content-settings.store';
import { ObjRectangleDto } from '../model/obj/obj-utils.dto';
import { PinDocument } from '../components/pin/model/pin-view.model';
export class ImageResizeFactory {
static resize = (size: ObjRectangleDto, b64image: string): Promise<string> => {
static resize = (doc: PinDocument, size: ObjRectangleDto, b64image: string): Promise<string> => {
const rect = {
x: size.x,
y: size.y,
width: size.width,
height: Math.min(size.height, window.innerHeight - size.y)
height: Math.min(size.height, doc.window.innerHeight - size.y)
};
return new Promise<string>((resolve, reject) => {
const img = new Image();
img.onload = () => {
try {
const can = document.createElement('canvas');
const can = doc.document.createElement('canvas');
can.width = rect.width;
can.height = rect.height;
const wr = img.naturalWidth / window.innerWidth;
const hr = img.naturalHeight / window.innerHeight;
const wr = img.naturalWidth / doc.window.innerWidth;
const hr = img.naturalHeight / doc.window.innerHeight;
const ctx = can.getContext('2d');
ctx?.drawImage(
img,
@ -46,10 +46,7 @@ export class ImageResizeFactory {
rect.width,
rect.height
);
b64image = can.toDataURL(
`image/${ContentSettingsStore.screenshotFormat}`,
ContentSettingsStore.screenshotQuality
);
b64image = can.toDataURL(`image/${doc.settings.screenshotFormat}`, doc.settings.screenshotQuality);
} finally {
window.URL.revokeObjectURL(b64image);
img.onerror = null;

@ -14,7 +14,7 @@
* 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 { ObjRectangleDto } from '../../common/model/obj/obj-utils.dto';
import { ObjRectangleDto } from '../model/obj/obj-utils.dto';
export class PinPointFactory {
static calculateRect(ref: HTMLElement): ObjRectangleDto {

@ -19,18 +19,19 @@ import { BusMessageType } from '../model/bus.model';
import { ImageResizeFactory } from './image-resize.factory';
import { ObjRectangleDto } from '../model/obj/obj-utils.dto';
import { ObjUrlDto } from '../model/obj/obj.dto';
import { PinDocument } from '../components/pin/model/pin-view.model';
import { TinyEventDispatcher } from '../service/tiny.event.dispatcher';
import { fnConsoleLog } from '../fn/fn-console';
export class ScreenshotFactory {
static takeScreenshot = async (rect?: ObjRectangleDto, url?: ObjUrlDto): Promise<string> => {
static takeScreenshot = async (doc: PinDocument, rect?: ObjRectangleDto, url?: ObjUrlDto): Promise<string> => {
return new Promise((resolve, reject) => {
// Crop screenshot function
TinyEventDispatcher.addListener<string>(
BusMessageType.CONTENT_TAKE_SCREENSHOT,
async (event: string, key: string, screenshot: string) => {
TinyEventDispatcher.removeListener(event, key);
if (rect) screenshot = await ImageResizeFactory.resize(rect, screenshot);
if (rect) screenshot = await ImageResizeFactory.resize(doc, rect, screenshot);
resolve(screenshot);
}
);

@ -80,7 +80,7 @@ export class XpathFactory {
return subtree;
}
static newXPathResult(path: string): XPathResult {
static newXPathResult(document: Document, path: string): XPathResult {
return document.evaluate(path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE);
}

@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
export const isElementHiddenFn = (el: HTMLElement): boolean => {
export const fnIsElementHidden = (el: HTMLElement): boolean => {
const style = window.getComputedStyle(el);
return style.display === 'none' || el.offsetParent === null; // !document.body.contains(el);
};

@ -14,13 +14,13 @@
* 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 { PinVideoDataDto } from '../../common/model/obj/obj-pin.dto';
import { XpathFactory } from '../../common/factory/xpath.factory';
import { ObjVideoDataDto } from '../model/obj/obj-snapshot.dto';
import { XpathFactory } from '../factory/xpath.factory';
export const resolveVideoTimeFn = (videoTime?: PinVideoDataDto[]): void => {
export const fnResolveVideoTime = (videoTime?: ObjVideoDataDto[]): void => {
if (!videoTime) return;
for (const video of videoTime) {
const value = XpathFactory.newXPathResult(video.xpath);
const value = XpathFactory.newXPathResult(document, video.xpath);
const node = value.singleNodeValue as HTMLVideoElement;
if (!node) continue;
node.currentTime = video.currentTime;

@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
export const scrollToElementFn = (view?: HTMLElement, offset?: number): number => {
export const fnScrollToElement = (view?: HTMLElement, offset?: number): number => {
if (!view) return -1;
const rect = view.getBoundingClientRect();
// TODO fix scroll

@ -15,8 +15,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { ICommand } from '../../../common/model/shared/common.dto';
import { ObjDto } from '../../../common/model/obj/obj.dto';
import { ObjPinDto } from '../../../common/model/obj/obj-pin.dto';
import { ObjTypeDto } from '../../../common/model/obj/obj.dto';
import { PinAddXpathCommand } from './pin-add-xpath.command';
import { PinPendingStore } from '../../store/pin-pending.store';
@ -43,7 +41,7 @@ export class InvalidatePinsCommand implements ICommand<Promise<void>> {
for (const pin of pinList) {
switch (pin.type) {
case ObjTypeDto.PageElementPin:
if (new PinAddXpathCommand(pin as ObjDto<ObjPinDto>).execute()) {
if (new PinAddXpathCommand(pin).execute()) {
PinPendingStore.remove(pin.id);
}
break;

@ -21,16 +21,16 @@ import { PinComponentAddCommand } from './pin-component-add.command';
import { PinPendingStore } from '../../store/pin-pending.store';
import { XpathFactory } from '../../../common/factory/xpath.factory';
import { fnConsoleLog } from '../../../common/fn/fn-console';
import { isElementHiddenFn } from '../../fn/is-element-hidden.fn';
import { fnIsElementHidden } from '../../../common/fn/fn-is-element-hidden';
export class PinAddXpathCommand implements ICommand<boolean> {
constructor(private data: ObjDto<ObjPinDto>) {}
execute(): boolean {
const pin = this.data.data;
const value = XpathFactory.newXPathResult(pin.xpath);
const value = XpathFactory.newXPathResult(document, pin.xpath);
fnConsoleLog('PinAddXpathCommand->xpath', pin.xpath, 'singleNodeValue', value.singleNodeValue);
const node = value.singleNodeValue as HTMLElement;
if (!this.data.local?.visible || !node || isElementHiddenFn(node)) {
if (!this.data.local?.visible || !node || fnIsElementHidden(node)) {
// will be created on invalidate
PinPendingStore.add(this.data);
return false;

@ -19,6 +19,7 @@ import { BrowserApi } from '../../../common/service/browser.api.wrapper';
import { BrowserStorageWrapper } from '../../../common/service/browser.storage.wrapper';
import { BusMessageType } from '../../../common/model/bus.model';
import { ContentPageSnapshotAddCommand } from '../snapshot/content-page-snapshot-add.command';
import { ContentSettingsStore } from '../../store/content-settings.store';
import { ICommand } from '../../../common/model/shared/common.dto';
import { LinkHrefOriginStore } from '../../../common/store/link-href-origin.store';
import { ObjNextIdCommand } from '../../../common/command/obj/id/obj-next-id.command';
@ -58,7 +59,7 @@ export class PinAddCommand implements ICommand<Promise<ObjDto<ObjPinDto>>> {
const hasSnapshot = await LinkHrefOriginStore.hasPageSnapshot(this.pin.url.href);
if (!hasSnapshot) {
await new ContentPageSnapshotAddCommand(this.pin.url).execute();
await new ContentPageSnapshotAddCommand(ContentSettingsStore.settings, this.pin.url).execute();
}
// Send stop - iframe loads own content scripts

@ -14,17 +14,22 @@
* 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 { HtmlComponent } from '../../model/html.model';
import { ContentSettingsStore } from '../../store/content-settings.store';
import { HtmlComponent } from '../../../common/components/pin/model/pin-view.model';
import { ICommand } from '../../../common/model/shared/common.dto';
import { ObjDto } from '../../../common/model/obj/obj.dto';
import { ObjPinDto } from '../../../common/model/obj/obj-pin.dto';
import { PinComponent } from '../../components/pin.component';
import { PinComponent } from '../../../common/components/pin/pin.component';
import { PinStore } from '../../store/pin.store';
export class PinComponentAddCommand implements ICommand<HtmlComponent<HTMLElement> | undefined> {
constructor(private ref: HTMLElement, private dto: ObjDto<ObjPinDto>, private focus = false) {}
execute(): HtmlComponent<HTMLElement> | undefined {
const pinComponent = new PinComponent(this.ref, this.dto);
const pinComponent = new PinComponent(this.ref, this.dto, {
document,
window,
settings: ContentSettingsStore.settings
});
pinComponent.render();
if (this.focus) pinComponent.focus();

@ -21,13 +21,22 @@ import { ICommand } from '../../../common/model/shared/common.dto';
import { ObjSnapshotDto } from '../../../common/model/obj/obj-snapshot.dto';
import { PageSnapshotAddCommand } from '../../../common/command/snapshot/page-snapshot-add.command';
import { ScreenshotFactory } from '../../../common/factory/screenshot.factory';
import { SettingsConfig } from '../../../common/environment';
import { SnapshotContentSaveCommand } from './snapshot-content-save.command';
export class ContentPageSnapshotAddCommand implements ICommand<Promise<void>> {
constructor(private url: ObjUrlDto) {}
constructor(private settings: SettingsConfig, private url: ObjUrlDto) {}
async execute(): Promise<void> {
const screenshot = await ScreenshotFactory.takeScreenshot(undefined, this.url);
const screenshot = await ScreenshotFactory.takeScreenshot(
{
document,
window,
settings: this.settings
},
undefined,
this.url
);
const res = await new SnapshotContentSaveCommand(document.body, [], false).execute();

@ -18,12 +18,14 @@ import { ObjCanvasDto, ObjSnapshotDto } from '../../../common/model/obj/obj-snap
import { ICommand } from '../../../common/model/shared/common.dto';
import { ObjUrlDto } from '../../../common/model/obj/obj.dto';
import { ScreenshotFactory } from '../../../common/factory/screenshot.factory';
import { SettingsConfig } from '../../../common/environment';
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>> {
constructor(
private settings: SettingsConfig,
private url: ObjUrlDto,
private element: HTMLElement,
private skipElements: string[],
@ -41,7 +43,11 @@ export class SnapshotCreateCommand implements ICommand<Promise<ObjSnapshotDto>>
} else if (this.element instanceof HTMLImageElement) {
contentId = await new SnapshotSaveImageCommand(this.element).execute();
}
const screenshot = await ScreenshotFactory.takeScreenshot(rect, this.url);
const screenshot = await ScreenshotFactory.takeScreenshot(
{ settings: this.settings, document, window },
rect,
this.url
);
const title = this.element.innerText.substring(0, 100) || document.title;
return {
title,

@ -17,6 +17,7 @@
import { BrowserGlobalSender, BusMessage, BusMessageType } from '../common/model/bus.model';
import { BrowserApi } from '../common/service/browser.api.wrapper';
import { ContentPageSnapshotAddCommand } from './command/snapshot/content-page-snapshot-add.command';
import { ContentSettingsStore } from './store/content-settings.store';
import { DocumentMediator } from './mediator/document.mediator';
import { ExtensionPopupInitData } from '../common/model/obj-request.model';
import { IFrameMessageHandler } from './iframe-message.handler';
@ -63,7 +64,7 @@ export class ContentMessageHandler {
});
switch (msg.type) {
case BusMessageType.POPUP_PAGE_SNAPSHOT_ADD:
if (!this.iframe) await new ContentPageSnapshotAddCommand(msg.data).execute();
if (!this.iframe) await new ContentPageSnapshotAddCommand(ContentSettingsStore.settings, msg.data).execute();
break;
case BusMessageType.IFRAME_INDEX:
case BusMessageType.IFRAME_PING:

@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { ObjPinDto, PinBorderDataDto } from '../../common/model/obj/obj-pin.dto';
import { ContentSettingsStore } from '../store/content-settings.store';
import { ObjCanvasDto } from '../../common/model/obj/obj-snapshot.dto';
import { ObjRectangleDto } from '../../common/model/obj/obj-utils.dto';
import { ObjUrlDto } from '../../common/model/obj/obj.dto';
@ -30,7 +31,15 @@ export class PinFactory {
canvas?: ObjCanvasDto
): Promise<ObjPinDto> => {
const rect = canvas ? canvas.rect : XpathFactory.computeRect(ref);
const screenshot = await ScreenshotFactory.takeScreenshot(rect, url);
const screenshot = await ScreenshotFactory.takeScreenshot(
{
settings: ContentSettingsStore.settings,
document,
window
},
rect,
url
);
const xpath = XpathFactory.newXPathString(ref);
return {
xpath,

@ -17,6 +17,7 @@
import { BrowserApi } from '../../common/service/browser.api.wrapper';
import { BusMessageType } from '../../common/model/bus.model';
import { CIRCLE_PRELOADER_SVG } from './capture.preloader';
import { ContentSettingsStore } from '../store/content-settings.store';
import { IFrameIndexMessage } from '../../common/model/iframe-message.model';
import { IFrameStore } from '../store/iframe.store';
import { ObjCanvasDto } from '../../common/model/obj/obj-snapshot.dto';
@ -34,7 +35,7 @@ import { applyStylesToElement } from '../../common/style.utils';
import { fnConsoleLog } from '../../common/fn/fn-console';
import { fnSleep } from '../../common/fn/fn-sleep';
import { fnUid } from '../../common/fn/fn-uid';
import { pinStyles } from '../components/styles/pin.styles';
import { pinStyles } from '../../common/components/pin/styles/pin.styles';
export class DocumentMediator {
static type?: ObjTypeDto;
@ -294,7 +295,13 @@ export class DocumentMediator {
const skipUid = this.showPreloader();
const url = UrlFactory.newUrl();
const dto = await new SnapshotCreateCommand(url, element, [skipUid], canvas).execute();
const dto = await new SnapshotCreateCommand(
ContentSettingsStore.settings,
url,
element,
[skipUid],
canvas
).execute();
await new PageSnapshotAddCommand(dto, ObjTypeDto.PageElementSnapshot).execute();
await BrowserApi.sendRuntimeMessage({ type: BusMessageType.POPUP_PAGE_ELEMENT_SNAPSHOT_ADD });
}

@ -15,27 +15,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { ObjContentDto } from '../../common/model/obj/obj-content.dto';
import { PinModel } from '../components/pin.model';
export interface HtmlIntermediateData {
html: string;
content: ObjContentDto[];
}
export interface HtmlComponentFocusable {
focusin(): void;
focusout(): void;
}
export interface PageComponent {
model: PinModel; // TODO REMOVE here
focus(goto: boolean): void;
cleanup(): void;
resize(): void;
render(): any;
isHidden(): boolean;
}
export interface HtmlComponent<T> {
render(): T;
}

@ -14,39 +14,38 @@
* 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 { SettingsConfig, environmentConfig } from '../../common/environment';
import { BrowserStorageWrapper } from '../../common/service/browser.storage.wrapper';
import { ObjectStoreKeys } from '../../common/keys/object.store.keys';
import { SettingsConfig } from '../../common/environment';
export class ContentSettingsStore {
private static settings: SettingsConfig;
static readonly borderNone = 'none';
private static settingsData: SettingsConfig;
static get borderStyle(): string {
return this.settings.borderStyle;
static get settings(): SettingsConfig {
return this.settingsData;
}
static get newElementStyle(): string {
return environmentConfig.settings.newElementStyle;
return this.settingsData.newElementStyle;
}
static get borderRadius(): string {
return this.settings.borderRadius;
return this.settingsData.borderRadius;
}
static get screenshotQuality(): number {
return this.settings.screenshotQuality;
return this.settingsData.screenshotQuality;
}
static get screenshotFormat(): string {
return this.settings.screenshotFormat;
return this.settingsData.screenshotFormat;
}
static get skipCssImageSize(): number {
return this.settings.skipCssImageSizeMB;
return this.settingsData.skipCssImageSizeMB;
}
static initSettings = async (): Promise<void> => {
this.settings = await BrowserStorageWrapper.get<SettingsConfig>(ObjectStoreKeys.CONTENT_SETTINGS_KEY);
this.settingsData = await BrowserStorageWrapper.get<SettingsConfig>(ObjectStoreKeys.CONTENT_SETTINGS_KEY);
};
}

@ -15,16 +15,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { ObjDto } from '../../common/model/obj/obj.dto';
import { ObjPinDto } from '../../common/model/obj/obj-pin.dto';
export class PinPendingStore {
// Map of pending pins
private static pendingPins: { [id: number]: ObjDto } = {};
private static pendingPins: { [id: number]: ObjDto<ObjPinDto> } = {};
static get values(): ObjDto[] {
static get values(): ObjDto<ObjPinDto>[] {
return Object.values(PinPendingStore.pendingPins);
}
static add(pin: ObjDto): void {
static add(pin: ObjDto<ObjPinDto>): void {
this.pendingPins[pin.id] = pin;
}

@ -16,7 +16,7 @@
*/
import { ObjDto } from '../../common/model/obj/obj.dto';
import { ObjPinDto } from '../../common/model/obj/obj-pin.dto';
import { PageComponent } from '../model/html.model';
import { PageComponent } from '../../common/components/pin/model/pin-view.model';
import { fnConsoleLog } from '../../common/fn/fn-console';
export class PinStore {

@ -27,7 +27,7 @@ export const MainFooterButton: FunctionComponent = () => {
variant="outlined"
onClick={() => BrowserApi.openOptionsPage()}
>
Go to pin board
Go on board
</Button>
</div>
);

@ -15,7 +15,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React, { FunctionComponent, useState } from 'react';
import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
import { BrowserApi } from '../../../common/service/browser.api.wrapper';
import { BusMessageType } from '../../../common/model/bus.model';
import DeleteIcon from '@mui/icons-material/Delete';
@ -26,7 +25,6 @@ import { ObjDto } from '../../../common/model/obj/obj.dto';
import { ObjPinDto } from '../../../common/model/obj/obj-pin.dto';
import { PinListExpandComponent } from './pin-list-expand.component';
import { PinUpdateCommand } from '../../../common/command/pin/pin-update.command';
import { PopupActiveTabStore } from '../../store/popup-active-tab.store';
import PushPinIcon from '@mui/icons-material/PushPin';
import Typography from '@mui/material/Typography';
import VisibilityIcon from '@mui/icons-material/Visibility';
@ -40,20 +38,6 @@ interface PinListElementProps {
export const PinListElement: FunctionComponent<PinListElementProps> = (props) => {
const [isExpanded, setIsExpanded] = useState(false);
const [isVisible, setIsVisible] = useState(props.obj.local?.visible);
const handleNavigate = async (data: ObjDto<ObjPinDto>): Promise<void> => {
if (!isVisible) {
data.local.visible = true;
await new PinUpdateCommand(data).execute();
setIsVisible(true);
}
if (PopupActiveTabStore.url?.href !== data.data.url.href) {
await BrowserApi.setActiveTabUrl(data.data.url.href);
} else {
await BrowserApi.sendTabMessage<ObjDto<ObjPinDto>>({ type: BusMessageType.CONTENT_PIN_NAVIGATE, data });
}
window.close();
};
const handlePinVisible = async (data: ObjDto<ObjPinDto>): Promise<void> => {
data.local.visible = !data.local.visible;
@ -116,9 +100,6 @@ export const PinListElement: FunctionComponent<PinListElementProps> = (props) =>
}}
>
{visibleIcon}
<IconButton title="Go to page" size="small" onClick={() => handleNavigate(props.obj)}>
<ArrowForwardIcon sx={{ fontSize: '12px' }} />
</IconButton>
<IconButton title="Remove pin" size="small" onClick={() => handlePinRemove(props.obj)}>
<DeleteIcon sx={{ fontSize: '12px' }} />
</IconButton>

@ -24,7 +24,6 @@ import {
ObjGetSnapshotContentCommand,
ObjSnapshotData
} from '../../../common/command/obj/content/obj-get-snapshot-content.command';
import { ObjPageDto, ObjPinDto } from '../../../common/model/obj/obj-pin.dto';
import React, { FunctionComponent, useEffect, useRef, useState } from 'react';
import { BrowserApi } from '../../../common/service/browser.api.wrapper';
import CircularProgress from '@mui/material/CircularProgress';
@ -32,9 +31,14 @@ import ClearIcon from '@mui/icons-material/Clear';
import DownloadIcon from '@mui/icons-material/Download';
import IconButton from '@mui/material/IconButton';
import { IframeHtmlFactory } from '../../../common/factory/iframe-html.factory';
import { LinkHrefOriginStore } from '../../../common/store/link-href-origin.store';
import { ObjGetCommand } from '../../../common/command/obj/obj-get.command';
import { ObjPageDto } from '../../../common/model/obj/obj-pin.dto';
import { ObjPinGetCommand } from '../../../common/command/obj/obj-pin-get.command';
import { ObjSnapshotDto } from '../../../common/model/obj/obj-snapshot.dto';
import { ObjTypeDto } from '../../../common/model/obj/obj.dto';
import { PinComponent } from '../../../common/components/pin/pin.component';
import { SettingsStore } from '../../store/settings.store';
import { XpathFactory } from '../../../common/factory/xpath.factory';
import { fnConsoleLog } from '../../../common/fn/fn-console';
import { fnParse5 } from '../../../common/fn/fn-parse5';
@ -93,10 +97,6 @@ export const HtmlPreviewComponent: FunctionComponent<Props> = (props) => {
const dom = fnParse5(c.snapshot.html);
fnConsoleLog('DOM !!!', dom, 'in', Date.now() - a);
fnConsoleLog('obj', obj, 'snapshot', c);
if (obj.type === ObjTypeDto.PageElementPin) {
const pin = obj.data as ObjPinDto;
fnConsoleLog('XPATH SUBTREE', XpathFactory.evaluateTree(pin.xpath, dom));
}
setSnapshotData(c);
}
if (obj.data.snapshot.canvas) {
@ -104,9 +104,39 @@ export const HtmlPreviewComponent: FunctionComponent<Props> = (props) => {
} else {
await renderSnapshot(obj.data.snapshot, c);
}
if (obj.type === ObjTypeDto.PageSnapshot) {
const pinIds = await LinkHrefOriginStore.pinIds(obj.data.snapshot.url.href);
await renderPins(pinIds);
}
});
};
const renderPins = async (ids: number[]) => {
if (!htmlRef.current?.lastElementChild) return;
const el = htmlRef.current?.lastElementChild as HTMLIFrameElement;
if (!el.contentDocument || !el.contentWindow) return;
await SettingsStore.fetchData();
if (!SettingsStore.settings) return;
fnConsoleLog('PIN IDS !!!!', ids, 'iframe', el);
for (const id of ids) {
const pin = await new ObjPinGetCommand(id).execute();
const value = XpathFactory.newXPathResult(el.contentDocument, pin.data.xpath);
const node = value.singleNodeValue as HTMLElement;
if (!node) continue;
const pinComponent = new PinComponent(node, pin, {
settings: SettingsStore.settings,
document: el.contentDocument,
window: el.contentWindow
});
pinComponent.render();
fnConsoleLog('PIN !!!', id, pin, value);
}
};
const renderCanvas = (s: ObjSnapshotDto, c?: ObjSnapshotData) => {
renderHeader(s, c?.size);