4
1
mirror of https://github.com/Qortal/qortal-ui.git synced 2025-02-11 17:55:51 +00:00

added linting for lit and removed unused vars

This commit is contained in:
PhilReact 2023-09-24 11:19:36 -05:00
parent e0c8093740
commit d7d18a61b9
12 changed files with 2226 additions and 1340 deletions

1
.eslintignore Normal file
View File

@ -0,0 +1 @@
/node_modules

View File

@ -3,6 +3,7 @@
"browser": true, "browser": true,
"es2021": true "es2021": true
}, },
"plugins": ["lit", "wc"],
"extends": ["eslint:recommended", "plugin:lit/recommended", "plugin:wc/recommended"], "extends": ["eslint:recommended", "plugin:lit/recommended", "plugin:wc/recommended"],
"parserOptions": { "parserOptions": {
"ecmaVersion": 12, "ecmaVersion": 12,

953
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -27,18 +27,30 @@
"build-electron": "electron-builder build --publish never", "build-electron": "electron-builder build --publish never",
"deploy-electron": "electron-builder build --win --publish never", "deploy-electron": "electron-builder build --win --publish never",
"release": "NODE_ENV=production electron-builder build --publish never", "release": "NODE_ENV=production electron-builder build --publish never",
"publish": "electron-builder -p always" "publish": "electron-builder -p always",
"lint": "eslint './**/*.{js,mjs}'"
}, },
"dependencies": { "dependencies": {
"@hapi/hapi": "21.3.2",
"@hapi/inert": "7.1.0",
"@lit-labs/motion": "1.0.4",
"@tiptap/core": "2.0.4",
"@tiptap/extension-highlight": "2.0.4",
"@tiptap/extension-image": "2.0.4",
"@tiptap/extension-placeholder": "2.0.4",
"@tiptap/extension-underline": "2.0.4",
"@tiptap/html": "2.0.4",
"@tiptap/pm": "2.0.4",
"@tiptap/starter-kit": "2.0.4",
"asmcrypto.js": "2.3.2", "asmcrypto.js": "2.3.2",
"bcryptjs": "2.4.3", "bcryptjs": "2.4.3",
"buffer": "6.0.3", "buffer": "6.0.3",
"compressorjs": "1.2.1", "compressorjs": "1.2.1",
"crypto-js": "4.1.1", "crypto-js": "4.1.1",
"electron-log": "4.4.8",
"electron-updater": "6.1.4",
"electron-dl": "3.5.0", "electron-dl": "3.5.0",
"electron-log": "4.4.8",
"electron-store": "8.1.0", "electron-store": "8.1.0",
"electron-updater": "6.1.4",
"emoji-picker-js": "https://github.com/Qortal/emoji-picker-js", "emoji-picker-js": "https://github.com/Qortal/emoji-picker-js",
"extract-zip": "2.0.1", "extract-zip": "2.0.1",
"jssha": "3.3.1", "jssha": "3.3.1",
@ -57,40 +69,9 @@
"prosemirror-transform": "1.7.5", "prosemirror-transform": "1.7.5",
"prosemirror-view": "1.31.7", "prosemirror-view": "1.31.7",
"sass": "1.66.1", "sass": "1.66.1",
"short-unique-id": "5.0.2", "short-unique-id": "5.0.2"
"@hapi/hapi": "21.3.2",
"@hapi/inert": "7.1.0",
"@lit-labs/motion": "1.0.4",
"@tiptap/pm": "2.0.4",
"@tiptap/core": "2.0.4",
"@tiptap/extension-highlight": "2.0.4",
"@tiptap/extension-image": "2.0.4",
"@tiptap/extension-placeholder": "2.0.4",
"@tiptap/extension-underline": "2.0.4",
"@tiptap/html": "2.0.4",
"@tiptap/starter-kit": "2.0.4"
}, },
"devDependencies": { "devDependencies": {
"axios": "1.5.0",
"electron": "26.2.0",
"electron-builder": "24.6.4",
"electron-packager": "17.1.2",
"epml": "0.3.3",
"file-saver": "2.0.5",
"highcharts": "11.1.0",
"html-escaper": "3.0.3",
"is-electron": "2.2.2",
"lit": "2.8.0",
"lit-translate": "2.0.1",
"pwa-helpers": "0.9.1",
"passive-events-support": "1.1.0",
"redux": "4.2.1",
"redux-thunk": "2.4.2",
"rollup": "3.29.0",
"rollup-plugin-node-globals": "1.4.0",
"rollup-plugin-progress": "1.1.2",
"rollup-plugin-scss": "3.0.0",
"shelljs": "0.8.5",
"@babel/core": "7.22.17", "@babel/core": "7.22.17",
"@material/mwc-button": "0.27.0", "@material/mwc-button": "0.27.0",
"@material/mwc-checkbox": "0.27.0", "@material/mwc-checkbox": "0.27.0",
@ -140,7 +121,30 @@
"@vaadin/icons": "24.1.7", "@vaadin/icons": "24.1.7",
"@vaadin/password-field": "24.1.7", "@vaadin/password-field": "24.1.7",
"@vaadin/tooltip": "24.1.7", "@vaadin/tooltip": "24.1.7",
"@zip.js/zip.js": "2.7.29" "@zip.js/zip.js": "2.7.29",
"axios": "1.5.0",
"electron": "26.2.0",
"electron-builder": "24.6.4",
"electron-packager": "17.1.2",
"epml": "0.3.3",
"eslint": "^8.50.0",
"eslint-plugin-lit": "^1.9.1",
"eslint-plugin-wc": "^2.0.3",
"file-saver": "2.0.5",
"highcharts": "11.1.0",
"html-escaper": "3.0.3",
"is-electron": "2.2.2",
"lit": "2.8.0",
"lit-translate": "2.0.1",
"passive-events-support": "1.1.0",
"pwa-helpers": "0.9.1",
"redux": "4.2.1",
"redux-thunk": "2.4.2",
"rollup": "3.29.0",
"rollup-plugin-node-globals": "1.4.0",
"rollup-plugin-progress": "1.1.2",
"rollup-plugin-scss": "3.0.0",
"shelljs": "0.8.5"
}, },
"engines": { "engines": {
"node": ">=18.16.1" "node": ">=18.16.1"

View File

@ -1,11 +1,7 @@
import { LitElement, html, css } from 'lit'; import { LitElement, html, css } from 'lit';
import { render } from 'lit/html.js';
import { import {
use,
get, get,
translate, translate,
translateUnsafeHTML,
registerTranslateConfig,
} from 'lit-translate'; } from 'lit-translate';
import axios from 'axios' import axios from 'axios'
import { RequestQueueWithPromise } from '../../utils/queue'; import { RequestQueueWithPromise } from '../../utils/queue';
@ -228,9 +224,7 @@ getMyNode(){
identifier: this.resource.identifier identifier: this.resource.identifier
}) })
this.fetchStatus() this.fetchStatus()
} catch (error) { } catch (error) { /* empty */ }
}
} }
firstUpdated(){ firstUpdated(){

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,5 @@
import { LitElement, html, css } from 'lit'; import { LitElement, html, css } from 'lit';
import { render } from 'lit/html.js';
import { Epml } from '../../../epml'; import { Epml } from '../../../epml';
import { getUserNameFromAddress } from '../../utils/getUserNameFromAddress';
import snackbar from './snackbar.js';
import '@material/mwc-button'; import '@material/mwc-button';
import '@material/mwc-dialog'; import '@material/mwc-dialog';
import '@polymer/paper-spinner/paper-spinner-lite.js'; import '@polymer/paper-spinner/paper-spinner-lite.js';
@ -15,11 +12,8 @@ import './UserInfo/UserInfo';
import './ChatImage'; import './ChatImage';
import './ReusableImage'; import './ReusableImage';
import { import {
use,
get, get,
translate, translate,
translateUnsafeHTML,
registerTranslateConfig,
} from 'lit-translate'; } from 'lit-translate';
import { generateIdFromAddresses } from '../../utils/id-generation'; import { generateIdFromAddresses } from '../../utils/id-generation';

View File

@ -1,22 +1,16 @@
import { LitElement, html, css } from 'lit'; import { LitElement, html, } from 'lit';
import { render } from 'lit/html.js';
import { repeat } from 'lit/directives/repeat.js'; import { repeat } from 'lit/directives/repeat.js';
import { import {
use,
get, get,
translate, translate,
translateUnsafeHTML,
registerTranslateConfig,
} from 'lit-translate'; } from 'lit-translate';
import { unsafeHTML } from 'lit/directives/unsafe-html.js'; import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import { chatStyles } from './ChatScroller-css.js'; import { chatStyles } from './ChatScroller-css.js';
import { Epml } from '../../../epml'; import { Epml } from '../../../epml';
import { cropAddress } from '../../utils/cropAddress'; import { cropAddress } from '../../utils/cropAddress';
import { roundToNearestDecimal } from '../../utils/roundToNearestDecimal.js'; import { roundToNearestDecimal } from '../../utils/roundToNearestDecimal.js';
import { EmojiPicker } from 'emoji-picker-js';
import { generateHTML } from '@tiptap/core'; import { generateHTML } from '@tiptap/core';
import isElectron from 'is-electron'; import isElectron from 'is-electron';
import localForage from 'localforage';
import axios from 'axios'; import axios from 'axios';
import Highlight from '@tiptap/extension-highlight'; import Highlight from '@tiptap/extension-highlight';
@ -40,9 +34,6 @@ import '@vaadin/tooltip';
import { chatLimit, totalMsgCount } from './ChatPage.js'; import { chatLimit, totalMsgCount } from './ChatPage.js';
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent }); const parentEpml = new Epml({ type: 'WINDOW', source: window.parent });
const chatLastSeen = localForage.createInstance({
name: 'chat-last-seen',
});
let toggledMessage = {}; let toggledMessage = {};
const uid = new ShortUniqueId(); const uid = new ShortUniqueId();
@ -61,7 +52,7 @@ const extractComponents = async (url) => {
return null; return null;
} }
url = url.replace(/^(qortal\:\/\/)/, ''); url = url.replace(/^(qortal:\/\/)/, '');
if (url.includes('/')) { if (url.includes('/')) {
let parts = url.split('/'); let parts = url.split('/');
const service = parts[0].toUpperCase(); const service = parts[0].toUpperCase();
@ -313,7 +304,7 @@ class ChatScroller extends LitElement {
this.requestUpdate(); this.requestUpdate();
} }
async newListMessages(newMessages, message) { async newListMessages(newMessages) {
let data = []; let data = [];
const copy = [...newMessages]; const copy = [...newMessages];
copy.forEach((newMessage) => { copy.forEach((newMessage) => {
@ -370,7 +361,7 @@ class ChatScroller extends LitElement {
} }
} }
copy.forEach((newMessage, groupIndex) => { copy.forEach((newMessage) => {
const lastGroupedMessage = data[data.length - 1]; const lastGroupedMessage = data[data.length - 1];
if ( if (
@ -399,13 +390,8 @@ class ChatScroller extends LitElement {
async addNewMessages(newMessages, type) { async addNewMessages(newMessages, type) {
if (this.disableAddingNewMessages && type === 'newComingInAuto') return; if (this.disableAddingNewMessages && type === 'newComingInAuto') return;
let previousScrollTop;
let previousScrollHeight;
const viewElement = this.shadowRoot.querySelector('#viewElement'); const viewElement = this.shadowRoot.querySelector('#viewElement');
previousScrollTop = viewElement.scrollTop;
previousScrollHeight = viewElement.scrollHeight;
const copy = type === 'initial' ? [] : [...this.messagesToRender]; const copy = type === 'initial' ? [] : [...this.messagesToRender];
for (const newMessage of newMessages) { for (const newMessage of newMessages) {
@ -531,8 +517,6 @@ class ChatScroller extends LitElement {
viewElement.scrollTop + viewElement.clientHeight === viewElement.scrollTop + viewElement.clientHeight ===
viewElement.scrollHeight; viewElement.scrollHeight;
const previousScrollTop = viewElement.scrollTop;
const previousScrollHeight = viewElement.scrollHeight;
// Using map to return a new array, rather than mutating the old one // Using map to return a new array, rather than mutating the old one
const newMessagesToRender = this.messagesToRender.map((group) => { const newMessagesToRender = this.messagesToRender.map((group) => {
@ -750,7 +734,7 @@ class ChatScroller extends LitElement {
this.chatId.includes(item._chatId) this.chatId.includes(item._chatId)
), ),
(message) => message.messageText, (message) => message.messageText,
(message, indexMessage) => html` (message) => html`
<message-template <message-template
.emojiPicker=${this.emojiPicker} .emojiPicker=${this.emojiPicker}
.escapeHTML=${this.escapeHTML} .escapeHTML=${this.escapeHTML}
@ -885,8 +869,7 @@ class ChatScroller extends LitElement {
} }
clearConsole() { clearConsole() {
if (!isElectron()) { if (!isElectron()) { /* empty */ } else {
} else {
console.clear(); console.clear();
window.parent.electronAPI.clearCache(); window.parent.electronAPI.clearCache();
} }
@ -939,8 +922,7 @@ class ChatScroller extends LitElement {
!entries[0].isIntersecting || !entries[0].isIntersecting ||
!entries[0].target || !entries[0].target ||
!entries[0].target.previousElementSibling !entries[0].target.previousElementSibling
) { ) { /* empty */ } else {
} else {
this.disableFetching = true; this.disableFetching = true;
this.isLoadingAfter = true; this.isLoadingAfter = true;
let _scrollElement = entries[0].target.previousElementSibling; let _scrollElement = entries[0].target.previousElementSibling;
@ -1191,8 +1173,7 @@ class MessageTemplate extends LitElement {
} }
clearConsole() { clearConsole() {
if (!isElectron()) { if (!isElectron()) { /* empty */ } else {
} else {
console.clear(); console.clear();
window.parent.electronAPI.clearCache(); window.parent.electronAPI.clearCache();
} }
@ -1258,7 +1239,6 @@ class MessageTemplate extends LitElement {
} }
let avatarImg = ''; let avatarImg = '';
let imageHTML = ''; let imageHTML = '';
let imageHTMLDialog = '';
let imageUrl = ''; let imageUrl = '';
let gifHTML = ''; let gifHTML = '';
let gifHTMLDialog = ''; let gifHTMLDialog = '';
@ -1393,7 +1373,7 @@ class MessageTemplate extends LitElement {
try { try {
const parsedMsg = JSON.parse(repliedToData.decodedMessage); const parsedMsg = JSON.parse(repliedToData.decodedMessage);
repliedToData.decodedMessage = parsedMsg; repliedToData.decodedMessage = parsedMsg;
} catch (error) {} } catch (error) { /* empty */ }
} }
let repliedToMessageText = ''; let repliedToMessageText = '';
@ -1412,7 +1392,7 @@ class MessageTemplate extends LitElement {
// other extensions … // other extensions …
] ]
); );
} catch (error) {} } catch (error) { /* empty */ }
} }
let replacedMessage = ''; let replacedMessage = '';
@ -1420,6 +1400,7 @@ class MessageTemplate extends LitElement {
const escapedMessage = this.escapeHTML(message); const escapedMessage = this.escapeHTML(message);
if (escapedMessage) { if (escapedMessage) {
replacedMessage = escapedMessage.replace( replacedMessage = escapedMessage.replace(
// eslint-disable-next-line no-control-regex
new RegExp('\r?\n', 'g'), new RegExp('\r?\n', 'g'),
'<br />' '<br />'
); );
@ -2016,7 +1997,7 @@ class MessageTemplate extends LitElement {
this.messageObj, this.messageObj,
reaction: reaction.type, reaction: reaction.type,
})} })}
id=${`reactions-${indexMessageTemplate}`} id=${`reactions-${index}`}
class="reactions-bg" class="reactions-bg"
> >
${reaction.type} ${reaction.qty} ${reaction.type} ${reaction.qty}
@ -2359,7 +2340,7 @@ class ChatMenu extends LitElement {
publicKey.key = ''; publicKey.key = '';
publicKey.hasPubKey = false; publicKey.hasPubKey = false;
} }
} catch (error) {} } catch (error) { /* empty */ }
try { try {
const message = { const message = {
@ -2368,29 +2349,11 @@ class ChatMenu extends LitElement {
}; };
const stringifyMessageObject = JSON.stringify(message); const stringifyMessageObject = JSON.stringify(message);
this.setForwardProperties(stringifyMessageObject); this.setForwardProperties(stringifyMessageObject);
} catch (error) {} } catch (error) { /* empty */ }
} }
render() { render() {
return html` return html`
<div class="container"> <div class="container">
<!-- <div
class=${`menu-icon reaction ${
!this.firstMessageInChat ? 'tooltip' : ''
}`}
data-text="${translate('blockpage.bcchange13')}"
@click=${(e) => {
if (this.version === '0') {
this.versionErrorSnack();
return;
}
try {
this.setToggledMessage(this.originalMessage);
this.emojiPicker.togglePicker(e.target);
} catch (error) {}
}}
>
<vaadin-icon icon="vaadin:smiley-o" slot="icon"></vaadin-icon>
</div> -->
<div <div
class=${`menu-icon ${ class=${`menu-icon ${
!this.firstMessageInChat ? 'tooltip' : '' !this.firstMessageInChat ? 'tooltip' : ''

View File

@ -1,23 +1,16 @@
import { LitElement, html, css } from 'lit'; import { LitElement, html, css } from 'lit';
import { render } from 'lit/html.js';
import { import {
use,
get,
translate, translate,
translateUnsafeHTML,
registerTranslateConfig,
} from 'lit-translate'; } from 'lit-translate';
import axios from 'axios'; import axios from 'axios';
import { RequestQueueWithPromise } from '../../utils/queue'; import { RequestQueueWithPromise } from '../../utils/queue';
import '@material/mwc-menu'; import '@material/mwc-menu';
import '@material/mwc-list/mwc-list-item.js'; import '@material/mwc-list/mwc-list-item.js';
import { Epml } from '../../../epml';
import '@material/mwc-dialog' import '@material/mwc-dialog'
const requestQueue = new RequestQueueWithPromise(5); const requestQueue = new RequestQueueWithPromise(5);
const requestQueue2 = new RequestQueueWithPromise(5); const requestQueue2 = new RequestQueueWithPromise(5);
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent });
export class ResuableImage extends LitElement { export class ResuableImage extends LitElement {
static get properties() { static get properties() {
@ -254,7 +247,7 @@ export class ResuableImage extends LitElement {
identifier: this.resource.identifier, identifier: this.resource.identifier,
}); });
this.fetchStatus(); this.fetchStatus();
} catch (error) {} } catch (error) { /* empty */ }
} }
firstUpdated() { firstUpdated() {

View File

@ -157,6 +157,9 @@ export const qchatStyles = css`
padding-top: 20px; padding-top: 20px;
padding-left: 20px; padding-left: 20px;
padding-right: 20px; padding-right: 20px;
display: flex;
align-items: center;
gap: 10px;
} }
.center { .center {
@ -172,13 +175,13 @@ export const qchatStyles = css`
border-radius: 5px; border-radius: 5px;
border: none; border: none;
display: inline-block; display: inline-block;
padding: 14px;
color: #fff; color: #fff;
background: var(--tradehead);
width: 100%; width: 100%;
font-size: 15px; font-size: 15px;
text-align: center; text-align: center;
cursor: pointer; cursor: pointer;
display: flex;
flex: 0;
} }
.people-list .create-chat:hover { .people-list .create-chat:hover {

View File

@ -1,10 +1,9 @@
import { LitElement, html, css } from 'lit' import { LitElement, html } from 'lit'
import { render } from 'lit/html.js' import { render } from 'lit/html.js'
import { passiveSupport } from 'passive-events-support/src/utils' import { passiveSupport } from 'passive-events-support/src/utils'
import { Epml } from '../../../../epml.js' import { Epml } from '../../../../epml.js'
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate' import { get, translate } from 'lit-translate'
import { qchatStyles } from './q-chat-css.src.js' import { qchatStyles } from './q-chat-css.src.js'
import { repeat } from 'lit/directives/repeat.js'
import { Editor, Extension } from '@tiptap/core' import { Editor, Extension } from '@tiptap/core'
import isElectron from 'is-electron' import isElectron from 'is-electron'
import WebWorker from 'web-worker:./computePowWorker.src.js' import WebWorker from 'web-worker:./computePowWorker.src.js'
@ -59,7 +58,9 @@ class Chat extends LitElement {
} }
} }
static styles = [qchatStyles] static get styles() {
return [qchatStyles];
}
constructor() { constructor() {
super() super()
@ -167,8 +168,7 @@ class Chat extends LitElement {
if(currentState.app.accountInfo && currentState.app.accountInfo.addressInfo && currentState.app.accountInfo.addressInfo.address && this.loggedInUserAddress !== currentState.app.accountInfo.addressInfo.address){ if(currentState.app.accountInfo && currentState.app.accountInfo.addressInfo && currentState.app.accountInfo.addressInfo.address && this.loggedInUserAddress !== currentState.app.accountInfo.addressInfo.address){
this.loggedInUserAddress = currentState.app.accountInfo.addressInfo.address this.loggedInUserAddress = currentState.app.accountInfo.addressInfo.address
} }
} catch (error) { } catch (error) { /* empty */ }
}
}) })
} }
@ -194,31 +194,21 @@ class Chat extends LitElement {
<div class="people-list" id="people-list"> <div class="people-list" id="people-list">
<div class="search"> <div class="search">
<div class="create-chat" @click=${() => { this.openPrivateMessage = true }}> <div class="create-chat" @click=${() => { this.openPrivateMessage = true }}>
${translate("chatpage.cchange1")} <mwc-icon style="color: var(--black);">edit_square</mwc-icon>
${translate("chatpage.cchange1")}
</div>
<div class="create-chat" @click=${() => { this.openPrivateMessage = true }}>
<mwc-icon style="color: var(--black);">group_add</mwc-icon>
</div>
<div class="create-chat" @click=${() => { this.openPrivateMessage = true }}>
<mwc-icon style="color: var(--black);">person_off</mwc-icon>
</div> </div>
</div> </div>
<ul class="list"> <ul class="list">
${this.isEmptyArray(this.chatHeads) ? this.renderLoadingText() : this.renderChatHead(this.chatHeads)} ${this.isEmptyArray(this.chatHeads) ? this.renderLoadingText() : this.renderChatHead(this.chatHeads)}
</ul> </ul>
<div class="blockedusers"> <div class="blockedusers">
<!-- <div class="groups-button-container">
<button
@click=${() => { this.redirectToGroups() }}
class="groups-button">
<mwc-icon>groups</mwc-icon>
${translate("sidemenu.groupmanagement")}
</button>
${this.groupInvites.length > 0 ? (
html`
<div class="groups-button-notif">
${this.groupInvites.length}
</div>
<div class="groups-button-notif-number">
${this.groupInvites.length} ${translate("chatpage.cchange60")}
</div>
`
) : null}
</div> -->
<mwc-button <mwc-button
raised raised
label="${translate("chatpage.cchange3")}" label="${translate("chatpage.cchange3")}"
@ -442,8 +432,7 @@ class Chat extends LitElement {
document.querySelector('html').setAttribute('theme', this.theme) document.querySelector('html').setAttribute('theme', this.theme)
}) })
if (!isElectron()) { if (!isElectron()) { /* empty */ } else {
} else {
window.addEventListener('contextmenu', (event) => { window.addEventListener('contextmenu', (event) => {
// Check if the clicked element has the class // Check if the clicked element has the class
let target = event.target; let target = event.target;
@ -497,8 +486,7 @@ class Chat extends LitElement {
clearConsole() { clearConsole() {
if (!isElectron()) { if (!isElectron()) { /* empty */ } else {
} else {
console.clear() console.clear()
window.parent.electronAPI.clearCache() window.parent.electronAPI.clearCache()
} }
@ -588,7 +576,7 @@ class Chat extends LitElement {
recipient = _recipient recipient = _recipient
} else { } else {
recipient = myNameRes.owner recipient = myNameRes.owner
}; }
const getAddressPublicKey = async () => { const getAddressPublicKey = async () => {
let isEncrypted; let isEncrypted;
@ -643,7 +631,7 @@ class Chat extends LitElement {
const worker = new WebWorker() const worker = new WebWorker()
let nonce = null let nonce = null
let chatBytesArray = null; let chatBytesArray = null;
await new Promise((res, rej) => { await new Promise((res) => {
worker.postMessage({chatBytes, path, difficulty}) worker.postMessage({chatBytes, path, difficulty})
worker.onmessage = e => { worker.onmessage = e => {
worker.terminate() worker.terminate()