aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/frontend/src/persistence/Compressor.ts
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <marussy@mit.bme.hu>2023-09-26 17:58:31 +0200
committerLibravatar GitHub <noreply@github.com>2023-09-26 17:58:31 +0200
commitf0eb2f6c5ca20c324325817898f2c934cbf5aaec (patch)
tree66c0d598fdcf93db51cf988547c4417bf80906a7 /subprojects/frontend/src/persistence/Compressor.ts
parentfix(query-interpreter): functional dependencies (diff)
parentfeat(frontend): save in URL fragment (diff)
downloadrefinery-f0eb2f6c5ca20c324325817898f2c934cbf5aaec.tar.gz
refinery-f0eb2f6c5ca20c324325817898f2c934cbf5aaec.tar.zst
refinery-f0eb2f6c5ca20c324325817898f2c934cbf5aaec.zip
Merge pull request #42 from kris7t/save-in-url
feat(frontend): save in URL fragment
Diffstat (limited to 'subprojects/frontend/src/persistence/Compressor.ts')
-rw-r--r--subprojects/frontend/src/persistence/Compressor.ts108
1 files changed, 108 insertions, 0 deletions
diff --git a/subprojects/frontend/src/persistence/Compressor.ts b/subprojects/frontend/src/persistence/Compressor.ts
new file mode 100644
index 00000000..94878370
--- /dev/null
+++ b/subprojects/frontend/src/persistence/Compressor.ts
@@ -0,0 +1,108 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6
7import getLogger from '../utils/getLogger';
8
9import {
10 type CompressRequest,
11 CompressorResponse,
12 type DecompressRequest,
13} from './compressionMessages';
14import CompressionWorker from './compressionWorker?worker';
15import initialValue from './initialValue';
16
17const LOG = getLogger('persistence.Compressor');
18
19const FRAGMENT_PREFIX = '#/1/';
20
21export default class Compressor {
22 private readonly worker = new CompressionWorker();
23
24 private readonly hashChangeHandler = () => this.updateHash();
25
26 private fragment: string | undefined;
27
28 private compressing = false;
29
30 private toCompress: string | undefined;
31
32 constructor(private readonly onDecompressed: (text: string) => void) {
33 this.worker.onerror = (error) => LOG.error('Worker error', error);
34 this.worker.onmessageerror = (error) =>
35 LOG.error('Worker message error', error);
36 this.worker.onmessage = (event) => {
37 try {
38 const message = CompressorResponse.parse(event.data);
39 switch (message.response) {
40 case 'compressed':
41 this.fragment = `${FRAGMENT_PREFIX}${message.compressedText}`;
42 this.compressionEnded();
43 window.history.replaceState(null, '', this.fragment);
44 break;
45 case 'decompressed':
46 this.onDecompressed(message.text);
47 break;
48 case 'error':
49 this.compressionEnded();
50 LOG.error('Error processing compressor request', message.message);
51 break;
52 default:
53 LOG.error('Unknown response from compressor worker', event.data);
54 break;
55 }
56 } catch (error) {
57 LOG.error('Error processing worker message', event, error);
58 }
59 };
60 window.addEventListener('hashchange', this.hashChangeHandler);
61 }
62
63 decompressInitial(): void {
64 this.updateHash();
65 if (this.fragment === undefined) {
66 LOG.debug('Loading default source');
67 this.onDecompressed(initialValue);
68 }
69 }
70
71 compress(text: string): void {
72 this.toCompress = text;
73 if (this.compressing) {
74 return;
75 }
76 this.compressing = true;
77 this.worker.postMessage({
78 request: 'compress',
79 text,
80 } satisfies CompressRequest);
81 }
82
83 dispose(): void {
84 window.removeEventListener('hashchange', this.hashChangeHandler);
85 this.worker.terminate();
86 }
87
88 private compressionEnded(): void {
89 this.compressing = false;
90 if (this.toCompress !== undefined) {
91 this.compress(this.toCompress);
92 this.toCompress = undefined;
93 }
94 }
95
96 private updateHash(): void {
97 if (
98 window.location.hash !== this.fragment &&
99 window.location.hash.startsWith(FRAGMENT_PREFIX)
100 ) {
101 this.fragment = window.location.hash;
102 this.worker.postMessage({
103 request: 'decompress',
104 compressedText: this.fragment.substring(FRAGMENT_PREFIX.length),
105 } satisfies DecompressRequest);
106 }
107 }
108}