feat: sync get changes from server
This commit is contained in:
parent
4e3cb1f889
commit
9c8f0804e7
@ -1,10 +1,8 @@
|
||||
#!/bin/bash
|
||||
export NODE_ENV=development
|
||||
# swap manifests
|
||||
mv src/manifest.json src/manifest.dev.json
|
||||
mv src/manifest.ch.json src/manifest.json
|
||||
cp src/manifest.ch.json src/manifest.json
|
||||
# build
|
||||
npm run prod
|
||||
# swap manifests back
|
||||
mv src/manifest.json src/manifest.ch.json
|
||||
mv src/manifest.dev.json src/manifest.json
|
||||
cp src/manifest.dev.json src/manifest.json
|
@ -1,10 +1,8 @@
|
||||
#!/bin/bash
|
||||
export NODE_ENV=production
|
||||
# swap manifests
|
||||
mv src/manifest.json src/manifest.dev.json
|
||||
mv src/manifest.ch.json src/manifest.json
|
||||
cp src/manifest.ch.json src/manifest.json
|
||||
# build
|
||||
npm run prod
|
||||
# swap manifests back
|
||||
mv src/manifest.json src/manifest.ch.json
|
||||
mv src/manifest.dev.json src/manifest.json
|
||||
cp src/manifest.dev.json src/manifest.json
|
@ -1,10 +1,8 @@
|
||||
#!/bin/bash
|
||||
export NODE_ENV=development
|
||||
# swap manifests
|
||||
mv src/manifest.json src/manifest.ch.json
|
||||
mv src/manifest.ff.json src/manifest.json
|
||||
cp src/manifest.ff.json src/manifest.json
|
||||
# build
|
||||
npm run dev:ff
|
||||
# swap manifests back
|
||||
mv src/manifest.json src/manifest.ff.json
|
||||
mv src/manifest.ch.json src/manifest.json
|
||||
cp src/manifest.dev.json src/manifest.json
|
@ -1,10 +1,8 @@
|
||||
#!/bin/bash
|
||||
export NODE_ENV=production
|
||||
# swap manifests
|
||||
mv src/manifest.json src/manifest.dev.json
|
||||
mv src/manifest.ff.json src/manifest.json
|
||||
cp src/manifest.ff.json src/manifest.json
|
||||
# build
|
||||
npm run prod:ff
|
||||
# swap manifests back
|
||||
mv src/manifest.json src/manifest.ff.json
|
||||
mv src/manifest.dev.json src/manifest.json
|
||||
cp src/manifest.dev.json src/manifest.json
|
@ -34,10 +34,6 @@ export class ObjGetOriginCommand implements ICommand<Promise<ObjDto<ObjPageDataD
|
||||
const out: ObjDto<ObjPageDataDto>[] = [];
|
||||
for (const id of pinIds) {
|
||||
const obj = await new ObjGetCommand<ObjPageDataDto | ObjPinDto>(id).execute();
|
||||
if (!obj) {
|
||||
fnConsoleLog('PROBLEM !!!!!!!!!');
|
||||
continue;
|
||||
}
|
||||
if ([ObjTypeDto.PageSnapshot, ObjTypeDto.PageElementSnapshot].includes(obj.type)) {
|
||||
if ((obj.data as ObjPageDto).snapshot.info.url.href === this.data.href) continue;
|
||||
} else if (obj.type === ObjTypeDto.PageElementPin) {
|
||||
@ -48,8 +44,6 @@ export class ObjGetOriginCommand implements ICommand<Promise<ObjDto<ObjPageDataD
|
||||
if ((obj.data as ObjPdfDto).data.rawUrl === this.data.href) continue;
|
||||
}
|
||||
out.push(obj);
|
||||
// TODO pagination - now show last 10
|
||||
if (out.length === 10) break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ export const LoginComponent: FunctionComponent<Props> = ({ loginSuccess }) => {
|
||||
if (value.ok) {
|
||||
loginSuccess(value.data);
|
||||
} else {
|
||||
setResponseError(value.data as ServerErrorDto);
|
||||
setResponseError(value.data as any as ServerErrorDto);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
43
src/manifest.dev.json
Normal file
43
src/manifest.dev.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "pinmenote-dev",
|
||||
"short_name": "pinmenote-dev",
|
||||
"description": "Pin note, modify, draw, comment and archive websites.",
|
||||
"version": "0.1.0",
|
||||
"icons": {
|
||||
"16": "assets/icon/16.png",
|
||||
"32": "assets/icon/32.png",
|
||||
"64": "assets/icon/64.png",
|
||||
"128": "assets/icon/128.png"
|
||||
},
|
||||
"author": "pinmenote (contact@pintmenote.com)",
|
||||
"action": {
|
||||
"default_icon": {
|
||||
"16": "assets/icon/16.png",
|
||||
"24": "assets/icon/24.png",
|
||||
"32": "assets/icon/32.png"
|
||||
},
|
||||
"default_title": "pinmenote",
|
||||
"default_popup": "default-popup/default-popup.html"
|
||||
},
|
||||
"permissions": ["activeTab", "storage", "unlimitedStorage", "scripting", "downloads"],
|
||||
"host_permissions": ["<all_urls>"],
|
||||
"background": {
|
||||
"service_worker": "service-worker/service-worker.ts",
|
||||
"type": "module"
|
||||
},
|
||||
"content_scripts": [{
|
||||
"matches": ["<all_urls>"],
|
||||
"all_frames": false,
|
||||
"js": ["content-script/content-script.ts"],
|
||||
"run_at": "document_start"
|
||||
},{
|
||||
"matches": ["<all_urls>"],
|
||||
"all_frames": true,
|
||||
"js": ["iframe/iframe-script.ts"],
|
||||
"run_at": "document_idle"
|
||||
}],
|
||||
"options_ui": {
|
||||
"page": "options-ui/options-ui.html"
|
||||
}
|
||||
}
|
@ -14,6 +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 { ObjTypeDto } from '../../../../common/model/obj/obj.dto';
|
||||
|
||||
export interface BeginTxResponse {
|
||||
tx: string;
|
||||
locked: boolean;
|
||||
@ -24,13 +26,15 @@ export interface BeginTxResponse {
|
||||
resetStorage: boolean;
|
||||
}
|
||||
|
||||
enum HashOperation {
|
||||
ADD = 'ADD',
|
||||
DEL = 'DEL'
|
||||
}
|
||||
|
||||
export interface HashChangeResponse {
|
||||
export interface ObjSingleChange {
|
||||
localId: number;
|
||||
serverId: number;
|
||||
deletedId: number;
|
||||
type: ObjTypeDto;
|
||||
createdAt: number;
|
||||
operation: HashOperation;
|
||||
hash: string;
|
||||
}
|
||||
|
||||
export interface ObjChangesResponse {
|
||||
data: ObjSingleChange[];
|
||||
}
|
||||
|
@ -20,15 +20,7 @@ import { ObjTypeDto } from '../../../../../common/model/obj/obj.dto';
|
||||
import { ICommand, ServerErrorDto } from '../../../../../common/model/shared/common.dto';
|
||||
import { ApiErrorCode } from '../../../../../common/model/shared/api.error-code';
|
||||
import { FetchService } from '@pinmenote/fetch-service';
|
||||
import { BeginTxResponse } from '../api-store.model';
|
||||
|
||||
export interface ObjSingleChange {
|
||||
serverId: number;
|
||||
localId: number;
|
||||
type: ObjTypeDto;
|
||||
createdAt: number;
|
||||
hash: string;
|
||||
}
|
||||
import { BeginTxResponse, ObjSingleChange } from '../api-store.model';
|
||||
|
||||
export class ApiObjGetByHashCommand extends ApiCallBase implements ICommand<Promise<ObjSingleChange | ServerErrorDto>> {
|
||||
constructor(private hash: string, private tx: BeginTxResponse) {
|
||||
|
@ -14,24 +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 { ApiCallBase } from '../api-call.base';
|
||||
import { ApiCallBase } from '../../api-call.base';
|
||||
import { FetchService } from '@pinmenote/fetch-service';
|
||||
import { HashChangeResponse } from './api-store.model';
|
||||
import { ICommand } from '../../../../common/model/shared/common.dto';
|
||||
import { fnConsoleLog } from '../../../../common/fn/fn-console';
|
||||
import { ICommand } from '../../../../../common/model/shared/common.dto';
|
||||
import { fnConsoleLog } from '../../../../../common/fn/fn-console';
|
||||
import { ObjChangesResponse } from '../api-store.model';
|
||||
|
||||
export class ApiStoreChangesCommand
|
||||
extends ApiCallBase
|
||||
implements ICommand<Promise<{ data: HashChangeResponse[] } | undefined>>
|
||||
{
|
||||
export class ApiObjGetChangesCommand extends ApiCallBase implements ICommand<Promise<ObjChangesResponse | undefined>> {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
async execute(): Promise<{ data: HashChangeResponse[] } | undefined> {
|
||||
async execute(): Promise<ObjChangesResponse | undefined> {
|
||||
await this.initTokenData();
|
||||
if (!this.storeUrl) return;
|
||||
try {
|
||||
const resp = await FetchService.fetch<{ data: HashChangeResponse[] }>(
|
||||
const resp = await FetchService.fetch<ObjChangesResponse>(
|
||||
`${this.storeUrl}/api/v1/obj/changes`,
|
||||
{ headers: this.getAuthHeaders() },
|
||||
this.refreshParams()
|
@ -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 { ApiCallBase } from '../../api-call.base';
|
||||
import { FetchService } from '@pinmenote/fetch-service';
|
||||
import { ObjSingleChange } from '../api-store.model';
|
||||
import { ICommand } from '../../../../../common/model/shared/common.dto';
|
||||
import { fnConsoleLog } from '../../../../../common/fn/fn-console';
|
||||
|
||||
export class ApiObjGetChangesCommand extends ApiCallBase implements ICommand<Promise<ObjSingleChange | undefined>> {
|
||||
constructor(private id: number) {
|
||||
super();
|
||||
}
|
||||
async execute(): Promise<ObjSingleChange | undefined> {
|
||||
await this.initTokenData();
|
||||
if (!this.storeUrl) return;
|
||||
try {
|
||||
const resp = await FetchService.fetch<ObjSingleChange>(
|
||||
`${this.storeUrl}/api/v1/obj/${this.id}`,
|
||||
{ headers: this.getAuthHeaders() },
|
||||
this.refreshParams()
|
||||
);
|
||||
fnConsoleLog('ApiStoreChangesCommand->response', resp);
|
||||
return resp.data;
|
||||
} catch (e) {
|
||||
fnConsoleLog('ApiStoreChangesCommand->Error', e);
|
||||
}
|
||||
}
|
||||
}
|
@ -24,20 +24,20 @@ import { SyncProgress } from '../sync.model';
|
||||
export class SyncGetProgressCommand implements ICommand<Promise<SyncProgress>> {
|
||||
async execute(): Promise<SyncProgress> {
|
||||
const sync = await BrowserStorage.get<SyncProgress | undefined>(ObjectStoreKeys.SYNC_PROGRESS);
|
||||
if (!sync) {
|
||||
const obj = await SyncGetProgressCommand.getFirstObject();
|
||||
return { state: 'update', timestamp: obj.createdAt, id: obj.id };
|
||||
}
|
||||
return sync;
|
||||
if (sync) return sync;
|
||||
const obj = await SyncGetProgressCommand.getFirstObject();
|
||||
if (!obj) return { timestamp: -1, id: -1, serverId: -1 };
|
||||
return { timestamp: obj.createdAt, id: obj.id, serverId: -1 };
|
||||
}
|
||||
|
||||
static async getFirstObject(): Promise<ObjDto> {
|
||||
static async getFirstObject(): Promise<ObjDto | undefined> {
|
||||
let id = undefined;
|
||||
let i = 1;
|
||||
// find first not empty list
|
||||
while (!id) {
|
||||
const key = `${ObjectStoreKeys.OBJECT_LIST}:${i}`;
|
||||
const list = await BrowserStorage.get<number[]>(key);
|
||||
if (!list) return undefined;
|
||||
id = list.shift();
|
||||
i++;
|
||||
}
|
||||
|
@ -27,10 +27,12 @@ import { fnConsoleLog } from '../../../../common/fn/fn-console';
|
||||
export class SyncResetProgressCommand implements ICommand<Promise<void>> {
|
||||
async execute(): Promise<void> {
|
||||
const obj = await SyncGetProgressCommand.getFirstObject();
|
||||
const timestamp = obj?.createdAt || -1;
|
||||
const id = obj?.id || -1;
|
||||
await BrowserStorage.set<SyncProgress>(ObjectStoreKeys.SYNC_PROGRESS, {
|
||||
state: 'update',
|
||||
timestamp: obj.createdAt,
|
||||
id: obj.id
|
||||
timestamp,
|
||||
id,
|
||||
serverId: -1
|
||||
});
|
||||
await this.resetObjects();
|
||||
}
|
||||
|
@ -38,8 +38,10 @@ export class SyncMonthCommand implements ICommand<Promise<SyncObjectStatus>> {
|
||||
const lastIndexElement = indexList[indexList.length - 1];
|
||||
// fnConsoleLog('SyncMonthCommand->last', lastIndexElement, 'progress', this.progress);
|
||||
// we are last so escape early, so we don't waste request for begin / commit
|
||||
if (this.progress.id === lastIndexElement.id && this.progress.timestamp === lastIndexElement.dt)
|
||||
if (this.progress.id === lastIndexElement.id && this.progress.timestamp === lastIndexElement.dt) {
|
||||
// TODO check if last object got deleted
|
||||
return SyncObjectStatus.LAST_ELEMENT;
|
||||
}
|
||||
|
||||
let nextObjectIndex = indexList.findIndex((value) => value.id === this.progress.id);
|
||||
|
||||
|
@ -22,6 +22,10 @@ import { SyncProgress } from './sync.model';
|
||||
import { SyncTxHelper } from './sync-tx.helper';
|
||||
import { fnConsoleLog } from '../../../common/fn/fn-console';
|
||||
import { fnDateKeyFormat } from '../../../common/fn/fn-date-format';
|
||||
import { TokenStorageGetCommand } from '../../../common/command/server/token/token-storage-get.command';
|
||||
import jwtDecode from 'jwt-decode';
|
||||
import { TokenDataDto } from '../../../common/model/shared/token.dto';
|
||||
import { ApiObjGetChangesCommand } from '../api/store/obj/api-obj-get-changes.command';
|
||||
|
||||
export class SyncServerCommand implements ICommand<Promise<void>> {
|
||||
private static isInSync = false;
|
||||
@ -32,11 +36,15 @@ export class SyncServerCommand implements ICommand<Promise<void>> {
|
||||
try {
|
||||
// await new SyncResetProgressCommand().execute();
|
||||
|
||||
const token = await new TokenStorageGetCommand().execute();
|
||||
if (token) console.log(jwtDecode<TokenDataDto>(token.access_token));
|
||||
|
||||
SyncServerCommand.isInSync = true;
|
||||
|
||||
const a = Date.now();
|
||||
const progress = await new SyncGetProgressCommand().execute();
|
||||
await this.sync(progress);
|
||||
await this.syncOutgoing(progress);
|
||||
await this.syncIncoming(progress);
|
||||
|
||||
fnConsoleLog('SyncServerCommand->execute', progress, 'in', Date.now() - a);
|
||||
} finally {
|
||||
@ -44,7 +52,23 @@ export class SyncServerCommand implements ICommand<Promise<void>> {
|
||||
}
|
||||
}
|
||||
|
||||
private async sync(progress: SyncProgress): Promise<void> {
|
||||
private async syncIncoming(progress: SyncProgress): Promise<void> {
|
||||
fnConsoleLog('SyncServerCommand->syncIncoming');
|
||||
const changesResp = await new ApiObjGetChangesCommand().execute();
|
||||
if (!changesResp) return;
|
||||
for (const change of changesResp.data) {
|
||||
console.log(change);
|
||||
break;
|
||||
}
|
||||
const token = await new TokenStorageGetCommand().execute();
|
||||
if (!token) return;
|
||||
const tokenData = jwtDecode(token.access_token);
|
||||
console.log('tokenData', tokenData);
|
||||
}
|
||||
|
||||
private async syncOutgoing(progress: SyncProgress): Promise<void> {
|
||||
// Empty list - fresh install
|
||||
if (progress.id == -1) return;
|
||||
const dt = fnDateToMonthFirstDay(new Date(progress.timestamp));
|
||||
const lastDay = fnMonthLastDay();
|
||||
|
||||
|
@ -16,8 +16,8 @@
|
||||
*/
|
||||
export interface SyncProgress {
|
||||
timestamp: number;
|
||||
state: 'update' | 'remove' | 'remote';
|
||||
id: number;
|
||||
serverId: number;
|
||||
}
|
||||
|
||||
export enum SyncObjectStatus {
|
||||
|
Loading…
Reference in New Issue
Block a user