feat: popup show all page releated content

This commit is contained in:
Michal Szczepanski 2023-04-25 21:48:42 +02:00
parent 6543531747
commit 22e1c5ab39
93 changed files with 413 additions and 313 deletions

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -0,0 +1,39 @@
/*
* 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 { ObjDto, ObjPageDataDto, ObjUrlDto } from '../../../model/obj/obj.dto';
import { BrowserStorageWrapper } from '../../../service/browser.storage.wrapper';
import { ICommand } from '../../../model/shared/common.dto';
import { LinkHrefOriginStore } from '../../../store/link-href-origin.store';
import { ObjectStoreKeys } from '../../../keys/object.store.keys';
import { fnConsoleLog } from '../../../fn/console.fn';
export class ObjGetHrefCommand implements ICommand<Promise<ObjDto<ObjPageDataDto>[]>> {
constructor(private data: ObjUrlDto) {}
async execute(): Promise<ObjDto<ObjPageDataDto>[]> {
const pinIds = (await LinkHrefOriginStore.hrefIds(this.data.href)).reverse();
fnConsoleLog('WorkerPinManager->pinGetHref', this.data.href, 'ids->', pinIds);
// await this.test();
const out: ObjDto<ObjPageDataDto>[] = [];
for (const id of pinIds) {
const key = `${ObjectStoreKeys.OBJECT_ID}:${id}`;
const obj = await BrowserStorageWrapper.get<ObjDto<ObjPageDataDto>>(key);
out.push(obj);
}
return out;
}
}

@ -0,0 +1,51 @@
/*
* 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 { ObjDto, ObjPageDataDto, ObjTypeDto, ObjUrlDto } from '../../../model/obj/obj.dto';
import { BrowserStorageWrapper } from '../../../service/browser.storage.wrapper';
import { ICommand } from '../../../model/shared/common.dto';
import { LinkHrefOriginStore } from '../../../store/link-href-origin.store';
import { ObjNoteDto } from '../../../model/obj/obj-note.dto';
import { ObjPagePinDto } from '../../../model/obj/obj-pin.dto';
import { ObjSnapshotDto } from '../../../model/obj/obj-snapshot.dto';
import { ObjTaskDto } from '../../../model/obj/obj-task.dto';
import { ObjectStoreKeys } from '../../../keys/object.store.keys';
import { fnConsoleLog } from '../../../fn/console.fn';
export class ObjGetOriginCommand implements ICommand<Promise<ObjDto<ObjPageDataDto>[]>> {
constructor(private data: ObjUrlDto) {}
async execute(): Promise<ObjDto<ObjPageDataDto>[]> {
fnConsoleLog('WorkerPinManager->pinGetOrigin', this.data);
const pinIds = (await LinkHrefOriginStore.originIds(this.data.origin)).reverse();
const out: ObjDto<ObjPageDataDto>[] = [];
for (const id of pinIds) {
const key = `${ObjectStoreKeys.OBJECT_ID}:${id}`;
const obj = await BrowserStorageWrapper.get<ObjDto<ObjPageDataDto>>(key);
if (obj.type === ObjTypeDto.PageElementPin) {
if ((obj.data as ObjPagePinDto).snapshot.url.href === this.data.href) continue;
} else if (obj.type === ObjTypeDto.PageSnapshot || obj.type === ObjTypeDto.PageElementSnapshot) {
if ((obj.data as ObjSnapshotDto).url.href === this.data.href) continue;
} else if (obj.type === ObjTypeDto.PageNote) {
if ((obj.data as ObjNoteDto).url?.href === this.data.href) continue;
} else if (obj.type === ObjTypeDto.PageTask) {
if ((obj.data as ObjTaskDto).url?.href === this.data.href) continue;
}
out.push(obj);
}
return out;
}
}

@ -58,6 +58,7 @@ export class PinAddCommand implements ICommand<Promise<ObjDto<ObjPagePinDto>>> {
await BrowserStorageWrapper.set(key, dto);
await LinkHrefOriginStore.addHrefOriginId(this.pin.snapshot.url, id);
await LinkHrefOriginStore.pinAdd(this.pin.snapshot.url, id);
await new ObjAddIdCommand(id, dt).execute();

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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
@ -23,18 +23,18 @@ import { ObjectStoreKeys } from '../../keys/object.store.keys';
import { fnConsoleLog } from '../../fn/console.fn';
export class PinGetHrefCommand implements ICommand<Promise<ObjDto<ObjPagePinDto>[]>> {
constructor(private data: ObjUrlDto, private filterVisible = false) {}
constructor(private data: ObjUrlDto) {}
async execute(): Promise<ObjDto<ObjPagePinDto>[]> {
const pinIds = (await LinkHrefOriginStore.hrefIds(this.data.href)).reverse();
fnConsoleLog('WorkerPinManager->pinGetHref', this.data.href, 'ids->', pinIds);
// await this.test();
const pinIds = (await LinkHrefOriginStore.pinIds(this.data.href)).reverse();
fnConsoleLog('PinGetHrefCommand->execute', this.data.href, 'ids->', pinIds);
const out: ObjDto<ObjPagePinDto>[] = [];
for (const id of pinIds) {
const key = `${ObjectStoreKeys.OBJECT_ID}:${id}`;
const obj = await BrowserStorageWrapper.get<ObjDto<ObjPagePinDto>>(key);
// TODO revisit visible flag in pin.manager.ts in content scripts
if (this.filterVisible && !obj.local?.visible) continue;
if (!obj.local?.visible) continue;
out.push(obj);
}
return out;

@ -1,40 +0,0 @@
/*
* 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 { ObjDto, ObjUrlDto } from '../../model/obj/obj.dto';
import { BrowserStorageWrapper } from '../../service/browser.storage.wrapper';
import { ICommand } from '../../model/shared/common.dto';
import { LinkHrefOriginStore } from '../../store/link-href-origin.store';
import { ObjPagePinDto } from '../../model/obj/obj-pin.dto';
import { ObjectStoreKeys } from '../../keys/object.store.keys';
import { fnConsoleLog } from '../../fn/console.fn';
export class PinGetOriginCommand implements ICommand<Promise<ObjDto<ObjPagePinDto>[]>> {
constructor(private data: ObjUrlDto, private filterHref: boolean = true) {}
async execute(): Promise<ObjDto<ObjPagePinDto>[]> {
fnConsoleLog('WorkerPinManager->pinGetOrigin', this.data);
const pinIds = (await LinkHrefOriginStore.originIds(this.data.origin)).reverse();
const out: ObjDto<ObjPagePinDto>[] = [];
for (const id of pinIds) {
const key = `${ObjectStoreKeys.OBJECT_ID}:${id}`;
const obj = await BrowserStorageWrapper.get<ObjDto<ObjPagePinDto>>(key);
if (this.filterHref && obj.data.snapshot.url.href === this.data.href) continue;
out.push(obj);
}
return out;
}
}

@ -29,7 +29,9 @@ export class PinRemoveCommand implements ICommand<void> {
async execute(): Promise<void> {
fnConsoleLog('WorkerPinManager->pinRemove', this.obj);
await BrowserStorageWrapper.remove(`${ObjectStoreKeys.OBJECT_ID}:${this.obj.id}`);
await LinkHrefOriginStore.delHrefOriginId(this.obj.data.snapshot.url, this.obj.id);
await LinkHrefOriginStore.pinDel(this.obj.data.snapshot.url, this.obj.id);
await new ObjRemoveIdCommand(this.obj.id, new Date(this.obj.createdAt)).execute();

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -17,6 +17,7 @@
import { OBJ_DTO_VERSION, ObjDto, ObjTypeDto } from '../../model/obj/obj.dto';
import { BrowserStorageWrapper } from '../../service/browser.storage.wrapper';
import { ICommand } from '../../model/shared/common.dto';
import { LinkHrefOriginStore } from '../../store/link-href-origin.store';
import { ObjAddIdCommand } from '../obj/id/obj-add-id.command';
import { ObjNextIdCommand } from '../obj/id/obj-next-id.command';
import { ObjSnapshotDto } from '../../model/obj/obj-snapshot.dto';
@ -50,6 +51,8 @@ export class PageElementSnapshotAddCommand implements ICommand<Promise<void>> {
const key = `${ObjectStoreKeys.OBJECT_ID}:${id}`;
await BrowserStorageWrapper.set(key, dto);
await LinkHrefOriginStore.addHrefOriginId(this.dto.url, id);
await new ObjAddIdCommand(id, dt).execute();
}
}

@ -17,6 +17,7 @@
import { OBJ_DTO_VERSION, ObjDto, ObjTypeDto } from '../../model/obj/obj.dto';
import { BrowserStorageWrapper } from '../../service/browser.storage.wrapper';
import { ICommand } from '../../model/shared/common.dto';
import { LinkHrefOriginStore } from '../../store/link-href-origin.store';
import { ObjAddIdCommand } from '../obj/id/obj-add-id.command';
import { ObjNextIdCommand } from '../obj/id/obj-next-id.command';
import { ObjSnapshotDto } from '../../model/obj/obj-snapshot.dto';
@ -50,5 +51,7 @@ export class PageSnapshotAddCommand implements ICommand<Promise<void>> {
await BrowserStorageWrapper.set(key, dto);
await new ObjAddIdCommand(id, dt).execute();
await LinkHrefOriginStore.addHrefOriginId(this.dto.url, id);
}
}

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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
@ -35,6 +35,7 @@ export class ObjectStoreKeys {
// INDEX
static readonly SEARCH_INDEX = 's:i';
static readonly SEARCH_WORD = 's:w';
static readonly SEARCH_START = 's:s';
static readonly ACCESS_TOKEN = 'accessToken';

@ -34,9 +34,8 @@ export enum BusMessageType {
OPT_SHOW_HTML = 'opt.show.html',
// Internal popup
POP_CONSOLE_LOG = 'pop.console.log',
POP_PIN_REMOVE = 'pop.pin.remove',
POP_IS_ADDING = 'pop.is.adding',
POP_UPDATE_URL = 'pop.update.url',
POP_UPDATE_ADDING = 'pop.update.adding',
// Ack
CONTENT_ACK = 'content.ack',
POPUP_ACK = 'popup.ack',

@ -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 { ObjDataDto, ObjDto, ObjTypeDto, ObjUrlDto } from './obj/obj.dto';
import { ObjDto, ObjTypeDto, ObjUrlDto } from './obj/obj.dto';
export interface ObjIdRangeResponse {
ids: number[];
@ -30,7 +30,7 @@ export interface ObjRangeRequest {
export interface ObjRangeResponse {
listId: number;
data: ObjDto<ObjDataDto>[];
data: ObjDto[];
}
export interface PopupPinStartRequest {
@ -47,5 +47,5 @@ export interface FetchImageRequest {
}
export interface ExtensionPopupInitData {
isAddingNote: boolean;
isAdding: boolean;
}

@ -14,6 +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 { ObjUrlDto } from './obj.dto';
export interface ObjNoteDto {
title: string;
value: string;
url?: ObjUrlDto;
}

@ -0,0 +1,23 @@
/*
* 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 { ObjUrlDto } from './obj.dto';
export interface ObjTaskDto {
title: string;
description: string;
url?: ObjUrlDto;
}

@ -17,6 +17,7 @@
import { ObjNoteDto } from './obj-note.dto';
import { ObjPagePinDto } from './obj-pin.dto';
import { ObjSnapshotDto } from './obj-snapshot.dto';
import { ObjTaskDto } from './obj-task.dto';
export const OBJ_DTO_VERSION = 1;
@ -46,6 +47,7 @@ export enum ObjTypeDto {
}
export type ObjDataDto = ObjPagePinDto | ObjSnapshotDto | ObjNoteDto;
export type ObjPageDataDto = ObjPagePinDto | ObjSnapshotDto | ObjNoteDto | ObjTaskDto;
export interface ObjDto<T = ObjDataDto> {
id: number;

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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
@ -19,17 +19,19 @@ import { ObjUrlDto } from '../model/obj/obj.dto';
export class LinkHrefOriginStore {
private static PIN_HREF = 'pin:href';
private static PIN_ORIGIN = 'pin:origin';
private static OBJ_HREF = 'obj:href';
private static OBJ_ORIGIN = 'obj:origin';
static async addHrefOriginId(url: ObjUrlDto, id: number): Promise<void> {
// Update hrefs
const hrefIds = await this.hrefIds(url.href);
hrefIds.push(id);
await BrowserStorageWrapper.set(`${this.PIN_HREF}:${url.href}`, hrefIds);
await BrowserStorageWrapper.set(`${this.OBJ_HREF}:${url.href}`, hrefIds);
// Update origin
const originIds = await this.originIds(url.origin);
originIds.push(id);
await BrowserStorageWrapper.set(`${this.PIN_ORIGIN}:${url.origin}`, originIds);
await BrowserStorageWrapper.set(`${this.OBJ_ORIGIN}:${url.origin}`, originIds);
}
static async delHrefOriginId(url: ObjUrlDto, id: number): Promise<void> {
@ -37,28 +39,50 @@ export class LinkHrefOriginStore {
const hrefIds = await this.hrefIds(url.href);
const newHref = hrefIds.filter((i) => i !== id);
if (newHref.length === 0) {
await BrowserStorageWrapper.remove(`${this.PIN_HREF}:${url.href}`);
await BrowserStorageWrapper.remove(`${this.OBJ_HREF}:${url.href}`);
} else {
await BrowserStorageWrapper.set(`${this.PIN_HREF}:${url.href}`, newHref);
await BrowserStorageWrapper.set(`${this.OBJ_HREF}:${url.href}`, newHref);
}
// Update origin
const originIds = await this.originIds(url.origin);
const newOrigin = originIds.filter((i) => i !== id);
if (newOrigin.length === 0) {
await BrowserStorageWrapper.remove(`${this.PIN_ORIGIN}:${url.origin}`);
await BrowserStorageWrapper.remove(`${this.OBJ_ORIGIN}:${url.origin}`);
} else {
await BrowserStorageWrapper.set(`${this.PIN_ORIGIN}:${url.origin}`, newOrigin);
await BrowserStorageWrapper.set(`${this.OBJ_ORIGIN}:${url.origin}`, newOrigin);
}
}
static async hrefIds(url: string): Promise<number[]> {
const key = `${this.PIN_HREF}:${url}`;
const key = `${this.OBJ_HREF}:${url}`;
const value = await BrowserStorageWrapper.get<number[] | undefined>(key);
return value || [];
}
static async originIds(url: string): Promise<number[]> {
const key = `${this.PIN_ORIGIN}:${url}`;
const key = `${this.OBJ_ORIGIN}:${url}`;
const value = await BrowserStorageWrapper.get<number[] | undefined>(key);
return value || [];
}
static async pinAdd(url: ObjUrlDto, id: number): Promise<void> {
const hrefIds = await this.pinIds(url.href);
hrefIds.push(id);
await BrowserStorageWrapper.set(`${this.PIN_HREF}:${url.href}`, hrefIds);
}
static async pinDel(url: ObjUrlDto, id: number): Promise<void> {
const hrefIds = await this.pinIds(url.href);
const newHref = hrefIds.filter((i) => i !== id);
if (newHref.length === 0) {
await BrowserStorageWrapper.remove(`${this.PIN_HREF}:${url.href}`);
} else {
await BrowserStorageWrapper.set(`${this.PIN_HREF}:${url.href}`, newHref);
}
}
static async pinIds(url: string): Promise<number[]> {
const key = `${this.PIN_HREF}:${url}`;
const value = await BrowserStorageWrapper.get<number[] | undefined>(key);
return value || [];
}

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -77,9 +77,11 @@ export class WordIndex {
await BrowserStorageWrapper.set<number[]>(key, arr);
};
private static saveWord = async (word: string) => {
private static saveWord = async (word: string): Promise<void> => {
if (word.length < 3) return;
const start = word.substring(0, 2);
await this.saveStartIndex(start);
const key = `${ObjectStoreKeys.SEARCH_WORD}:${start}`;
let arr = await BrowserStorageWrapper.get<string[]>(key);
if (arr) {
@ -107,4 +109,17 @@ export class WordIndex {
await BrowserStorageWrapper.set<string[]>(key, arr);
}
};
private static saveStartIndex = async (start: string): Promise<void> => {
const key = `${ObjectStoreKeys.SEARCH_START}`;
let arr = await BrowserStorageWrapper.get<string[]>(key);
if (arr) {
const idx = arr.indexOf(start);
if (idx !== -1) return;
arr.push(start);
} else {
arr = [start];
}
await BrowserStorageWrapper.set<string[]>(key, arr);
};
}

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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
@ -23,7 +23,7 @@ import { UrlFactory } from '../../../common/factory/url.factory';
export class RuntimePinGetHrefCommand implements ICommand<Promise<void>> {
async execute(): Promise<void> {
const data = await new PinGetHrefCommand(UrlFactory.newUrl(), true).execute();
const data = await new PinGetHrefCommand(UrlFactory.newUrl()).execute();
PinStore.clear();
for (const pin of data) {
new PinAddXpathCommand(pin).execute();

@ -71,11 +71,12 @@ export class EditBarParentButton implements HtmlComponent<HTMLElement> {
skipUrlCache: new Set<string>(),
isPartial: true
});
const html = HtmlFactory.computeHtmlParent(this.parent.ref.parentElement, htmlContent.html, true);
// snapshot content
const key = `${ObjectStoreKeys.CONTENT_ID}:${this.parent.object.data.snapshot.contentId}`;
const snapshot = await BrowserStorageWrapper.get<ObjSnapshotContentDto>(key);
snapshot.html = htmlContent.html;
snapshot.html = html;
snapshot.video = htmlContent.video;
snapshot.content = htmlContent.content;
await BrowserStorageWrapper.set(key, snapshot);

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -95,7 +95,7 @@ export class ContentMessageHandler {
private static handlePopupOpen = async (): Promise<void> => {
const data: ExtensionPopupInitData = {
isAddingNote: !!PinAddFactory.currentElement
isAdding: !!PinAddFactory.currentElement
};
fnConsoleLog('ContentMessageHandler->handlePopupOpen', data);
await BrowserApi.sendRuntimeMessage<ExtensionPopupInitData>({ type: BusMessageType.POPUP_INIT, data });

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -37,6 +37,7 @@ export const AccountDetailsComponent: FunctionComponent<AccountDetailsComponentP
const [responseError, setResponseError] = useState<ServerErrorDto | undefined>(undefined);
useEffect(() => {
LogManager.log(`AccountDetailsComponent init`);
if (PopupTokenStore.token) {
setTokenData(jwtDecode<TokenDataDto>(PopupTokenStore.token.access_token));
}

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -16,7 +16,7 @@
*/
export enum MainViewEnum {
CREATE_LIST = 1,
PIN,
PAGE_OBJECTS,
TASK,
NOTE,
ENCRYPT,

@ -32,16 +32,13 @@ export const EncryptMessageComponent: FunctionComponent<EncryptMessageComponentP
const [usernameList, setUsernameList] = useState<string[]>([]);
const [message, setMessage] = useState<string>(props.message.message);
const reloadList = async () => {
const list = await CryptoStore.getUsernameKeyList();
setUsernameList(list);
};
useEffect(() => {
setTimeout(async () => {
await reloadList();
}, 0);
});
// eslint-disable-next-line @typescript-eslint/no-floating-promises
(async () => {
const list = await CryptoStore.getUsernameKeyList();
setUsernameList(list);
})();
}, []);
const handleUsernameChange = (e: React.SyntheticEvent, value: string | null) => {
if (value) setUsername(value);

@ -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 React, { FunctionComponent, useEffect, useState } from 'react';
import React, { FunctionComponent } from 'react';
import AddIcon from '@mui/icons-material/Add';
import { BrowserApi } from '../../../common/service/browser.api.wrapper';
import { BusMessageType } from '../../../common/model/bus.model';
@ -25,7 +25,6 @@ import { MainViewEnum } from '../component-model';
import { ObjTypeDto } from '../../../common/model/obj/obj.dto';
import { PopupActiveTabStore } from '../../store/popup-active-tab.store';
import { PopupPinStartRequest } from '../../../common/model/obj-request.model';
import { TinyEventDispatcher } from '../../../common/service/tiny.event.dispatcher';
interface CreateComponentProps {
currentView: MainViewEnum;
@ -34,17 +33,6 @@ interface CreateComponentProps {
}
export const MainHeaderComponent: FunctionComponent<CreateComponentProps> = (props) => {
const [isAdding, setIsAdding] = useState<boolean>(PopupActiveTabStore.isAddingNote);
useEffect(() => {
const addKey = TinyEventDispatcher.addListener(BusMessageType.POP_UPDATE_ADDING, () => {
setIsAdding(PopupActiveTabStore.isAddingNote);
});
return () => {
TinyEventDispatcher.removeListener(BusMessageType.POP_UPDATE_ADDING, addKey);
};
});
const handleNewPin = async () => {
try {
if (!PopupActiveTabStore.url) return;
@ -72,7 +60,7 @@ export const MainHeaderComponent: FunctionComponent<CreateComponentProps> = (pro
window.close();
};
const pinBtn = isAdding ? (
const pinBtn = PopupActiveTabStore.isAdding ? (
<Button sx={{ width: '100%' }} variant="outlined" onClick={handlePinStop}>
Cancel
</Button>

@ -51,14 +51,14 @@ enum IsLoadingType {
PageSave
}
export const MainCreateListComponent: FunctionComponent<CreateListProps> = (props) => {
export const MainMenuListComponent: FunctionComponent<CreateListProps> = (props) => {
const [isLoading, setIsLoading] = useState<IsLoadingType>(IsLoadingType.None);
const handleSavePageClick = async () => {
TinyEventDispatcher.addListener<string>(BusMessageType.POPUP_PAGE_SNAPSHOT_ADD, (event, key) => {
TinyEventDispatcher.removeListener(event, key);
setIsLoading(IsLoadingType.None);
setTimeout(() => props.closeListCallback(MainViewEnum.PIN), 100);
setTimeout(() => props.closeListCallback(MainViewEnum.PAGE_OBJECTS), 100);
});
await BrowserApi.sendTabMessage({ type: BusMessageType.POPUP_PAGE_SNAPSHOT_ADD, data: PopupActiveTabStore.url });
setIsLoading(IsLoadingType.PageSave);
@ -73,7 +73,7 @@ export const MainCreateListComponent: FunctionComponent<CreateListProps> = (prop
type: ObjTypeDto.PageElementSnapshot
}
});
props.closeListCallback(MainViewEnum.PIN);
props.closeListCallback(MainViewEnum.PAGE_OBJECTS);
window.close();
};
@ -95,11 +95,11 @@ export const MainCreateListComponent: FunctionComponent<CreateListProps> = (prop
</ListItemButton>
</ListItem>
<ListItem sx={zeroPad}>
<ListItemButton onClick={() => props.closeListCallback(MainViewEnum.PIN)}>
<ListItemButton onClick={() => props.closeListCallback(MainViewEnum.PAGE_OBJECTS)}>
<ListItemIcon>
<PushPinIcon />
</ListItemIcon>
<ListItemText primary="Show Pins" />
<ListItemText primary="Show Page Objects" />
</ListItemButton>
</ListItem>
<ListItem sx={zeroPad} style={{ display: 'none' }}>

@ -18,12 +18,12 @@ import React, { FunctionComponent, ReactElement, useState } from 'react';
import { CalendarComponent } from '../calendar/calendar.component';
import { DecryptComponent } from '../decrypt/decrypt.component';
import { EncryptComponent } from '../encrypt/encrypt.component';
import { MainCreateListComponent } from './main-create-list.component';
import { MainFooterButton } from './main-footer.button';
import { MainHeaderComponent } from './main-header.component';
import { MainMenuListComponent } from './main-menu-list.component';
import { MainViewEnum } from '../component-model';
import { NoteComponent } from '../note/note.component';
import { PinListViewComponent } from '../pins/pin-list-view.component';
import { ObjListViewComponent } from '../obj/obj-list-view.component';
import { PopupFunctionsComponent } from '../popup-functions/popup-functions.component';
import { TaskComponent } from '../task/task.component';
@ -33,9 +33,9 @@ const getViewComponent = (
): ReactElement | undefined => {
switch (viewType) {
case MainViewEnum.CREATE_LIST:
return <MainCreateListComponent closeListCallback={closeListCallback} />;
case MainViewEnum.PIN:
return <PinListViewComponent />;
return <MainMenuListComponent closeListCallback={closeListCallback} />;
case MainViewEnum.PAGE_OBJECTS:
return <ObjListViewComponent />;
case MainViewEnum.ENCRYPT:
return <EncryptComponent />;
case MainViewEnum.DECRYPT:
@ -52,8 +52,8 @@ const getViewComponent = (
};
export const MainViewComponent: FunctionComponent = () => {
const [previousView, setPreviousView] = useState<MainViewEnum>(MainViewEnum.PIN);
const [currentView, setCurrentView] = useState<MainViewEnum>(MainViewEnum.PIN);
const [previousView, setPreviousView] = useState<MainViewEnum>(MainViewEnum.PAGE_OBJECTS);
const [currentView, setCurrentView] = useState<MainViewEnum>(MainViewEnum.PAGE_OBJECTS);
const changeMainTab = (viewType: MainViewEnum) => {
setPreviousView(currentView);

@ -14,38 +14,50 @@
* 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, ObjPageDataDto } from '../../../common/model/obj/obj.dto';
import React, { FunctionComponent, useEffect, useState } from 'react';
import { BusMessageType } from '../../../common/model/bus.model';
import { ObjDto } from '../../../common/model/obj/obj.dto';
import { ObjPagePinDto } from '../../../common/model/obj/obj-pin.dto';
import { PinListComponent } from './pin-list.component';
import { ObjGetHrefCommand } from '../../../common/command/obj/url/obj-get-href.command';
import { ObjGetOriginCommand } from '../../../common/command/obj/url/obj-get-origin.command';
import { ObjListComponent } from './obj-list.component';
import { PopupActiveTabStore } from '../../store/popup-active-tab.store';
import { TinyEventDispatcher } from '../../../common/service/tiny.event.dispatcher';
import Typography from '@mui/material/Typography';
export const PinListViewComponent: FunctionComponent = () => {
const [originPins, setOriginPins] = useState<ObjDto<ObjPagePinDto>[]>(PopupActiveTabStore.originPins);
const [hrefPins, setHrefPins] = useState<ObjDto<ObjPagePinDto>[]>(PopupActiveTabStore.hrefPins);
export const ObjListViewComponent: FunctionComponent = () => {
const [originObjs, setOriginObjs] = useState<ObjDto<ObjPageDataDto>[]>([]);
const [hrefObjs, setHrefObjs] = useState<ObjDto<ObjPageDataDto>[]>([]);
useEffect(() => {
const urlKey = TinyEventDispatcher.addListener(BusMessageType.POP_UPDATE_URL, () => {
setHrefPins(PopupActiveTabStore.hrefPins);
setOriginPins(PopupActiveTabStore.originPins);
// eslint-disable-next-line @typescript-eslint/no-floating-promises
(async () => {
await initUrl();
})();
const urlKey = TinyEventDispatcher.addListener(BusMessageType.POP_UPDATE_URL, async () => {
await initUrl();
});
return () => {
TinyEventDispatcher.removeListener(BusMessageType.POP_UPDATE_URL, urlKey);
};
});
}, []);
const initUrl = async () => {
if (!PopupActiveTabStore.url) return;
const href = await new ObjGetHrefCommand(PopupActiveTabStore.url).execute();
const origin = await new ObjGetOriginCommand(PopupActiveTabStore.url).execute();
setHrefObjs(href);
setOriginObjs(origin);
};
return (
<div>
<Typography fontWeight="bold" fontSize="14px">
On this page
</Typography>
<PinListComponent pinList={hrefPins} visibility={true} />
<ObjListComponent objList={hrefObjs} visibility={true} />
<Typography fontWeight="bold" fontSize="14px">
On {PopupActiveTabStore.url?.origin}
</Typography>
<PinListComponent pinList={originPins} visibility={false} />
<ObjListComponent objList={originObjs} visibility={false} />
</div>
);
};

@ -0,0 +1,69 @@
/*
* 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 { ObjDto, ObjPageDataDto, ObjTypeDto } from '../../../common/model/obj/obj.dto';
import React, { FunctionComponent, useState } from 'react';
import { BrowserApi } from '../../../common/service/browser.api.wrapper';
import { BusMessageType } from '../../../common/model/bus.model';
import { ObjPagePinDto } from '../../../common/model/obj/obj-pin.dto';
import { ObjSnapshotDto } from '../../../common/model/obj/obj-snapshot.dto';
import { PinListElement } from './pin-list-element.component';
import { PinRemoveCommand } from '../../../common/command/pin/pin-remove.command';
interface PinListProps {
objList: ObjDto<ObjPageDataDto>[];
visibility: boolean;
}
export const ObjListComponent: FunctionComponent<PinListProps> = ({ objList, visibility }) => {
const [reRender, setReRender] = useState(false);
const handleRemove = async (data: ObjDto<ObjPagePinDto>) => {
await new PinRemoveCommand(data).execute();
await BrowserApi.sendTabMessage<number>({ type: BusMessageType.CONTENT_PIN_REMOVE, data: data.id });
for (let i = 0; i < objList.length; i++) {
const pin = objList[i];
if (pin.id === data.id) {
objList.splice(i, 1);
setReRender(!reRender);
break;
}
}
};
// Render pins
const objs: React.ReactNode[] = [];
for (const obj of objList) {
if (obj.type === ObjTypeDto.PageElementPin) {
objs.push(
<PinListElement
visibility={visibility}
key={obj.id}
pin={obj as ObjDto<ObjPagePinDto>}
removeCallback={handleRemove}
/>
);
} else if (obj.type === ObjTypeDto.PageElementSnapshot) {
const o = obj.data as ObjSnapshotDto;
objs.push(<div>{o.title}</div>);
}
}
return (
<div style={{ width: '100%' }}>
<div style={{ width: '100%' }}>{objs}</div>
</div>
);
};

@ -27,10 +27,7 @@ import { ObjDto } from '../../../common/model/obj/obj.dto';
import { ObjPagePinDto } from '../../../common/model/obj/obj-pin.dto';
import { ObjectStoreKeys } from '../../../common/keys/object.store.keys';
import { PinElementExpandComponent } from './pin-element-expand.component';
import { PinRemoveCommand } from '../../../common/command/pin/pin-remove.command';
import { PinUpdateCommand } from '../../../common/command/pin/pin-update.command';
import RemoveMarkdown from 'remove-markdown';
import { TinyEventDispatcher } from '../../../common/service/tiny.event.dispatcher';
import Typography from '@mui/material/Typography';
import VisibilityIcon from '@mui/icons-material/Visibility';
import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
@ -38,11 +35,12 @@ import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
interface PinListElementProps {
pin: ObjDto<ObjPagePinDto>;
visibility: boolean;
removeCallback: (pin: ObjDto<ObjPagePinDto>) => void;
}
export const PinListElement: FunctionComponent<PinListElementProps> = ({ pin, visibility }) => {
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
const [isVisible, setIsVisible] = useState(pin.local?.visible);
export const PinListElement: FunctionComponent<PinListElementProps> = (props) => {
const [isExpanded, setIsExpanded] = useState(false);
const [isVisible, setIsVisible] = useState(props.pin.local?.visible);
const handlePinGo = async (data: ObjDto<ObjPagePinDto>): Promise<void> => {
data.local.visible = true;
await new PinUpdateCommand(data).execute();
@ -59,34 +57,32 @@ export const PinListElement: FunctionComponent<PinListElementProps> = ({ pin, vi
setIsVisible(data.local.visible);
};
const handlePinRemove = async (data: ObjDto<ObjPagePinDto>): Promise<void> => {
await new PinRemoveCommand(data).execute();
await BrowserApi.sendTabMessage<number>({ type: BusMessageType.CONTENT_PIN_REMOVE, data: data.id });
TinyEventDispatcher.dispatch(BusMessageType.POP_PIN_REMOVE, data);
const handlePinRemove = (data: ObjDto<ObjPagePinDto>): void => {
props.removeCallback(data);
};
const handlePopover = (): void => {
setIsPopoverOpen(!isPopoverOpen);
setIsExpanded(!isExpanded);
};
const expandIcon = isPopoverOpen ? (
const expandIcon = isExpanded ? (
<ExpandMoreIcon sx={{ fontSize: '12px' }} />
) : (
<NavigateNextIcon sx={{ fontSize: '12px' }} />
);
const visibleIcon = visibility ? (
<IconButton size="small" onClick={() => handlePinVisible(pin)}>
const visibleIcon = props.visibility ? (
<IconButton size="small" onClick={() => handlePinVisible(props.pin)}>
{isVisible ? <VisibilityIcon sx={{ fontSize: '12px' }} /> : <VisibilityOffIcon sx={{ fontSize: '12px' }} />}
</IconButton>
) : (
''
);
const value = RemoveMarkdown(pin.data.value);
const value = props.pin.data.snapshot.title;
const title = value.length > 30 ? `${value.substring(0, 30)}...` : value;
return (
<div key={pin.id} style={{ width: '100%', marginBottom: 15 }}>
<div key={props.pin.id} style={{ width: '100%', marginBottom: 15 }}>
<div
style={{
display: 'flex',
@ -113,15 +109,15 @@ export const PinListElement: FunctionComponent<PinListElementProps> = ({ pin, vi
}}
>
{visibleIcon}
<IconButton title="Go to pin" size="small" onClick={() => handlePinGo(pin)}>
<IconButton title="Go to pin" size="small" onClick={() => handlePinGo(props.pin)}>
<ArrowForwardIcon sx={{ fontSize: '12px' }} />
</IconButton>
<IconButton title="Remove pin" size="small" onClick={() => handlePinRemove(pin)}>
<IconButton title="Remove pin" size="small" onClick={() => handlePinRemove(props.pin)}>
<CloseIcon sx={{ fontSize: '12px' }} />
</IconButton>
</div>
</div>
<PinElementExpandComponent visible={isPopoverOpen} pin={pin}></PinElementExpandComponent>
<PinElementExpandComponent visible={isExpanded} pin={props.pin}></PinElementExpandComponent>
</div>
);
};

@ -1,64 +0,0 @@
/*
* 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 React, { FunctionComponent, useEffect, useState } from 'react';
import { BusMessageType } from '../../../common/model/bus.model';
import { ObjDto } from '../../../common/model/obj/obj.dto';
import { ObjPagePinDto } from '../../../common/model/obj/obj-pin.dto';
import { PinListElement } from './pin-list-element.component';
import { TinyEventDispatcher } from '../../../common/service/tiny.event.dispatcher';
interface PinListProps {
pinList: ObjDto<ObjPagePinDto>[];
visibility: boolean;
}
export const PinListComponent: FunctionComponent<PinListProps> = ({ pinList, visibility }) => {
const [reRender, setReRender] = useState(false);
useEffect(() => {
const removeKey = TinyEventDispatcher.addListener<ObjDto<ObjPagePinDto>>(
BusMessageType.POP_PIN_REMOVE,
(event, key, value) => {
if (value.data.snapshot.url.href === pinList[0].data.snapshot.url.href) {
for (let i = 0; i < pinList.length; i++) {
const pin = pinList[i];
if (pin.id === value.id) {
pinList.splice(i, 1);
break;
}
}
// Refresh state so component re-renders
setReRender(!reRender);
}
}
);
return () => {
TinyEventDispatcher.removeListener(BusMessageType.POP_PIN_REMOVE, removeKey);
};
});
// Render pins
const pins: React.ReactNode[] = [];
for (const pin of pinList) {
pins.push(<PinListElement visibility={visibility} key={pin.id} pin={pin} />);
}
return (
<div style={{ width: '100%' }}>
<div style={{ width: '100%' }}>{pins}</div>
</div>
);
};

@ -31,7 +31,7 @@ export const MainTabComponent: FunctionComponent = () => {
return () => {
TinyEventDispatcher.removeListener(BusMessageType.POP_UPDATE_URL, urlKey);
};
});
}, []);
return (
<div style={{ marginTop: 10, height: '100%' }}>

@ -19,7 +19,7 @@ import '@fontsource/roboto/400.css';
import '@fontsource/roboto/500.css';
import '@fontsource/roboto/700.css';
import React, { ReactElement, useState } from 'react';
import React, { ReactElement, useEffect, useState } from 'react';
import { AccountTabComponent } from './components/tabs/account-tab.component';
import Box from '@mui/material/Box';
import { LogManager } from '../common/popup/log.manager';
@ -59,6 +59,14 @@ const getCurrentPanel = (selectedPanel: PanelEnum): ReactElement | undefined =>
const ExtensionPopupApp: React.FC = () => {
const [selectedPanel, setSelectedPanel] = useState<PanelEnum>(PanelEnum.MAIN);
useEffect(() => {
LogManager.log('ExtensionPopupApp->init !!!');
// eslint-disable-next-line @typescript-eslint/no-floating-promises
(async () => {
await PopupMessageHandler.init();
})();
}, []);
const handleChange = (event: React.SyntheticEvent, newValue: PanelEnum) => {
setSelectedPanel(newValue);
};
@ -101,14 +109,3 @@ if (el) {
const root = createRoot(el);
root.render(<ExtensionPopupApp />);
}
try {
PopupMessageHandler.init()
.then((ack: any) => {
LogManager.log(`FIREFOX SENDS EMPTY ACK :/!!! ${JSON.stringify(ack)}`);
})
.catch((e) => {
LogManager.log(`Error ${JSON.stringify(e)}`);
});
} catch (e) {
LogManager.log(`Error ${JSON.stringify(e)}`);
}

@ -17,7 +17,6 @@
import { BrowserGlobalSender, BusMessage, BusMessageType } from '../common/model/bus.model';
import { BrowserApi } from '../common/service/browser.api.wrapper';
import { ExtensionPopupInitData } from '../common/model/obj-request.model';
import { LogManager } from '../common/popup/log.manager';
import { PopupActiveTabStore } from './store/popup-active-tab.store';
import { PopupTokenStore } from './store/popup-token.store';
import { TinyEventDispatcher } from '../common/service/tiny.event.dispatcher';
@ -30,14 +29,13 @@ export class PopupMessageHandler {
await PopupTokenStore.init();
await BrowserApi.sendTabMessage({ type: BusMessageType.POPUP_OPEN });
this.popupInitListener();
await BrowserApi.sendTabMessage({ type: BusMessageType.POPUP_OPEN });
}
private static popupInitListener(): void {
TinyEventDispatcher.addListener<ExtensionPopupInitData>(BusMessageType.POPUP_INIT, (event, key, value) => {
LogManager.log(`!!! INIT - ${event} ${JSON.stringify(value || {})}`);
PopupActiveTabStore.updateState(value);
});
}

@ -14,14 +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 { ObjDto, ObjUrlDto } from '../../common/model/obj/obj.dto';
import { BrowserApi } from '../../common/service/browser.api.wrapper';
import { BusMessageType } from '../../common/model/bus.model';
import { ExtensionPopupInitData } from '../../common/model/obj-request.model';
import { LogManager } from '../../common/popup/log.manager';
import { ObjPagePinDto } from '../../common/model/obj/obj-pin.dto';
import { PinGetHrefCommand } from '../../common/command/pin/pin-get-href.command';
import { PinGetOriginCommand } from '../../common/command/pin/pin-get-origin.command';
import { ObjGetHrefCommand } from '../../common/command/obj/url/obj-get-href.command';
import { ObjGetOriginCommand } from '../../common/command/obj/url/obj-get-origin.command';
import { ObjUrlDto } from '../../common/model/obj/obj.dto';
import { TinyEventDispatcher } from '../../common/service/tiny.event.dispatcher';
import { UrlFactory } from '../../common/factory/url.factory';
@ -29,29 +28,14 @@ export class PopupActiveTabStore {
private static urlValue?: ObjUrlDto;
private static isError = false;
private static extensionUrl = false;
private static isAddingNoteValue = false;
private static originPinsValue: ObjDto<ObjPagePinDto>[] = [];
private static hrefPinsValue: ObjDto<ObjPagePinDto>[] = [];
private static isAddingValue = false;
static get originPins(): ObjDto<ObjPagePinDto>[] {
return this.originPinsValue;
}
private static hrefData: any[] = [];
private static originData: any[] = [];
static set originPins(value: ObjDto<ObjPagePinDto>[]) {
this.originPinsValue = value;
}
static get hrefPins(): ObjDto<ObjPagePinDto>[] {
return this.hrefPinsValue;
}
static set hrefPins(value: ObjDto<ObjPagePinDto>[]) {
this.hrefPinsValue = value;
}
static get isAddingNote(): boolean {
return this.isAddingNoteValue;
static get isAdding(): boolean {
return this.isAddingValue;
}
static get url(): ObjUrlDto | undefined {
@ -71,14 +55,14 @@ export class PopupActiveTabStore {
if (tab.url) {
const url = new URL(tab.url);
this.urlValue = {
href: UrlFactory.normalizeHref(tab.url),
href: UrlFactory.normalizeHref(url.href),
origin: UrlFactory.normalizeOrigin(url.origin),
pathname: url.pathname,
search: url.search
};
LogManager.log(`updateState URL : ${JSON.stringify(this.urlValue)}`);
PopupActiveTabStore.hrefPins = await new PinGetHrefCommand(this.urlValue).execute();
PopupActiveTabStore.originPins = await new PinGetOriginCommand(this.urlValue).execute();
this.hrefData = await new ObjGetHrefCommand(this.urlValue).execute();
this.originData = await new ObjGetOriginCommand(this.urlValue).execute();
if (this.urlValue?.href.startsWith(BrowserApi.startUrl)) {
this.extensionUrl = true;
this.isError = true;
@ -90,11 +74,10 @@ export class PopupActiveTabStore {
};
static updateState = (initData?: ExtensionPopupInitData) => {
if (initData?.isAddingNote) {
// TODO fix this - use parent always
// Any true is valid because we can be inside iframe
this.isAddingNoteValue = true;
TinyEventDispatcher.dispatch<void>(BusMessageType.POP_UPDATE_ADDING);
LogManager.log(`PopupActiveTabStore->INIT - ${JSON.stringify(initData || {})}`);
if (initData?.isAdding) {
this.isAddingValue = true;
TinyEventDispatcher.dispatch<void>(BusMessageType.POP_IS_ADDING);
}
};
}

@ -148,7 +148,7 @@ export const HtmlPreviewComponent: FunctionComponent = () => {
sizeRef.current.innerHTML = `${fnByteToMb(size)} MB`;
}
if (titleRef.current) {
titleRef.current.innerText = s.title;
titleRef.current.innerHTML = s.title;
}
if (urlRef.current) {
urlRef.current.innerHTML = `<a href="${s.url.href}">${s.url.href}</a>`;

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -41,7 +41,7 @@ export class OptionsMessageHandler {
private static handlePopupOpen = async (): Promise<void> => {
await BrowserApi.sendRuntimeMessage<ExtensionPopupInitData>({
type: BusMessageType.POPUP_INIT,
data: { isAddingNote: false }
data: { isAdding: false }
});
};
}

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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
@ -14,10 +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 { ObjDataDto, ObjDto } from '../../../common/model/obj/obj.dto';
import { ObjRangeRequest, ObjRangeResponse } from 'src/common/model/obj-request.model';
import { BrowserStorageWrapper } from '../../../common/service/browser.storage.wrapper';
import { ICommand } from '../../../common/model/shared/common.dto';
import { ObjDto } from '../../../common/model/obj/obj.dto';
import { ObjRangeIdCommand } from '../../../common/command/obj/id/obj-range-id.command';
import { ObjectStoreKeys } from '../../../common/keys/object.store.keys';
import { fnConsoleLog } from '../../../common/fn/console.fn';
@ -40,7 +40,7 @@ export class OptionsObjGetRangeCommand implements ICommand<Promise<ObjRangeRespo
for (let i = 0; i < data.ids.length; i++) {
const key = `${ObjectStoreKeys.OBJECT_ID}:${data.ids[i]}`;
const obj = await BrowserStorageWrapper.get<ObjDto<ObjDataDto>>(key);
const obj = await BrowserStorageWrapper.get<ObjDto>(key);
out.push(obj);
}
return {
@ -48,9 +48,4 @@ export class OptionsObjGetRangeCommand implements ICommand<Promise<ObjRangeRespo
data: out
};
}
private async getListId(): Promise<number> {
const value = await BrowserStorageWrapper.get<number | undefined>(ObjectStoreKeys.OBJECT_LIST_ID);
return value || 1;
}
}

@ -1,6 +1,6 @@
/*
* This file is part of the pinmenote-extension distribution (https://github.com/pinmenote/pinmenote-extension).
* Copyright (c) 2022 Michal Szczepanski.
* 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