diff --git a/examples/test-app/CHANGELOG.md b/examples/test-app/CHANGELOG.md index ae59a32..a502c5d 100644 --- a/examples/test-app/CHANGELOG.md +++ b/examples/test-app/CHANGELOG.md @@ -1,5 +1,12 @@ # test-app +## 1.0.14 + +### Patch Changes + +- Updated dependencies + - @parcnet-js/app-connector@1.1.2 + ## 1.0.13 ### Patch Changes diff --git a/examples/test-app/package.json b/examples/test-app/package.json index 9e576c0..5b0a064 100644 --- a/examples/test-app/package.json +++ b/examples/test-app/package.json @@ -1,6 +1,6 @@ { "name": "test-app", - "version": "1.0.13", + "version": "1.0.14", "private": true, "type": "module", "scripts": { diff --git a/packages/app-connector/CHANGELOG.md b/packages/app-connector/CHANGELOG.md index 51be6c0..cbcb5ca 100644 --- a/packages/app-connector/CHANGELOG.md +++ b/packages/app-connector/CHANGELOG.md @@ -1,5 +1,11 @@ # @parcnet-js/app-connector +## 1.1.2 + +### Patch Changes + +- Allow user to cancel page unload while mutating operation in progress + ## 1.1.1 ### Patch Changes diff --git a/packages/app-connector/package.json b/packages/app-connector/package.json index 90e6af1..41f17d5 100644 --- a/packages/app-connector/package.json +++ b/packages/app-connector/package.json @@ -1,6 +1,6 @@ { "name": "@parcnet-js/app-connector", - "version": "1.1.1", + "version": "1.1.2", "license": "GPL-3.0-or-later", "type": "module", "main": "dist/index.cjs", diff --git a/packages/app-connector/src/api_wrapper.ts b/packages/app-connector/src/api_wrapper.ts index 0c265ab..2c85d76 100644 --- a/packages/app-connector/src/api_wrapper.ts +++ b/packages/app-connector/src/api_wrapper.ts @@ -52,11 +52,17 @@ export class ParcnetPODCollectionWrapper { #api: ParcnetRPCConnector; #collectionId: string; #subscriptionEmitters: Map>; + #unloadProtector: MutationUnloadProtector; - constructor(api: ParcnetRPCConnector, collectionId: string) { + constructor( + api: ParcnetRPCConnector, + collectionId: string, + unloadProtector: MutationUnloadProtector + ) { this.#api = api; this.#collectionId = collectionId; this.#subscriptionEmitters = new Map(); + this.#unloadProtector = unloadProtector; this.#api.on("subscription-update", (update) => { this.#subscriptionEmitters .get(update.subscriptionId) @@ -84,24 +90,58 @@ export class ParcnetPODCollectionWrapper { } async insert(podData: PODData): Promise { - return this.#api.pod.insert(this.#collectionId, podData); + return this.#unloadProtector.add( + this.#api.pod.insert(this.#collectionId, podData) + ); } async delete(signature: string): Promise { - return this.#api.pod.delete(this.#collectionId, signature); + return this.#unloadProtector.add( + this.#api.pod.delete(this.#collectionId, signature) + ); + } +} + +/** + * This class is used to prevent the page from being unloaded while there are + * pending mutations. + */ +class MutationUnloadProtector { + #mutations = new Set>(); + + public constructor() { + window.addEventListener("beforeunload", (event: BeforeUnloadEvent) => { + if (this.#mutations.size > 0) { + event.preventDefault(); + } + }); + } + + public add(mutation: Promise): Promise { + this.#mutations.add(mutation); + void mutation.finally(() => { + this.#mutations.delete(mutation); + }); + return mutation; } } export class ParcnetPODWrapper { #api: ParcnetRPCConnector; #modalEmitter: ModalEmitter; + #unloadProtector: MutationUnloadProtector = new MutationUnloadProtector(); + constructor(api: ParcnetRPCConnector, modalEmitter: ModalEmitter) { this.#api = api; this.#modalEmitter = modalEmitter; } collection(collectionId: string): ParcnetPODCollectionWrapper { - return new ParcnetPODCollectionWrapper(this.#api, collectionId); + return new ParcnetPODCollectionWrapper( + this.#api, + collectionId, + this.#unloadProtector + ); } async sign(entries: PODEntries): Promise {